Add reference to version number documentation to version 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 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
808
809 I<Note:> Don't use this call to test for availability
810 of features.  Distro backports makes this unreliable.  Use
811 C<guestfs_available> instead.");
812
813   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
814    [InitNone, Always, TestOutputTrue (
815       [["set_selinux"; "true"];
816        ["get_selinux"]])],
817    "set SELinux enabled or disabled at appliance boot",
818    "\
819 This sets the selinux flag that is passed to the appliance
820 at boot time.  The default is C<selinux=0> (disabled).
821
822 Note that if SELinux is enabled, it is always in
823 Permissive mode (C<enforcing=0>).
824
825 For more information on the architecture of libguestfs,
826 see L<guestfs(3)>.");
827
828   ("get_selinux", (RBool "selinux", []), -1, [],
829    [],
830    "get SELinux enabled flag",
831    "\
832 This returns the current setting of the selinux flag which
833 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
834
835 For more information on the architecture of libguestfs,
836 see L<guestfs(3)>.");
837
838   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
839    [InitNone, Always, TestOutputFalse (
840       [["set_trace"; "false"];
841        ["get_trace"]])],
842    "enable or disable command traces",
843    "\
844 If the command trace flag is set to 1, then commands are
845 printed on stdout before they are executed in a format
846 which is very similar to the one used by guestfish.  In
847 other words, you can run a program with this enabled, and
848 you will get out a script which you can feed to guestfish
849 to perform the same set of actions.
850
851 If you want to trace C API calls into libguestfs (and
852 other libraries) then possibly a better way is to use
853 the external ltrace(1) command.
854
855 Command traces are disabled unless the environment variable
856 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
857
858   ("get_trace", (RBool "trace", []), -1, [],
859    [],
860    "get command trace enabled flag",
861    "\
862 Return the command trace flag.");
863
864   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
865    [InitNone, Always, TestOutputFalse (
866       [["set_direct"; "false"];
867        ["get_direct"]])],
868    "enable or disable direct appliance mode",
869    "\
870 If the direct appliance mode flag is enabled, then stdin and
871 stdout are passed directly through to the appliance once it
872 is launched.
873
874 One consequence of this is that log messages aren't caught
875 by the library and handled by C<guestfs_set_log_message_callback>,
876 but go straight to stdout.
877
878 You probably don't want to use this unless you know what you
879 are doing.
880
881 The default is disabled.");
882
883   ("get_direct", (RBool "direct", []), -1, [],
884    [],
885    "get direct appliance mode flag",
886    "\
887 Return the direct appliance mode flag.");
888
889   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
890    [InitNone, Always, TestOutputTrue (
891       [["set_recovery_proc"; "true"];
892        ["get_recovery_proc"]])],
893    "enable or disable the recovery process",
894    "\
895 If this is called with the parameter C<false> then
896 C<guestfs_launch> does not create a recovery process.  The
897 purpose of the recovery process is to stop runaway qemu
898 processes in the case where the main program aborts abruptly.
899
900 This only has any effect if called before C<guestfs_launch>,
901 and the default is true.
902
903 About the only time when you would want to disable this is
904 if the main process will fork itself into the background
905 (\"daemonize\" itself).  In this case the recovery process
906 thinks that the main program has disappeared and so kills
907 qemu, which is not very helpful.");
908
909   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
910    [],
911    "get recovery process enabled flag",
912    "\
913 Return the recovery process enabled flag.");
914
915   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
916    [],
917    "add a drive specifying the QEMU block emulation to use",
918    "\
919 This is the same as C<guestfs_add_drive> but it allows you
920 to specify the QEMU interface emulation to use at run time.");
921
922   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
923    [],
924    "add a drive read-only specifying the QEMU block emulation to use",
925    "\
926 This is the same as C<guestfs_add_drive_ro> but it allows you
927 to specify the QEMU interface emulation to use at run time.");
928
929 ]
930
931 (* daemon_functions are any functions which cause some action
932  * to take place in the daemon.
933  *)
934
935 let daemon_functions = [
936   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
937    [InitEmpty, Always, TestOutput (
938       [["part_disk"; "/dev/sda"; "mbr"];
939        ["mkfs"; "ext2"; "/dev/sda1"];
940        ["mount"; "/dev/sda1"; "/"];
941        ["write_file"; "/new"; "new file contents"; "0"];
942        ["cat"; "/new"]], "new file contents")],
943    "mount a guest disk at a position in the filesystem",
944    "\
945 Mount a guest disk at a position in the filesystem.  Block devices
946 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
947 the guest.  If those block devices contain partitions, they will have
948 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
949 names can be used.
950
951 The rules are the same as for L<mount(2)>:  A filesystem must
952 first be mounted on C</> before others can be mounted.  Other
953 filesystems can only be mounted on directories which already
954 exist.
955
956 The mounted filesystem is writable, if we have sufficient permissions
957 on the underlying device.
958
959 B<Important note:>
960 When you use this call, the filesystem options C<sync> and C<noatime>
961 are set implicitly.  This was originally done because we thought it
962 would improve reliability, but it turns out that I<-o sync> has a
963 very large negative performance impact and negligible effect on
964 reliability.  Therefore we recommend that you avoid using
965 C<guestfs_mount> in any code that needs performance, and instead
966 use C<guestfs_mount_options> (use an empty string for the first
967 parameter if you don't want any options).");
968
969   ("sync", (RErr, []), 2, [],
970    [ InitEmpty, Always, TestRun [["sync"]]],
971    "sync disks, writes are flushed through to the disk image",
972    "\
973 This syncs the disk, so that any writes are flushed through to the
974 underlying disk image.
975
976 You should always call this if you have modified a disk image, before
977 closing the handle.");
978
979   ("touch", (RErr, [Pathname "path"]), 3, [],
980    [InitBasicFS, Always, TestOutputTrue (
981       [["touch"; "/new"];
982        ["exists"; "/new"]])],
983    "update file timestamps or create a new file",
984    "\
985 Touch acts like the L<touch(1)> command.  It can be used to
986 update the timestamps on a file, or, if the file does not exist,
987 to create a new zero-length file.");
988
989   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
990    [InitISOFS, Always, TestOutput (
991       [["cat"; "/known-2"]], "abcdef\n")],
992    "list the contents of a file",
993    "\
994 Return the contents of the file named C<path>.
995
996 Note that this function cannot correctly handle binary files
997 (specifically, files containing C<\\0> character which is treated
998 as end of string).  For those you need to use the C<guestfs_read_file>
999 or C<guestfs_download> functions which have a more complex interface.");
1000
1001   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1002    [], (* XXX Tricky to test because it depends on the exact format
1003         * of the 'ls -l' command, which changes between F10 and F11.
1004         *)
1005    "list the files in a directory (long format)",
1006    "\
1007 List the files in C<directory> (relative to the root directory,
1008 there is no cwd) in the format of 'ls -la'.
1009
1010 This command is mostly useful for interactive sessions.  It
1011 is I<not> intended that you try to parse the output string.");
1012
1013   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1014    [InitBasicFS, Always, TestOutputList (
1015       [["touch"; "/new"];
1016        ["touch"; "/newer"];
1017        ["touch"; "/newest"];
1018        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1019    "list the files in a directory",
1020    "\
1021 List the files in C<directory> (relative to the root directory,
1022 there is no cwd).  The '.' and '..' entries are not returned, but
1023 hidden files are shown.
1024
1025 This command is mostly useful for interactive sessions.  Programs
1026 should probably use C<guestfs_readdir> instead.");
1027
1028   ("list_devices", (RStringList "devices", []), 7, [],
1029    [InitEmpty, Always, TestOutputListOfDevices (
1030       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1031    "list the block devices",
1032    "\
1033 List all the block devices.
1034
1035 The full block device names are returned, eg. C</dev/sda>");
1036
1037   ("list_partitions", (RStringList "partitions", []), 8, [],
1038    [InitBasicFS, Always, TestOutputListOfDevices (
1039       [["list_partitions"]], ["/dev/sda1"]);
1040     InitEmpty, Always, TestOutputListOfDevices (
1041       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1042        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1043    "list the partitions",
1044    "\
1045 List all the partitions detected on all block devices.
1046
1047 The full partition device names are returned, eg. C</dev/sda1>
1048
1049 This does not return logical volumes.  For that you will need to
1050 call C<guestfs_lvs>.");
1051
1052   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1053    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1054       [["pvs"]], ["/dev/sda1"]);
1055     InitEmpty, Always, TestOutputListOfDevices (
1056       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1057        ["pvcreate"; "/dev/sda1"];
1058        ["pvcreate"; "/dev/sda2"];
1059        ["pvcreate"; "/dev/sda3"];
1060        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1061    "list the LVM physical volumes (PVs)",
1062    "\
1063 List all the physical volumes detected.  This is the equivalent
1064 of the L<pvs(8)> command.
1065
1066 This returns a list of just the device names that contain
1067 PVs (eg. C</dev/sda2>).
1068
1069 See also C<guestfs_pvs_full>.");
1070
1071   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1072    [InitBasicFSonLVM, Always, TestOutputList (
1073       [["vgs"]], ["VG"]);
1074     InitEmpty, Always, TestOutputList (
1075       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1076        ["pvcreate"; "/dev/sda1"];
1077        ["pvcreate"; "/dev/sda2"];
1078        ["pvcreate"; "/dev/sda3"];
1079        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1080        ["vgcreate"; "VG2"; "/dev/sda3"];
1081        ["vgs"]], ["VG1"; "VG2"])],
1082    "list the LVM volume groups (VGs)",
1083    "\
1084 List all the volumes groups detected.  This is the equivalent
1085 of the L<vgs(8)> command.
1086
1087 This returns a list of just the volume group names that were
1088 detected (eg. C<VolGroup00>).
1089
1090 See also C<guestfs_vgs_full>.");
1091
1092   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1093    [InitBasicFSonLVM, Always, TestOutputList (
1094       [["lvs"]], ["/dev/VG/LV"]);
1095     InitEmpty, Always, TestOutputList (
1096       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1097        ["pvcreate"; "/dev/sda1"];
1098        ["pvcreate"; "/dev/sda2"];
1099        ["pvcreate"; "/dev/sda3"];
1100        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1101        ["vgcreate"; "VG2"; "/dev/sda3"];
1102        ["lvcreate"; "LV1"; "VG1"; "50"];
1103        ["lvcreate"; "LV2"; "VG1"; "50"];
1104        ["lvcreate"; "LV3"; "VG2"; "50"];
1105        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1106    "list the LVM logical volumes (LVs)",
1107    "\
1108 List all the logical volumes detected.  This is the equivalent
1109 of the L<lvs(8)> command.
1110
1111 This returns a list of the logical volume device names
1112 (eg. C</dev/VolGroup00/LogVol00>).
1113
1114 See also C<guestfs_lvs_full>.");
1115
1116   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1117    [], (* XXX how to test? *)
1118    "list the LVM physical volumes (PVs)",
1119    "\
1120 List all the physical volumes detected.  This is the equivalent
1121 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1122
1123   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1124    [], (* XXX how to test? *)
1125    "list the LVM volume groups (VGs)",
1126    "\
1127 List all the volumes groups detected.  This is the equivalent
1128 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1129
1130   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1131    [], (* XXX how to test? *)
1132    "list the LVM logical volumes (LVs)",
1133    "\
1134 List all the logical volumes detected.  This is the equivalent
1135 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1136
1137   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1138    [InitISOFS, Always, TestOutputList (
1139       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1140     InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/empty"]], [])],
1142    "read file as lines",
1143    "\
1144 Return the contents of the file named C<path>.
1145
1146 The file contents are returned as a list of lines.  Trailing
1147 C<LF> and C<CRLF> character sequences are I<not> returned.
1148
1149 Note that this function cannot correctly handle binary files
1150 (specifically, files containing C<\\0> character which is treated
1151 as end of line).  For those you need to use the C<guestfs_read_file>
1152 function which has a more complex interface.");
1153
1154   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1155    [], (* XXX Augeas code needs tests. *)
1156    "create a new Augeas handle",
1157    "\
1158 Create a new Augeas handle for editing configuration files.
1159 If there was any previous Augeas handle associated with this
1160 guestfs session, then it is closed.
1161
1162 You must call this before using any other C<guestfs_aug_*>
1163 commands.
1164
1165 C<root> is the filesystem root.  C<root> must not be NULL,
1166 use C</> instead.
1167
1168 The flags are the same as the flags defined in
1169 E<lt>augeas.hE<gt>, the logical I<or> of the following
1170 integers:
1171
1172 =over 4
1173
1174 =item C<AUG_SAVE_BACKUP> = 1
1175
1176 Keep the original file with a C<.augsave> extension.
1177
1178 =item C<AUG_SAVE_NEWFILE> = 2
1179
1180 Save changes into a file with extension C<.augnew>, and
1181 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1182
1183 =item C<AUG_TYPE_CHECK> = 4
1184
1185 Typecheck lenses (can be expensive).
1186
1187 =item C<AUG_NO_STDINC> = 8
1188
1189 Do not use standard load path for modules.
1190
1191 =item C<AUG_SAVE_NOOP> = 16
1192
1193 Make save a no-op, just record what would have been changed.
1194
1195 =item C<AUG_NO_LOAD> = 32
1196
1197 Do not load the tree in C<guestfs_aug_init>.
1198
1199 =back
1200
1201 To close the handle, you can call C<guestfs_aug_close>.
1202
1203 To find out more about Augeas, see L<http://augeas.net/>.");
1204
1205   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1206    [], (* XXX Augeas code needs tests. *)
1207    "close the current Augeas handle",
1208    "\
1209 Close the current Augeas handle and free up any resources
1210 used by it.  After calling this, you have to call
1211 C<guestfs_aug_init> again before you can use any other
1212 Augeas functions.");
1213
1214   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1215    [], (* XXX Augeas code needs tests. *)
1216    "define an Augeas variable",
1217    "\
1218 Defines an Augeas variable C<name> whose value is the result
1219 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1220 undefined.
1221
1222 On success this returns the number of nodes in C<expr>, or
1223 C<0> if C<expr> evaluates to something which is not a nodeset.");
1224
1225   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1226    [], (* XXX Augeas code needs tests. *)
1227    "define an Augeas node",
1228    "\
1229 Defines a variable C<name> whose value is the result of
1230 evaluating C<expr>.
1231
1232 If C<expr> evaluates to an empty nodeset, a node is created,
1233 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1234 C<name> will be the nodeset containing that single node.
1235
1236 On success this returns a pair containing the
1237 number of nodes in the nodeset, and a boolean flag
1238 if a node was created.");
1239
1240   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1241    [], (* XXX Augeas code needs tests. *)
1242    "look up the value of an Augeas path",
1243    "\
1244 Look up the value associated with C<path>.  If C<path>
1245 matches exactly one node, the C<value> is returned.");
1246
1247   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1248    [], (* XXX Augeas code needs tests. *)
1249    "set Augeas path to value",
1250    "\
1251 Set the value associated with C<path> to C<value>.");
1252
1253   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254    [], (* XXX Augeas code needs tests. *)
1255    "insert a sibling Augeas node",
1256    "\
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1259 flag C<before>).
1260
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1264
1265   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266    [], (* XXX Augeas code needs tests. *)
1267    "remove an Augeas path",
1268    "\
1269 Remove C<path> and all of its children.
1270
1271 On success this returns the number of entries which were removed.");
1272
1273   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274    [], (* XXX Augeas code needs tests. *)
1275    "move Augeas node",
1276    "\
1277 Move the node C<src> to C<dest>.  C<src> must match exactly
1278 one node.  C<dest> is overwritten if it exists.");
1279
1280   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "return Augeas nodes which match augpath",
1283    "\
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1287
1288   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289    [], (* XXX Augeas code needs tests. *)
1290    "write all pending Augeas changes to disk",
1291    "\
1292 This writes all pending changes to disk.
1293
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1296
1297   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298    [], (* XXX Augeas code needs tests. *)
1299    "load files into the tree",
1300    "\
1301 Load files into the tree.
1302
1303 See C<aug_load> in the Augeas documentation for the full gory
1304 details.");
1305
1306   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307    [], (* XXX Augeas code needs tests. *)
1308    "list Augeas nodes under augpath",
1309    "\
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1312
1313   ("rm", (RErr, [Pathname "path"]), 29, [],
1314    [InitBasicFS, Always, TestRun
1315       [["touch"; "/new"];
1316        ["rm"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["rm"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["mkdir"; "/new"];
1321        ["rm"; "/new"]]],
1322    "remove a file",
1323    "\
1324 Remove the single file C<path>.");
1325
1326   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327    [InitBasicFS, Always, TestRun
1328       [["mkdir"; "/new"];
1329        ["rmdir"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["rmdir"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["touch"; "/new"];
1334        ["rmdir"; "/new"]]],
1335    "remove a directory",
1336    "\
1337 Remove the single directory C<path>.");
1338
1339   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340    [InitBasicFS, Always, TestOutputFalse
1341       [["mkdir"; "/new"];
1342        ["mkdir"; "/new/foo"];
1343        ["touch"; "/new/foo/bar"];
1344        ["rm_rf"; "/new"];
1345        ["exists"; "/new"]]],
1346    "remove a file or directory recursively",
1347    "\
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory.  This is like the C<rm -rf> shell
1350 command.");
1351
1352   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir"; "/new"];
1355        ["is_dir"; "/new"]];
1356     InitBasicFS, Always, TestLastFail
1357       [["mkdir"; "/new/foo/bar"]]],
1358    "create a directory",
1359    "\
1360 Create a directory named C<path>.");
1361
1362   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir_p"; "/new/foo/bar"];
1365        ["is_dir"; "/new/foo/bar"]];
1366     InitBasicFS, Always, TestOutputTrue
1367       [["mkdir_p"; "/new/foo/bar"];
1368        ["is_dir"; "/new/foo"]];
1369     InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new"]];
1372     (* Regression tests for RHBZ#503133: *)
1373     InitBasicFS, Always, TestRun
1374       [["mkdir"; "/new"];
1375        ["mkdir_p"; "/new"]];
1376     InitBasicFS, Always, TestLastFail
1377       [["touch"; "/new"];
1378        ["mkdir_p"; "/new"]]],
1379    "create a directory and parents",
1380    "\
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary.  This is like the C<mkdir -p> shell command.");
1383
1384   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385    [], (* XXX Need stat command to test *)
1386    "change file mode",
1387    "\
1388 Change the mode (permissions) of C<path> to C<mode>.  Only
1389 numeric modes are supported.
1390
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.
1394
1395 The mode actually set is affected by the umask.");
1396
1397   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1398    [], (* XXX Need stat command to test *)
1399    "change file owner and group",
1400    "\
1401 Change the file owner to C<owner> and group to C<group>.
1402
1403 Only numeric uid and gid are supported.  If you want to use
1404 names, you will need to locate and parse the password file
1405 yourself (Augeas support makes this relatively easy).");
1406
1407   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["exists"; "/empty"]]);
1410     InitISOFS, Always, TestOutputTrue (
1411       [["exists"; "/directory"]])],
1412    "test if file or directory exists",
1413    "\
1414 This returns C<true> if and only if there is a file, directory
1415 (or anything) with the given C<path> name.
1416
1417 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1418
1419   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1420    [InitISOFS, Always, TestOutputTrue (
1421       [["is_file"; "/known-1"]]);
1422     InitISOFS, Always, TestOutputFalse (
1423       [["is_file"; "/directory"]])],
1424    "test if file exists",
1425    "\
1426 This returns C<true> if and only if there is a file
1427 with the given C<path> name.  Note that it returns false for
1428 other objects like directories.
1429
1430 See also C<guestfs_stat>.");
1431
1432   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1433    [InitISOFS, Always, TestOutputFalse (
1434       [["is_dir"; "/known-3"]]);
1435     InitISOFS, Always, TestOutputTrue (
1436       [["is_dir"; "/directory"]])],
1437    "test if file exists",
1438    "\
1439 This returns C<true> if and only if there is a directory
1440 with the given C<path> name.  Note that it returns false for
1441 other objects like files.
1442
1443 See also C<guestfs_stat>.");
1444
1445   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1446    [InitEmpty, Always, TestOutputListOfDevices (
1447       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1448        ["pvcreate"; "/dev/sda1"];
1449        ["pvcreate"; "/dev/sda2"];
1450        ["pvcreate"; "/dev/sda3"];
1451        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1452    "create an LVM physical volume",
1453    "\
1454 This creates an LVM physical volume on the named C<device>,
1455 where C<device> should usually be a partition name such
1456 as C</dev/sda1>.");
1457
1458   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1459    [InitEmpty, Always, TestOutputList (
1460       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1461        ["pvcreate"; "/dev/sda1"];
1462        ["pvcreate"; "/dev/sda2"];
1463        ["pvcreate"; "/dev/sda3"];
1464        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1465        ["vgcreate"; "VG2"; "/dev/sda3"];
1466        ["vgs"]], ["VG1"; "VG2"])],
1467    "create an LVM volume group",
1468    "\
1469 This creates an LVM volume group called C<volgroup>
1470 from the non-empty list of physical volumes C<physvols>.");
1471
1472   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1473    [InitEmpty, Always, TestOutputList (
1474       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475        ["pvcreate"; "/dev/sda1"];
1476        ["pvcreate"; "/dev/sda2"];
1477        ["pvcreate"; "/dev/sda3"];
1478        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479        ["vgcreate"; "VG2"; "/dev/sda3"];
1480        ["lvcreate"; "LV1"; "VG1"; "50"];
1481        ["lvcreate"; "LV2"; "VG1"; "50"];
1482        ["lvcreate"; "LV3"; "VG2"; "50"];
1483        ["lvcreate"; "LV4"; "VG2"; "50"];
1484        ["lvcreate"; "LV5"; "VG2"; "50"];
1485        ["lvs"]],
1486       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1487        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1488    "create an LVM logical volume",
1489    "\
1490 This creates an LVM logical volume called C<logvol>
1491 on the volume group C<volgroup>, with C<size> megabytes.");
1492
1493   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1494    [InitEmpty, Always, TestOutput (
1495       [["part_disk"; "/dev/sda"; "mbr"];
1496        ["mkfs"; "ext2"; "/dev/sda1"];
1497        ["mount_options"; ""; "/dev/sda1"; "/"];
1498        ["write_file"; "/new"; "new file contents"; "0"];
1499        ["cat"; "/new"]], "new file contents")],
1500    "make a filesystem",
1501    "\
1502 This creates a filesystem on C<device> (usually a partition
1503 or LVM logical volume).  The filesystem type is C<fstype>, for
1504 example C<ext3>.");
1505
1506   ("sfdisk", (RErr, [Device "device";
1507                      Int "cyls"; Int "heads"; Int "sectors";
1508                      StringList "lines"]), 43, [DangerWillRobinson],
1509    [],
1510    "create partitions on a block device",
1511    "\
1512 This is a direct interface to the L<sfdisk(8)> program for creating
1513 partitions on block devices.
1514
1515 C<device> should be a block device, for example C</dev/sda>.
1516
1517 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1518 and sectors on the device, which are passed directly to sfdisk as
1519 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1520 of these, then the corresponding parameter is omitted.  Usually for
1521 'large' disks, you can just pass C<0> for these, but for small
1522 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1523 out the right geometry and you will need to tell it.
1524
1525 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1526 information refer to the L<sfdisk(8)> manpage.
1527
1528 To create a single partition occupying the whole disk, you would
1529 pass C<lines> as a single element list, when the single element being
1530 the string C<,> (comma).
1531
1532 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1533 C<guestfs_part_init>");
1534
1535   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1536    [InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "new file contents"; "0"];
1538        ["cat"; "/new"]], "new file contents");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1541        ["cat"; "/new"]], "\nnew file contents\n");
1542     InitBasicFS, Always, TestOutput (
1543       [["write_file"; "/new"; "\n\n"; "0"];
1544        ["cat"; "/new"]], "\n\n");
1545     InitBasicFS, Always, TestOutput (
1546       [["write_file"; "/new"; ""; "0"];
1547        ["cat"; "/new"]], "");
1548     InitBasicFS, Always, TestOutput (
1549       [["write_file"; "/new"; "\n\n\n"; "0"];
1550        ["cat"; "/new"]], "\n\n\n");
1551     InitBasicFS, Always, TestOutput (
1552       [["write_file"; "/new"; "\n"; "0"];
1553        ["cat"; "/new"]], "\n")],
1554    "create a file",
1555    "\
1556 This call creates a file called C<path>.  The contents of the
1557 file is the string C<content> (which can contain any 8 bit data),
1558 with length C<size>.
1559
1560 As a special case, if C<size> is C<0>
1561 then the length is calculated using C<strlen> (so in this case
1562 the content cannot contain embedded ASCII NULs).
1563
1564 I<NB.> Owing to a bug, writing content containing ASCII NUL
1565 characters does I<not> work, even if the length is specified.
1566 We hope to resolve this bug in a future version.  In the meantime
1567 use C<guestfs_upload>.");
1568
1569   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1570    [InitEmpty, Always, TestOutputListOfDevices (
1571       [["part_disk"; "/dev/sda"; "mbr"];
1572        ["mkfs"; "ext2"; "/dev/sda1"];
1573        ["mount_options"; ""; "/dev/sda1"; "/"];
1574        ["mounts"]], ["/dev/sda1"]);
1575     InitEmpty, Always, TestOutputList (
1576       [["part_disk"; "/dev/sda"; "mbr"];
1577        ["mkfs"; "ext2"; "/dev/sda1"];
1578        ["mount_options"; ""; "/dev/sda1"; "/"];
1579        ["umount"; "/"];
1580        ["mounts"]], [])],
1581    "unmount a filesystem",
1582    "\
1583 This unmounts the given filesystem.  The filesystem may be
1584 specified either by its mountpoint (path) or the device which
1585 contains the filesystem.");
1586
1587   ("mounts", (RStringList "devices", []), 46, [],
1588    [InitBasicFS, Always, TestOutputListOfDevices (
1589       [["mounts"]], ["/dev/sda1"])],
1590    "show mounted filesystems",
1591    "\
1592 This returns the list of currently mounted filesystems.  It returns
1593 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1594
1595 Some internal mounts are not shown.
1596
1597 See also: C<guestfs_mountpoints>");
1598
1599   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1600    [InitBasicFS, Always, TestOutputList (
1601       [["umount_all"];
1602        ["mounts"]], []);
1603     (* check that umount_all can unmount nested mounts correctly: *)
1604     InitEmpty, Always, TestOutputList (
1605       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1606        ["mkfs"; "ext2"; "/dev/sda1"];
1607        ["mkfs"; "ext2"; "/dev/sda2"];
1608        ["mkfs"; "ext2"; "/dev/sda3"];
1609        ["mount_options"; ""; "/dev/sda1"; "/"];
1610        ["mkdir"; "/mp1"];
1611        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1612        ["mkdir"; "/mp1/mp2"];
1613        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1614        ["mkdir"; "/mp1/mp2/mp3"];
1615        ["umount_all"];
1616        ["mounts"]], [])],
1617    "unmount all filesystems",
1618    "\
1619 This unmounts all mounted filesystems.
1620
1621 Some internal mounts are not unmounted by this call.");
1622
1623   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1624    [],
1625    "remove all LVM LVs, VGs and PVs",
1626    "\
1627 This command removes all LVM logical volumes, volume groups
1628 and physical volumes.");
1629
1630   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1631    [InitISOFS, Always, TestOutput (
1632       [["file"; "/empty"]], "empty");
1633     InitISOFS, Always, TestOutput (
1634       [["file"; "/known-1"]], "ASCII text");
1635     InitISOFS, Always, TestLastFail (
1636       [["file"; "/notexists"]])],
1637    "determine file type",
1638    "\
1639 This call uses the standard L<file(1)> command to determine
1640 the type or contents of the file.  This also works on devices,
1641 for example to find out whether a partition contains a filesystem.
1642
1643 This call will also transparently look inside various types
1644 of compressed file.
1645
1646 The exact command which runs is C<file -zbsL path>.  Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).");
1649
1650   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1651    [InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 1"]], "Result1");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 2"]], "Result2\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 3"]], "\nResult3");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 4"]], "\nResult4\n");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 5"]], "\nResult5\n\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 7"]], "");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 8"]], "\n");
1683     InitBasicFS, Always, TestOutput (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command 9"]], "\n\n");
1687     InitBasicFS, Always, TestOutput (
1688       [["upload"; "test-command"; "/test-command"];
1689        ["chmod"; "0o755"; "/test-command"];
1690        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1691     InitBasicFS, Always, TestOutput (
1692       [["upload"; "test-command"; "/test-command"];
1693        ["chmod"; "0o755"; "/test-command"];
1694        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1695     InitBasicFS, Always, TestLastFail (
1696       [["upload"; "test-command"; "/test-command"];
1697        ["chmod"; "0o755"; "/test-command"];
1698        ["command"; "/test-command"]])],
1699    "run a command from the guest filesystem",
1700    "\
1701 This call runs a command from the guest filesystem.  The
1702 filesystem must be mounted, and must contain a compatible
1703 operating system (ie. something Linux, with the same
1704 or compatible processor architecture).
1705
1706 The single parameter is an argv-style list of arguments.
1707 The first element is the name of the program to run.
1708 Subsequent elements are parameters.  The list must be
1709 non-empty (ie. must contain a program name).  Note that
1710 the command runs directly, and is I<not> invoked via
1711 the shell (see C<guestfs_sh>).
1712
1713 The return value is anything printed to I<stdout> by
1714 the command.
1715
1716 If the command returns a non-zero exit status, then
1717 this function returns an error message.  The error message
1718 string is the content of I<stderr> from the command.
1719
1720 The C<$PATH> environment variable will contain at least
1721 C</usr/bin> and C</bin>.  If you require a program from
1722 another location, you should provide the full path in the
1723 first parameter.
1724
1725 Shared libraries and data files required by the program
1726 must be available on filesystems which are mounted in the
1727 correct places.  It is the caller's responsibility to ensure
1728 all filesystems that are needed are mounted at the right
1729 locations.");
1730
1731   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1732    [InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 1"]], ["Result1"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 2"]], ["Result2"]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 7"]], []);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 8"]], [""]);
1764     InitBasicFS, Always, TestOutputList (
1765       [["upload"; "test-command"; "/test-command"];
1766        ["chmod"; "0o755"; "/test-command"];
1767        ["command_lines"; "/test-command 9"]], ["";""]);
1768     InitBasicFS, Always, TestOutputList (
1769       [["upload"; "test-command"; "/test-command"];
1770        ["chmod"; "0o755"; "/test-command"];
1771        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1772     InitBasicFS, Always, TestOutputList (
1773       [["upload"; "test-command"; "/test-command"];
1774        ["chmod"; "0o755"; "/test-command"];
1775        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1776    "run a command, returning lines",
1777    "\
1778 This is the same as C<guestfs_command>, but splits the
1779 result into a list of lines.
1780
1781 See also: C<guestfs_sh_lines>");
1782
1783   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1784    [InitISOFS, Always, TestOutputStruct (
1785       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786    "get file information",
1787    "\
1788 Returns file information for the given C<path>.
1789
1790 This is the same as the C<stat(2)> system call.");
1791
1792   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1795    "get file information for a symbolic link",
1796    "\
1797 Returns file information for the given C<path>.
1798
1799 This is the same as C<guestfs_stat> except that if C<path>
1800 is a symbolic link, then the link is stat-ed, not the file it
1801 refers to.
1802
1803 This is the same as the C<lstat(2)> system call.");
1804
1805   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1806    [InitISOFS, Always, TestOutputStruct (
1807       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1808    "get file system statistics",
1809    "\
1810 Returns file system statistics for any mounted file system.
1811 C<path> should be a file or directory in the mounted file system
1812 (typically it is the mount point itself, but it doesn't need to be).
1813
1814 This is the same as the C<statvfs(2)> system call.");
1815
1816   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1817    [], (* XXX test *)
1818    "get ext2/ext3/ext4 superblock details",
1819    "\
1820 This returns the contents of the ext2, ext3 or ext4 filesystem
1821 superblock on C<device>.
1822
1823 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1824 manpage for more details.  The list of fields returned isn't
1825 clearly defined, and depends on both the version of C<tune2fs>
1826 that libguestfs was built against, and the filesystem itself.");
1827
1828   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1829    [InitEmpty, Always, TestOutputTrue (
1830       [["blockdev_setro"; "/dev/sda"];
1831        ["blockdev_getro"; "/dev/sda"]])],
1832    "set block device to read-only",
1833    "\
1834 Sets the block device named C<device> to read-only.
1835
1836 This uses the L<blockdev(8)> command.");
1837
1838   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1839    [InitEmpty, Always, TestOutputFalse (
1840       [["blockdev_setrw"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "set block device to read-write",
1843    "\
1844 Sets the block device named C<device> to read-write.
1845
1846 This uses the L<blockdev(8)> command.");
1847
1848   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1849    [InitEmpty, Always, TestOutputTrue (
1850       [["blockdev_setro"; "/dev/sda"];
1851        ["blockdev_getro"; "/dev/sda"]])],
1852    "is block device set to read-only",
1853    "\
1854 Returns a boolean indicating if the block device is read-only
1855 (true if read-only, false if not).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getss"; "/dev/sda"]], 512)],
1862    "get sectorsize of block device",
1863    "\
1864 This returns the size of sectors on a block device.
1865 Usually 512, but can be larger for modern devices.
1866
1867 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1868 for that).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1873    [InitEmpty, Always, TestOutputInt (
1874       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1875    "get blocksize of block device",
1876    "\
1877 This returns the block size of a device.
1878
1879 (Note this is different from both I<size in blocks> and
1880 I<filesystem block size>).
1881
1882 This uses the L<blockdev(8)> command.");
1883
1884   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1885    [], (* XXX test *)
1886    "set blocksize of block device",
1887    "\
1888 This sets the block size of a device.
1889
1890 (Note this is different from both I<size in blocks> and
1891 I<filesystem block size>).
1892
1893 This uses the L<blockdev(8)> command.");
1894
1895   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1896    [InitEmpty, Always, TestOutputInt (
1897       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1898    "get total size of device in 512-byte sectors",
1899    "\
1900 This returns the size of the device in units of 512-byte sectors
1901 (even if the sectorsize isn't 512 bytes ... weird).
1902
1903 See also C<guestfs_blockdev_getss> for the real sector size of
1904 the device, and C<guestfs_blockdev_getsize64> for the more
1905 useful I<size in bytes>.
1906
1907 This uses the L<blockdev(8)> command.");
1908
1909   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1910    [InitEmpty, Always, TestOutputInt (
1911       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1912    "get total size of device in bytes",
1913    "\
1914 This returns the size of the device in bytes.
1915
1916 See also C<guestfs_blockdev_getsz>.
1917
1918 This uses the L<blockdev(8)> command.");
1919
1920   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1921    [InitEmpty, Always, TestRun
1922       [["blockdev_flushbufs"; "/dev/sda"]]],
1923    "flush device buffers",
1924    "\
1925 This tells the kernel to flush internal buffers associated
1926 with C<device>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1931    [InitEmpty, Always, TestRun
1932       [["blockdev_rereadpt"; "/dev/sda"]]],
1933    "reread partition table",
1934    "\
1935 Reread the partition table on C<device>.
1936
1937 This uses the L<blockdev(8)> command.");
1938
1939   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1940    [InitBasicFS, Always, TestOutput (
1941       (* Pick a file from cwd which isn't likely to change. *)
1942       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1943        ["checksum"; "md5"; "/COPYING.LIB"]],
1944       Digest.to_hex (Digest.file "COPYING.LIB"))],
1945    "upload a file from the local machine",
1946    "\
1947 Upload local file C<filename> to C<remotefilename> on the
1948 filesystem.
1949
1950 C<filename> can also be a named pipe.
1951
1952 See also C<guestfs_download>.");
1953
1954   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1955    [InitBasicFS, Always, TestOutput (
1956       (* Pick a file from cwd which isn't likely to change. *)
1957       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1958        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1959        ["upload"; "testdownload.tmp"; "/upload"];
1960        ["checksum"; "md5"; "/upload"]],
1961       Digest.to_hex (Digest.file "COPYING.LIB"))],
1962    "download a file to the local machine",
1963    "\
1964 Download file C<remotefilename> and save it as C<filename>
1965 on the local machine.
1966
1967 C<filename> can also be a named pipe.
1968
1969 See also C<guestfs_upload>, C<guestfs_cat>.");
1970
1971   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1972    [InitISOFS, Always, TestOutput (
1973       [["checksum"; "crc"; "/known-3"]], "2891671662");
1974     InitISOFS, Always, TestLastFail (
1975       [["checksum"; "crc"; "/notexists"]]);
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1988    "compute MD5, SHAx or CRC checksum of file",
1989    "\
1990 This call computes the MD5, SHAx or CRC checksum of the
1991 file named C<path>.
1992
1993 The type of checksum to compute is given by the C<csumtype>
1994 parameter which must have one of the following values:
1995
1996 =over 4
1997
1998 =item C<crc>
1999
2000 Compute the cyclic redundancy check (CRC) specified by POSIX
2001 for the C<cksum> command.
2002
2003 =item C<md5>
2004
2005 Compute the MD5 hash (using the C<md5sum> program).
2006
2007 =item C<sha1>
2008
2009 Compute the SHA1 hash (using the C<sha1sum> program).
2010
2011 =item C<sha224>
2012
2013 Compute the SHA224 hash (using the C<sha224sum> program).
2014
2015 =item C<sha256>
2016
2017 Compute the SHA256 hash (using the C<sha256sum> program).
2018
2019 =item C<sha384>
2020
2021 Compute the SHA384 hash (using the C<sha384sum> program).
2022
2023 =item C<sha512>
2024
2025 Compute the SHA512 hash (using the C<sha512sum> program).
2026
2027 =back
2028
2029 The checksum is returned as a printable string.");
2030
2031   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2032    [InitBasicFS, Always, TestOutput (
2033       [["tar_in"; "../images/helloworld.tar"; "/"];
2034        ["cat"; "/hello"]], "hello\n")],
2035    "unpack tarfile to directory",
2036    "\
2037 This command uploads and unpacks local file C<tarfile> (an
2038 I<uncompressed> tar file) into C<directory>.
2039
2040 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2041
2042   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2043    [],
2044    "pack directory into tarfile",
2045    "\
2046 This command packs the contents of C<directory> and downloads
2047 it to local file C<tarfile>.
2048
2049 To download a compressed tarball, use C<guestfs_tgz_out>.");
2050
2051   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2052    [InitBasicFS, Always, TestOutput (
2053       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2054        ["cat"; "/hello"]], "hello\n")],
2055    "unpack compressed tarball to directory",
2056    "\
2057 This command uploads and unpacks local file C<tarball> (a
2058 I<gzip compressed> tar file) into C<directory>.
2059
2060 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2061
2062   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2063    [],
2064    "pack directory into compressed tarball",
2065    "\
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarball>.
2068
2069 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2070
2071   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2072    [InitBasicFS, Always, TestLastFail (
2073       [["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["touch"; "/new"]]);
2076     InitBasicFS, Always, TestOutput (
2077       [["write_file"; "/new"; "data"; "0"];
2078        ["umount"; "/"];
2079        ["mount_ro"; "/dev/sda1"; "/"];
2080        ["cat"; "/new"]], "data")],
2081    "mount a guest disk, read-only",
2082    "\
2083 This is the same as the C<guestfs_mount> command, but it
2084 mounts the filesystem with the read-only (I<-o ro>) flag.");
2085
2086   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2087    [],
2088    "mount a guest disk with mount options",
2089    "\
2090 This is the same as the C<guestfs_mount> command, but it
2091 allows you to set the mount options as for the
2092 L<mount(8)> I<-o> flag.
2093
2094 If the C<options> parameter is an empty string, then
2095 no options are passed (all options default to whatever
2096 the filesystem uses).");
2097
2098   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2099    [],
2100    "mount a guest disk with mount options and vfstype",
2101    "\
2102 This is the same as the C<guestfs_mount> command, but it
2103 allows you to set both the mount options and the vfstype
2104 as for the L<mount(8)> I<-o> and I<-t> flags.");
2105
2106   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2107    [],
2108    "debugging and internals",
2109    "\
2110 The C<guestfs_debug> command exposes some internals of
2111 C<guestfsd> (the guestfs daemon) that runs inside the
2112 qemu subprocess.
2113
2114 There is no comprehensive help for this command.  You have
2115 to look at the file C<daemon/debug.c> in the libguestfs source
2116 to find out what you can do.");
2117
2118   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2119    [InitEmpty, Always, TestOutputList (
2120       [["part_disk"; "/dev/sda"; "mbr"];
2121        ["pvcreate"; "/dev/sda1"];
2122        ["vgcreate"; "VG"; "/dev/sda1"];
2123        ["lvcreate"; "LV1"; "VG"; "50"];
2124        ["lvcreate"; "LV2"; "VG"; "50"];
2125        ["lvremove"; "/dev/VG/LV1"];
2126        ["lvs"]], ["/dev/VG/LV2"]);
2127     InitEmpty, Always, TestOutputList (
2128       [["part_disk"; "/dev/sda"; "mbr"];
2129        ["pvcreate"; "/dev/sda1"];
2130        ["vgcreate"; "VG"; "/dev/sda1"];
2131        ["lvcreate"; "LV1"; "VG"; "50"];
2132        ["lvcreate"; "LV2"; "VG"; "50"];
2133        ["lvremove"; "/dev/VG"];
2134        ["lvs"]], []);
2135     InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG"];
2142        ["vgs"]], ["VG"])],
2143    "remove an LVM logical volume",
2144    "\
2145 Remove an LVM logical volume C<device>, where C<device> is
2146 the path to the LV, such as C</dev/VG/LV>.
2147
2148 You can also remove all LVs in a volume group by specifying
2149 the VG name, C</dev/VG>.");
2150
2151   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2152    [InitEmpty, Always, TestOutputList (
2153       [["part_disk"; "/dev/sda"; "mbr"];
2154        ["pvcreate"; "/dev/sda1"];
2155        ["vgcreate"; "VG"; "/dev/sda1"];
2156        ["lvcreate"; "LV1"; "VG"; "50"];
2157        ["lvcreate"; "LV2"; "VG"; "50"];
2158        ["vgremove"; "VG"];
2159        ["lvs"]], []);
2160     InitEmpty, Always, TestOutputList (
2161       [["part_disk"; "/dev/sda"; "mbr"];
2162        ["pvcreate"; "/dev/sda1"];
2163        ["vgcreate"; "VG"; "/dev/sda1"];
2164        ["lvcreate"; "LV1"; "VG"; "50"];
2165        ["lvcreate"; "LV2"; "VG"; "50"];
2166        ["vgremove"; "VG"];
2167        ["vgs"]], [])],
2168    "remove an LVM volume group",
2169    "\
2170 Remove an LVM volume group C<vgname>, (for example C<VG>).
2171
2172 This also forcibly removes all logical volumes in the volume
2173 group (if any).");
2174
2175   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2176    [InitEmpty, Always, TestOutputListOfDevices (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["pvremove"; "/dev/sda1"];
2184        ["lvs"]], []);
2185     InitEmpty, Always, TestOutputListOfDevices (
2186       [["part_disk"; "/dev/sda"; "mbr"];
2187        ["pvcreate"; "/dev/sda1"];
2188        ["vgcreate"; "VG"; "/dev/sda1"];
2189        ["lvcreate"; "LV1"; "VG"; "50"];
2190        ["lvcreate"; "LV2"; "VG"; "50"];
2191        ["vgremove"; "VG"];
2192        ["pvremove"; "/dev/sda1"];
2193        ["vgs"]], []);
2194     InitEmpty, Always, TestOutputListOfDevices (
2195       [["part_disk"; "/dev/sda"; "mbr"];
2196        ["pvcreate"; "/dev/sda1"];
2197        ["vgcreate"; "VG"; "/dev/sda1"];
2198        ["lvcreate"; "LV1"; "VG"; "50"];
2199        ["lvcreate"; "LV2"; "VG"; "50"];
2200        ["vgremove"; "VG"];
2201        ["pvremove"; "/dev/sda1"];
2202        ["pvs"]], [])],
2203    "remove an LVM physical volume",
2204    "\
2205 This wipes a physical volume C<device> so that LVM will no longer
2206 recognise it.
2207
2208 The implementation uses the C<pvremove> command which refuses to
2209 wipe physical volumes that contain any volume groups, so you have
2210 to remove those first.");
2211
2212   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2213    [InitBasicFS, Always, TestOutput (
2214       [["set_e2label"; "/dev/sda1"; "testlabel"];
2215        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2216    "set the ext2/3/4 filesystem label",
2217    "\
2218 This sets the ext2/3/4 filesystem label of the filesystem on
2219 C<device> to C<label>.  Filesystem labels are limited to
2220 16 characters.
2221
2222 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2223 to return the existing label on a filesystem.");
2224
2225   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2226    [],
2227    "get the ext2/3/4 filesystem label",
2228    "\
2229 This returns the ext2/3/4 filesystem label of the filesystem on
2230 C<device>.");
2231
2232   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2233    (let uuid = uuidgen () in
2234     [InitBasicFS, Always, TestOutput (
2235        [["set_e2uuid"; "/dev/sda1"; uuid];
2236         ["get_e2uuid"; "/dev/sda1"]], uuid);
2237      InitBasicFS, Always, TestOutput (
2238        [["set_e2uuid"; "/dev/sda1"; "clear"];
2239         ["get_e2uuid"; "/dev/sda1"]], "");
2240      (* We can't predict what UUIDs will be, so just check the commands run. *)
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2243      InitBasicFS, Always, TestRun (
2244        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2245    "set the ext2/3/4 filesystem UUID",
2246    "\
2247 This sets the ext2/3/4 filesystem UUID of the filesystem on
2248 C<device> to C<uuid>.  The format of the UUID and alternatives
2249 such as C<clear>, C<random> and C<time> are described in the
2250 L<tune2fs(8)> manpage.
2251
2252 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2253 to return the existing UUID of a filesystem.");
2254
2255   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2256    [],
2257    "get the ext2/3/4 filesystem UUID",
2258    "\
2259 This returns the ext2/3/4 filesystem UUID of the filesystem on
2260 C<device>.");
2261
2262   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2263    [InitBasicFS, Always, TestOutputInt (
2264       [["umount"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2266     InitBasicFS, Always, TestOutputInt (
2267       [["umount"; "/dev/sda1"];
2268        ["zero"; "/dev/sda1"];
2269        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2270    "run the filesystem checker",
2271    "\
2272 This runs the filesystem checker (fsck) on C<device> which
2273 should have filesystem type C<fstype>.
2274
2275 The returned integer is the status.  See L<fsck(8)> for the
2276 list of status codes from C<fsck>.
2277
2278 Notes:
2279
2280 =over 4
2281
2282 =item *
2283
2284 Multiple status codes can be summed together.
2285
2286 =item *
2287
2288 A non-zero return code can mean \"success\", for example if
2289 errors have been corrected on the filesystem.
2290
2291 =item *
2292
2293 Checking or repairing NTFS volumes is not supported
2294 (by linux-ntfs).
2295
2296 =back
2297
2298 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2299
2300   ("zero", (RErr, [Device "device"]), 85, [],
2301    [InitBasicFS, Always, TestOutput (
2302       [["umount"; "/dev/sda1"];
2303        ["zero"; "/dev/sda1"];
2304        ["file"; "/dev/sda1"]], "data")],
2305    "write zeroes to the device",
2306    "\
2307 This command writes zeroes over the first few blocks of C<device>.
2308
2309 How many blocks are zeroed isn't specified (but it's I<not> enough
2310 to securely wipe the device).  It should be sufficient to remove
2311 any partition tables, filesystem superblocks and so on.
2312
2313 See also: C<guestfs_scrub_device>.");
2314
2315   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2316    (* Test disabled because grub-install incompatible with virtio-blk driver.
2317     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2318     *)
2319    [InitBasicFS, Disabled, TestOutputTrue (
2320       [["grub_install"; "/"; "/dev/sda1"];
2321        ["is_dir"; "/boot"]])],
2322    "install GRUB",
2323    "\
2324 This command installs GRUB (the Grand Unified Bootloader) on
2325 C<device>, with the root directory being C<root>.");
2326
2327   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2328    [InitBasicFS, Always, TestOutput (
2329       [["write_file"; "/old"; "file content"; "0"];
2330        ["cp"; "/old"; "/new"];
2331        ["cat"; "/new"]], "file content");
2332     InitBasicFS, Always, TestOutputTrue (
2333       [["write_file"; "/old"; "file content"; "0"];
2334        ["cp"; "/old"; "/new"];
2335        ["is_file"; "/old"]]);
2336     InitBasicFS, Always, TestOutput (
2337       [["write_file"; "/old"; "file content"; "0"];
2338        ["mkdir"; "/dir"];
2339        ["cp"; "/old"; "/dir/new"];
2340        ["cat"; "/dir/new"]], "file content")],
2341    "copy a file",
2342    "\
2343 This copies a file from C<src> to C<dest> where C<dest> is
2344 either a destination filename or destination directory.");
2345
2346   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2347    [InitBasicFS, Always, TestOutput (
2348       [["mkdir"; "/olddir"];
2349        ["mkdir"; "/newdir"];
2350        ["write_file"; "/olddir/file"; "file content"; "0"];
2351        ["cp_a"; "/olddir"; "/newdir"];
2352        ["cat"; "/newdir/olddir/file"]], "file content")],
2353    "copy a file or directory recursively",
2354    "\
2355 This copies a file or directory from C<src> to C<dest>
2356 recursively using the C<cp -a> command.");
2357
2358   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2359    [InitBasicFS, Always, TestOutput (
2360       [["write_file"; "/old"; "file content"; "0"];
2361        ["mv"; "/old"; "/new"];
2362        ["cat"; "/new"]], "file content");
2363     InitBasicFS, Always, TestOutputFalse (
2364       [["write_file"; "/old"; "file content"; "0"];
2365        ["mv"; "/old"; "/new"];
2366        ["is_file"; "/old"]])],
2367    "move a file",
2368    "\
2369 This moves a file from C<src> to C<dest> where C<dest> is
2370 either a destination filename or destination directory.");
2371
2372   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2373    [InitEmpty, Always, TestRun (
2374       [["drop_caches"; "3"]])],
2375    "drop kernel page cache, dentries and inodes",
2376    "\
2377 This instructs the guest kernel to drop its page cache,
2378 and/or dentries and inode caches.  The parameter C<whattodrop>
2379 tells the kernel what precisely to drop, see
2380 L<http://linux-mm.org/Drop_Caches>
2381
2382 Setting C<whattodrop> to 3 should drop everything.
2383
2384 This automatically calls L<sync(2)> before the operation,
2385 so that the maximum guest memory is freed.");
2386
2387   ("dmesg", (RString "kmsgs", []), 91, [],
2388    [InitEmpty, Always, TestRun (
2389       [["dmesg"]])],
2390    "return kernel messages",
2391    "\
2392 This returns the kernel messages (C<dmesg> output) from
2393 the guest kernel.  This is sometimes useful for extended
2394 debugging of problems.
2395
2396 Another way to get the same information is to enable
2397 verbose messages with C<guestfs_set_verbose> or by setting
2398 the environment variable C<LIBGUESTFS_DEBUG=1> before
2399 running the program.");
2400
2401   ("ping_daemon", (RErr, []), 92, [],
2402    [InitEmpty, Always, TestRun (
2403       [["ping_daemon"]])],
2404    "ping the guest daemon",
2405    "\
2406 This is a test probe into the guestfs daemon running inside
2407 the qemu subprocess.  Calling this function checks that the
2408 daemon responds to the ping message, without affecting the daemon
2409 or attached block device(s) in any other way.");
2410
2411   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2412    [InitBasicFS, Always, TestOutputTrue (
2413       [["write_file"; "/file1"; "contents of a file"; "0"];
2414        ["cp"; "/file1"; "/file2"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestOutputFalse (
2417       [["write_file"; "/file1"; "contents of a file"; "0"];
2418        ["write_file"; "/file2"; "contents of another file"; "0"];
2419        ["equal"; "/file1"; "/file2"]]);
2420     InitBasicFS, Always, TestLastFail (
2421       [["equal"; "/file1"; "/file2"]])],
2422    "test if two files have equal contents",
2423    "\
2424 This compares the two files C<file1> and C<file2> and returns
2425 true if their content is exactly equal, or false otherwise.
2426
2427 The external L<cmp(1)> program is used for the comparison.");
2428
2429   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2430    [InitISOFS, Always, TestOutputList (
2431       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2432     InitISOFS, Always, TestOutputList (
2433       [["strings"; "/empty"]], [])],
2434    "print the printable strings in a file",
2435    "\
2436 This runs the L<strings(1)> command on a file and returns
2437 the list of printable strings found.");
2438
2439   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2440    [InitISOFS, Always, TestOutputList (
2441       [["strings_e"; "b"; "/known-5"]], []);
2442     InitBasicFS, Disabled, TestOutputList (
2443       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2444        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2445    "print the printable strings in a file",
2446    "\
2447 This is like the C<guestfs_strings> command, but allows you to
2448 specify the encoding of strings that are looked for in
2449 the source file C<path>.
2450
2451 Allowed encodings are:
2452
2453 =over 4
2454
2455 =item s
2456
2457 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2458 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2459
2460 =item S
2461
2462 Single 8-bit-byte characters.
2463
2464 =item b
2465
2466 16-bit big endian strings such as those encoded in
2467 UTF-16BE or UCS-2BE.
2468
2469 =item l (lower case letter L)
2470
2471 16-bit little endian such as UTF-16LE and UCS-2LE.
2472 This is useful for examining binaries in Windows guests.
2473
2474 =item B
2475
2476 32-bit big endian such as UCS-4BE.
2477
2478 =item L
2479
2480 32-bit little endian such as UCS-4LE.
2481
2482 =back
2483
2484 The returned strings are transcoded to UTF-8.");
2485
2486   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2487    [InitISOFS, Always, TestOutput (
2488       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2489     (* Test for RHBZ#501888c2 regression which caused large hexdump
2490      * commands to segfault.
2491      *)
2492     InitISOFS, Always, TestRun (
2493       [["hexdump"; "/100krandom"]])],
2494    "dump a file in hexadecimal",
2495    "\
2496 This runs C<hexdump -C> on the given C<path>.  The result is
2497 the human-readable, canonical hex dump of the file.");
2498
2499   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2500    [InitNone, Always, TestOutput (
2501       [["part_disk"; "/dev/sda"; "mbr"];
2502        ["mkfs"; "ext3"; "/dev/sda1"];
2503        ["mount_options"; ""; "/dev/sda1"; "/"];
2504        ["write_file"; "/new"; "test file"; "0"];
2505        ["umount"; "/dev/sda1"];
2506        ["zerofree"; "/dev/sda1"];
2507        ["mount_options"; ""; "/dev/sda1"; "/"];
2508        ["cat"; "/new"]], "test file")],
2509    "zero unused inodes and disk blocks on ext2/3 filesystem",
2510    "\
2511 This runs the I<zerofree> program on C<device>.  This program
2512 claims to zero unused inodes and disk blocks on an ext2/3
2513 filesystem, thus making it possible to compress the filesystem
2514 more effectively.
2515
2516 You should B<not> run this program if the filesystem is
2517 mounted.
2518
2519 It is possible that using this program can damage the filesystem
2520 or data on the filesystem.");
2521
2522   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2523    [],
2524    "resize an LVM physical volume",
2525    "\
2526 This resizes (expands or shrinks) an existing LVM physical
2527 volume to match the new size of the underlying device.");
2528
2529   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2530                        Int "cyls"; Int "heads"; Int "sectors";
2531                        String "line"]), 99, [DangerWillRobinson],
2532    [],
2533    "modify a single partition on a block device",
2534    "\
2535 This runs L<sfdisk(8)> option to modify just the single
2536 partition C<n> (note: C<n> counts from 1).
2537
2538 For other parameters, see C<guestfs_sfdisk>.  You should usually
2539 pass C<0> for the cyls/heads/sectors parameters.
2540
2541 See also: C<guestfs_part_add>");
2542
2543   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2544    [],
2545    "display the partition table",
2546    "\
2547 This displays the partition table on C<device>, in the
2548 human-readable output of the L<sfdisk(8)> command.  It is
2549 not intended to be parsed.
2550
2551 See also: C<guestfs_part_list>");
2552
2553   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2554    [],
2555    "display the kernel geometry",
2556    "\
2557 This displays the kernel's idea of the geometry of C<device>.
2558
2559 The result is in human-readable format, and not designed to
2560 be parsed.");
2561
2562   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2563    [],
2564    "display the disk geometry from the partition table",
2565    "\
2566 This displays the disk geometry of C<device> read from the
2567 partition table.  Especially in the case where the underlying
2568 block device has been resized, this can be different from the
2569 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2570
2571 The result is in human-readable format, and not designed to
2572 be parsed.");
2573
2574   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2575    [],
2576    "activate or deactivate all volume groups",
2577    "\
2578 This command activates or (if C<activate> is false) deactivates
2579 all logical volumes in all volume groups.
2580 If activated, then they are made known to the
2581 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2582 then those devices disappear.
2583
2584 This command is the same as running C<vgchange -a y|n>");
2585
2586   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2587    [],
2588    "activate or deactivate some volume groups",
2589    "\
2590 This command activates or (if C<activate> is false) deactivates
2591 all logical volumes in the listed volume groups C<volgroups>.
2592 If activated, then they are made known to the
2593 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2594 then those devices disappear.
2595
2596 This command is the same as running C<vgchange -a y|n volgroups...>
2597
2598 Note that if C<volgroups> is an empty list then B<all> volume groups
2599 are activated or deactivated.");
2600
2601   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2602    [InitNone, Always, TestOutput (
2603       [["part_disk"; "/dev/sda"; "mbr"];
2604        ["pvcreate"; "/dev/sda1"];
2605        ["vgcreate"; "VG"; "/dev/sda1"];
2606        ["lvcreate"; "LV"; "VG"; "10"];
2607        ["mkfs"; "ext2"; "/dev/VG/LV"];
2608        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2609        ["write_file"; "/new"; "test content"; "0"];
2610        ["umount"; "/"];
2611        ["lvresize"; "/dev/VG/LV"; "20"];
2612        ["e2fsck_f"; "/dev/VG/LV"];
2613        ["resize2fs"; "/dev/VG/LV"];
2614        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2615        ["cat"; "/new"]], "test content");
2616     InitNone, Always, TestRun (
2617       (* Make an LV smaller to test RHBZ#587484. *)
2618       [["part_disk"; "/dev/sda"; "mbr"];
2619        ["pvcreate"; "/dev/sda1"];
2620        ["vgcreate"; "VG"; "/dev/sda1"];
2621        ["lvcreate"; "LV"; "VG"; "20"];
2622        ["lvresize"; "/dev/VG/LV"; "10"]])],
2623    "resize an LVM logical volume",
2624    "\
2625 This resizes (expands or shrinks) an existing LVM logical
2626 volume to C<mbytes>.  When reducing, data in the reduced part
2627 is lost.");
2628
2629   ("resize2fs", (RErr, [Device "device"]), 106, [],
2630    [], (* lvresize tests this *)
2631    "resize an ext2/ext3 filesystem",
2632    "\
2633 This resizes an ext2 or ext3 filesystem to match the size of
2634 the underlying device.
2635
2636 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2637 on the C<device> before calling this command.  For unknown reasons
2638 C<resize2fs> sometimes gives an error about this and sometimes not.
2639 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2640 calling this function.");
2641
2642   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2643    [InitBasicFS, Always, TestOutputList (
2644       [["find"; "/"]], ["lost+found"]);
2645     InitBasicFS, Always, TestOutputList (
2646       [["touch"; "/a"];
2647        ["mkdir"; "/b"];
2648        ["touch"; "/b/c"];
2649        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2650     InitBasicFS, Always, TestOutputList (
2651       [["mkdir_p"; "/a/b/c"];
2652        ["touch"; "/a/b/c/d"];
2653        ["find"; "/a/b/"]], ["c"; "c/d"])],
2654    "find all files and directories",
2655    "\
2656 This command lists out all files and directories, recursively,
2657 starting at C<directory>.  It is essentially equivalent to
2658 running the shell command C<find directory -print> but some
2659 post-processing happens on the output, described below.
2660
2661 This returns a list of strings I<without any prefix>.  Thus
2662 if the directory structure was:
2663
2664  /tmp/a
2665  /tmp/b
2666  /tmp/c/d
2667
2668 then the returned list from C<guestfs_find> C</tmp> would be
2669 4 elements:
2670
2671  a
2672  b
2673  c
2674  c/d
2675
2676 If C<directory> is not a directory, then this command returns
2677 an error.
2678
2679 The returned list is sorted.
2680
2681 See also C<guestfs_find0>.");
2682
2683   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2684    [], (* lvresize tests this *)
2685    "check an ext2/ext3 filesystem",
2686    "\
2687 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2688 filesystem checker on C<device>, noninteractively (C<-p>),
2689 even if the filesystem appears to be clean (C<-f>).
2690
2691 This command is only needed because of C<guestfs_resize2fs>
2692 (q.v.).  Normally you should use C<guestfs_fsck>.");
2693
2694   ("sleep", (RErr, [Int "secs"]), 109, [],
2695    [InitNone, Always, TestRun (
2696       [["sleep"; "1"]])],
2697    "sleep for some seconds",
2698    "\
2699 Sleep for C<secs> seconds.");
2700
2701   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2702    [InitNone, Always, TestOutputInt (
2703       [["part_disk"; "/dev/sda"; "mbr"];
2704        ["mkfs"; "ntfs"; "/dev/sda1"];
2705        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2706     InitNone, Always, TestOutputInt (
2707       [["part_disk"; "/dev/sda"; "mbr"];
2708        ["mkfs"; "ext2"; "/dev/sda1"];
2709        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2710    "probe NTFS volume",
2711    "\
2712 This command runs the L<ntfs-3g.probe(8)> command which probes
2713 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2714 be mounted read-write, and some cannot be mounted at all).
2715
2716 C<rw> is a boolean flag.  Set it to true if you want to test
2717 if the volume can be mounted read-write.  Set it to false if
2718 you want to test if the volume can be mounted read-only.
2719
2720 The return value is an integer which C<0> if the operation
2721 would succeed, or some non-zero value documented in the
2722 L<ntfs-3g.probe(8)> manual page.");
2723
2724   ("sh", (RString "output", [String "command"]), 111, [],
2725    [], (* XXX needs tests *)
2726    "run a command via the shell",
2727    "\
2728 This call runs a command from the guest filesystem via the
2729 guest's C</bin/sh>.
2730
2731 This is like C<guestfs_command>, but passes the command to:
2732
2733  /bin/sh -c \"command\"
2734
2735 Depending on the guest's shell, this usually results in
2736 wildcards being expanded, shell expressions being interpolated
2737 and so on.
2738
2739 All the provisos about C<guestfs_command> apply to this call.");
2740
2741   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2742    [], (* XXX needs tests *)
2743    "run a command via the shell returning lines",
2744    "\
2745 This is the same as C<guestfs_sh>, but splits the result
2746 into a list of lines.
2747
2748 See also: C<guestfs_command_lines>");
2749
2750   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2751    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2752     * code in stubs.c, since all valid glob patterns must start with "/".
2753     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2754     *)
2755    [InitBasicFS, Always, TestOutputList (
2756       [["mkdir_p"; "/a/b/c"];
2757        ["touch"; "/a/b/c/d"];
2758        ["touch"; "/a/b/c/e"];
2759        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2760     InitBasicFS, Always, TestOutputList (
2761       [["mkdir_p"; "/a/b/c"];
2762        ["touch"; "/a/b/c/d"];
2763        ["touch"; "/a/b/c/e"];
2764        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2765     InitBasicFS, Always, TestOutputList (
2766       [["mkdir_p"; "/a/b/c"];
2767        ["touch"; "/a/b/c/d"];
2768        ["touch"; "/a/b/c/e"];
2769        ["glob_expand"; "/a/*/x/*"]], [])],
2770    "expand a wildcard path",
2771    "\
2772 This command searches for all the pathnames matching
2773 C<pattern> according to the wildcard expansion rules
2774 used by the shell.
2775
2776 If no paths match, then this returns an empty list
2777 (note: not an error).
2778
2779 It is just a wrapper around the C L<glob(3)> function
2780 with flags C<GLOB_MARK|GLOB_BRACE>.
2781 See that manual page for more details.");
2782
2783   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2784    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2785       [["scrub_device"; "/dev/sdc"]])],
2786    "scrub (securely wipe) a device",
2787    "\
2788 This command writes patterns over C<device> to make data retrieval
2789 more difficult.
2790
2791 It is an interface to the L<scrub(1)> program.  See that
2792 manual page for more details.");
2793
2794   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2795    [InitBasicFS, Always, TestRun (
2796       [["write_file"; "/file"; "content"; "0"];
2797        ["scrub_file"; "/file"]])],
2798    "scrub (securely wipe) a file",
2799    "\
2800 This command writes patterns over a file to make data retrieval
2801 more difficult.
2802
2803 The file is I<removed> after scrubbing.
2804
2805 It is an interface to the L<scrub(1)> program.  See that
2806 manual page for more details.");
2807
2808   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2809    [], (* XXX needs testing *)
2810    "scrub (securely wipe) free space",
2811    "\
2812 This command creates the directory C<dir> and then fills it
2813 with files until the filesystem is full, and scrubs the files
2814 as for C<guestfs_scrub_file>, and deletes them.
2815 The intention is to scrub any free space on the partition
2816 containing C<dir>.
2817
2818 It is an interface to the L<scrub(1)> program.  See that
2819 manual page for more details.");
2820
2821   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2822    [InitBasicFS, Always, TestRun (
2823       [["mkdir"; "/tmp"];
2824        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2825    "create a temporary directory",
2826    "\
2827 This command creates a temporary directory.  The
2828 C<template> parameter should be a full pathname for the
2829 temporary directory name with the final six characters being
2830 \"XXXXXX\".
2831
2832 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2833 the second one being suitable for Windows filesystems.
2834
2835 The name of the temporary directory that was created
2836 is returned.
2837
2838 The temporary directory is created with mode 0700
2839 and is owned by root.
2840
2841 The caller is responsible for deleting the temporary
2842 directory and its contents after use.
2843
2844 See also: L<mkdtemp(3)>");
2845
2846   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2847    [InitISOFS, Always, TestOutputInt (
2848       [["wc_l"; "/10klines"]], 10000)],
2849    "count lines in a file",
2850    "\
2851 This command counts the lines in a file, using the
2852 C<wc -l> external command.");
2853
2854   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2855    [InitISOFS, Always, TestOutputInt (
2856       [["wc_w"; "/10klines"]], 10000)],
2857    "count words in a file",
2858    "\
2859 This command counts the words in a file, using the
2860 C<wc -w> external command.");
2861
2862   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2863    [InitISOFS, Always, TestOutputInt (
2864       [["wc_c"; "/100kallspaces"]], 102400)],
2865    "count characters in a file",
2866    "\
2867 This command counts the characters in a file, using the
2868 C<wc -c> external command.");
2869
2870   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2871    [InitISOFS, Always, TestOutputList (
2872       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2873    "return first 10 lines of a file",
2874    "\
2875 This command returns up to the first 10 lines of a file as
2876 a list of strings.");
2877
2878   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2879    [InitISOFS, Always, TestOutputList (
2880       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2881     InitISOFS, Always, TestOutputList (
2882       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2883     InitISOFS, Always, TestOutputList (
2884       [["head_n"; "0"; "/10klines"]], [])],
2885    "return first N lines of a file",
2886    "\
2887 If the parameter C<nrlines> is a positive number, this returns the first
2888 C<nrlines> lines of the file C<path>.
2889
2890 If the parameter C<nrlines> is a negative number, this returns lines
2891 from the file C<path>, excluding the last C<nrlines> lines.
2892
2893 If the parameter C<nrlines> is zero, this returns an empty list.");
2894
2895   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2896    [InitISOFS, Always, TestOutputList (
2897       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2898    "return last 10 lines of a file",
2899    "\
2900 This command returns up to the last 10 lines of a file as
2901 a list of strings.");
2902
2903   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2904    [InitISOFS, Always, TestOutputList (
2905       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2906     InitISOFS, Always, TestOutputList (
2907       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2908     InitISOFS, Always, TestOutputList (
2909       [["tail_n"; "0"; "/10klines"]], [])],
2910    "return last N lines of a file",
2911    "\
2912 If the parameter C<nrlines> is a positive number, this returns the last
2913 C<nrlines> lines of the file C<path>.
2914
2915 If the parameter C<nrlines> is a negative number, this returns lines
2916 from the file C<path>, starting with the C<-nrlines>th line.
2917
2918 If the parameter C<nrlines> is zero, this returns an empty list.");
2919
2920   ("df", (RString "output", []), 125, [],
2921    [], (* XXX Tricky to test because it depends on the exact format
2922         * of the 'df' command and other imponderables.
2923         *)
2924    "report file system disk space usage",
2925    "\
2926 This command runs the C<df> command to report disk space used.
2927
2928 This command is mostly useful for interactive sessions.  It
2929 is I<not> intended that you try to parse the output string.
2930 Use C<statvfs> from programs.");
2931
2932   ("df_h", (RString "output", []), 126, [],
2933    [], (* XXX Tricky to test because it depends on the exact format
2934         * of the 'df' command and other imponderables.
2935         *)
2936    "report file system disk space usage (human readable)",
2937    "\
2938 This command runs the C<df -h> command to report disk space used
2939 in human-readable format.
2940
2941 This command is mostly useful for interactive sessions.  It
2942 is I<not> intended that you try to parse the output string.
2943 Use C<statvfs> from programs.");
2944
2945   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2946    [InitISOFS, Always, TestOutputInt (
2947       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2948    "estimate file space usage",
2949    "\
2950 This command runs the C<du -s> command to estimate file space
2951 usage for C<path>.
2952
2953 C<path> can be a file or a directory.  If C<path> is a directory
2954 then the estimate includes the contents of the directory and all
2955 subdirectories (recursively).
2956
2957 The result is the estimated size in I<kilobytes>
2958 (ie. units of 1024 bytes).");
2959
2960   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2961    [InitISOFS, Always, TestOutputList (
2962       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2963    "list files in an initrd",
2964    "\
2965 This command lists out files contained in an initrd.
2966
2967 The files are listed without any initial C</> character.  The
2968 files are listed in the order they appear (not necessarily
2969 alphabetical).  Directory names are listed as separate items.
2970
2971 Old Linux kernels (2.4 and earlier) used a compressed ext2
2972 filesystem as initrd.  We I<only> support the newer initramfs
2973 format (compressed cpio files).");
2974
2975   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2976    [],
2977    "mount a file using the loop device",
2978    "\
2979 This command lets you mount C<file> (a filesystem image
2980 in a file) on a mount point.  It is entirely equivalent to
2981 the command C<mount -o loop file mountpoint>.");
2982
2983   ("mkswap", (RErr, [Device "device"]), 130, [],
2984    [InitEmpty, Always, TestRun (
2985       [["part_disk"; "/dev/sda"; "mbr"];
2986        ["mkswap"; "/dev/sda1"]])],
2987    "create a swap partition",
2988    "\
2989 Create a swap partition on C<device>.");
2990
2991   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2992    [InitEmpty, Always, TestRun (
2993       [["part_disk"; "/dev/sda"; "mbr"];
2994        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2995    "create a swap partition with a label",
2996    "\
2997 Create a swap partition on C<device> with label C<label>.
2998
2999 Note that you cannot attach a swap label to a block device
3000 (eg. C</dev/sda>), just to a partition.  This appears to be
3001 a limitation of the kernel or swap tools.");
3002
3003   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3004    (let uuid = uuidgen () in
3005     [InitEmpty, Always, TestRun (
3006        [["part_disk"; "/dev/sda"; "mbr"];
3007         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3008    "create a swap partition with an explicit UUID",
3009    "\
3010 Create a swap partition on C<device> with UUID C<uuid>.");
3011
3012   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3013    [InitBasicFS, Always, TestOutputStruct (
3014       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3015        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3016        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3017     InitBasicFS, Always, TestOutputStruct (
3018       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3019        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3020    "make block, character or FIFO devices",
3021    "\
3022 This call creates block or character special devices, or
3023 named pipes (FIFOs).
3024
3025 The C<mode> parameter should be the mode, using the standard
3026 constants.  C<devmajor> and C<devminor> are the
3027 device major and minor numbers, only used when creating block
3028 and character special devices.
3029
3030 Note that, just like L<mknod(2)>, the mode must be bitwise
3031 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3032 just creates a regular file).  These constants are
3033 available in the standard Linux header files, or you can use
3034 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3035 which are wrappers around this command which bitwise OR
3036 in the appropriate constant for you.
3037
3038 The mode actually set is affected by the umask.");
3039
3040   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3041    [InitBasicFS, Always, TestOutputStruct (
3042       [["mkfifo"; "0o777"; "/node"];
3043        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3044    "make FIFO (named pipe)",
3045    "\
3046 This call creates a FIFO (named pipe) called C<path> with
3047 mode C<mode>.  It is just a convenient wrapper around
3048 C<guestfs_mknod>.
3049
3050 The mode actually set is affected by the umask.");
3051
3052   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3053    [InitBasicFS, Always, TestOutputStruct (
3054       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3055        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3056    "make block device node",
3057    "\
3058 This call creates a block device node called C<path> with
3059 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3060 It is just a convenient wrapper around C<guestfs_mknod>.
3061
3062 The mode actually set is affected by the umask.");
3063
3064   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3065    [InitBasicFS, Always, TestOutputStruct (
3066       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3067        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3068    "make char device node",
3069    "\
3070 This call creates a char device node called C<path> with
3071 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3072 It is just a convenient wrapper around C<guestfs_mknod>.
3073
3074 The mode actually set is affected by the umask.");
3075
3076   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3077    [InitEmpty, Always, TestOutputInt (
3078       [["umask"; "0o22"]], 0o22)],
3079    "set file mode creation mask (umask)",
3080    "\
3081 This function sets the mask used for creating new files and
3082 device nodes to C<mask & 0777>.
3083
3084 Typical umask values would be C<022> which creates new files
3085 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3086 C<002> which creates new files with permissions like
3087 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3088
3089 The default umask is C<022>.  This is important because it
3090 means that directories and device nodes will be created with
3091 C<0644> or C<0755> mode even if you specify C<0777>.
3092
3093 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3094
3095 This call returns the previous umask.");
3096
3097   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3098    [],
3099    "read directories entries",
3100    "\
3101 This returns the list of directory entries in directory C<dir>.
3102
3103 All entries in the directory are returned, including C<.> and
3104 C<..>.  The entries are I<not> sorted, but returned in the same
3105 order as the underlying filesystem.
3106
3107 Also this call returns basic file type information about each
3108 file.  The C<ftyp> field will contain one of the following characters:
3109
3110 =over 4
3111
3112 =item 'b'
3113
3114 Block special
3115
3116 =item 'c'
3117
3118 Char special
3119
3120 =item 'd'
3121
3122 Directory
3123
3124 =item 'f'
3125
3126 FIFO (named pipe)
3127
3128 =item 'l'
3129
3130 Symbolic link
3131
3132 =item 'r'
3133
3134 Regular file
3135
3136 =item 's'
3137
3138 Socket
3139
3140 =item 'u'
3141
3142 Unknown file type
3143
3144 =item '?'
3145
3146 The L<readdir(3)> call returned a C<d_type> field with an
3147 unexpected value
3148
3149 =back
3150
3151 This function is primarily intended for use by programs.  To
3152 get a simple list of names, use C<guestfs_ls>.  To get a printable
3153 directory for human consumption, use C<guestfs_ll>.");
3154
3155   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3156    [],
3157    "create partitions on a block device",
3158    "\
3159 This is a simplified interface to the C<guestfs_sfdisk>
3160 command, where partition sizes are specified in megabytes
3161 only (rounded to the nearest cylinder) and you don't need
3162 to specify the cyls, heads and sectors parameters which
3163 were rarely if ever used anyway.
3164
3165 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3166 and C<guestfs_part_disk>");
3167
3168   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3169    [],
3170    "determine file type inside a compressed file",
3171    "\
3172 This command runs C<file> after first decompressing C<path>
3173 using C<method>.
3174
3175 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3176
3177 Since 1.0.63, use C<guestfs_file> instead which can now
3178 process compressed files.");
3179
3180   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3181    [],
3182    "list extended attributes of a file or directory",
3183    "\
3184 This call lists the extended attributes of the file or directory
3185 C<path>.
3186
3187 At the system call level, this is a combination of the
3188 L<listxattr(2)> and L<getxattr(2)> calls.
3189
3190 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3191
3192   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3193    [],
3194    "list extended attributes of a file or directory",
3195    "\
3196 This is the same as C<guestfs_getxattrs>, but if C<path>
3197 is a symbolic link, then it returns the extended attributes
3198 of the link itself.");
3199
3200   ("setxattr", (RErr, [String "xattr";
3201                        String "val"; Int "vallen"; (* will be BufferIn *)
3202                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3203    [],
3204    "set extended attribute of a file or directory",
3205    "\
3206 This call sets the extended attribute named C<xattr>
3207 of the file C<path> to the value C<val> (of length C<vallen>).
3208 The value is arbitrary 8 bit data.
3209
3210 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3211
3212   ("lsetxattr", (RErr, [String "xattr";
3213                         String "val"; Int "vallen"; (* will be BufferIn *)
3214                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3215    [],
3216    "set extended attribute of a file or directory",
3217    "\
3218 This is the same as C<guestfs_setxattr>, but if C<path>
3219 is a symbolic link, then it sets an extended attribute
3220 of the link itself.");
3221
3222   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3223    [],
3224    "remove extended attribute of a file or directory",
3225    "\
3226 This call removes the extended attribute named C<xattr>
3227 of the file C<path>.
3228
3229 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3230
3231   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3232    [],
3233    "remove extended attribute of a file or directory",
3234    "\
3235 This is the same as C<guestfs_removexattr>, but if C<path>
3236 is a symbolic link, then it removes an extended attribute
3237 of the link itself.");
3238
3239   ("mountpoints", (RHashtable "mps", []), 147, [],
3240    [],
3241    "show mountpoints",
3242    "\
3243 This call is similar to C<guestfs_mounts>.  That call returns
3244 a list of devices.  This one returns a hash table (map) of
3245 device name to directory where the device is mounted.");
3246
3247   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3248    (* This is a special case: while you would expect a parameter
3249     * of type "Pathname", that doesn't work, because it implies
3250     * NEED_ROOT in the generated calling code in stubs.c, and
3251     * this function cannot use NEED_ROOT.
3252     *)
3253    [],
3254    "create a mountpoint",
3255    "\
3256 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3257 specialized calls that can be used to create extra mountpoints
3258 before mounting the first filesystem.
3259
3260 These calls are I<only> necessary in some very limited circumstances,
3261 mainly the case where you want to mount a mix of unrelated and/or
3262 read-only filesystems together.
3263
3264 For example, live CDs often contain a \"Russian doll\" nest of
3265 filesystems, an ISO outer layer, with a squashfs image inside, with
3266 an ext2/3 image inside that.  You can unpack this as follows
3267 in guestfish:
3268
3269  add-ro Fedora-11-i686-Live.iso
3270  run
3271  mkmountpoint /cd
3272  mkmountpoint /squash
3273  mkmountpoint /ext3
3274  mount /dev/sda /cd
3275  mount-loop /cd/LiveOS/squashfs.img /squash
3276  mount-loop /squash/LiveOS/ext3fs.img /ext3
3277
3278 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3279
3280   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3281    [],
3282    "remove a mountpoint",
3283    "\
3284 This calls removes a mountpoint that was previously created
3285 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3286 for full details.");
3287
3288   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3289    [InitISOFS, Always, TestOutputBuffer (
3290       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3291     (* Test various near large, large and too large files (RHBZ#589039). *)
3292     InitBasicFS, Always, TestLastFail (
3293       [["touch"; "/a"];
3294        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3295        ["read_file"; "/a"]]);
3296     InitBasicFS, Always, TestLastFail (
3297       [["touch"; "/a"];
3298        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3299        ["read_file"; "/a"]]);
3300     InitBasicFS, Always, TestLastFail (
3301       [["touch"; "/a"];
3302        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3303        ["read_file"; "/a"]])],
3304    "read a file",
3305    "\
3306 This calls returns the contents of the file C<path> as a
3307 buffer.
3308
3309 Unlike C<guestfs_cat>, this function can correctly
3310 handle files that contain embedded ASCII NUL characters.
3311 However unlike C<guestfs_download>, this function is limited
3312 in the total size of file that can be handled.");
3313
3314   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3315    [InitISOFS, Always, TestOutputList (
3316       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3317     InitISOFS, Always, TestOutputList (
3318       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3319    "return lines matching a pattern",
3320    "\
3321 This calls the external C<grep> program and returns the
3322 matching lines.");
3323
3324   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3325    [InitISOFS, Always, TestOutputList (
3326       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3327    "return lines matching a pattern",
3328    "\
3329 This calls the external C<egrep> program and returns the
3330 matching lines.");
3331
3332   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3333    [InitISOFS, Always, TestOutputList (
3334       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3335    "return lines matching a pattern",
3336    "\
3337 This calls the external C<fgrep> program and returns the
3338 matching lines.");
3339
3340   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3341    [InitISOFS, Always, TestOutputList (
3342       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3343    "return lines matching a pattern",
3344    "\
3345 This calls the external C<grep -i> program and returns the
3346 matching lines.");
3347
3348   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3349    [InitISOFS, Always, TestOutputList (
3350       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3351    "return lines matching a pattern",
3352    "\
3353 This calls the external C<egrep -i> program and returns the
3354 matching lines.");
3355
3356   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3357    [InitISOFS, Always, TestOutputList (
3358       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3359    "return lines matching a pattern",
3360    "\
3361 This calls the external C<fgrep -i> program and returns the
3362 matching lines.");
3363
3364   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3365    [InitISOFS, Always, TestOutputList (
3366       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3367    "return lines matching a pattern",
3368    "\
3369 This calls the external C<zgrep> program and returns the
3370 matching lines.");
3371
3372   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3373    [InitISOFS, Always, TestOutputList (
3374       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3375    "return lines matching a pattern",
3376    "\
3377 This calls the external C<zegrep> program and returns the
3378 matching lines.");
3379
3380   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3381    [InitISOFS, Always, TestOutputList (
3382       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3383    "return lines matching a pattern",
3384    "\
3385 This calls the external C<zfgrep> program and returns the
3386 matching lines.");
3387
3388   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3389    [InitISOFS, Always, TestOutputList (
3390       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3391    "return lines matching a pattern",
3392    "\
3393 This calls the external C<zgrep -i> program and returns the
3394 matching lines.");
3395
3396   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3397    [InitISOFS, Always, TestOutputList (
3398       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3399    "return lines matching a pattern",
3400    "\
3401 This calls the external C<zegrep -i> program and returns the
3402 matching lines.");
3403
3404   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3405    [InitISOFS, Always, TestOutputList (
3406       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3407    "return lines matching a pattern",
3408    "\
3409 This calls the external C<zfgrep -i> program and returns the
3410 matching lines.");
3411
3412   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3413    [InitISOFS, Always, TestOutput (
3414       [["realpath"; "/../directory"]], "/directory")],
3415    "canonicalized absolute pathname",
3416    "\
3417 Return the canonicalized absolute pathname of C<path>.  The
3418 returned path has no C<.>, C<..> or symbolic link path elements.");
3419
3420   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3421    [InitBasicFS, Always, TestOutputStruct (
3422       [["touch"; "/a"];
3423        ["ln"; "/a"; "/b"];
3424        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3425    "create a hard link",
3426    "\
3427 This command creates a hard link using the C<ln> command.");
3428
3429   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3430    [InitBasicFS, Always, TestOutputStruct (
3431       [["touch"; "/a"];
3432        ["touch"; "/b"];
3433        ["ln_f"; "/a"; "/b"];
3434        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3435    "create a hard link",
3436    "\
3437 This command creates a hard link using the C<ln -f> command.
3438 The C<-f> option removes the link (C<linkname>) if it exists already.");
3439
3440   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3441    [InitBasicFS, Always, TestOutputStruct (
3442       [["touch"; "/a"];
3443        ["ln_s"; "a"; "/b"];
3444        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3445    "create a symbolic link",
3446    "\
3447 This command creates a symbolic link using the C<ln -s> command.");
3448
3449   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3450    [InitBasicFS, Always, TestOutput (
3451       [["mkdir_p"; "/a/b"];
3452        ["touch"; "/a/b/c"];
3453        ["ln_sf"; "../d"; "/a/b/c"];
3454        ["readlink"; "/a/b/c"]], "../d")],
3455    "create a symbolic link",
3456    "\
3457 This command creates a symbolic link using the C<ln -sf> command,
3458 The C<-f> option removes the link (C<linkname>) if it exists already.");
3459
3460   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3461    [] (* XXX tested above *),
3462    "read the target of a symbolic link",
3463    "\
3464 This command reads the target of a symbolic link.");
3465
3466   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3467    [InitBasicFS, Always, TestOutputStruct (
3468       [["fallocate"; "/a"; "1000000"];
3469        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3470    "preallocate a file in the guest filesystem",
3471    "\
3472 This command preallocates a file (containing zero bytes) named
3473 C<path> of size C<len> bytes.  If the file exists already, it
3474 is overwritten.
3475
3476 Do not confuse this with the guestfish-specific
3477 C<alloc> command which allocates a file in the host and
3478 attaches it as a device.");
3479
3480   ("swapon_device", (RErr, [Device "device"]), 170, [],
3481    [InitPartition, Always, TestRun (
3482       [["mkswap"; "/dev/sda1"];
3483        ["swapon_device"; "/dev/sda1"];
3484        ["swapoff_device"; "/dev/sda1"]])],
3485    "enable swap on device",
3486    "\
3487 This command enables the libguestfs appliance to use the
3488 swap device or partition named C<device>.  The increased
3489 memory is made available for all commands, for example
3490 those run using C<guestfs_command> or C<guestfs_sh>.
3491
3492 Note that you should not swap to existing guest swap
3493 partitions unless you know what you are doing.  They may
3494 contain hibernation information, or other information that
3495 the guest doesn't want you to trash.  You also risk leaking
3496 information about the host to the guest this way.  Instead,
3497 attach a new host device to the guest and swap on that.");
3498
3499   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3500    [], (* XXX tested by swapon_device *)
3501    "disable swap on device",
3502    "\
3503 This command disables the libguestfs appliance swap
3504 device or partition named C<device>.
3505 See C<guestfs_swapon_device>.");
3506
3507   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3508    [InitBasicFS, Always, TestRun (
3509       [["fallocate"; "/swap"; "8388608"];
3510        ["mkswap_file"; "/swap"];
3511        ["swapon_file"; "/swap"];
3512        ["swapoff_file"; "/swap"]])],
3513    "enable swap on file",
3514    "\
3515 This command enables swap to a file.
3516 See C<guestfs_swapon_device> for other notes.");
3517
3518   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3519    [], (* XXX tested by swapon_file *)
3520    "disable swap on file",
3521    "\
3522 This command disables the libguestfs appliance swap on file.");
3523
3524   ("swapon_label", (RErr, [String "label"]), 174, [],
3525    [InitEmpty, Always, TestRun (
3526       [["part_disk"; "/dev/sdb"; "mbr"];
3527        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3528        ["swapon_label"; "swapit"];
3529        ["swapoff_label"; "swapit"];
3530        ["zero"; "/dev/sdb"];
3531        ["blockdev_rereadpt"; "/dev/sdb"]])],
3532    "enable swap on labeled swap partition",
3533    "\
3534 This command enables swap to a labeled swap partition.
3535 See C<guestfs_swapon_device> for other notes.");
3536
3537   ("swapoff_label", (RErr, [String "label"]), 175, [],
3538    [], (* XXX tested by swapon_label *)
3539    "disable swap on labeled swap partition",
3540    "\
3541 This command disables the libguestfs appliance swap on
3542 labeled swap partition.");
3543
3544   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3545    (let uuid = uuidgen () in
3546     [InitEmpty, Always, TestRun (
3547        [["mkswap_U"; uuid; "/dev/sdb"];
3548         ["swapon_uuid"; uuid];
3549         ["swapoff_uuid"; uuid]])]),
3550    "enable swap on swap partition by UUID",
3551    "\
3552 This command enables swap to a swap partition with the given UUID.
3553 See C<guestfs_swapon_device> for other notes.");
3554
3555   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3556    [], (* XXX tested by swapon_uuid *)
3557    "disable swap on swap partition by UUID",
3558    "\
3559 This command disables the libguestfs appliance swap partition
3560 with the given UUID.");
3561
3562   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3563    [InitBasicFS, Always, TestRun (
3564       [["fallocate"; "/swap"; "8388608"];
3565        ["mkswap_file"; "/swap"]])],
3566    "create a swap file",
3567    "\
3568 Create a swap file.
3569
3570 This command just writes a swap file signature to an existing
3571 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3572
3573   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3574    [InitISOFS, Always, TestRun (
3575       [["inotify_init"; "0"]])],
3576    "create an inotify handle",
3577    "\
3578 This command creates a new inotify handle.
3579 The inotify subsystem can be used to notify events which happen to
3580 objects in the guest filesystem.
3581
3582 C<maxevents> is the maximum number of events which will be
3583 queued up between calls to C<guestfs_inotify_read> or
3584 C<guestfs_inotify_files>.
3585 If this is passed as C<0>, then the kernel (or previously set)
3586 default is used.  For Linux 2.6.29 the default was 16384 events.
3587 Beyond this limit, the kernel throws away events, but records
3588 the fact that it threw them away by setting a flag
3589 C<IN_Q_OVERFLOW> in the returned structure list (see
3590 C<guestfs_inotify_read>).
3591
3592 Before any events are generated, you have to add some
3593 watches to the internal watch list.  See:
3594 C<guestfs_inotify_add_watch>,
3595 C<guestfs_inotify_rm_watch> and
3596 C<guestfs_inotify_watch_all>.
3597
3598 Queued up events should be read periodically by calling
3599 C<guestfs_inotify_read>
3600 (or C<guestfs_inotify_files> which is just a helpful
3601 wrapper around C<guestfs_inotify_read>).  If you don't
3602 read the events out often enough then you risk the internal
3603 queue overflowing.
3604
3605 The handle should be closed after use by calling
3606 C<guestfs_inotify_close>.  This also removes any
3607 watches automatically.
3608
3609 See also L<inotify(7)> for an overview of the inotify interface
3610 as exposed by the Linux kernel, which is roughly what we expose
3611 via libguestfs.  Note that there is one global inotify handle
3612 per libguestfs instance.");
3613
3614   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3615    [InitBasicFS, Always, TestOutputList (
3616       [["inotify_init"; "0"];
3617        ["inotify_add_watch"; "/"; "1073741823"];
3618        ["touch"; "/a"];
3619        ["touch"; "/b"];
3620        ["inotify_files"]], ["a"; "b"])],
3621    "add an inotify watch",
3622    "\
3623 Watch C<path> for the events listed in C<mask>.
3624
3625 Note that if C<path> is a directory then events within that
3626 directory are watched, but this does I<not> happen recursively
3627 (in subdirectories).
3628
3629 Note for non-C or non-Linux callers: the inotify events are
3630 defined by the Linux kernel ABI and are listed in
3631 C</usr/include/sys/inotify.h>.");
3632
3633   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3634    [],
3635    "remove an inotify watch",
3636    "\
3637 Remove a previously defined inotify watch.
3638 See C<guestfs_inotify_add_watch>.");
3639
3640   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3641    [],
3642    "return list of inotify events",
3643    "\
3644 Return the complete queue of events that have happened
3645 since the previous read call.
3646
3647 If no events have happened, this returns an empty list.
3648
3649 I<Note>: In order to make sure that all events have been
3650 read, you must call this function repeatedly until it
3651 returns an empty list.  The reason is that the call will
3652 read events up to the maximum appliance-to-host message
3653 size and leave remaining events in the queue.");
3654
3655   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3656    [],
3657    "return list of watched files that had events",
3658    "\
3659 This function is a helpful wrapper around C<guestfs_inotify_read>
3660 which just returns a list of pathnames of objects that were
3661 touched.  The returned pathnames are sorted and deduplicated.");
3662
3663   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3664    [],
3665    "close the inotify handle",
3666    "\
3667 This closes the inotify handle which was previously
3668 opened by inotify_init.  It removes all watches, throws
3669 away any pending events, and deallocates all resources.");
3670
3671   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3672    [],
3673    "set SELinux security context",
3674    "\
3675 This sets the SELinux security context of the daemon
3676 to the string C<context>.
3677
3678 See the documentation about SELINUX in L<guestfs(3)>.");
3679
3680   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3681    [],
3682    "get SELinux security context",
3683    "\
3684 This gets the SELinux security context of the daemon.
3685
3686 See the documentation about SELINUX in L<guestfs(3)>,
3687 and C<guestfs_setcon>");
3688
3689   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3690    [InitEmpty, Always, TestOutput (
3691       [["part_disk"; "/dev/sda"; "mbr"];
3692        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3693        ["mount_options"; ""; "/dev/sda1"; "/"];
3694        ["write_file"; "/new"; "new file contents"; "0"];
3695        ["cat"; "/new"]], "new file contents")],
3696    "make a filesystem with block size",
3697    "\
3698 This call is similar to C<guestfs_mkfs>, but it allows you to
3699 control the block size of the resulting filesystem.  Supported
3700 block sizes depend on the filesystem type, but typically they
3701 are C<1024>, C<2048> or C<4096> only.");
3702
3703   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3704    [InitEmpty, Always, TestOutput (
3705       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3706        ["mke2journal"; "4096"; "/dev/sda1"];
3707        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3708        ["mount_options"; ""; "/dev/sda2"; "/"];
3709        ["write_file"; "/new"; "new file contents"; "0"];
3710        ["cat"; "/new"]], "new file contents")],
3711    "make ext2/3/4 external journal",
3712    "\
3713 This creates an ext2 external journal on C<device>.  It is equivalent
3714 to the command:
3715
3716  mke2fs -O journal_dev -b blocksize device");
3717
3718   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3719    [InitEmpty, Always, TestOutput (
3720       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3721        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3722        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3723        ["mount_options"; ""; "/dev/sda2"; "/"];
3724        ["write_file"; "/new"; "new file contents"; "0"];
3725        ["cat"; "/new"]], "new file contents")],
3726    "make ext2/3/4 external journal with label",
3727    "\
3728 This creates an ext2 external journal on C<device> with label C<label>.");
3729
3730   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3731    (let uuid = uuidgen () in
3732     [InitEmpty, Always, TestOutput (
3733        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3734         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3735         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3736         ["mount_options"; ""; "/dev/sda2"; "/"];
3737         ["write_file"; "/new"; "new file contents"; "0"];
3738         ["cat"; "/new"]], "new file contents")]),
3739    "make ext2/3/4 external journal with UUID",
3740    "\
3741 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3742
3743   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3744    [],
3745    "make ext2/3/4 filesystem with external journal",
3746    "\
3747 This creates an ext2/3/4 filesystem on C<device> with
3748 an external journal on C<journal>.  It is equivalent
3749 to the command:
3750
3751  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3752
3753 See also C<guestfs_mke2journal>.");
3754
3755   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3756    [],
3757    "make ext2/3/4 filesystem with external journal",
3758    "\
3759 This creates an ext2/3/4 filesystem on C<device> with
3760 an external journal on the journal labeled C<label>.
3761
3762 See also C<guestfs_mke2journal_L>.");
3763
3764   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3765    [],
3766    "make ext2/3/4 filesystem with external journal",
3767    "\
3768 This creates an ext2/3/4 filesystem on C<device> with
3769 an external journal on the journal with UUID C<uuid>.
3770
3771 See also C<guestfs_mke2journal_U>.");
3772
3773   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3774    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3775    "load a kernel module",
3776    "\
3777 This loads a kernel module in the appliance.
3778
3779 The kernel module must have been whitelisted when libguestfs
3780 was built (see C<appliance/kmod.whitelist.in> in the source).");
3781
3782   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3783    [InitNone, Always, TestOutput (
3784       [["echo_daemon"; "This is a test"]], "This is a test"
3785     )],
3786    "echo arguments back to the client",
3787    "\
3788 This command concatenates the list of C<words> passed with single spaces
3789 between them and returns the resulting string.
3790
3791 You can use this command to test the connection through to the daemon.
3792
3793 See also C<guestfs_ping_daemon>.");
3794
3795   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3796    [], (* There is a regression test for this. *)
3797    "find all files and directories, returning NUL-separated list",
3798    "\
3799 This command lists out all files and directories, recursively,
3800 starting at C<directory>, placing the resulting list in the
3801 external file called C<files>.
3802
3803 This command works the same way as C<guestfs_find> with the
3804 following exceptions:
3805
3806 =over 4
3807
3808 =item *
3809
3810 The resulting list is written to an external file.
3811
3812 =item *
3813
3814 Items (filenames) in the result are separated
3815 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3816
3817 =item *
3818
3819 This command is not limited in the number of names that it
3820 can return.
3821
3822 =item *
3823
3824 The result list is not sorted.
3825
3826 =back");
3827
3828   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3829    [InitISOFS, Always, TestOutput (
3830       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3831     InitISOFS, Always, TestOutput (
3832       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3833     InitISOFS, Always, TestOutput (
3834       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3835     InitISOFS, Always, TestLastFail (
3836       [["case_sensitive_path"; "/Known-1/"]]);
3837     InitBasicFS, Always, TestOutput (
3838       [["mkdir"; "/a"];
3839        ["mkdir"; "/a/bbb"];
3840        ["touch"; "/a/bbb/c"];
3841        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3842     InitBasicFS, Always, TestOutput (
3843       [["mkdir"; "/a"];
3844        ["mkdir"; "/a/bbb"];
3845        ["touch"; "/a/bbb/c"];
3846        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3847     InitBasicFS, Always, TestLastFail (
3848       [["mkdir"; "/a"];
3849        ["mkdir"; "/a/bbb"];
3850        ["touch"; "/a/bbb/c"];
3851        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3852    "return true path on case-insensitive filesystem",
3853    "\
3854 This can be used to resolve case insensitive paths on
3855 a filesystem which is case sensitive.  The use case is
3856 to resolve paths which you have read from Windows configuration
3857 files or the Windows Registry, to the true path.
3858
3859 The command handles a peculiarity of the Linux ntfs-3g
3860 filesystem driver (and probably others), which is that although
3861 the underlying filesystem is case-insensitive, the driver
3862 exports the filesystem to Linux as case-sensitive.
3863
3864 One consequence of this is that special directories such
3865 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3866 (or other things) depending on the precise details of how
3867 they were created.  In Windows itself this would not be
3868 a problem.
3869
3870 Bug or feature?  You decide:
3871 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3872
3873 This function resolves the true case of each element in the
3874 path and returns the case-sensitive path.
3875
3876 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3877 might return C<\"/WINDOWS/system32\"> (the exact return value
3878 would depend on details of how the directories were originally
3879 created under Windows).
3880
3881 I<Note>:
3882 This function does not handle drive names, backslashes etc.
3883
3884 See also C<guestfs_realpath>.");
3885
3886   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3887    [InitBasicFS, Always, TestOutput (
3888       [["vfs_type"; "/dev/sda1"]], "ext2")],
3889    "get the Linux VFS type corresponding to a mounted device",
3890    "\
3891 This command gets the block device type corresponding to
3892 a mounted device called C<device>.
3893
3894 Usually the result is the name of the Linux VFS module that
3895 is used to mount this device (probably determined automatically
3896 if you used the C<guestfs_mount> call).");
3897
3898   ("truncate", (RErr, [Pathname "path"]), 199, [],
3899    [InitBasicFS, Always, TestOutputStruct (
3900       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3901        ["truncate"; "/test"];
3902        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3903    "truncate a file to zero size",
3904    "\
3905 This command truncates C<path> to a zero-length file.  The
3906 file must exist already.");
3907
3908   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3909    [InitBasicFS, Always, TestOutputStruct (
3910       [["touch"; "/test"];
3911        ["truncate_size"; "/test"; "1000"];
3912        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3913    "truncate a file to a particular size",
3914    "\
3915 This command truncates C<path> to size C<size> bytes.  The file
3916 must exist already.
3917
3918 If the current file size is less than C<size> then
3919 the file is extended to the required size with zero bytes.
3920 This creates a sparse file (ie. disk blocks are not allocated
3921 for the file until you write to it).  To create a non-sparse
3922 file of zeroes, use C<guestfs_fallocate64> instead.");
3923
3924   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3925    [InitBasicFS, Always, TestOutputStruct (
3926       [["touch"; "/test"];
3927        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3928        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3929    "set timestamp of a file with nanosecond precision",
3930    "\
3931 This command sets the timestamps of a file with nanosecond
3932 precision.
3933
3934 C<atsecs, atnsecs> are the last access time (atime) in secs and
3935 nanoseconds from the epoch.
3936
3937 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3938 secs and nanoseconds from the epoch.
3939
3940 If the C<*nsecs> field contains the special value C<-1> then
3941 the corresponding timestamp is set to the current time.  (The
3942 C<*secs> field is ignored in this case).
3943
3944 If the C<*nsecs> field contains the special value C<-2> then
3945 the corresponding timestamp is left unchanged.  (The
3946 C<*secs> field is ignored in this case).");
3947
3948   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3949    [InitBasicFS, Always, TestOutputStruct (
3950       [["mkdir_mode"; "/test"; "0o111"];
3951        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3952    "create a directory with a particular mode",
3953    "\
3954 This command creates a directory, setting the initial permissions
3955 of the directory to C<mode>.
3956
3957 For common Linux filesystems, the actual mode which is set will
3958 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3959 interpret the mode in other ways.
3960
3961 See also C<guestfs_mkdir>, C<guestfs_umask>");
3962
3963   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3964    [], (* XXX *)
3965    "change file owner and group",
3966    "\
3967 Change the file owner to C<owner> and group to C<group>.
3968 This is like C<guestfs_chown> but if C<path> is a symlink then
3969 the link itself is changed, not the target.
3970
3971 Only numeric uid and gid are supported.  If you want to use
3972 names, you will need to locate and parse the password file
3973 yourself (Augeas support makes this relatively easy).");
3974
3975   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3976    [], (* XXX *)
3977    "lstat on multiple files",
3978    "\
3979 This call allows you to perform the C<guestfs_lstat> operation
3980 on multiple files, where all files are in the directory C<path>.
3981 C<names> is the list of files from this directory.
3982
3983 On return you get a list of stat structs, with a one-to-one
3984 correspondence to the C<names> list.  If any name did not exist
3985 or could not be lstat'd, then the C<ino> field of that structure
3986 is set to C<-1>.
3987
3988 This call is intended for programs that want to efficiently
3989 list a directory contents without making many round-trips.
3990 See also C<guestfs_lxattrlist> for a similarly efficient call
3991 for getting extended attributes.  Very long directory listings
3992 might cause the protocol message size to be exceeded, causing
3993 this call to fail.  The caller must split up such requests
3994 into smaller groups of names.");
3995
3996   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3997    [], (* XXX *)
3998    "lgetxattr on multiple files",
3999    "\
4000 This call allows you to get the extended attributes
4001 of multiple files, where all files are in the directory C<path>.
4002 C<names> is the list of files from this directory.
4003
4004 On return you get a flat list of xattr structs which must be
4005 interpreted sequentially.  The first xattr struct always has a zero-length
4006 C<attrname>.  C<attrval> in this struct is zero-length
4007 to indicate there was an error doing C<lgetxattr> for this
4008 file, I<or> is a C string which is a decimal number
4009 (the number of following attributes for this file, which could
4010 be C<\"0\">).  Then after the first xattr struct are the
4011 zero or more attributes for the first named file.
4012 This repeats for the second and subsequent files.
4013
4014 This call is intended for programs that want to efficiently
4015 list a directory contents without making many round-trips.
4016 See also C<guestfs_lstatlist> for a similarly efficient call
4017 for getting standard stats.  Very long directory listings
4018 might cause the protocol message size to be exceeded, causing
4019 this call to fail.  The caller must split up such requests
4020 into smaller groups of names.");
4021
4022   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4023    [], (* XXX *)
4024    "readlink on multiple files",
4025    "\
4026 This call allows you to do a C<readlink> operation
4027 on multiple files, where all files are in the directory C<path>.
4028 C<names> is the list of files from this directory.
4029
4030 On return you get a list of strings, with a one-to-one
4031 correspondence to the C<names> list.  Each string is the
4032 value of the symbolic link.
4033
4034 If the C<readlink(2)> operation fails on any name, then
4035 the corresponding result string is the empty string C<\"\">.
4036 However the whole operation is completed even if there
4037 were C<readlink(2)> errors, and so you can call this
4038 function with names where you don't know if they are
4039 symbolic links already (albeit slightly less efficient).
4040
4041 This call is intended for programs that want to efficiently
4042 list a directory contents without making many round-trips.
4043 Very long directory listings might cause the protocol
4044 message size to be exceeded, causing
4045 this call to fail.  The caller must split up such requests
4046 into smaller groups of names.");
4047
4048   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4049    [InitISOFS, Always, TestOutputBuffer (
4050       [["pread"; "/known-4"; "1"; "3"]], "\n");
4051     InitISOFS, Always, TestOutputBuffer (
4052       [["pread"; "/empty"; "0"; "100"]], "")],
4053    "read part of a file",
4054    "\
4055 This command lets you read part of a file.  It reads C<count>
4056 bytes of the file, starting at C<offset>, from file C<path>.
4057
4058 This may read fewer bytes than requested.  For further details
4059 see the L<pread(2)> system call.");
4060
4061   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4062    [InitEmpty, Always, TestRun (
4063       [["part_init"; "/dev/sda"; "gpt"]])],
4064    "create an empty partition table",
4065    "\
4066 This creates an empty partition table on C<device> of one of the
4067 partition types listed below.  Usually C<parttype> should be
4068 either C<msdos> or C<gpt> (for large disks).
4069
4070 Initially there are no partitions.  Following this, you should
4071 call C<guestfs_part_add> for each partition required.
4072
4073 Possible values for C<parttype> are:
4074
4075 =over 4
4076
4077 =item B<efi> | B<gpt>
4078
4079 Intel EFI / GPT partition table.
4080
4081 This is recommended for >= 2 TB partitions that will be accessed
4082 from Linux and Intel-based Mac OS X.  It also has limited backwards
4083 compatibility with the C<mbr> format.
4084
4085 =item B<mbr> | B<msdos>
4086
4087 The standard PC \"Master Boot Record\" (MBR) format used
4088 by MS-DOS and Windows.  This partition type will B<only> work
4089 for device sizes up to 2 TB.  For large disks we recommend
4090 using C<gpt>.
4091
4092 =back
4093
4094 Other partition table types that may work but are not
4095 supported include:
4096
4097 =over 4
4098
4099 =item B<aix>
4100
4101 AIX disk labels.
4102
4103 =item B<amiga> | B<rdb>
4104
4105 Amiga \"Rigid Disk Block\" format.
4106
4107 =item B<bsd>
4108
4109 BSD disk labels.
4110
4111 =item B<dasd>
4112
4113 DASD, used on IBM mainframes.
4114
4115 =item B<dvh>
4116
4117 MIPS/SGI volumes.
4118
4119 =item B<mac>
4120
4121 Old Mac partition format.  Modern Macs use C<gpt>.
4122
4123 =item B<pc98>
4124
4125 NEC PC-98 format, common in Japan apparently.
4126
4127 =item B<sun>
4128
4129 Sun disk labels.
4130
4131 =back");
4132
4133   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4134    [InitEmpty, Always, TestRun (
4135       [["part_init"; "/dev/sda"; "mbr"];
4136        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4137     InitEmpty, Always, TestRun (
4138       [["part_init"; "/dev/sda"; "gpt"];
4139        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4140        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4141     InitEmpty, Always, TestRun (
4142       [["part_init"; "/dev/sda"; "mbr"];
4143        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4144        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4145        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4146        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4147    "add a partition to the device",
4148    "\
4149 This command adds a partition to C<device>.  If there is no partition
4150 table on the device, call C<guestfs_part_init> first.
4151
4152 The C<prlogex> parameter is the type of partition.  Normally you
4153 should pass C<p> or C<primary> here, but MBR partition tables also
4154 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4155 types.
4156
4157 C<startsect> and C<endsect> are the start and end of the partition
4158 in I<sectors>.  C<endsect> may be negative, which means it counts
4159 backwards from the end of the disk (C<-1> is the last sector).
4160
4161 Creating a partition which covers the whole disk is not so easy.
4162 Use C<guestfs_part_disk> to do that.");
4163
4164   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4165    [InitEmpty, Always, TestRun (
4166       [["part_disk"; "/dev/sda"; "mbr"]]);
4167     InitEmpty, Always, TestRun (
4168       [["part_disk"; "/dev/sda"; "gpt"]])],
4169    "partition whole disk with a single primary partition",
4170    "\
4171 This command is simply a combination of C<guestfs_part_init>
4172 followed by C<guestfs_part_add> to create a single primary partition
4173 covering the whole disk.
4174
4175 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4176 but other possible values are described in C<guestfs_part_init>.");
4177
4178   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4179    [InitEmpty, Always, TestRun (
4180       [["part_disk"; "/dev/sda"; "mbr"];
4181        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4182    "make a partition bootable",
4183    "\
4184 This sets the bootable flag on partition numbered C<partnum> on
4185 device C<device>.  Note that partitions are numbered from 1.
4186
4187 The bootable flag is used by some operating systems (notably
4188 Windows) to determine which partition to boot from.  It is by
4189 no means universally recognized.");
4190
4191   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4192    [InitEmpty, Always, TestRun (
4193       [["part_disk"; "/dev/sda"; "gpt"];
4194        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4195    "set partition name",
4196    "\
4197 This sets the partition name on partition numbered C<partnum> on
4198 device C<device>.  Note that partitions are numbered from 1.
4199
4200 The partition name can only be set on certain types of partition
4201 table.  This works on C<gpt> but not on C<mbr> partitions.");
4202
4203   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4204    [], (* XXX Add a regression test for this. *)
4205    "list partitions on a device",
4206    "\
4207 This command parses the partition table on C<device> and
4208 returns the list of partitions found.
4209
4210 The fields in the returned structure are:
4211
4212 =over 4
4213
4214 =item B<part_num>
4215
4216 Partition number, counting from 1.
4217
4218 =item B<part_start>
4219
4220 Start of the partition I<in bytes>.  To get sectors you have to
4221 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4222
4223 =item B<part_end>
4224
4225 End of the partition in bytes.
4226
4227 =item B<part_size>
4228
4229 Size of the partition in bytes.
4230
4231 =back");
4232
4233   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4234    [InitEmpty, Always, TestOutput (
4235       [["part_disk"; "/dev/sda"; "gpt"];
4236        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4237    "get the partition table type",
4238    "\
4239 This command examines the partition table on C<device> and
4240 returns the partition table type (format) being used.
4241
4242 Common return values include: C<msdos> (a DOS/Windows style MBR
4243 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4244 values are possible, although unusual.  See C<guestfs_part_init>
4245 for a full list.");
4246
4247   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4248    [InitBasicFS, Always, TestOutputBuffer (
4249       [["fill"; "0x63"; "10"; "/test"];
4250        ["read_file"; "/test"]], "cccccccccc")],
4251    "fill a file with octets",
4252    "\
4253 This command creates a new file called C<path>.  The initial
4254 content of the file is C<len> octets of C<c>, where C<c>
4255 must be a number in the range C<[0..255]>.
4256
4257 To fill a file with zero bytes (sparsely), it is
4258 much more efficient to use C<guestfs_truncate_size>.");
4259
4260   ("available", (RErr, [StringList "groups"]), 216, [],
4261    [InitNone, Always, TestRun [["available"; ""]]],
4262    "test availability of some parts of the API",
4263    "\
4264 This command is used to check the availability of some
4265 groups of functionality in the appliance, which not all builds of
4266 the libguestfs appliance will be able to provide.
4267
4268 The libguestfs groups, and the functions that those
4269 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4270
4271 The argument C<groups> is a list of group names, eg:
4272 C<[\"inotify\", \"augeas\"]> would check for the availability of
4273 the Linux inotify functions and Augeas (configuration file
4274 editing) functions.
4275
4276 The command returns no error if I<all> requested groups are available.
4277
4278 It fails with an error if one or more of the requested
4279 groups is unavailable in the appliance.
4280
4281 If an unknown group name is included in the
4282 list of groups then an error is always returned.
4283
4284 I<Notes:>
4285
4286 =over 4
4287
4288 =item *
4289
4290 You must call C<guestfs_launch> before calling this function.
4291
4292 The reason is because we don't know what groups are
4293 supported by the appliance/daemon until it is running and can
4294 be queried.
4295
4296 =item *
4297
4298 If a group of functions is available, this does not necessarily
4299 mean that they will work.  You still have to check for errors
4300 when calling individual API functions even if they are
4301 available.
4302
4303 =item *
4304
4305 It is usually the job of distro packagers to build
4306 complete functionality into the libguestfs appliance.
4307 Upstream libguestfs, if built from source with all
4308 requirements satisfied, will support everything.
4309
4310 =item *
4311
4312 This call was added in version C<1.0.80>.  In previous
4313 versions of libguestfs all you could do would be to speculatively
4314 execute a command to find out if the daemon implemented it.
4315 See also C<guestfs_version>.
4316
4317 =back");
4318
4319   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4320    [InitBasicFS, Always, TestOutputBuffer (
4321       [["write_file"; "/src"; "hello, world"; "0"];
4322        ["dd"; "/src"; "/dest"];
4323        ["read_file"; "/dest"]], "hello, world")],
4324    "copy from source to destination using dd",
4325    "\
4326 This command copies from one source device or file C<src>
4327 to another destination device or file C<dest>.  Normally you
4328 would use this to copy to or from a device or partition, for
4329 example to duplicate a filesystem.
4330
4331 If the destination is a device, it must be as large or larger
4332 than the source file or device, otherwise the copy will fail.
4333 This command cannot do partial copies (see C<guestfs_copy_size>).");
4334
4335   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4336    [InitBasicFS, Always, TestOutputInt (
4337       [["write_file"; "/file"; "hello, world"; "0"];
4338        ["filesize"; "/file"]], 12)],
4339    "return the size of the file in bytes",
4340    "\
4341 This command returns the size of C<file> in bytes.
4342
4343 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4344 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4345 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4346
4347   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4348    [InitBasicFSonLVM, Always, TestOutputList (
4349       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4350        ["lvs"]], ["/dev/VG/LV2"])],
4351    "rename an LVM logical volume",
4352    "\
4353 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4354
4355   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4356    [InitBasicFSonLVM, Always, TestOutputList (
4357       [["umount"; "/"];
4358        ["vg_activate"; "false"; "VG"];
4359        ["vgrename"; "VG"; "VG2"];
4360        ["vg_activate"; "true"; "VG2"];
4361        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4362        ["vgs"]], ["VG2"])],
4363    "rename an LVM volume group",
4364    "\
4365 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4366
4367   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4368    [InitISOFS, Always, TestOutputBuffer (
4369       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4370    "list the contents of a single file in an initrd",
4371    "\
4372 This command unpacks the file C<filename> from the initrd file
4373 called C<initrdpath>.  The filename must be given I<without> the
4374 initial C</> character.
4375
4376 For example, in guestfish you could use the following command
4377 to examine the boot script (usually called C</init>)
4378 contained in a Linux initrd or initramfs image:
4379
4380  initrd-cat /boot/initrd-<version>.img init
4381
4382 See also C<guestfs_initrd_list>.");
4383
4384   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4385    [],
4386    "get the UUID of a physical volume",
4387    "\
4388 This command returns the UUID of the LVM PV C<device>.");
4389
4390   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4391    [],
4392    "get the UUID of a volume group",
4393    "\
4394 This command returns the UUID of the LVM VG named C<vgname>.");
4395
4396   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4397    [],
4398    "get the UUID of a logical volume",
4399    "\
4400 This command returns the UUID of the LVM LV C<device>.");
4401
4402   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4403    [],
4404    "get the PV UUIDs containing the volume group",
4405    "\
4406 Given a VG called C<vgname>, this returns the UUIDs of all
4407 the physical volumes that this volume group resides on.
4408
4409 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4410 calls to associate physical volumes and volume groups.
4411
4412 See also C<guestfs_vglvuuids>.");
4413
4414   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4415    [],
4416    "get the LV UUIDs of all LVs in the volume group",
4417    "\
4418 Given a VG called C<vgname>, this returns the UUIDs of all
4419 the logical volumes created in this volume group.
4420
4421 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4422 calls to associate logical volumes and volume groups.
4423
4424 See also C<guestfs_vgpvuuids>.");
4425
4426   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4427    [InitBasicFS, Always, TestOutputBuffer (
4428       [["write_file"; "/src"; "hello, world"; "0"];
4429        ["copy_size"; "/src"; "/dest"; "5"];
4430        ["read_file"; "/dest"]], "hello")],
4431    "copy size bytes from source to destination using dd",
4432    "\
4433 This command copies exactly C<size> bytes from one source device
4434 or file C<src> to another destination device or file C<dest>.
4435
4436 Note this will fail if the source is too short or if the destination
4437 is not large enough.");
4438
4439   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4440    [InitEmpty, Always, TestRun (
4441       [["part_init"; "/dev/sda"; "mbr"];
4442        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4443        ["part_del"; "/dev/sda"; "1"]])],
4444    "delete a partition",
4445    "\
4446 This command deletes the partition numbered C<partnum> on C<device>.
4447
4448 Note that in the case of MBR partitioning, deleting an
4449 extended partition also deletes any logical partitions
4450 it contains.");
4451
4452   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4453    [InitEmpty, Always, TestOutputTrue (
4454       [["part_init"; "/dev/sda"; "mbr"];
4455        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4456        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4457        ["part_get_bootable"; "/dev/sda"; "1"]])],
4458    "return true if a partition is bootable",
4459    "\
4460 This command returns true if the partition C<partnum> on
4461 C<device> has the bootable flag set.
4462
4463 See also C<guestfs_part_set_bootable>.");
4464
4465   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4466    [InitEmpty, Always, TestOutputInt (
4467       [["part_init"; "/dev/sda"; "mbr"];
4468        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4469        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4470        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4471    "get the MBR type byte (ID byte) from a partition",
4472    "\
4473 Returns the MBR type byte (also known as the ID byte) from
4474 the numbered partition C<partnum>.
4475
4476 Note that only MBR (old DOS-style) partitions have type bytes.
4477 You will get undefined results for other partition table
4478 types (see C<guestfs_part_get_parttype>).");
4479
4480   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4481    [], (* tested by part_get_mbr_id *)
4482    "set the MBR type byte (ID byte) of a partition",
4483    "\
4484 Sets the MBR type byte (also known as the ID byte) of
4485 the numbered partition C<partnum> to C<idbyte>.  Note
4486 that the type bytes quoted in most documentation are
4487 in fact hexadecimal numbers, but usually documented
4488 without any leading \"0x\" which might be confusing.
4489
4490 Note that only MBR (old DOS-style) partitions have type bytes.
4491 You will get undefined results for other partition table
4492 types (see C<guestfs_part_get_parttype>).");
4493
4494 ]
4495
4496 let all_functions = non_daemon_functions @ daemon_functions
4497
4498 (* In some places we want the functions to be displayed sorted
4499  * alphabetically, so this is useful:
4500  *)
4501 let all_functions_sorted =
4502   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4503                compare n1 n2) all_functions
4504
4505 (* Field types for structures. *)
4506 type field =
4507   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4508   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4509   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4510   | FUInt32
4511   | FInt32
4512   | FUInt64
4513   | FInt64
4514   | FBytes                      (* Any int measure that counts bytes. *)
4515   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4516   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4517
4518 (* Because we generate extra parsing code for LVM command line tools,
4519  * we have to pull out the LVM columns separately here.
4520  *)
4521 let lvm_pv_cols = [
4522   "pv_name", FString;
4523   "pv_uuid", FUUID;
4524   "pv_fmt", FString;
4525   "pv_size", FBytes;
4526   "dev_size", FBytes;
4527   "pv_free", FBytes;
4528   "pv_used", FBytes;
4529   "pv_attr", FString (* XXX *);
4530   "pv_pe_count", FInt64;
4531   "pv_pe_alloc_count", FInt64;
4532   "pv_tags", FString;
4533   "pe_start", FBytes;
4534   "pv_mda_count", FInt64;
4535   "pv_mda_free", FBytes;
4536   (* Not in Fedora 10:
4537      "pv_mda_size", FBytes;
4538   *)
4539 ]
4540 let lvm_vg_cols = [
4541   "vg_name", FString;
4542   "vg_uuid", FUUID;
4543   "vg_fmt", FString;
4544   "vg_attr", FString (* XXX *);
4545   "vg_size", FBytes;
4546   "vg_free", FBytes;
4547   "vg_sysid", FString;
4548   "vg_extent_size", FBytes;
4549   "vg_extent_count", FInt64;
4550   "vg_free_count", FInt64;
4551   "max_lv", FInt64;
4552   "max_pv", FInt64;
4553   "pv_count", FInt64;
4554   "lv_count", FInt64;
4555   "snap_count", FInt64;
4556   "vg_seqno", FInt64;
4557   "vg_tags", FString;
4558   "vg_mda_count", FInt64;
4559   "vg_mda_free", FBytes;
4560   (* Not in Fedora 10:
4561      "vg_mda_size", FBytes;
4562   *)
4563 ]
4564 let lvm_lv_cols = [
4565   "lv_name", FString;
4566   "lv_uuid", FUUID;
4567   "lv_attr", FString (* XXX *);
4568   "lv_major", FInt64;
4569   "lv_minor", FInt64;
4570   "lv_kernel_major", FInt64;
4571   "lv_kernel_minor", FInt64;
4572   "lv_size", FBytes;
4573   "seg_count", FInt64;
4574   "origin", FString;
4575   "snap_percent", FOptPercent;
4576   "copy_percent", FOptPercent;
4577   "move_pv", FString;
4578   "lv_tags", FString;
4579   "mirror_log", FString;
4580   "modules", FString;
4581 ]
4582
4583 (* Names and fields in all structures (in RStruct and RStructList)
4584  * that we support.
4585  *)
4586 let structs = [
4587   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4588    * not use this struct in any new code.
4589    *)
4590   "int_bool", [
4591     "i", FInt32;                (* for historical compatibility *)
4592     "b", FInt32;                (* for historical compatibility *)
4593   ];
4594
4595   (* LVM PVs, VGs, LVs. *)
4596   "lvm_pv", lvm_pv_cols;
4597   "lvm_vg", lvm_vg_cols;
4598   "lvm_lv", lvm_lv_cols;
4599
4600   (* Column names and types from stat structures.
4601    * NB. Can't use things like 'st_atime' because glibc header files
4602    * define some of these as macros.  Ugh.
4603    *)
4604   "stat", [
4605     "dev", FInt64;
4606     "ino", FInt64;
4607     "mode", FInt64;
4608     "nlink", FInt64;
4609     "uid", FInt64;
4610     "gid", FInt64;
4611     "rdev", FInt64;
4612     "size", FInt64;
4613     "blksize", FInt64;
4614     "blocks", FInt64;
4615     "atime", FInt64;
4616     "mtime", FInt64;
4617     "ctime", FInt64;
4618   ];
4619   "statvfs", [
4620     "bsize", FInt64;
4621     "frsize", FInt64;
4622     "blocks", FInt64;
4623     "bfree", FInt64;
4624     "bavail", FInt64;
4625     "files", FInt64;
4626     "ffree", FInt64;
4627     "favail", FInt64;
4628     "fsid", FInt64;
4629     "flag", FInt64;
4630     "namemax", FInt64;
4631   ];
4632
4633   (* Column names in dirent structure. *)
4634   "dirent", [
4635     "ino", FInt64;
4636     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4637     "ftyp", FChar;
4638     "name", FString;
4639   ];
4640
4641   (* Version numbers. *)
4642   "version", [
4643     "major", FInt64;
4644     "minor", FInt64;
4645     "release", FInt64;
4646     "extra", FString;
4647   ];
4648
4649   (* Extended attribute. *)
4650   "xattr", [
4651     "attrname", FString;
4652     "attrval", FBuffer;
4653   ];
4654
4655   (* Inotify events. *)
4656   "inotify_event", [
4657     "in_wd", FInt64;
4658     "in_mask", FUInt32;
4659     "in_cookie", FUInt32;
4660     "in_name", FString;
4661   ];
4662
4663   (* Partition table entry. *)
4664   "partition", [
4665     "part_num", FInt32;
4666     "part_start", FBytes;
4667     "part_end", FBytes;
4668     "part_size", FBytes;
4669   ];
4670 ] (* end of structs *)
4671
4672 (* Ugh, Java has to be different ..
4673  * These names are also used by the Haskell bindings.
4674  *)
4675 let java_structs = [
4676   "int_bool", "IntBool";
4677   "lvm_pv", "PV";
4678   "lvm_vg", "VG";
4679   "lvm_lv", "LV";
4680   "stat", "Stat";
4681   "statvfs", "StatVFS";
4682   "dirent", "Dirent";
4683   "version", "Version";
4684   "xattr", "XAttr";
4685   "inotify_event", "INotifyEvent";
4686   "partition", "Partition";
4687 ]
4688
4689 (* What structs are actually returned. *)
4690 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4691
4692 (* Returns a list of RStruct/RStructList structs that are returned
4693  * by any function.  Each element of returned list is a pair:
4694  *
4695  * (structname, RStructOnly)
4696  *    == there exists function which returns RStruct (_, structname)
4697  * (structname, RStructListOnly)
4698  *    == there exists function which returns RStructList (_, structname)
4699  * (structname, RStructAndList)
4700  *    == there are functions returning both RStruct (_, structname)
4701  *                                      and RStructList (_, structname)
4702  *)
4703 let rstructs_used_by functions =
4704   (* ||| is a "logical OR" for rstructs_used_t *)
4705   let (|||) a b =
4706     match a, b with
4707     | RStructAndList, _
4708     | _, RStructAndList -> RStructAndList
4709     | RStructOnly, RStructListOnly
4710     | RStructListOnly, RStructOnly -> RStructAndList
4711     | RStructOnly, RStructOnly -> RStructOnly
4712     | RStructListOnly, RStructListOnly -> RStructListOnly
4713   in
4714
4715   let h = Hashtbl.create 13 in
4716
4717   (* if elem->oldv exists, update entry using ||| operator,
4718    * else just add elem->newv to the hash
4719    *)
4720   let update elem newv =
4721     try  let oldv = Hashtbl.find h elem in
4722          Hashtbl.replace h elem (newv ||| oldv)
4723     with Not_found -> Hashtbl.add h elem newv
4724   in
4725
4726   List.iter (
4727     fun (_, style, _, _, _, _, _) ->
4728       match fst style with
4729       | RStruct (_, structname) -> update structname RStructOnly
4730       | RStructList (_, structname) -> update structname RStructListOnly
4731       | _ -> ()
4732   ) functions;
4733
4734   (* return key->values as a list of (key,value) *)
4735   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4736
4737 (* Used for testing language bindings. *)
4738 type callt =
4739   | CallString of string
4740   | CallOptString of string option
4741   | CallStringList of string list
4742   | CallInt of int
4743   | CallInt64 of int64
4744   | CallBool of bool
4745
4746 (* Used to memoize the result of pod2text. *)
4747 let pod2text_memo_filename = "src/.pod2text.data"
4748 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4749   try
4750     let chan = open_in pod2text_memo_filename in
4751     let v = input_value chan in
4752     close_in chan;
4753     v
4754   with
4755     _ -> Hashtbl.create 13
4756 let pod2text_memo_updated () =
4757   let chan = open_out pod2text_memo_filename in
4758   output_value chan pod2text_memo;
4759   close_out chan
4760
4761 (* Useful functions.
4762  * Note we don't want to use any external OCaml libraries which
4763  * makes this a bit harder than it should be.
4764  *)
4765 module StringMap = Map.Make (String)
4766
4767 let failwithf fs = ksprintf failwith fs
4768
4769 let unique = let i = ref 0 in fun () -> incr i; !i
4770
4771 let replace_char s c1 c2 =
4772   let s2 = String.copy s in
4773   let r = ref false in
4774   for i = 0 to String.length s2 - 1 do
4775     if String.unsafe_get s2 i = c1 then (
4776       String.unsafe_set s2 i c2;
4777       r := true
4778     )
4779   done;
4780   if not !r then s else s2
4781
4782 let isspace c =
4783   c = ' '
4784   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4785
4786 let triml ?(test = isspace) str =
4787   let i = ref 0 in
4788   let n = ref (String.length str) in
4789   while !n > 0 && test str.[!i]; do
4790     decr n;
4791     incr i
4792   done;
4793   if !i = 0 then str
4794   else String.sub str !i !n
4795
4796 let trimr ?(test = isspace) str =
4797   let n = ref (String.length str) in
4798   while !n > 0 && test str.[!n-1]; do
4799     decr n
4800   done;
4801   if !n = String.length str then str
4802   else String.sub str 0 !n
4803
4804 let trim ?(test = isspace) str =
4805   trimr ~test (triml ~test str)
4806
4807 let rec find s sub =
4808   let len = String.length s in
4809   let sublen = String.length sub in
4810   let rec loop i =
4811     if i <= len-sublen then (
4812       let rec loop2 j =
4813         if j < sublen then (
4814           if s.[i+j] = sub.[j] then loop2 (j+1)
4815           else -1
4816         ) else
4817           i (* found *)
4818       in
4819       let r = loop2 0 in
4820       if r = -1 then loop (i+1) else r
4821     ) else
4822       -1 (* not found *)
4823   in
4824   loop 0
4825
4826 let rec replace_str s s1 s2 =
4827   let len = String.length s in
4828   let sublen = String.length s1 in
4829   let i = find s s1 in
4830   if i = -1 then s
4831   else (
4832     let s' = String.sub s 0 i in
4833     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4834     s' ^ s2 ^ replace_str s'' s1 s2
4835   )
4836
4837 let rec string_split sep str =
4838   let len = String.length str in
4839   let seplen = String.length sep in
4840   let i = find str sep in
4841   if i = -1 then [str]
4842   else (
4843     let s' = String.sub str 0 i in
4844     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4845     s' :: string_split sep s''
4846   )
4847
4848 let files_equal n1 n2 =
4849   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4850   match Sys.command cmd with
4851   | 0 -> true
4852   | 1 -> false
4853   | i -> failwithf "%s: failed with error code %d" cmd i
4854
4855 let rec filter_map f = function
4856   | [] -> []
4857   | x :: xs ->
4858       match f x with
4859       | Some y -> y :: filter_map f xs
4860       | None -> filter_map f xs
4861
4862 let rec find_map f = function
4863   | [] -> raise Not_found
4864   | x :: xs ->
4865       match f x with
4866       | Some y -> y
4867       | None -> find_map f xs
4868
4869 let iteri f xs =
4870   let rec loop i = function
4871     | [] -> ()
4872     | x :: xs -> f i x; loop (i+1) xs
4873   in
4874   loop 0 xs
4875
4876 let mapi f xs =
4877   let rec loop i = function
4878     | [] -> []
4879     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4880   in
4881   loop 0 xs
4882
4883 let count_chars c str =
4884   let count = ref 0 in
4885   for i = 0 to String.length str - 1 do
4886     if c = String.unsafe_get str i then incr count
4887   done;
4888   !count
4889
4890 let name_of_argt = function
4891   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4892   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4893   | FileIn n | FileOut n -> n
4894
4895 let java_name_of_struct typ =
4896   try List.assoc typ java_structs
4897   with Not_found ->
4898     failwithf
4899       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4900
4901 let cols_of_struct typ =
4902   try List.assoc typ structs
4903   with Not_found ->
4904     failwithf "cols_of_struct: unknown struct %s" typ
4905
4906 let seq_of_test = function
4907   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4908   | TestOutputListOfDevices (s, _)
4909   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4910   | TestOutputTrue s | TestOutputFalse s
4911   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4912   | TestOutputStruct (s, _)
4913   | TestLastFail s -> s
4914
4915 (* Handling for function flags. *)
4916 let protocol_limit_warning =
4917   "Because of the message protocol, there is a transfer limit
4918 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4919
4920 let danger_will_robinson =
4921   "B<This command is dangerous.  Without careful use you
4922 can easily destroy all your data>."
4923
4924 let deprecation_notice flags =
4925   try
4926     let alt =
4927       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4928     let txt =
4929       sprintf "This function is deprecated.
4930 In new code, use the C<%s> call instead.
4931
4932 Deprecated functions will not be removed from the API, but the
4933 fact that they are deprecated indicates that there are problems
4934 with correct use of these functions." alt in
4935     Some txt
4936   with
4937     Not_found -> None
4938
4939 (* Create list of optional groups. *)
4940 let optgroups =
4941   let h = Hashtbl.create 13 in
4942   List.iter (
4943     fun (name, _, _, flags, _, _, _) ->
4944       List.iter (
4945         function
4946         | Optional group ->
4947             let names = try Hashtbl.find h group with Not_found -> [] in
4948             Hashtbl.replace h group (name :: names)
4949         | _ -> ()
4950       ) flags
4951   ) daemon_functions;
4952   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4953   let groups =
4954     List.map (
4955       fun group -> group, List.sort compare (Hashtbl.find h group)
4956     ) groups in
4957   List.sort (fun x y -> compare (fst x) (fst y)) groups
4958
4959 (* Check function names etc. for consistency. *)
4960 let check_functions () =
4961   let contains_uppercase str =
4962     let len = String.length str in
4963     let rec loop i =
4964       if i >= len then false
4965       else (
4966         let c = str.[i] in
4967         if c >= 'A' && c <= 'Z' then true
4968         else loop (i+1)
4969       )
4970     in
4971     loop 0
4972   in
4973
4974   (* Check function names. *)
4975   List.iter (
4976     fun (name, _, _, _, _, _, _) ->
4977       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4978         failwithf "function name %s does not need 'guestfs' prefix" name;
4979       if name = "" then
4980         failwithf "function name is empty";
4981       if name.[0] < 'a' || name.[0] > 'z' then
4982         failwithf "function name %s must start with lowercase a-z" name;
4983       if String.contains name '-' then
4984         failwithf "function name %s should not contain '-', use '_' instead."
4985           name
4986   ) all_functions;
4987
4988   (* Check function parameter/return names. *)
4989   List.iter (
4990     fun (name, style, _, _, _, _, _) ->
4991       let check_arg_ret_name n =
4992         if contains_uppercase n then
4993           failwithf "%s param/ret %s should not contain uppercase chars"
4994             name n;
4995         if String.contains n '-' || String.contains n '_' then
4996           failwithf "%s param/ret %s should not contain '-' or '_'"
4997             name n;
4998         if n = "value" then
4999           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;
5000         if n = "int" || n = "char" || n = "short" || n = "long" then
5001           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5002         if n = "i" || n = "n" then
5003           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5004         if n = "argv" || n = "args" then
5005           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5006
5007         (* List Haskell, OCaml and C keywords here.
5008          * http://www.haskell.org/haskellwiki/Keywords
5009          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5010          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5011          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5012          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5013          * Omitting _-containing words, since they're handled above.
5014          * Omitting the OCaml reserved word, "val", is ok,
5015          * and saves us from renaming several parameters.
5016          *)
5017         let reserved = [
5018           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5019           "char"; "class"; "const"; "constraint"; "continue"; "data";
5020           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5021           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5022           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5023           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5024           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5025           "interface";
5026           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5027           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5028           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5029           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5030           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5031           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5032           "volatile"; "when"; "where"; "while";
5033           ] in
5034         if List.mem n reserved then
5035           failwithf "%s has param/ret using reserved word %s" name n;
5036       in
5037
5038       (match fst style with
5039        | RErr -> ()
5040        | RInt n | RInt64 n | RBool n
5041        | RConstString n | RConstOptString n | RString n
5042        | RStringList n | RStruct (n, _) | RStructList (n, _)
5043        | RHashtable n | RBufferOut n ->
5044            check_arg_ret_name n
5045       );
5046       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5047   ) all_functions;
5048
5049   (* Check short descriptions. *)
5050   List.iter (
5051     fun (name, _, _, _, _, shortdesc, _) ->
5052       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5053         failwithf "short description of %s should begin with lowercase." name;
5054       let c = shortdesc.[String.length shortdesc-1] in
5055       if c = '\n' || c = '.' then
5056         failwithf "short description of %s should not end with . or \\n." name
5057   ) all_functions;
5058
5059   (* Check long descriptions. *)
5060   List.iter (
5061     fun (name, _, _, _, _, _, longdesc) ->
5062       if longdesc.[String.length longdesc-1] = '\n' then
5063         failwithf "long description of %s should not end with \\n." name
5064   ) all_functions;
5065
5066   (* Check proc_nrs. *)
5067   List.iter (
5068     fun (name, _, proc_nr, _, _, _, _) ->
5069       if proc_nr <= 0 then
5070         failwithf "daemon function %s should have proc_nr > 0" name
5071   ) daemon_functions;
5072
5073   List.iter (
5074     fun (name, _, proc_nr, _, _, _, _) ->
5075       if proc_nr <> -1 then
5076         failwithf "non-daemon function %s should have proc_nr -1" name
5077   ) non_daemon_functions;
5078
5079   let proc_nrs =
5080     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5081       daemon_functions in
5082   let proc_nrs =
5083     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5084   let rec loop = function
5085     | [] -> ()
5086     | [_] -> ()
5087     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5088         loop rest
5089     | (name1,nr1) :: (name2,nr2) :: _ ->
5090         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5091           name1 name2 nr1 nr2
5092   in
5093   loop proc_nrs;
5094
5095   (* Check tests. *)
5096   List.iter (
5097     function
5098       (* Ignore functions that have no tests.  We generate a
5099        * warning when the user does 'make check' instead.
5100        *)
5101     | name, _, _, _, [], _, _ -> ()
5102     | name, _, _, _, tests, _, _ ->
5103         let funcs =
5104           List.map (
5105             fun (_, _, test) ->
5106               match seq_of_test test with
5107               | [] ->
5108                   failwithf "%s has a test containing an empty sequence" name
5109               | cmds -> List.map List.hd cmds
5110           ) tests in
5111         let funcs = List.flatten funcs in
5112
5113         let tested = List.mem name funcs in
5114
5115         if not tested then
5116           failwithf "function %s has tests but does not test itself" name
5117   ) all_functions
5118
5119 (* 'pr' prints to the current output file. *)
5120 let chan = ref Pervasives.stdout
5121 let lines = ref 0
5122 let pr fs =
5123   ksprintf
5124     (fun str ->
5125        let i = count_chars '\n' str in
5126        lines := !lines + i;
5127        output_string !chan str
5128     ) fs
5129
5130 let copyright_years =
5131   let this_year = 1900 + (localtime (time ())).tm_year in
5132   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5133
5134 (* Generate a header block in a number of standard styles. *)
5135 type comment_style =
5136     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5137 type license = GPLv2plus | LGPLv2plus
5138
5139 let generate_header ?(extra_inputs = []) comment license =
5140   let inputs = "src/generator.ml" :: extra_inputs in
5141   let c = match comment with
5142     | CStyle ->         pr "/* "; " *"
5143     | CPlusPlusStyle -> pr "// "; "//"
5144     | HashStyle ->      pr "# ";  "#"
5145     | OCamlStyle ->     pr "(* "; " *"
5146     | HaskellStyle ->   pr "{- "; "  " in
5147   pr "libguestfs generated file\n";
5148   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5149   List.iter (pr "%s   %s\n" c) inputs;
5150   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5151   pr "%s\n" c;
5152   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5153   pr "%s\n" c;
5154   (match license with
5155    | GPLv2plus ->
5156        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5157        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5158        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5159        pr "%s (at your option) any later version.\n" c;
5160        pr "%s\n" c;
5161        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5162        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5163        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5164        pr "%s GNU General Public License for more details.\n" c;
5165        pr "%s\n" c;
5166        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5167        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5168        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5169
5170    | LGPLv2plus ->
5171        pr "%s This library is free software; you can redistribute it and/or\n" c;
5172        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5173        pr "%s License as published by the Free Software Foundation; either\n" c;
5174        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5175        pr "%s\n" c;
5176        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5177        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5178        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5179        pr "%s Lesser General Public License for more details.\n" c;
5180        pr "%s\n" c;
5181        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5182        pr "%s License along with this library; if not, write to the Free Software\n" c;
5183        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5184   );
5185   (match comment with
5186    | CStyle -> pr " */\n"
5187    | CPlusPlusStyle
5188    | HashStyle -> ()
5189    | OCamlStyle -> pr " *)\n"
5190    | HaskellStyle -> pr "-}\n"
5191   );
5192   pr "\n"
5193
5194 (* Start of main code generation functions below this line. *)
5195
5196 (* Generate the pod documentation for the C API. *)
5197 let rec generate_actions_pod () =
5198   List.iter (
5199     fun (shortname, style, _, flags, _, _, longdesc) ->
5200       if not (List.mem NotInDocs flags) then (
5201         let name = "guestfs_" ^ shortname in
5202         pr "=head2 %s\n\n" name;
5203         pr " ";
5204         generate_prototype ~extern:false ~handle:"g" name style;
5205         pr "\n\n";
5206         pr "%s\n\n" longdesc;
5207         (match fst style with
5208          | RErr ->
5209              pr "This function returns 0 on success or -1 on error.\n\n"
5210          | RInt _ ->
5211              pr "On error this function returns -1.\n\n"
5212          | RInt64 _ ->
5213              pr "On error this function returns -1.\n\n"
5214          | RBool _ ->
5215              pr "This function returns a C truth value on success or -1 on error.\n\n"
5216          | RConstString _ ->
5217              pr "This function returns a string, or NULL on error.
5218 The string is owned by the guest handle and must I<not> be freed.\n\n"
5219          | RConstOptString _ ->
5220              pr "This function returns a string which may be NULL.
5221 There is way to return an error from this function.
5222 The string is owned by the guest handle and must I<not> be freed.\n\n"
5223          | RString _ ->
5224              pr "This function returns a string, or NULL on error.
5225 I<The caller must free the returned string after use>.\n\n"
5226          | RStringList _ ->
5227              pr "This function returns a NULL-terminated array of strings
5228 (like L<environ(3)>), or NULL if there was an error.
5229 I<The caller must free the strings and the array after use>.\n\n"
5230          | RStruct (_, typ) ->
5231              pr "This function returns a C<struct guestfs_%s *>,
5232 or NULL if there was an error.
5233 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5234          | RStructList (_, typ) ->
5235              pr "This function returns a C<struct guestfs_%s_list *>
5236 (see E<lt>guestfs-structs.hE<gt>),
5237 or NULL if there was an error.
5238 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5239          | RHashtable _ ->
5240              pr "This function returns a NULL-terminated array of
5241 strings, or NULL if there was an error.
5242 The array of strings will always have length C<2n+1>, where
5243 C<n> keys and values alternate, followed by the trailing NULL entry.
5244 I<The caller must free the strings and the array after use>.\n\n"
5245          | RBufferOut _ ->
5246              pr "This function returns a buffer, or NULL on error.
5247 The size of the returned buffer is written to C<*size_r>.
5248 I<The caller must free the returned buffer after use>.\n\n"
5249         );
5250         if List.mem ProtocolLimitWarning flags then
5251           pr "%s\n\n" protocol_limit_warning;
5252         if List.mem DangerWillRobinson flags then
5253           pr "%s\n\n" danger_will_robinson;
5254         match deprecation_notice flags with
5255         | None -> ()
5256         | Some txt -> pr "%s\n\n" txt
5257       )
5258   ) all_functions_sorted
5259
5260 and generate_structs_pod () =
5261   (* Structs documentation. *)
5262   List.iter (
5263     fun (typ, cols) ->
5264       pr "=head2 guestfs_%s\n" typ;
5265       pr "\n";
5266       pr " struct guestfs_%s {\n" typ;
5267       List.iter (
5268         function
5269         | name, FChar -> pr "   char %s;\n" name
5270         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5271         | name, FInt32 -> pr "   int32_t %s;\n" name
5272         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5273         | name, FInt64 -> pr "   int64_t %s;\n" name
5274         | name, FString -> pr "   char *%s;\n" name
5275         | name, FBuffer ->
5276             pr "   /* The next two fields describe a byte array. */\n";
5277             pr "   uint32_t %s_len;\n" name;
5278             pr "   char *%s;\n" name
5279         | name, FUUID ->
5280             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5281             pr "   char %s[32];\n" name
5282         | name, FOptPercent ->
5283             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5284             pr "   float %s;\n" name
5285       ) cols;
5286       pr " };\n";
5287       pr " \n";
5288       pr " struct guestfs_%s_list {\n" typ;
5289       pr "   uint32_t len; /* Number of elements in list. */\n";
5290       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5291       pr " };\n";
5292       pr " \n";
5293       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5294       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5295         typ typ;
5296       pr "\n"
5297   ) structs
5298
5299 and generate_availability_pod () =
5300   (* Availability documentation. *)
5301   pr "=over 4\n";
5302   pr "\n";
5303   List.iter (
5304     fun (group, functions) ->
5305       pr "=item B<%s>\n" group;
5306       pr "\n";
5307       pr "The following functions:\n";
5308       List.iter (pr "L</guestfs_%s>\n") functions;
5309       pr "\n"
5310   ) optgroups;
5311   pr "=back\n";
5312   pr "\n"
5313
5314 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5315  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5316  *
5317  * We have to use an underscore instead of a dash because otherwise
5318  * rpcgen generates incorrect code.
5319  *
5320  * This header is NOT exported to clients, but see also generate_structs_h.
5321  *)
5322 and generate_xdr () =
5323   generate_header CStyle LGPLv2plus;
5324
5325   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5326   pr "typedef string str<>;\n";
5327   pr "\n";
5328
5329   (* Internal structures. *)
5330   List.iter (
5331     function
5332     | typ, cols ->
5333         pr "struct guestfs_int_%s {\n" typ;
5334         List.iter (function
5335                    | name, FChar -> pr "  char %s;\n" name
5336                    | name, FString -> pr "  string %s<>;\n" name
5337                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5338                    | name, FUUID -> pr "  opaque %s[32];\n" name
5339                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5340                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5341                    | name, FOptPercent -> pr "  float %s;\n" name
5342                   ) cols;
5343         pr "};\n";
5344         pr "\n";
5345         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5346         pr "\n";
5347   ) structs;
5348
5349   List.iter (
5350     fun (shortname, style, _, _, _, _, _) ->
5351       let name = "guestfs_" ^ shortname in
5352
5353       (match snd style with
5354        | [] -> ()
5355        | args ->
5356            pr "struct %s_args {\n" name;
5357            List.iter (
5358              function
5359              | Pathname n | Device n | Dev_or_Path n | String n ->
5360                  pr "  string %s<>;\n" n
5361              | OptString n -> pr "  str *%s;\n" n
5362              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5363              | Bool n -> pr "  bool %s;\n" n
5364              | Int n -> pr "  int %s;\n" n
5365              | Int64 n -> pr "  hyper %s;\n" n
5366              | FileIn _ | FileOut _ -> ()
5367            ) args;
5368            pr "};\n\n"
5369       );
5370       (match fst style with
5371        | RErr -> ()
5372        | RInt n ->
5373            pr "struct %s_ret {\n" name;
5374            pr "  int %s;\n" n;
5375            pr "};\n\n"
5376        | RInt64 n ->
5377            pr "struct %s_ret {\n" name;
5378            pr "  hyper %s;\n" n;
5379            pr "};\n\n"
5380        | RBool n ->
5381            pr "struct %s_ret {\n" name;
5382            pr "  bool %s;\n" n;
5383            pr "};\n\n"
5384        | RConstString _ | RConstOptString _ ->
5385            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5386        | RString n ->
5387            pr "struct %s_ret {\n" name;
5388            pr "  string %s<>;\n" n;
5389            pr "};\n\n"
5390        | RStringList n ->
5391            pr "struct %s_ret {\n" name;
5392            pr "  str %s<>;\n" n;
5393            pr "};\n\n"
5394        | RStruct (n, typ) ->
5395            pr "struct %s_ret {\n" name;
5396            pr "  guestfs_int_%s %s;\n" typ n;
5397            pr "};\n\n"
5398        | RStructList (n, typ) ->
5399            pr "struct %s_ret {\n" name;
5400            pr "  guestfs_int_%s_list %s;\n" typ n;
5401            pr "};\n\n"
5402        | RHashtable n ->
5403            pr "struct %s_ret {\n" name;
5404            pr "  str %s<>;\n" n;
5405            pr "};\n\n"
5406        | RBufferOut n ->
5407            pr "struct %s_ret {\n" name;
5408            pr "  opaque %s<>;\n" n;
5409            pr "};\n\n"
5410       );
5411   ) daemon_functions;
5412
5413   (* Table of procedure numbers. *)
5414   pr "enum guestfs_procedure {\n";
5415   List.iter (
5416     fun (shortname, _, proc_nr, _, _, _, _) ->
5417       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5418   ) daemon_functions;
5419   pr "  GUESTFS_PROC_NR_PROCS\n";
5420   pr "};\n";
5421   pr "\n";
5422
5423   (* Having to choose a maximum message size is annoying for several
5424    * reasons (it limits what we can do in the API), but it (a) makes
5425    * the protocol a lot simpler, and (b) provides a bound on the size
5426    * of the daemon which operates in limited memory space.
5427    *)
5428   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5429   pr "\n";
5430
5431   (* Message header, etc. *)
5432   pr "\
5433 /* The communication protocol is now documented in the guestfs(3)
5434  * manpage.
5435  */
5436
5437 const GUESTFS_PROGRAM = 0x2000F5F5;
5438 const GUESTFS_PROTOCOL_VERSION = 1;
5439
5440 /* These constants must be larger than any possible message length. */
5441 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5442 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5443
5444 enum guestfs_message_direction {
5445   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5446   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5447 };
5448
5449 enum guestfs_message_status {
5450   GUESTFS_STATUS_OK = 0,
5451   GUESTFS_STATUS_ERROR = 1
5452 };
5453
5454 const GUESTFS_ERROR_LEN = 256;
5455
5456 struct guestfs_message_error {
5457   string error_message<GUESTFS_ERROR_LEN>;
5458 };
5459
5460 struct guestfs_message_header {
5461   unsigned prog;                     /* GUESTFS_PROGRAM */
5462   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5463   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5464   guestfs_message_direction direction;
5465   unsigned serial;                   /* message serial number */
5466   guestfs_message_status status;
5467 };
5468
5469 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5470
5471 struct guestfs_chunk {
5472   int cancel;                        /* if non-zero, transfer is cancelled */
5473   /* data size is 0 bytes if the transfer has finished successfully */
5474   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5475 };
5476 "
5477
5478 (* Generate the guestfs-structs.h file. *)
5479 and generate_structs_h () =
5480   generate_header CStyle LGPLv2plus;
5481
5482   (* This is a public exported header file containing various
5483    * structures.  The structures are carefully written to have
5484    * exactly the same in-memory format as the XDR structures that
5485    * we use on the wire to the daemon.  The reason for creating
5486    * copies of these structures here is just so we don't have to
5487    * export the whole of guestfs_protocol.h (which includes much
5488    * unrelated and XDR-dependent stuff that we don't want to be
5489    * public, or required by clients).
5490    *
5491    * To reiterate, we will pass these structures to and from the
5492    * client with a simple assignment or memcpy, so the format
5493    * must be identical to what rpcgen / the RFC defines.
5494    *)
5495
5496   (* Public structures. *)
5497   List.iter (
5498     fun (typ, cols) ->
5499       pr "struct guestfs_%s {\n" typ;
5500       List.iter (
5501         function
5502         | name, FChar -> pr "  char %s;\n" name
5503         | name, FString -> pr "  char *%s;\n" name
5504         | name, FBuffer ->
5505             pr "  uint32_t %s_len;\n" name;
5506             pr "  char *%s;\n" name
5507         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5508         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5509         | name, FInt32 -> pr "  int32_t %s;\n" name
5510         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5511         | name, FInt64 -> pr "  int64_t %s;\n" name
5512         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5513       ) cols;
5514       pr "};\n";
5515       pr "\n";
5516       pr "struct guestfs_%s_list {\n" typ;
5517       pr "  uint32_t len;\n";
5518       pr "  struct guestfs_%s *val;\n" typ;
5519       pr "};\n";
5520       pr "\n";
5521       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5522       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5523       pr "\n"
5524   ) structs
5525
5526 (* Generate the guestfs-actions.h file. *)
5527 and generate_actions_h () =
5528   generate_header CStyle LGPLv2plus;
5529   List.iter (
5530     fun (shortname, style, _, _, _, _, _) ->
5531       let name = "guestfs_" ^ shortname in
5532       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5533         name style
5534   ) all_functions
5535
5536 (* Generate the guestfs-internal-actions.h file. *)
5537 and generate_internal_actions_h () =
5538   generate_header CStyle LGPLv2plus;
5539   List.iter (
5540     fun (shortname, style, _, _, _, _, _) ->
5541       let name = "guestfs__" ^ shortname in
5542       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5543         name style
5544   ) non_daemon_functions
5545
5546 (* Generate the client-side dispatch stubs. *)
5547 and generate_client_actions () =
5548   generate_header CStyle LGPLv2plus;
5549
5550   pr "\
5551 #include <stdio.h>
5552 #include <stdlib.h>
5553 #include <stdint.h>
5554 #include <string.h>
5555 #include <inttypes.h>
5556
5557 #include \"guestfs.h\"
5558 #include \"guestfs-internal.h\"
5559 #include \"guestfs-internal-actions.h\"
5560 #include \"guestfs_protocol.h\"
5561
5562 #define error guestfs_error
5563 //#define perrorf guestfs_perrorf
5564 #define safe_malloc guestfs_safe_malloc
5565 #define safe_realloc guestfs_safe_realloc
5566 //#define safe_strdup guestfs_safe_strdup
5567 #define safe_memdup guestfs_safe_memdup
5568
5569 /* Check the return message from a call for validity. */
5570 static int
5571 check_reply_header (guestfs_h *g,
5572                     const struct guestfs_message_header *hdr,
5573                     unsigned int proc_nr, unsigned int serial)
5574 {
5575   if (hdr->prog != GUESTFS_PROGRAM) {
5576     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5577     return -1;
5578   }
5579   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5580     error (g, \"wrong protocol version (%%d/%%d)\",
5581            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5582     return -1;
5583   }
5584   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5585     error (g, \"unexpected message direction (%%d/%%d)\",
5586            hdr->direction, GUESTFS_DIRECTION_REPLY);
5587     return -1;
5588   }
5589   if (hdr->proc != proc_nr) {
5590     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5591     return -1;
5592   }
5593   if (hdr->serial != serial) {
5594     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5595     return -1;
5596   }
5597
5598   return 0;
5599 }
5600
5601 /* Check we are in the right state to run a high-level action. */
5602 static int
5603 check_state (guestfs_h *g, const char *caller)
5604 {
5605   if (!guestfs__is_ready (g)) {
5606     if (guestfs__is_config (g) || guestfs__is_launching (g))
5607       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5608         caller);
5609     else
5610       error (g, \"%%s called from the wrong state, %%d != READY\",
5611         caller, guestfs__get_state (g));
5612     return -1;
5613   }
5614   return 0;
5615 }
5616
5617 ";
5618
5619   (* Generate code to generate guestfish call traces. *)
5620   let trace_call shortname style =
5621     pr "  if (guestfs__get_trace (g)) {\n";
5622
5623     let needs_i =
5624       List.exists (function
5625                    | StringList _ | DeviceList _ -> true
5626                    | _ -> false) (snd style) in
5627     if needs_i then (
5628       pr "    int i;\n";
5629       pr "\n"
5630     );
5631
5632     pr "    printf (\"%s\");\n" shortname;
5633     List.iter (
5634       function
5635       | String n                        (* strings *)
5636       | Device n
5637       | Pathname n
5638       | Dev_or_Path n
5639       | FileIn n
5640       | FileOut n ->
5641           (* guestfish doesn't support string escaping, so neither do we *)
5642           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5643       | OptString n ->                  (* string option *)
5644           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5645           pr "    else printf (\" null\");\n"
5646       | StringList n
5647       | DeviceList n ->                 (* string list *)
5648           pr "    putchar (' ');\n";
5649           pr "    putchar ('\"');\n";
5650           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5651           pr "      if (i > 0) putchar (' ');\n";
5652           pr "      fputs (%s[i], stdout);\n" n;
5653           pr "    }\n";
5654           pr "    putchar ('\"');\n";
5655       | Bool n ->                       (* boolean *)
5656           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5657       | Int n ->                        (* int *)
5658           pr "    printf (\" %%d\", %s);\n" n
5659       | Int64 n ->
5660           pr "    printf (\" %%\" PRIi64, %s);\n" n
5661     ) (snd style);
5662     pr "    putchar ('\\n');\n";
5663     pr "  }\n";
5664     pr "\n";
5665   in
5666
5667   (* For non-daemon functions, generate a wrapper around each function. *)
5668   List.iter (
5669     fun (shortname, style, _, _, _, _, _) ->
5670       let name = "guestfs_" ^ shortname in
5671
5672       generate_prototype ~extern:false ~semicolon:false ~newline:true
5673         ~handle:"g" name style;
5674       pr "{\n";
5675       trace_call shortname style;
5676       pr "  return guestfs__%s " shortname;
5677       generate_c_call_args ~handle:"g" style;
5678       pr ";\n";
5679       pr "}\n";
5680       pr "\n"
5681   ) non_daemon_functions;
5682
5683   (* Client-side stubs for each function. *)
5684   List.iter (
5685     fun (shortname, style, _, _, _, _, _) ->
5686       let name = "guestfs_" ^ shortname in
5687
5688       (* Generate the action stub. *)
5689       generate_prototype ~extern:false ~semicolon:false ~newline:true
5690         ~handle:"g" name style;
5691
5692       let error_code =
5693         match fst style with
5694         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5695         | RConstString _ | RConstOptString _ ->
5696             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5697         | RString _ | RStringList _
5698         | RStruct _ | RStructList _
5699         | RHashtable _ | RBufferOut _ ->
5700             "NULL" in
5701
5702       pr "{\n";
5703
5704       (match snd style with
5705        | [] -> ()
5706        | _ -> pr "  struct %s_args args;\n" name
5707       );
5708
5709       pr "  guestfs_message_header hdr;\n";
5710       pr "  guestfs_message_error err;\n";
5711       let has_ret =
5712         match fst style with
5713         | RErr -> false
5714         | RConstString _ | RConstOptString _ ->
5715             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5716         | RInt _ | RInt64 _
5717         | RBool _ | RString _ | RStringList _
5718         | RStruct _ | RStructList _
5719         | RHashtable _ | RBufferOut _ ->
5720             pr "  struct %s_ret ret;\n" name;
5721             true in
5722
5723       pr "  int serial;\n";
5724       pr "  int r;\n";
5725       pr "\n";
5726       trace_call shortname style;
5727       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5728       pr "  guestfs___set_busy (g);\n";
5729       pr "\n";
5730
5731       (* Send the main header and arguments. *)
5732       (match snd style with
5733        | [] ->
5734            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5735              (String.uppercase shortname)
5736        | args ->
5737            List.iter (
5738              function
5739              | Pathname n | Device n | Dev_or_Path n | String n ->
5740                  pr "  args.%s = (char *) %s;\n" n n
5741              | OptString n ->
5742                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5743              | StringList n | DeviceList n ->
5744                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5745                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5746              | Bool n ->
5747                  pr "  args.%s = %s;\n" n n
5748              | Int n ->
5749                  pr "  args.%s = %s;\n" n n
5750              | Int64 n ->
5751                  pr "  args.%s = %s;\n" n n
5752              | FileIn _ | FileOut _ -> ()
5753            ) args;
5754            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5755              (String.uppercase shortname);
5756            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5757              name;
5758       );
5759       pr "  if (serial == -1) {\n";
5760       pr "    guestfs___end_busy (g);\n";
5761       pr "    return %s;\n" error_code;
5762       pr "  }\n";
5763       pr "\n";
5764
5765       (* Send any additional files (FileIn) requested. *)
5766       let need_read_reply_label = ref false in
5767       List.iter (
5768         function
5769         | FileIn n ->
5770             pr "  r = guestfs___send_file (g, %s);\n" n;
5771             pr "  if (r == -1) {\n";
5772             pr "    guestfs___end_busy (g);\n";
5773             pr "    return %s;\n" error_code;
5774             pr "  }\n";
5775             pr "  if (r == -2) /* daemon cancelled */\n";
5776             pr "    goto read_reply;\n";
5777             need_read_reply_label := true;
5778             pr "\n";
5779         | _ -> ()
5780       ) (snd style);
5781
5782       (* Wait for the reply from the remote end. *)
5783       if !need_read_reply_label then pr " read_reply:\n";
5784       pr "  memset (&hdr, 0, sizeof hdr);\n";
5785       pr "  memset (&err, 0, sizeof err);\n";
5786       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5787       pr "\n";
5788       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5789       if not has_ret then
5790         pr "NULL, NULL"
5791       else
5792         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5793       pr ");\n";
5794
5795       pr "  if (r == -1) {\n";
5796       pr "    guestfs___end_busy (g);\n";
5797       pr "    return %s;\n" error_code;
5798       pr "  }\n";
5799       pr "\n";
5800
5801       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5802         (String.uppercase shortname);
5803       pr "    guestfs___end_busy (g);\n";
5804       pr "    return %s;\n" error_code;
5805       pr "  }\n";
5806       pr "\n";
5807
5808       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5809       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5810       pr "    free (err.error_message);\n";
5811       pr "    guestfs___end_busy (g);\n";
5812       pr "    return %s;\n" error_code;
5813       pr "  }\n";
5814       pr "\n";
5815
5816       (* Expecting to receive further files (FileOut)? *)
5817       List.iter (
5818         function
5819         | FileOut n ->
5820             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5821             pr "    guestfs___end_busy (g);\n";
5822             pr "    return %s;\n" error_code;
5823             pr "  }\n";
5824             pr "\n";
5825         | _ -> ()
5826       ) (snd style);
5827
5828       pr "  guestfs___end_busy (g);\n";
5829
5830       (match fst style with
5831        | RErr -> pr "  return 0;\n"
5832        | RInt n | RInt64 n | RBool n ->
5833            pr "  return ret.%s;\n" n
5834        | RConstString _ | RConstOptString _ ->
5835            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5836        | RString n ->
5837            pr "  return ret.%s; /* caller will free */\n" n
5838        | RStringList n | RHashtable n ->
5839            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5840            pr "  ret.%s.%s_val =\n" n n;
5841            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5842            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5843              n n;
5844            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5845            pr "  return ret.%s.%s_val;\n" n n
5846        | RStruct (n, _) ->
5847            pr "  /* caller will free this */\n";
5848            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5849        | RStructList (n, _) ->
5850            pr "  /* caller will free this */\n";
5851            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5852        | RBufferOut n ->
5853            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5854            pr "   * _val might be NULL here.  To make the API saner for\n";
5855            pr "   * callers, we turn this case into a unique pointer (using\n";
5856            pr "   * malloc(1)).\n";
5857            pr "   */\n";
5858            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5859            pr "    *size_r = ret.%s.%s_len;\n" n n;
5860            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5861            pr "  } else {\n";
5862            pr "    free (ret.%s.%s_val);\n" n n;
5863            pr "    char *p = safe_malloc (g, 1);\n";
5864            pr "    *size_r = ret.%s.%s_len;\n" n n;
5865            pr "    return p;\n";
5866            pr "  }\n";
5867       );
5868
5869       pr "}\n\n"
5870   ) daemon_functions;
5871
5872   (* Functions to free structures. *)
5873   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5874   pr " * structure format is identical to the XDR format.  See note in\n";
5875   pr " * generator.ml.\n";
5876   pr " */\n";
5877   pr "\n";
5878
5879   List.iter (
5880     fun (typ, _) ->
5881       pr "void\n";
5882       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5883       pr "{\n";
5884       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5885       pr "  free (x);\n";
5886       pr "}\n";
5887       pr "\n";
5888
5889       pr "void\n";
5890       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5891       pr "{\n";
5892       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5893       pr "  free (x);\n";
5894       pr "}\n";
5895       pr "\n";
5896
5897   ) structs;
5898
5899 (* Generate daemon/actions.h. *)
5900 and generate_daemon_actions_h () =
5901   generate_header CStyle GPLv2plus;
5902
5903   pr "#include \"../src/guestfs_protocol.h\"\n";
5904   pr "\n";
5905
5906   List.iter (
5907     fun (name, style, _, _, _, _, _) ->
5908       generate_prototype
5909         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5910         name style;
5911   ) daemon_functions
5912
5913 (* Generate the linker script which controls the visibility of
5914  * symbols in the public ABI and ensures no other symbols get
5915  * exported accidentally.
5916  *)
5917 and generate_linker_script () =
5918   generate_header HashStyle GPLv2plus;
5919
5920   let globals = [
5921     "guestfs_create";
5922     "guestfs_close";
5923     "guestfs_get_error_handler";
5924     "guestfs_get_out_of_memory_handler";
5925     "guestfs_last_error";
5926     "guestfs_set_error_handler";
5927     "guestfs_set_launch_done_callback";
5928     "guestfs_set_log_message_callback";
5929     "guestfs_set_out_of_memory_handler";
5930     "guestfs_set_subprocess_quit_callback";
5931
5932     (* Unofficial parts of the API: the bindings code use these
5933      * functions, so it is useful to export them.
5934      *)
5935     "guestfs_safe_calloc";
5936     "guestfs_safe_malloc";
5937   ] in
5938   let functions =
5939     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5940       all_functions in
5941   let structs =
5942     List.concat (
5943       List.map (fun (typ, _) ->
5944                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5945         structs
5946     ) in
5947   let globals = List.sort compare (globals @ functions @ structs) in
5948
5949   pr "{\n";
5950   pr "    global:\n";
5951   List.iter (pr "        %s;\n") globals;
5952   pr "\n";
5953
5954   pr "    local:\n";
5955   pr "        *;\n";
5956   pr "};\n"
5957
5958 (* Generate the server-side stubs. *)
5959 and generate_daemon_actions () =
5960   generate_header CStyle GPLv2plus;
5961
5962   pr "#include <config.h>\n";
5963   pr "\n";
5964   pr "#include <stdio.h>\n";
5965   pr "#include <stdlib.h>\n";
5966   pr "#include <string.h>\n";
5967   pr "#include <inttypes.h>\n";
5968   pr "#include <rpc/types.h>\n";
5969   pr "#include <rpc/xdr.h>\n";
5970   pr "\n";
5971   pr "#include \"daemon.h\"\n";
5972   pr "#include \"c-ctype.h\"\n";
5973   pr "#include \"../src/guestfs_protocol.h\"\n";
5974   pr "#include \"actions.h\"\n";
5975   pr "\n";
5976
5977   List.iter (
5978     fun (name, style, _, _, _, _, _) ->
5979       (* Generate server-side stubs. *)
5980       pr "static void %s_stub (XDR *xdr_in)\n" name;
5981       pr "{\n";
5982       let error_code =
5983         match fst style with
5984         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5985         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5986         | RBool _ -> pr "  int r;\n"; "-1"
5987         | RConstString _ | RConstOptString _ ->
5988             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5989         | RString _ -> pr "  char *r;\n"; "NULL"
5990         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5991         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5992         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5993         | RBufferOut _ ->
5994             pr "  size_t size = 1;\n";
5995             pr "  char *r;\n";
5996             "NULL" in
5997
5998       (match snd style with
5999        | [] -> ()
6000        | args ->
6001            pr "  struct guestfs_%s_args args;\n" name;
6002            List.iter (
6003              function
6004              | Device n | Dev_or_Path n
6005              | Pathname n
6006              | String n -> ()
6007              | OptString n -> pr "  char *%s;\n" n
6008              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6009              | Bool n -> pr "  int %s;\n" n
6010              | Int n -> pr "  int %s;\n" n
6011              | Int64 n -> pr "  int64_t %s;\n" n
6012              | FileIn _ | FileOut _ -> ()
6013            ) args
6014       );
6015       pr "\n";
6016
6017       (match snd style with
6018        | [] -> ()
6019        | args ->
6020            pr "  memset (&args, 0, sizeof args);\n";
6021            pr "\n";
6022            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6023            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6024            pr "    return;\n";
6025            pr "  }\n";
6026            let pr_args n =
6027              pr "  char *%s = args.%s;\n" n n
6028            in
6029            let pr_list_handling_code n =
6030              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6031              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6032              pr "  if (%s == NULL) {\n" n;
6033              pr "    reply_with_perror (\"realloc\");\n";
6034              pr "    goto done;\n";
6035              pr "  }\n";
6036              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6037              pr "  args.%s.%s_val = %s;\n" n n n;
6038            in
6039            List.iter (
6040              function
6041              | Pathname n ->
6042                  pr_args n;
6043                  pr "  ABS_PATH (%s, goto done);\n" n;
6044              | Device n ->
6045                  pr_args n;
6046                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6047              | Dev_or_Path n ->
6048                  pr_args n;
6049                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6050              | String n -> pr_args n
6051              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6052              | StringList n ->
6053                  pr_list_handling_code n;
6054              | DeviceList n ->
6055                  pr_list_handling_code n;
6056                  pr "  /* Ensure that each is a device,\n";
6057                  pr "   * and perform device name translation. */\n";
6058                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6059                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6060                  pr "  }\n";
6061              | Bool n -> pr "  %s = args.%s;\n" n n
6062              | Int n -> pr "  %s = args.%s;\n" n n
6063              | Int64 n -> pr "  %s = args.%s;\n" n n
6064              | FileIn _ | FileOut _ -> ()
6065            ) args;
6066            pr "\n"
6067       );
6068
6069
6070       (* this is used at least for do_equal *)
6071       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6072         (* Emit NEED_ROOT just once, even when there are two or
6073            more Pathname args *)
6074         pr "  NEED_ROOT (goto done);\n";
6075       );
6076
6077       (* Don't want to call the impl with any FileIn or FileOut
6078        * parameters, since these go "outside" the RPC protocol.
6079        *)
6080       let args' =
6081         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6082           (snd style) in
6083       pr "  r = do_%s " name;
6084       generate_c_call_args (fst style, args');
6085       pr ";\n";
6086
6087       (match fst style with
6088        | RErr | RInt _ | RInt64 _ | RBool _
6089        | RConstString _ | RConstOptString _
6090        | RString _ | RStringList _ | RHashtable _
6091        | RStruct (_, _) | RStructList (_, _) ->
6092            pr "  if (r == %s)\n" error_code;
6093            pr "    /* do_%s has already called reply_with_error */\n" name;
6094            pr "    goto done;\n";
6095            pr "\n"
6096        | RBufferOut _ ->
6097            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6098            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6099            pr "   */\n";
6100            pr "  if (size == 1 && r == %s)\n" error_code;
6101            pr "    /* do_%s has already called reply_with_error */\n" name;
6102            pr "    goto done;\n";
6103            pr "\n"
6104       );
6105
6106       (* If there are any FileOut parameters, then the impl must
6107        * send its own reply.
6108        *)
6109       let no_reply =
6110         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6111       if no_reply then
6112         pr "  /* do_%s has already sent a reply */\n" name
6113       else (
6114         match fst style with
6115         | RErr -> pr "  reply (NULL, NULL);\n"
6116         | RInt n | RInt64 n | RBool n ->
6117             pr "  struct guestfs_%s_ret ret;\n" name;
6118             pr "  ret.%s = r;\n" n;
6119             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6120               name
6121         | RConstString _ | RConstOptString _ ->
6122             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6123         | RString n ->
6124             pr "  struct guestfs_%s_ret ret;\n" name;
6125             pr "  ret.%s = r;\n" n;
6126             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6127               name;
6128             pr "  free (r);\n"
6129         | RStringList n | RHashtable n ->
6130             pr "  struct guestfs_%s_ret ret;\n" name;
6131             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6132             pr "  ret.%s.%s_val = r;\n" n n;
6133             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6134               name;
6135             pr "  free_strings (r);\n"
6136         | RStruct (n, _) ->
6137             pr "  struct guestfs_%s_ret ret;\n" name;
6138             pr "  ret.%s = *r;\n" n;
6139             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6140               name;
6141             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6142               name
6143         | RStructList (n, _) ->
6144             pr "  struct guestfs_%s_ret ret;\n" name;
6145             pr "  ret.%s = *r;\n" n;
6146             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6147               name;
6148             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6149               name
6150         | RBufferOut n ->
6151             pr "  struct guestfs_%s_ret ret;\n" name;
6152             pr "  ret.%s.%s_val = r;\n" n n;
6153             pr "  ret.%s.%s_len = size;\n" n n;
6154             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6155               name;
6156             pr "  free (r);\n"
6157       );
6158
6159       (* Free the args. *)
6160       (match snd style with
6161        | [] ->
6162            pr "done: ;\n";
6163        | _ ->
6164            pr "done:\n";
6165            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6166              name
6167       );
6168
6169       pr "}\n\n";
6170   ) daemon_functions;
6171
6172   (* Dispatch function. *)
6173   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6174   pr "{\n";
6175   pr "  switch (proc_nr) {\n";
6176
6177   List.iter (
6178     fun (name, style, _, _, _, _, _) ->
6179       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6180       pr "      %s_stub (xdr_in);\n" name;
6181       pr "      break;\n"
6182   ) daemon_functions;
6183
6184   pr "    default:\n";
6185   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";
6186   pr "  }\n";
6187   pr "}\n";
6188   pr "\n";
6189
6190   (* LVM columns and tokenization functions. *)
6191   (* XXX This generates crap code.  We should rethink how we
6192    * do this parsing.
6193    *)
6194   List.iter (
6195     function
6196     | typ, cols ->
6197         pr "static const char *lvm_%s_cols = \"%s\";\n"
6198           typ (String.concat "," (List.map fst cols));
6199         pr "\n";
6200
6201         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6202         pr "{\n";
6203         pr "  char *tok, *p, *next;\n";
6204         pr "  int i, j;\n";
6205         pr "\n";
6206         (*
6207           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6208           pr "\n";
6209         *)
6210         pr "  if (!str) {\n";
6211         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6212         pr "    return -1;\n";
6213         pr "  }\n";
6214         pr "  if (!*str || c_isspace (*str)) {\n";
6215         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6216         pr "    return -1;\n";
6217         pr "  }\n";
6218         pr "  tok = str;\n";
6219         List.iter (
6220           fun (name, coltype) ->
6221             pr "  if (!tok) {\n";
6222             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6223             pr "    return -1;\n";
6224             pr "  }\n";
6225             pr "  p = strchrnul (tok, ',');\n";
6226             pr "  if (*p) next = p+1; else next = NULL;\n";
6227             pr "  *p = '\\0';\n";
6228             (match coltype with
6229              | FString ->
6230                  pr "  r->%s = strdup (tok);\n" name;
6231                  pr "  if (r->%s == NULL) {\n" name;
6232                  pr "    perror (\"strdup\");\n";
6233                  pr "    return -1;\n";
6234                  pr "  }\n"
6235              | FUUID ->
6236                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6237                  pr "    if (tok[j] == '\\0') {\n";
6238                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6239                  pr "      return -1;\n";
6240                  pr "    } else if (tok[j] != '-')\n";
6241                  pr "      r->%s[i++] = tok[j];\n" name;
6242                  pr "  }\n";
6243              | FBytes ->
6244                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6245                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6246                  pr "    return -1;\n";
6247                  pr "  }\n";
6248              | FInt64 ->
6249                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6250                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6251                  pr "    return -1;\n";
6252                  pr "  }\n";
6253              | FOptPercent ->
6254                  pr "  if (tok[0] == '\\0')\n";
6255                  pr "    r->%s = -1;\n" name;
6256                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6257                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6258                  pr "    return -1;\n";
6259                  pr "  }\n";
6260              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6261                  assert false (* can never be an LVM column *)
6262             );
6263             pr "  tok = next;\n";
6264         ) cols;
6265
6266         pr "  if (tok != NULL) {\n";
6267         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6268         pr "    return -1;\n";
6269         pr "  }\n";
6270         pr "  return 0;\n";
6271         pr "}\n";
6272         pr "\n";
6273
6274         pr "guestfs_int_lvm_%s_list *\n" typ;
6275         pr "parse_command_line_%ss (void)\n" typ;
6276         pr "{\n";
6277         pr "  char *out, *err;\n";
6278         pr "  char *p, *pend;\n";
6279         pr "  int r, i;\n";
6280         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6281         pr "  void *newp;\n";
6282         pr "\n";
6283         pr "  ret = malloc (sizeof *ret);\n";
6284         pr "  if (!ret) {\n";
6285         pr "    reply_with_perror (\"malloc\");\n";
6286         pr "    return NULL;\n";
6287         pr "  }\n";
6288         pr "\n";
6289         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6290         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6291         pr "\n";
6292         pr "  r = command (&out, &err,\n";
6293         pr "           \"lvm\", \"%ss\",\n" typ;
6294         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6295         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6296         pr "  if (r == -1) {\n";
6297         pr "    reply_with_error (\"%%s\", err);\n";
6298         pr "    free (out);\n";
6299         pr "    free (err);\n";
6300         pr "    free (ret);\n";
6301         pr "    return NULL;\n";
6302         pr "  }\n";
6303         pr "\n";
6304         pr "  free (err);\n";
6305         pr "\n";
6306         pr "  /* Tokenize each line of the output. */\n";
6307         pr "  p = out;\n";
6308         pr "  i = 0;\n";
6309         pr "  while (p) {\n";
6310         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6311         pr "    if (pend) {\n";
6312         pr "      *pend = '\\0';\n";
6313         pr "      pend++;\n";
6314         pr "    }\n";
6315         pr "\n";
6316         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6317         pr "      p++;\n";
6318         pr "\n";
6319         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6320         pr "      p = pend;\n";
6321         pr "      continue;\n";
6322         pr "    }\n";
6323         pr "\n";
6324         pr "    /* Allocate some space to store this next entry. */\n";
6325         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6326         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6327         pr "    if (newp == NULL) {\n";
6328         pr "      reply_with_perror (\"realloc\");\n";
6329         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6330         pr "      free (ret);\n";
6331         pr "      free (out);\n";
6332         pr "      return NULL;\n";
6333         pr "    }\n";
6334         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6335         pr "\n";
6336         pr "    /* Tokenize the next entry. */\n";
6337         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6338         pr "    if (r == -1) {\n";
6339         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6340         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6341         pr "      free (ret);\n";
6342         pr "      free (out);\n";
6343         pr "      return NULL;\n";
6344         pr "    }\n";
6345         pr "\n";
6346         pr "    ++i;\n";
6347         pr "    p = pend;\n";
6348         pr "  }\n";
6349         pr "\n";
6350         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6351         pr "\n";
6352         pr "  free (out);\n";
6353         pr "  return ret;\n";
6354         pr "}\n"
6355
6356   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6357
6358 (* Generate a list of function names, for debugging in the daemon.. *)
6359 and generate_daemon_names () =
6360   generate_header CStyle GPLv2plus;
6361
6362   pr "#include <config.h>\n";
6363   pr "\n";
6364   pr "#include \"daemon.h\"\n";
6365   pr "\n";
6366
6367   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6368   pr "const char *function_names[] = {\n";
6369   List.iter (
6370     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6371   ) daemon_functions;
6372   pr "};\n";
6373
6374 (* Generate the optional groups for the daemon to implement
6375  * guestfs_available.
6376  *)
6377 and generate_daemon_optgroups_c () =
6378   generate_header CStyle GPLv2plus;
6379
6380   pr "#include <config.h>\n";
6381   pr "\n";
6382   pr "#include \"daemon.h\"\n";
6383   pr "#include \"optgroups.h\"\n";
6384   pr "\n";
6385
6386   pr "struct optgroup optgroups[] = {\n";
6387   List.iter (
6388     fun (group, _) ->
6389       pr "  { \"%s\", optgroup_%s_available },\n" group group
6390   ) optgroups;
6391   pr "  { NULL, NULL }\n";
6392   pr "};\n"
6393
6394 and generate_daemon_optgroups_h () =
6395   generate_header CStyle GPLv2plus;
6396
6397   List.iter (
6398     fun (group, _) ->
6399       pr "extern int optgroup_%s_available (void);\n" group
6400   ) optgroups
6401
6402 (* Generate the tests. *)
6403 and generate_tests () =
6404   generate_header CStyle GPLv2plus;
6405
6406   pr "\
6407 #include <stdio.h>
6408 #include <stdlib.h>
6409 #include <string.h>
6410 #include <unistd.h>
6411 #include <sys/types.h>
6412 #include <fcntl.h>
6413
6414 #include \"guestfs.h\"
6415 #include \"guestfs-internal.h\"
6416
6417 static guestfs_h *g;
6418 static int suppress_error = 0;
6419
6420 static void print_error (guestfs_h *g, void *data, const char *msg)
6421 {
6422   if (!suppress_error)
6423     fprintf (stderr, \"%%s\\n\", msg);
6424 }
6425
6426 /* FIXME: nearly identical code appears in fish.c */
6427 static void print_strings (char *const *argv)
6428 {
6429   int argc;
6430
6431   for (argc = 0; argv[argc] != NULL; ++argc)
6432     printf (\"\\t%%s\\n\", argv[argc]);
6433 }
6434
6435 /*
6436 static void print_table (char const *const *argv)
6437 {
6438   int i;
6439
6440   for (i = 0; argv[i] != NULL; i += 2)
6441     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6442 }
6443 */
6444
6445 ";
6446
6447   (* Generate a list of commands which are not tested anywhere. *)
6448   pr "static void no_test_warnings (void)\n";
6449   pr "{\n";
6450
6451   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6452   List.iter (
6453     fun (_, _, _, _, tests, _, _) ->
6454       let tests = filter_map (
6455         function
6456         | (_, (Always|If _|Unless _), test) -> Some test
6457         | (_, Disabled, _) -> None
6458       ) tests in
6459       let seq = List.concat (List.map seq_of_test tests) in
6460       let cmds_tested = List.map List.hd seq in
6461       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6462   ) all_functions;
6463
6464   List.iter (
6465     fun (name, _, _, _, _, _, _) ->
6466       if not (Hashtbl.mem hash name) then
6467         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6468   ) all_functions;
6469
6470   pr "}\n";
6471   pr "\n";
6472
6473   (* Generate the actual tests.  Note that we generate the tests
6474    * in reverse order, deliberately, so that (in general) the
6475    * newest tests run first.  This makes it quicker and easier to
6476    * debug them.
6477    *)
6478   let test_names =
6479     List.map (
6480       fun (name, _, _, flags, tests, _, _) ->
6481         mapi (generate_one_test name flags) tests
6482     ) (List.rev all_functions) in
6483   let test_names = List.concat test_names in
6484   let nr_tests = List.length test_names in
6485
6486   pr "\
6487 int main (int argc, char *argv[])
6488 {
6489   char c = 0;
6490   unsigned long int n_failed = 0;
6491   const char *filename;
6492   int fd;
6493   int nr_tests, test_num = 0;
6494
6495   setbuf (stdout, NULL);
6496
6497   no_test_warnings ();
6498
6499   g = guestfs_create ();
6500   if (g == NULL) {
6501     printf (\"guestfs_create FAILED\\n\");
6502     exit (EXIT_FAILURE);
6503   }
6504
6505   guestfs_set_error_handler (g, print_error, NULL);
6506
6507   guestfs_set_path (g, \"../appliance\");
6508
6509   filename = \"test1.img\";
6510   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6511   if (fd == -1) {
6512     perror (filename);
6513     exit (EXIT_FAILURE);
6514   }
6515   if (lseek (fd, %d, SEEK_SET) == -1) {
6516     perror (\"lseek\");
6517     close (fd);
6518     unlink (filename);
6519     exit (EXIT_FAILURE);
6520   }
6521   if (write (fd, &c, 1) == -1) {
6522     perror (\"write\");
6523     close (fd);
6524     unlink (filename);
6525     exit (EXIT_FAILURE);
6526   }
6527   if (close (fd) == -1) {
6528     perror (filename);
6529     unlink (filename);
6530     exit (EXIT_FAILURE);
6531   }
6532   if (guestfs_add_drive (g, filename) == -1) {
6533     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6534     exit (EXIT_FAILURE);
6535   }
6536
6537   filename = \"test2.img\";
6538   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6539   if (fd == -1) {
6540     perror (filename);
6541     exit (EXIT_FAILURE);
6542   }
6543   if (lseek (fd, %d, SEEK_SET) == -1) {
6544     perror (\"lseek\");
6545     close (fd);
6546     unlink (filename);
6547     exit (EXIT_FAILURE);
6548   }
6549   if (write (fd, &c, 1) == -1) {
6550     perror (\"write\");
6551     close (fd);
6552     unlink (filename);
6553     exit (EXIT_FAILURE);
6554   }
6555   if (close (fd) == -1) {
6556     perror (filename);
6557     unlink (filename);
6558     exit (EXIT_FAILURE);
6559   }
6560   if (guestfs_add_drive (g, filename) == -1) {
6561     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6562     exit (EXIT_FAILURE);
6563   }
6564
6565   filename = \"test3.img\";
6566   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6567   if (fd == -1) {
6568     perror (filename);
6569     exit (EXIT_FAILURE);
6570   }
6571   if (lseek (fd, %d, SEEK_SET) == -1) {
6572     perror (\"lseek\");
6573     close (fd);
6574     unlink (filename);
6575     exit (EXIT_FAILURE);
6576   }
6577   if (write (fd, &c, 1) == -1) {
6578     perror (\"write\");
6579     close (fd);
6580     unlink (filename);
6581     exit (EXIT_FAILURE);
6582   }
6583   if (close (fd) == -1) {
6584     perror (filename);
6585     unlink (filename);
6586     exit (EXIT_FAILURE);
6587   }
6588   if (guestfs_add_drive (g, filename) == -1) {
6589     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6590     exit (EXIT_FAILURE);
6591   }
6592
6593   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6594     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6595     exit (EXIT_FAILURE);
6596   }
6597
6598   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6599   alarm (600);
6600
6601   if (guestfs_launch (g) == -1) {
6602     printf (\"guestfs_launch FAILED\\n\");
6603     exit (EXIT_FAILURE);
6604   }
6605
6606   /* Cancel previous alarm. */
6607   alarm (0);
6608
6609   nr_tests = %d;
6610
6611 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6612
6613   iteri (
6614     fun i test_name ->
6615       pr "  test_num++;\n";
6616       pr "  if (guestfs_get_verbose (g))\n";
6617       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6618       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6619       pr "  if (%s () == -1) {\n" test_name;
6620       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6621       pr "    n_failed++;\n";
6622       pr "  }\n";
6623   ) test_names;
6624   pr "\n";
6625
6626   pr "  guestfs_close (g);\n";
6627   pr "  unlink (\"test1.img\");\n";
6628   pr "  unlink (\"test2.img\");\n";
6629   pr "  unlink (\"test3.img\");\n";
6630   pr "\n";
6631
6632   pr "  if (n_failed > 0) {\n";
6633   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6634   pr "    exit (EXIT_FAILURE);\n";
6635   pr "  }\n";
6636   pr "\n";
6637
6638   pr "  exit (EXIT_SUCCESS);\n";
6639   pr "}\n"
6640
6641 and generate_one_test name flags i (init, prereq, test) =
6642   let test_name = sprintf "test_%s_%d" name i in
6643
6644   pr "\
6645 static int %s_skip (void)
6646 {
6647   const char *str;
6648
6649   str = getenv (\"TEST_ONLY\");
6650   if (str)
6651     return strstr (str, \"%s\") == NULL;
6652   str = getenv (\"SKIP_%s\");
6653   if (str && STREQ (str, \"1\")) return 1;
6654   str = getenv (\"SKIP_TEST_%s\");
6655   if (str && STREQ (str, \"1\")) return 1;
6656   return 0;
6657 }
6658
6659 " test_name name (String.uppercase test_name) (String.uppercase name);
6660
6661   (match prereq with
6662    | Disabled | Always -> ()
6663    | If code | Unless code ->
6664        pr "static int %s_prereq (void)\n" test_name;
6665        pr "{\n";
6666        pr "  %s\n" code;
6667        pr "}\n";
6668        pr "\n";
6669   );
6670
6671   pr "\
6672 static int %s (void)
6673 {
6674   if (%s_skip ()) {
6675     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6676     return 0;
6677   }
6678
6679 " test_name test_name test_name;
6680
6681   (* Optional functions should only be tested if the relevant
6682    * support is available in the daemon.
6683    *)
6684   List.iter (
6685     function
6686     | Optional group ->
6687         pr "  {\n";
6688         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6689         pr "    int r;\n";
6690         pr "    suppress_error = 1;\n";
6691         pr "    r = guestfs_available (g, (char **) groups);\n";
6692         pr "    suppress_error = 0;\n";
6693         pr "    if (r == -1) {\n";
6694         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6695         pr "      return 0;\n";
6696         pr "    }\n";
6697         pr "  }\n";
6698     | _ -> ()
6699   ) flags;
6700
6701   (match prereq with
6702    | Disabled ->
6703        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6704    | If _ ->
6705        pr "  if (! %s_prereq ()) {\n" test_name;
6706        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6707        pr "    return 0;\n";
6708        pr "  }\n";
6709        pr "\n";
6710        generate_one_test_body name i test_name init test;
6711    | Unless _ ->
6712        pr "  if (%s_prereq ()) {\n" test_name;
6713        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6714        pr "    return 0;\n";
6715        pr "  }\n";
6716        pr "\n";
6717        generate_one_test_body name i test_name init test;
6718    | Always ->
6719        generate_one_test_body name i test_name init test
6720   );
6721
6722   pr "  return 0;\n";
6723   pr "}\n";
6724   pr "\n";
6725   test_name
6726
6727 and generate_one_test_body name i test_name init test =
6728   (match init with
6729    | InitNone (* XXX at some point, InitNone and InitEmpty became
6730                * folded together as the same thing.  Really we should
6731                * make InitNone do nothing at all, but the tests may
6732                * need to be checked to make sure this is OK.
6733                *)
6734    | InitEmpty ->
6735        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6736        List.iter (generate_test_command_call test_name)
6737          [["blockdev_setrw"; "/dev/sda"];
6738           ["umount_all"];
6739           ["lvm_remove_all"]]
6740    | InitPartition ->
6741        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6742        List.iter (generate_test_command_call test_name)
6743          [["blockdev_setrw"; "/dev/sda"];
6744           ["umount_all"];
6745           ["lvm_remove_all"];
6746           ["part_disk"; "/dev/sda"; "mbr"]]
6747    | InitBasicFS ->
6748        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6749        List.iter (generate_test_command_call test_name)
6750          [["blockdev_setrw"; "/dev/sda"];
6751           ["umount_all"];
6752           ["lvm_remove_all"];
6753           ["part_disk"; "/dev/sda"; "mbr"];
6754           ["mkfs"; "ext2"; "/dev/sda1"];
6755           ["mount_options"; ""; "/dev/sda1"; "/"]]
6756    | InitBasicFSonLVM ->
6757        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6758          test_name;
6759        List.iter (generate_test_command_call test_name)
6760          [["blockdev_setrw"; "/dev/sda"];
6761           ["umount_all"];
6762           ["lvm_remove_all"];
6763           ["part_disk"; "/dev/sda"; "mbr"];
6764           ["pvcreate"; "/dev/sda1"];
6765           ["vgcreate"; "VG"; "/dev/sda1"];
6766           ["lvcreate"; "LV"; "VG"; "8"];
6767           ["mkfs"; "ext2"; "/dev/VG/LV"];
6768           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6769    | InitISOFS ->
6770        pr "  /* InitISOFS for %s */\n" test_name;
6771        List.iter (generate_test_command_call test_name)
6772          [["blockdev_setrw"; "/dev/sda"];
6773           ["umount_all"];
6774           ["lvm_remove_all"];
6775           ["mount_ro"; "/dev/sdd"; "/"]]
6776   );
6777
6778   let get_seq_last = function
6779     | [] ->
6780         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6781           test_name
6782     | seq ->
6783         let seq = List.rev seq in
6784         List.rev (List.tl seq), List.hd seq
6785   in
6786
6787   match test with
6788   | TestRun seq ->
6789       pr "  /* TestRun for %s (%d) */\n" name i;
6790       List.iter (generate_test_command_call test_name) seq
6791   | TestOutput (seq, expected) ->
6792       pr "  /* TestOutput for %s (%d) */\n" name i;
6793       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6794       let seq, last = get_seq_last seq in
6795       let test () =
6796         pr "    if (STRNEQ (r, expected)) {\n";
6797         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6798         pr "      return -1;\n";
6799         pr "    }\n"
6800       in
6801       List.iter (generate_test_command_call test_name) seq;
6802       generate_test_command_call ~test test_name last
6803   | TestOutputList (seq, expected) ->
6804       pr "  /* TestOutputList for %s (%d) */\n" name i;
6805       let seq, last = get_seq_last seq in
6806       let test () =
6807         iteri (
6808           fun i str ->
6809             pr "    if (!r[%d]) {\n" i;
6810             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6811             pr "      print_strings (r);\n";
6812             pr "      return -1;\n";
6813             pr "    }\n";
6814             pr "    {\n";
6815             pr "      const char *expected = \"%s\";\n" (c_quote str);
6816             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6817             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6818             pr "        return -1;\n";
6819             pr "      }\n";
6820             pr "    }\n"
6821         ) expected;
6822         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6823         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6824           test_name;
6825         pr "      print_strings (r);\n";
6826         pr "      return -1;\n";
6827         pr "    }\n"
6828       in
6829       List.iter (generate_test_command_call test_name) seq;
6830       generate_test_command_call ~test test_name last
6831   | TestOutputListOfDevices (seq, expected) ->
6832       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6833       let seq, last = get_seq_last seq in
6834       let test () =
6835         iteri (
6836           fun i str ->
6837             pr "    if (!r[%d]) {\n" i;
6838             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6839             pr "      print_strings (r);\n";
6840             pr "      return -1;\n";
6841             pr "    }\n";
6842             pr "    {\n";
6843             pr "      const char *expected = \"%s\";\n" (c_quote str);
6844             pr "      r[%d][5] = 's';\n" i;
6845             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6846             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6847             pr "        return -1;\n";
6848             pr "      }\n";
6849             pr "    }\n"
6850         ) expected;
6851         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6852         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6853           test_name;
6854         pr "      print_strings (r);\n";
6855         pr "      return -1;\n";
6856         pr "    }\n"
6857       in
6858       List.iter (generate_test_command_call test_name) seq;
6859       generate_test_command_call ~test test_name last
6860   | TestOutputInt (seq, expected) ->
6861       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6862       let seq, last = get_seq_last seq in
6863       let test () =
6864         pr "    if (r != %d) {\n" expected;
6865         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6866           test_name expected;
6867         pr "               (int) r);\n";
6868         pr "      return -1;\n";
6869         pr "    }\n"
6870       in
6871       List.iter (generate_test_command_call test_name) seq;
6872       generate_test_command_call ~test test_name last
6873   | TestOutputIntOp (seq, op, expected) ->
6874       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6875       let seq, last = get_seq_last seq in
6876       let test () =
6877         pr "    if (! (r %s %d)) {\n" op expected;
6878         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6879           test_name op expected;
6880         pr "               (int) r);\n";
6881         pr "      return -1;\n";
6882         pr "    }\n"
6883       in
6884       List.iter (generate_test_command_call test_name) seq;
6885       generate_test_command_call ~test test_name last
6886   | TestOutputTrue seq ->
6887       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6888       let seq, last = get_seq_last seq in
6889       let test () =
6890         pr "    if (!r) {\n";
6891         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6892           test_name;
6893         pr "      return -1;\n";
6894         pr "    }\n"
6895       in
6896       List.iter (generate_test_command_call test_name) seq;
6897       generate_test_command_call ~test test_name last
6898   | TestOutputFalse seq ->
6899       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6900       let seq, last = get_seq_last seq in
6901       let test () =
6902         pr "    if (r) {\n";
6903         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6904           test_name;
6905         pr "      return -1;\n";
6906         pr "    }\n"
6907       in
6908       List.iter (generate_test_command_call test_name) seq;
6909       generate_test_command_call ~test test_name last
6910   | TestOutputLength (seq, expected) ->
6911       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6912       let seq, last = get_seq_last seq in
6913       let test () =
6914         pr "    int j;\n";
6915         pr "    for (j = 0; j < %d; ++j)\n" expected;
6916         pr "      if (r[j] == NULL) {\n";
6917         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6918           test_name;
6919         pr "        print_strings (r);\n";
6920         pr "        return -1;\n";
6921         pr "      }\n";
6922         pr "    if (r[j] != NULL) {\n";
6923         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6924           test_name;
6925         pr "      print_strings (r);\n";
6926         pr "      return -1;\n";
6927         pr "    }\n"
6928       in
6929       List.iter (generate_test_command_call test_name) seq;
6930       generate_test_command_call ~test test_name last
6931   | TestOutputBuffer (seq, expected) ->
6932       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6933       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6934       let seq, last = get_seq_last seq in
6935       let len = String.length expected in
6936       let test () =
6937         pr "    if (size != %d) {\n" len;
6938         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6939         pr "      return -1;\n";
6940         pr "    }\n";
6941         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6942         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6943         pr "      return -1;\n";
6944         pr "    }\n"
6945       in
6946       List.iter (generate_test_command_call test_name) seq;
6947       generate_test_command_call ~test test_name last
6948   | TestOutputStruct (seq, checks) ->
6949       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6950       let seq, last = get_seq_last seq in
6951       let test () =
6952         List.iter (
6953           function
6954           | CompareWithInt (field, expected) ->
6955               pr "    if (r->%s != %d) {\n" field expected;
6956               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6957                 test_name field expected;
6958               pr "               (int) r->%s);\n" field;
6959               pr "      return -1;\n";
6960               pr "    }\n"
6961           | CompareWithIntOp (field, op, expected) ->
6962               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6963               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6964                 test_name field op expected;
6965               pr "               (int) r->%s);\n" field;
6966               pr "      return -1;\n";
6967               pr "    }\n"
6968           | CompareWithString (field, expected) ->
6969               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6970               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6971                 test_name field expected;
6972               pr "               r->%s);\n" field;
6973               pr "      return -1;\n";
6974               pr "    }\n"
6975           | CompareFieldsIntEq (field1, field2) ->
6976               pr "    if (r->%s != r->%s) {\n" field1 field2;
6977               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6978                 test_name field1 field2;
6979               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6980               pr "      return -1;\n";
6981               pr "    }\n"
6982           | CompareFieldsStrEq (field1, field2) ->
6983               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6984               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6985                 test_name field1 field2;
6986               pr "               r->%s, r->%s);\n" field1 field2;
6987               pr "      return -1;\n";
6988               pr "    }\n"
6989         ) checks
6990       in
6991       List.iter (generate_test_command_call test_name) seq;
6992       generate_test_command_call ~test test_name last
6993   | TestLastFail seq ->
6994       pr "  /* TestLastFail for %s (%d) */\n" name i;
6995       let seq, last = get_seq_last seq in
6996       List.iter (generate_test_command_call test_name) seq;
6997       generate_test_command_call test_name ~expect_error:true last
6998
6999 (* Generate the code to run a command, leaving the result in 'r'.
7000  * If you expect to get an error then you should set expect_error:true.
7001  *)
7002 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7003   match cmd with
7004   | [] -> assert false
7005   | name :: args ->
7006       (* Look up the command to find out what args/ret it has. *)
7007       let style =
7008         try
7009           let _, style, _, _, _, _, _ =
7010             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7011           style
7012         with Not_found ->
7013           failwithf "%s: in test, command %s was not found" test_name name in
7014
7015       if List.length (snd style) <> List.length args then
7016         failwithf "%s: in test, wrong number of args given to %s"
7017           test_name name;
7018
7019       pr "  {\n";
7020
7021       List.iter (
7022         function
7023         | OptString n, "NULL" -> ()
7024         | Pathname n, arg
7025         | Device n, arg
7026         | Dev_or_Path n, arg
7027         | String n, arg
7028         | OptString n, arg ->
7029             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7030         | Int _, _
7031         | Int64 _, _
7032         | Bool _, _
7033         | FileIn _, _ | FileOut _, _ -> ()
7034         | StringList n, "" | DeviceList n, "" ->
7035             pr "    const char *const %s[1] = { NULL };\n" n
7036         | StringList n, arg | DeviceList n, arg ->
7037             let strs = string_split " " arg in
7038             iteri (
7039               fun i str ->
7040                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7041             ) strs;
7042             pr "    const char *const %s[] = {\n" n;
7043             iteri (
7044               fun i _ -> pr "      %s_%d,\n" n i
7045             ) strs;
7046             pr "      NULL\n";
7047             pr "    };\n";
7048       ) (List.combine (snd style) args);
7049
7050       let error_code =
7051         match fst style with
7052         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7053         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7054         | RConstString _ | RConstOptString _ ->
7055             pr "    const char *r;\n"; "NULL"
7056         | RString _ -> pr "    char *r;\n"; "NULL"
7057         | RStringList _ | RHashtable _ ->
7058             pr "    char **r;\n";
7059             pr "    int i;\n";
7060             "NULL"
7061         | RStruct (_, typ) ->
7062             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7063         | RStructList (_, typ) ->
7064             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7065         | RBufferOut _ ->
7066             pr "    char *r;\n";
7067             pr "    size_t size;\n";
7068             "NULL" in
7069
7070       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7071       pr "    r = guestfs_%s (g" name;
7072
7073       (* Generate the parameters. *)
7074       List.iter (
7075         function
7076         | OptString _, "NULL" -> pr ", NULL"
7077         | Pathname n, _
7078         | Device n, _ | Dev_or_Path n, _
7079         | String n, _
7080         | OptString n, _ ->
7081             pr ", %s" n
7082         | FileIn _, arg | FileOut _, arg ->
7083             pr ", \"%s\"" (c_quote arg)
7084         | StringList n, _ | DeviceList n, _ ->
7085             pr ", (char **) %s" n
7086         | Int _, arg ->
7087             let i =
7088               try int_of_string arg
7089               with Failure "int_of_string" ->
7090                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7091             pr ", %d" i
7092         | Int64 _, arg ->
7093             let i =
7094               try Int64.of_string arg
7095               with Failure "int_of_string" ->
7096                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7097             pr ", %Ld" i
7098         | Bool _, arg ->
7099             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7100       ) (List.combine (snd style) args);
7101
7102       (match fst style with
7103        | RBufferOut _ -> pr ", &size"
7104        | _ -> ()
7105       );
7106
7107       pr ");\n";
7108
7109       if not expect_error then
7110         pr "    if (r == %s)\n" error_code
7111       else
7112         pr "    if (r != %s)\n" error_code;
7113       pr "      return -1;\n";
7114
7115       (* Insert the test code. *)
7116       (match test with
7117        | None -> ()
7118        | Some f -> f ()
7119       );
7120
7121       (match fst style with
7122        | RErr | RInt _ | RInt64 _ | RBool _
7123        | RConstString _ | RConstOptString _ -> ()
7124        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7125        | RStringList _ | RHashtable _ ->
7126            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7127            pr "      free (r[i]);\n";
7128            pr "    free (r);\n"
7129        | RStruct (_, typ) ->
7130            pr "    guestfs_free_%s (r);\n" typ
7131        | RStructList (_, typ) ->
7132            pr "    guestfs_free_%s_list (r);\n" typ
7133       );
7134
7135       pr "  }\n"
7136
7137 and c_quote str =
7138   let str = replace_str str "\r" "\\r" in
7139   let str = replace_str str "\n" "\\n" in
7140   let str = replace_str str "\t" "\\t" in
7141   let str = replace_str str "\000" "\\0" in
7142   str
7143
7144 (* Generate a lot of different functions for guestfish. *)
7145 and generate_fish_cmds () =
7146   generate_header CStyle GPLv2plus;
7147
7148   let all_functions =
7149     List.filter (
7150       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7151     ) all_functions in
7152   let all_functions_sorted =
7153     List.filter (
7154       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7155     ) all_functions_sorted in
7156
7157   pr "#include <config.h>\n";
7158   pr "\n";
7159   pr "#include <stdio.h>\n";
7160   pr "#include <stdlib.h>\n";
7161   pr "#include <string.h>\n";
7162   pr "#include <inttypes.h>\n";
7163   pr "\n";
7164   pr "#include <guestfs.h>\n";
7165   pr "#include \"c-ctype.h\"\n";
7166   pr "#include \"full-write.h\"\n";
7167   pr "#include \"xstrtol.h\"\n";
7168   pr "#include \"fish.h\"\n";
7169   pr "\n";
7170
7171   (* list_commands function, which implements guestfish -h *)
7172   pr "void list_commands (void)\n";
7173   pr "{\n";
7174   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7175   pr "  list_builtin_commands ();\n";
7176   List.iter (
7177     fun (name, _, _, flags, _, shortdesc, _) ->
7178       let name = replace_char name '_' '-' in
7179       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7180         name shortdesc
7181   ) all_functions_sorted;
7182   pr "  printf (\"    %%s\\n\",";
7183   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7184   pr "}\n";
7185   pr "\n";
7186
7187   (* display_command function, which implements guestfish -h cmd *)
7188   pr "void display_command (const char *cmd)\n";
7189   pr "{\n";
7190   List.iter (
7191     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7192       let name2 = replace_char name '_' '-' in
7193       let alias =
7194         try find_map (function FishAlias n -> Some n | _ -> None) flags
7195         with Not_found -> name in
7196       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7197       let synopsis =
7198         match snd style with
7199         | [] -> name2
7200         | args ->
7201             sprintf "%s %s"
7202               name2 (String.concat " " (List.map name_of_argt args)) in
7203
7204       let warnings =
7205         if List.mem ProtocolLimitWarning flags then
7206           ("\n\n" ^ protocol_limit_warning)
7207         else "" in
7208
7209       (* For DangerWillRobinson commands, we should probably have
7210        * guestfish prompt before allowing you to use them (especially
7211        * in interactive mode). XXX
7212        *)
7213       let warnings =
7214         warnings ^
7215           if List.mem DangerWillRobinson flags then
7216             ("\n\n" ^ danger_will_robinson)
7217           else "" in
7218
7219       let warnings =
7220         warnings ^
7221           match deprecation_notice flags with
7222           | None -> ""
7223           | Some txt -> "\n\n" ^ txt in
7224
7225       let describe_alias =
7226         if name <> alias then
7227           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7228         else "" in
7229
7230       pr "  if (";
7231       pr "STRCASEEQ (cmd, \"%s\")" name;
7232       if name <> name2 then
7233         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7234       if name <> alias then
7235         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7236       pr ")\n";
7237       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7238         name2 shortdesc
7239         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7240          "=head1 DESCRIPTION\n\n" ^
7241          longdesc ^ warnings ^ describe_alias);
7242       pr "  else\n"
7243   ) all_functions;
7244   pr "    display_builtin_command (cmd);\n";
7245   pr "}\n";
7246   pr "\n";
7247
7248   let emit_print_list_function typ =
7249     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7250       typ typ typ;
7251     pr "{\n";
7252     pr "  unsigned int i;\n";
7253     pr "\n";
7254     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7255     pr "    printf (\"[%%d] = {\\n\", i);\n";
7256     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7257     pr "    printf (\"}\\n\");\n";
7258     pr "  }\n";
7259     pr "}\n";
7260     pr "\n";
7261   in
7262
7263   (* print_* functions *)
7264   List.iter (
7265     fun (typ, cols) ->
7266       let needs_i =
7267         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7268
7269       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7270       pr "{\n";
7271       if needs_i then (
7272         pr "  unsigned int i;\n";
7273         pr "\n"
7274       );
7275       List.iter (
7276         function
7277         | name, FString ->
7278             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7279         | name, FUUID ->
7280             pr "  printf (\"%%s%s: \", indent);\n" name;
7281             pr "  for (i = 0; i < 32; ++i)\n";
7282             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7283             pr "  printf (\"\\n\");\n"
7284         | name, FBuffer ->
7285             pr "  printf (\"%%s%s: \", indent);\n" name;
7286             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7287             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7288             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7289             pr "    else\n";
7290             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7291             pr "  printf (\"\\n\");\n"
7292         | name, (FUInt64|FBytes) ->
7293             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7294               name typ name
7295         | name, FInt64 ->
7296             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7297               name typ name
7298         | name, FUInt32 ->
7299             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7300               name typ name
7301         | name, FInt32 ->
7302             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7303               name typ name
7304         | name, FChar ->
7305             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7306               name typ name
7307         | name, FOptPercent ->
7308             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7309               typ name name typ name;
7310             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7311       ) cols;
7312       pr "}\n";
7313       pr "\n";
7314   ) structs;
7315
7316   (* Emit a print_TYPE_list function definition only if that function is used. *)
7317   List.iter (
7318     function
7319     | typ, (RStructListOnly | RStructAndList) ->
7320         (* generate the function for typ *)
7321         emit_print_list_function typ
7322     | typ, _ -> () (* empty *)
7323   ) (rstructs_used_by all_functions);
7324
7325   (* Emit a print_TYPE function definition only if that function is used. *)
7326   List.iter (
7327     function
7328     | typ, (RStructOnly | RStructAndList) ->
7329         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7330         pr "{\n";
7331         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7332         pr "}\n";
7333         pr "\n";
7334     | typ, _ -> () (* empty *)
7335   ) (rstructs_used_by all_functions);
7336
7337   (* run_<action> actions *)
7338   List.iter (
7339     fun (name, style, _, flags, _, _, _) ->
7340       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7341       pr "{\n";
7342       (match fst style with
7343        | RErr
7344        | RInt _
7345        | RBool _ -> pr "  int r;\n"
7346        | RInt64 _ -> pr "  int64_t r;\n"
7347        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7348        | RString _ -> pr "  char *r;\n"
7349        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7350        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7351        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7352        | RBufferOut _ ->
7353            pr "  char *r;\n";
7354            pr "  size_t size;\n";
7355       );
7356       List.iter (
7357         function
7358         | Device n
7359         | String n
7360         | OptString n
7361         | FileIn n
7362         | FileOut n -> pr "  const char *%s;\n" n
7363         | Pathname n
7364         | Dev_or_Path n -> pr "  char *%s;\n" n
7365         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7366         | Bool n -> pr "  int %s;\n" n
7367         | Int n -> pr "  int %s;\n" n
7368         | Int64 n -> pr "  int64_t %s;\n" n
7369       ) (snd style);
7370
7371       (* Check and convert parameters. *)
7372       let argc_expected = List.length (snd style) in
7373       pr "  if (argc != %d) {\n" argc_expected;
7374       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7375         argc_expected;
7376       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7377       pr "    return -1;\n";
7378       pr "  }\n";
7379
7380       let parse_integer fn fntyp rtyp range name i =
7381         pr "  {\n";
7382         pr "    strtol_error xerr;\n";
7383         pr "    %s r;\n" fntyp;
7384         pr "\n";
7385         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7386         pr "    if (xerr != LONGINT_OK) {\n";
7387         pr "      fprintf (stderr,\n";
7388         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7389         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7390         pr "      return -1;\n";
7391         pr "    }\n";
7392         (match range with
7393          | None -> ()
7394          | Some (min, max, comment) ->
7395              pr "    /* %s */\n" comment;
7396              pr "    if (r < %s || r > %s) {\n" min max;
7397              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7398                name;
7399              pr "      return -1;\n";
7400              pr "    }\n";
7401              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7402         );
7403         pr "    %s = r;\n" name;
7404         pr "  }\n";
7405       in
7406
7407       iteri (
7408         fun i ->
7409           function
7410           | Device name
7411           | String name ->
7412               pr "  %s = argv[%d];\n" name i
7413           | Pathname name
7414           | Dev_or_Path name ->
7415               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7416               pr "  if (%s == NULL) return -1;\n" name
7417           | OptString name ->
7418               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7419                 name i i
7420           | FileIn name ->
7421               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7422                 name i i
7423           | FileOut name ->
7424               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7425                 name i i
7426           | StringList name | DeviceList name ->
7427               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7428               pr "  if (%s == NULL) return -1;\n" name;
7429           | Bool name ->
7430               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7431           | Int name ->
7432               let range =
7433                 let min = "(-(2LL<<30))"
7434                 and max = "((2LL<<30)-1)"
7435                 and comment =
7436                   "The Int type in the generator is a signed 31 bit int." in
7437                 Some (min, max, comment) in
7438               parse_integer "xstrtoll" "long long" "int" range name i
7439           | Int64 name ->
7440               parse_integer "xstrtoll" "long long" "int64_t" None name i
7441       ) (snd style);
7442
7443       (* Call C API function. *)
7444       let fn =
7445         try find_map (function FishAction n -> Some n | _ -> None) flags
7446         with Not_found -> sprintf "guestfs_%s" name in
7447       pr "  r = %s " fn;
7448       generate_c_call_args ~handle:"g" style;
7449       pr ";\n";
7450
7451       List.iter (
7452         function
7453         | Device name | String name
7454         | OptString name | FileIn name | FileOut name | Bool name
7455         | Int name | Int64 name -> ()
7456         | Pathname name | Dev_or_Path name ->
7457             pr "  free (%s);\n" name
7458         | StringList name | DeviceList name ->
7459             pr "  free_strings (%s);\n" name
7460       ) (snd style);
7461
7462       (* Check return value for errors and display command results. *)
7463       (match fst style with
7464        | RErr -> pr "  return r;\n"
7465        | RInt _ ->
7466            pr "  if (r == -1) return -1;\n";
7467            pr "  printf (\"%%d\\n\", r);\n";
7468            pr "  return 0;\n"
7469        | RInt64 _ ->
7470            pr "  if (r == -1) return -1;\n";
7471            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7472            pr "  return 0;\n"
7473        | RBool _ ->
7474            pr "  if (r == -1) return -1;\n";
7475            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7476            pr "  return 0;\n"
7477        | RConstString _ ->
7478            pr "  if (r == NULL) return -1;\n";
7479            pr "  printf (\"%%s\\n\", r);\n";
7480            pr "  return 0;\n"
7481        | RConstOptString _ ->
7482            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7483            pr "  return 0;\n"
7484        | RString _ ->
7485            pr "  if (r == NULL) return -1;\n";
7486            pr "  printf (\"%%s\\n\", r);\n";
7487            pr "  free (r);\n";
7488            pr "  return 0;\n"
7489        | RStringList _ ->
7490            pr "  if (r == NULL) return -1;\n";
7491            pr "  print_strings (r);\n";
7492            pr "  free_strings (r);\n";
7493            pr "  return 0;\n"
7494        | RStruct (_, typ) ->
7495            pr "  if (r == NULL) return -1;\n";
7496            pr "  print_%s (r);\n" typ;
7497            pr "  guestfs_free_%s (r);\n" typ;
7498            pr "  return 0;\n"
7499        | RStructList (_, typ) ->
7500            pr "  if (r == NULL) return -1;\n";
7501            pr "  print_%s_list (r);\n" typ;
7502            pr "  guestfs_free_%s_list (r);\n" typ;
7503            pr "  return 0;\n"
7504        | RHashtable _ ->
7505            pr "  if (r == NULL) return -1;\n";
7506            pr "  print_table (r);\n";
7507            pr "  free_strings (r);\n";
7508            pr "  return 0;\n"
7509        | RBufferOut _ ->
7510            pr "  if (r == NULL) return -1;\n";
7511            pr "  if (full_write (1, r, size) != size) {\n";
7512            pr "    perror (\"write\");\n";
7513            pr "    free (r);\n";
7514            pr "    return -1;\n";
7515            pr "  }\n";
7516            pr "  free (r);\n";
7517            pr "  return 0;\n"
7518       );
7519       pr "}\n";
7520       pr "\n"
7521   ) all_functions;
7522
7523   (* run_action function *)
7524   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7525   pr "{\n";
7526   List.iter (
7527     fun (name, _, _, flags, _, _, _) ->
7528       let name2 = replace_char name '_' '-' in
7529       let alias =
7530         try find_map (function FishAlias n -> Some n | _ -> None) flags
7531         with Not_found -> name in
7532       pr "  if (";
7533       pr "STRCASEEQ (cmd, \"%s\")" name;
7534       if name <> name2 then
7535         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7536       if name <> alias then
7537         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7538       pr ")\n";
7539       pr "    return run_%s (cmd, argc, argv);\n" name;
7540       pr "  else\n";
7541   ) all_functions;
7542   pr "    {\n";
7543   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7544   pr "      if (command_num == 1)\n";
7545   pr "        extended_help_message ();\n";
7546   pr "      return -1;\n";
7547   pr "    }\n";
7548   pr "  return 0;\n";
7549   pr "}\n";
7550   pr "\n"
7551
7552 (* Readline completion for guestfish. *)
7553 and generate_fish_completion () =
7554   generate_header CStyle GPLv2plus;
7555
7556   let all_functions =
7557     List.filter (
7558       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7559     ) all_functions in
7560
7561   pr "\
7562 #include <config.h>
7563
7564 #include <stdio.h>
7565 #include <stdlib.h>
7566 #include <string.h>
7567
7568 #ifdef HAVE_LIBREADLINE
7569 #include <readline/readline.h>
7570 #endif
7571
7572 #include \"fish.h\"
7573
7574 #ifdef HAVE_LIBREADLINE
7575
7576 static const char *const commands[] = {
7577   BUILTIN_COMMANDS_FOR_COMPLETION,
7578 ";
7579
7580   (* Get the commands, including the aliases.  They don't need to be
7581    * sorted - the generator() function just does a dumb linear search.
7582    *)
7583   let commands =
7584     List.map (
7585       fun (name, _, _, flags, _, _, _) ->
7586         let name2 = replace_char name '_' '-' in
7587         let alias =
7588           try find_map (function FishAlias n -> Some n | _ -> None) flags
7589           with Not_found -> name in
7590
7591         if name <> alias then [name2; alias] else [name2]
7592     ) all_functions in
7593   let commands = List.flatten commands in
7594
7595   List.iter (pr "  \"%s\",\n") commands;
7596
7597   pr "  NULL
7598 };
7599
7600 static char *
7601 generator (const char *text, int state)
7602 {
7603   static int index, len;
7604   const char *name;
7605
7606   if (!state) {
7607     index = 0;
7608     len = strlen (text);
7609   }
7610
7611   rl_attempted_completion_over = 1;
7612
7613   while ((name = commands[index]) != NULL) {
7614     index++;
7615     if (STRCASEEQLEN (name, text, len))
7616       return strdup (name);
7617   }
7618
7619   return NULL;
7620 }
7621
7622 #endif /* HAVE_LIBREADLINE */
7623
7624 #ifdef HAVE_RL_COMPLETION_MATCHES
7625 #define RL_COMPLETION_MATCHES rl_completion_matches
7626 #else
7627 #ifdef HAVE_COMPLETION_MATCHES
7628 #define RL_COMPLETION_MATCHES completion_matches
7629 #endif
7630 #endif /* else just fail if we don't have either symbol */
7631
7632 char **
7633 do_completion (const char *text, int start, int end)
7634 {
7635   char **matches = NULL;
7636
7637 #ifdef HAVE_LIBREADLINE
7638   rl_completion_append_character = ' ';
7639
7640   if (start == 0)
7641     matches = RL_COMPLETION_MATCHES (text, generator);
7642   else if (complete_dest_paths)
7643     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7644 #endif
7645
7646   return matches;
7647 }
7648 ";
7649
7650 (* Generate the POD documentation for guestfish. *)
7651 and generate_fish_actions_pod () =
7652   let all_functions_sorted =
7653     List.filter (
7654       fun (_, _, _, flags, _, _, _) ->
7655         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7656     ) all_functions_sorted in
7657
7658   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7659
7660   List.iter (
7661     fun (name, style, _, flags, _, _, longdesc) ->
7662       let longdesc =
7663         Str.global_substitute rex (
7664           fun s ->
7665             let sub =
7666               try Str.matched_group 1 s
7667               with Not_found ->
7668                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7669             "C<" ^ replace_char sub '_' '-' ^ ">"
7670         ) longdesc in
7671       let name = replace_char name '_' '-' in
7672       let alias =
7673         try find_map (function FishAlias n -> Some n | _ -> None) flags
7674         with Not_found -> name in
7675
7676       pr "=head2 %s" name;
7677       if name <> alias then
7678         pr " | %s" alias;
7679       pr "\n";
7680       pr "\n";
7681       pr " %s" name;
7682       List.iter (
7683         function
7684         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7685         | OptString n -> pr " %s" n
7686         | StringList n | DeviceList n -> pr " '%s ...'" n
7687         | Bool _ -> pr " true|false"
7688         | Int n -> pr " %s" n
7689         | Int64 n -> pr " %s" n
7690         | FileIn n | FileOut n -> pr " (%s|-)" n
7691       ) (snd style);
7692       pr "\n";
7693       pr "\n";
7694       pr "%s\n\n" longdesc;
7695
7696       if List.exists (function FileIn _ | FileOut _ -> true
7697                       | _ -> false) (snd style) then
7698         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7699
7700       if List.mem ProtocolLimitWarning flags then
7701         pr "%s\n\n" protocol_limit_warning;
7702
7703       if List.mem DangerWillRobinson flags then
7704         pr "%s\n\n" danger_will_robinson;
7705
7706       match deprecation_notice flags with
7707       | None -> ()
7708       | Some txt -> pr "%s\n\n" txt
7709   ) all_functions_sorted
7710
7711 (* Generate a C function prototype. *)
7712 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7713     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7714     ?(prefix = "")
7715     ?handle name style =
7716   if extern then pr "extern ";
7717   if static then pr "static ";
7718   (match fst style with
7719    | RErr -> pr "int "
7720    | RInt _ -> pr "int "
7721    | RInt64 _ -> pr "int64_t "
7722    | RBool _ -> pr "int "
7723    | RConstString _ | RConstOptString _ -> pr "const char *"
7724    | RString _ | RBufferOut _ -> pr "char *"
7725    | RStringList _ | RHashtable _ -> pr "char **"
7726    | RStruct (_, typ) ->
7727        if not in_daemon then pr "struct guestfs_%s *" typ
7728        else pr "guestfs_int_%s *" typ
7729    | RStructList (_, typ) ->
7730        if not in_daemon then pr "struct guestfs_%s_list *" typ
7731        else pr "guestfs_int_%s_list *" typ
7732   );
7733   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7734   pr "%s%s (" prefix name;
7735   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7736     pr "void"
7737   else (
7738     let comma = ref false in
7739     (match handle with
7740      | None -> ()
7741      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7742     );
7743     let next () =
7744       if !comma then (
7745         if single_line then pr ", " else pr ",\n\t\t"
7746       );
7747       comma := true
7748     in
7749     List.iter (
7750       function
7751       | Pathname n
7752       | Device n | Dev_or_Path n
7753       | String n
7754       | OptString n ->
7755           next ();
7756           pr "const char *%s" n
7757       | StringList n | DeviceList n ->
7758           next ();
7759           pr "char *const *%s" n
7760       | Bool n -> next (); pr "int %s" n
7761       | Int n -> next (); pr "int %s" n
7762       | Int64 n -> next (); pr "int64_t %s" n
7763       | FileIn n
7764       | FileOut n ->
7765           if not in_daemon then (next (); pr "const char *%s" n)
7766     ) (snd style);
7767     if is_RBufferOut then (next (); pr "size_t *size_r");
7768   );
7769   pr ")";
7770   if semicolon then pr ";";
7771   if newline then pr "\n"
7772
7773 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7774 and generate_c_call_args ?handle ?(decl = false) style =
7775   pr "(";
7776   let comma = ref false in
7777   let next () =
7778     if !comma then pr ", ";
7779     comma := true
7780   in
7781   (match handle with
7782    | None -> ()
7783    | Some handle -> pr "%s" handle; comma := true
7784   );
7785   List.iter (
7786     fun arg ->
7787       next ();
7788       pr "%s" (name_of_argt arg)
7789   ) (snd style);
7790   (* For RBufferOut calls, add implicit &size parameter. *)
7791   if not decl then (
7792     match fst style with
7793     | RBufferOut _ ->
7794         next ();
7795         pr "&size"
7796     | _ -> ()
7797   );
7798   pr ")"
7799
7800 (* Generate the OCaml bindings interface. *)
7801 and generate_ocaml_mli () =
7802   generate_header OCamlStyle LGPLv2plus;
7803
7804   pr "\
7805 (** For API documentation you should refer to the C API
7806     in the guestfs(3) manual page.  The OCaml API uses almost
7807     exactly the same calls. *)
7808
7809 type t
7810 (** A [guestfs_h] handle. *)
7811
7812 exception Error of string
7813 (** This exception is raised when there is an error. *)
7814
7815 exception Handle_closed of string
7816 (** This exception is raised if you use a {!Guestfs.t} handle
7817     after calling {!close} on it.  The string is the name of
7818     the function. *)
7819
7820 val create : unit -> t
7821 (** Create a {!Guestfs.t} handle. *)
7822
7823 val close : t -> unit
7824 (** Close the {!Guestfs.t} handle and free up all resources used
7825     by it immediately.
7826
7827     Handles are closed by the garbage collector when they become
7828     unreferenced, but callers can call this in order to provide
7829     predictable cleanup. *)
7830
7831 ";
7832   generate_ocaml_structure_decls ();
7833
7834   (* The actions. *)
7835   List.iter (
7836     fun (name, style, _, _, _, shortdesc, _) ->
7837       generate_ocaml_prototype name style;
7838       pr "(** %s *)\n" shortdesc;
7839       pr "\n"
7840   ) all_functions_sorted
7841
7842 (* Generate the OCaml bindings implementation. *)
7843 and generate_ocaml_ml () =
7844   generate_header OCamlStyle LGPLv2plus;
7845
7846   pr "\
7847 type t
7848
7849 exception Error of string
7850 exception Handle_closed of string
7851
7852 external create : unit -> t = \"ocaml_guestfs_create\"
7853 external close : t -> unit = \"ocaml_guestfs_close\"
7854
7855 (* Give the exceptions names, so they can be raised from the C code. *)
7856 let () =
7857   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7858   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7859
7860 ";
7861
7862   generate_ocaml_structure_decls ();
7863
7864   (* The actions. *)
7865   List.iter (
7866     fun (name, style, _, _, _, shortdesc, _) ->
7867       generate_ocaml_prototype ~is_external:true name style;
7868   ) all_functions_sorted
7869
7870 (* Generate the OCaml bindings C implementation. *)
7871 and generate_ocaml_c () =
7872   generate_header CStyle LGPLv2plus;
7873
7874   pr "\
7875 #include <stdio.h>
7876 #include <stdlib.h>
7877 #include <string.h>
7878
7879 #include <caml/config.h>
7880 #include <caml/alloc.h>
7881 #include <caml/callback.h>
7882 #include <caml/fail.h>
7883 #include <caml/memory.h>
7884 #include <caml/mlvalues.h>
7885 #include <caml/signals.h>
7886
7887 #include <guestfs.h>
7888
7889 #include \"guestfs_c.h\"
7890
7891 /* Copy a hashtable of string pairs into an assoc-list.  We return
7892  * the list in reverse order, but hashtables aren't supposed to be
7893  * ordered anyway.
7894  */
7895 static CAMLprim value
7896 copy_table (char * const * argv)
7897 {
7898   CAMLparam0 ();
7899   CAMLlocal5 (rv, pairv, kv, vv, cons);
7900   int i;
7901
7902   rv = Val_int (0);
7903   for (i = 0; argv[i] != NULL; i += 2) {
7904     kv = caml_copy_string (argv[i]);
7905     vv = caml_copy_string (argv[i+1]);
7906     pairv = caml_alloc (2, 0);
7907     Store_field (pairv, 0, kv);
7908     Store_field (pairv, 1, vv);
7909     cons = caml_alloc (2, 0);
7910     Store_field (cons, 1, rv);
7911     rv = cons;
7912     Store_field (cons, 0, pairv);
7913   }
7914
7915   CAMLreturn (rv);
7916 }
7917
7918 ";
7919
7920   (* Struct copy functions. *)
7921
7922   let emit_ocaml_copy_list_function typ =
7923     pr "static CAMLprim value\n";
7924     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7925     pr "{\n";
7926     pr "  CAMLparam0 ();\n";
7927     pr "  CAMLlocal2 (rv, v);\n";
7928     pr "  unsigned int i;\n";
7929     pr "\n";
7930     pr "  if (%ss->len == 0)\n" typ;
7931     pr "    CAMLreturn (Atom (0));\n";
7932     pr "  else {\n";
7933     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7934     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7935     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7936     pr "      caml_modify (&Field (rv, i), v);\n";
7937     pr "    }\n";
7938     pr "    CAMLreturn (rv);\n";
7939     pr "  }\n";
7940     pr "}\n";
7941     pr "\n";
7942   in
7943
7944   List.iter (
7945     fun (typ, cols) ->
7946       let has_optpercent_col =
7947         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7948
7949       pr "static CAMLprim value\n";
7950       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7951       pr "{\n";
7952       pr "  CAMLparam0 ();\n";
7953       if has_optpercent_col then
7954         pr "  CAMLlocal3 (rv, v, v2);\n"
7955       else
7956         pr "  CAMLlocal2 (rv, v);\n";
7957       pr "\n";
7958       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7959       iteri (
7960         fun i col ->
7961           (match col with
7962            | name, FString ->
7963                pr "  v = caml_copy_string (%s->%s);\n" typ name
7964            | name, FBuffer ->
7965                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7966                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7967                  typ name typ name
7968            | name, FUUID ->
7969                pr "  v = caml_alloc_string (32);\n";
7970                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7971            | name, (FBytes|FInt64|FUInt64) ->
7972                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7973            | name, (FInt32|FUInt32) ->
7974                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7975            | name, FOptPercent ->
7976                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7977                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7978                pr "    v = caml_alloc (1, 0);\n";
7979                pr "    Store_field (v, 0, v2);\n";
7980                pr "  } else /* None */\n";
7981                pr "    v = Val_int (0);\n";
7982            | name, FChar ->
7983                pr "  v = Val_int (%s->%s);\n" typ name
7984           );
7985           pr "  Store_field (rv, %d, v);\n" i
7986       ) cols;
7987       pr "  CAMLreturn (rv);\n";
7988       pr "}\n";
7989       pr "\n";
7990   ) structs;
7991
7992   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7993   List.iter (
7994     function
7995     | typ, (RStructListOnly | RStructAndList) ->
7996         (* generate the function for typ *)
7997         emit_ocaml_copy_list_function typ
7998     | typ, _ -> () (* empty *)
7999   ) (rstructs_used_by all_functions);
8000
8001   (* The wrappers. *)
8002   List.iter (
8003     fun (name, style, _, _, _, _, _) ->
8004       pr "/* Automatically generated wrapper for function\n";
8005       pr " * ";
8006       generate_ocaml_prototype name style;
8007       pr " */\n";
8008       pr "\n";
8009
8010       let params =
8011         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8012
8013       let needs_extra_vs =
8014         match fst style with RConstOptString _ -> true | _ -> false in
8015
8016       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8017       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8018       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8019       pr "\n";
8020
8021       pr "CAMLprim value\n";
8022       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8023       List.iter (pr ", value %s") (List.tl params);
8024       pr ")\n";
8025       pr "{\n";
8026
8027       (match params with
8028        | [p1; p2; p3; p4; p5] ->
8029            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8030        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8031            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8032            pr "  CAMLxparam%d (%s);\n"
8033              (List.length rest) (String.concat ", " rest)
8034        | ps ->
8035            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8036       );
8037       if not needs_extra_vs then
8038         pr "  CAMLlocal1 (rv);\n"
8039       else
8040         pr "  CAMLlocal3 (rv, v, v2);\n";
8041       pr "\n";
8042
8043       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8044       pr "  if (g == NULL)\n";
8045       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8046       pr "\n";
8047
8048       List.iter (
8049         function
8050         | Pathname n
8051         | Device n | Dev_or_Path n
8052         | String n
8053         | FileIn n
8054         | FileOut n ->
8055             pr "  const char *%s = String_val (%sv);\n" n n
8056         | OptString n ->
8057             pr "  const char *%s =\n" n;
8058             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8059               n n
8060         | StringList n | DeviceList n ->
8061             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8062         | Bool n ->
8063             pr "  int %s = Bool_val (%sv);\n" n n
8064         | Int n ->
8065             pr "  int %s = Int_val (%sv);\n" n n
8066         | Int64 n ->
8067             pr "  int64_t %s = Int64_val (%sv);\n" n n
8068       ) (snd style);
8069       let error_code =
8070         match fst style with
8071         | RErr -> pr "  int r;\n"; "-1"
8072         | RInt _ -> pr "  int r;\n"; "-1"
8073         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8074         | RBool _ -> pr "  int r;\n"; "-1"
8075         | RConstString _ | RConstOptString _ ->
8076             pr "  const char *r;\n"; "NULL"
8077         | RString _ -> pr "  char *r;\n"; "NULL"
8078         | RStringList _ ->
8079             pr "  int i;\n";
8080             pr "  char **r;\n";
8081             "NULL"
8082         | RStruct (_, typ) ->
8083             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8084         | RStructList (_, typ) ->
8085             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8086         | RHashtable _ ->
8087             pr "  int i;\n";
8088             pr "  char **r;\n";
8089             "NULL"
8090         | RBufferOut _ ->
8091             pr "  char *r;\n";
8092             pr "  size_t size;\n";
8093             "NULL" in
8094       pr "\n";
8095
8096       pr "  caml_enter_blocking_section ();\n";
8097       pr "  r = guestfs_%s " name;
8098       generate_c_call_args ~handle:"g" style;
8099       pr ";\n";
8100       pr "  caml_leave_blocking_section ();\n";
8101
8102       List.iter (
8103         function
8104         | StringList n | DeviceList n ->
8105             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8106         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8107         | Bool _ | Int _ | Int64 _
8108         | FileIn _ | FileOut _ -> ()
8109       ) (snd style);
8110
8111       pr "  if (r == %s)\n" error_code;
8112       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8113       pr "\n";
8114
8115       (match fst style with
8116        | RErr -> pr "  rv = Val_unit;\n"
8117        | RInt _ -> pr "  rv = Val_int (r);\n"
8118        | RInt64 _ ->
8119            pr "  rv = caml_copy_int64 (r);\n"
8120        | RBool _ -> pr "  rv = Val_bool (r);\n"
8121        | RConstString _ ->
8122            pr "  rv = caml_copy_string (r);\n"
8123        | RConstOptString _ ->
8124            pr "  if (r) { /* Some string */\n";
8125            pr "    v = caml_alloc (1, 0);\n";
8126            pr "    v2 = caml_copy_string (r);\n";
8127            pr "    Store_field (v, 0, v2);\n";
8128            pr "  } else /* None */\n";
8129            pr "    v = Val_int (0);\n";
8130        | RString _ ->
8131            pr "  rv = caml_copy_string (r);\n";
8132            pr "  free (r);\n"
8133        | RStringList _ ->
8134            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8135            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8136            pr "  free (r);\n"
8137        | RStruct (_, typ) ->
8138            pr "  rv = copy_%s (r);\n" typ;
8139            pr "  guestfs_free_%s (r);\n" typ;
8140        | RStructList (_, typ) ->
8141            pr "  rv = copy_%s_list (r);\n" typ;
8142            pr "  guestfs_free_%s_list (r);\n" typ;
8143        | RHashtable _ ->
8144            pr "  rv = copy_table (r);\n";
8145            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8146            pr "  free (r);\n";
8147        | RBufferOut _ ->
8148            pr "  rv = caml_alloc_string (size);\n";
8149            pr "  memcpy (String_val (rv), r, size);\n";
8150       );
8151
8152       pr "  CAMLreturn (rv);\n";
8153       pr "}\n";
8154       pr "\n";
8155
8156       if List.length params > 5 then (
8157         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8158         pr "CAMLprim value ";
8159         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8160         pr "CAMLprim value\n";
8161         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8162         pr "{\n";
8163         pr "  return ocaml_guestfs_%s (argv[0]" name;
8164         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8165         pr ");\n";
8166         pr "}\n";
8167         pr "\n"
8168       )
8169   ) all_functions_sorted
8170
8171 and generate_ocaml_structure_decls () =
8172   List.iter (
8173     fun (typ, cols) ->
8174       pr "type %s = {\n" typ;
8175       List.iter (
8176         function
8177         | name, FString -> pr "  %s : string;\n" name
8178         | name, FBuffer -> pr "  %s : string;\n" name
8179         | name, FUUID -> pr "  %s : string;\n" name
8180         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8181         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8182         | name, FChar -> pr "  %s : char;\n" name
8183         | name, FOptPercent -> pr "  %s : float option;\n" name
8184       ) cols;
8185       pr "}\n";
8186       pr "\n"
8187   ) structs
8188
8189 and generate_ocaml_prototype ?(is_external = false) name style =
8190   if is_external then pr "external " else pr "val ";
8191   pr "%s : t -> " name;
8192   List.iter (
8193     function
8194     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8195     | OptString _ -> pr "string option -> "
8196     | StringList _ | DeviceList _ -> pr "string array -> "
8197     | Bool _ -> pr "bool -> "
8198     | Int _ -> pr "int -> "
8199     | Int64 _ -> pr "int64 -> "
8200   ) (snd style);
8201   (match fst style with
8202    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8203    | RInt _ -> pr "int"
8204    | RInt64 _ -> pr "int64"
8205    | RBool _ -> pr "bool"
8206    | RConstString _ -> pr "string"
8207    | RConstOptString _ -> pr "string option"
8208    | RString _ | RBufferOut _ -> pr "string"
8209    | RStringList _ -> pr "string array"
8210    | RStruct (_, typ) -> pr "%s" typ
8211    | RStructList (_, typ) -> pr "%s array" typ
8212    | RHashtable _ -> pr "(string * string) list"
8213   );
8214   if is_external then (
8215     pr " = ";
8216     if List.length (snd style) + 1 > 5 then
8217       pr "\"ocaml_guestfs_%s_byte\" " name;
8218     pr "\"ocaml_guestfs_%s\"" name
8219   );
8220   pr "\n"
8221
8222 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8223 and generate_perl_xs () =
8224   generate_header CStyle LGPLv2plus;
8225
8226   pr "\
8227 #include \"EXTERN.h\"
8228 #include \"perl.h\"
8229 #include \"XSUB.h\"
8230
8231 #include <guestfs.h>
8232
8233 #ifndef PRId64
8234 #define PRId64 \"lld\"
8235 #endif
8236
8237 static SV *
8238 my_newSVll(long long val) {
8239 #ifdef USE_64_BIT_ALL
8240   return newSViv(val);
8241 #else
8242   char buf[100];
8243   int len;
8244   len = snprintf(buf, 100, \"%%\" PRId64, val);
8245   return newSVpv(buf, len);
8246 #endif
8247 }
8248
8249 #ifndef PRIu64
8250 #define PRIu64 \"llu\"
8251 #endif
8252
8253 static SV *
8254 my_newSVull(unsigned long long val) {
8255 #ifdef USE_64_BIT_ALL
8256   return newSVuv(val);
8257 #else
8258   char buf[100];
8259   int len;
8260   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8261   return newSVpv(buf, len);
8262 #endif
8263 }
8264
8265 /* http://www.perlmonks.org/?node_id=680842 */
8266 static char **
8267 XS_unpack_charPtrPtr (SV *arg) {
8268   char **ret;
8269   AV *av;
8270   I32 i;
8271
8272   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8273     croak (\"array reference expected\");
8274
8275   av = (AV *)SvRV (arg);
8276   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8277   if (!ret)
8278     croak (\"malloc failed\");
8279
8280   for (i = 0; i <= av_len (av); i++) {
8281     SV **elem = av_fetch (av, i, 0);
8282
8283     if (!elem || !*elem)
8284       croak (\"missing element in list\");
8285
8286     ret[i] = SvPV_nolen (*elem);
8287   }
8288
8289   ret[i] = NULL;
8290
8291   return ret;
8292 }
8293
8294 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8295
8296 PROTOTYPES: ENABLE
8297
8298 guestfs_h *
8299 _create ()
8300    CODE:
8301       RETVAL = guestfs_create ();
8302       if (!RETVAL)
8303         croak (\"could not create guestfs handle\");
8304       guestfs_set_error_handler (RETVAL, NULL, NULL);
8305  OUTPUT:
8306       RETVAL
8307
8308 void
8309 DESTROY (g)
8310       guestfs_h *g;
8311  PPCODE:
8312       guestfs_close (g);
8313
8314 ";
8315
8316   List.iter (
8317     fun (name, style, _, _, _, _, _) ->
8318       (match fst style with
8319        | RErr -> pr "void\n"
8320        | RInt _ -> pr "SV *\n"
8321        | RInt64 _ -> pr "SV *\n"
8322        | RBool _ -> pr "SV *\n"
8323        | RConstString _ -> pr "SV *\n"
8324        | RConstOptString _ -> pr "SV *\n"
8325        | RString _ -> pr "SV *\n"
8326        | RBufferOut _ -> pr "SV *\n"
8327        | RStringList _
8328        | RStruct _ | RStructList _
8329        | RHashtable _ ->
8330            pr "void\n" (* all lists returned implictly on the stack *)
8331       );
8332       (* Call and arguments. *)
8333       pr "%s " name;
8334       generate_c_call_args ~handle:"g" ~decl:true style;
8335       pr "\n";
8336       pr "      guestfs_h *g;\n";
8337       iteri (
8338         fun i ->
8339           function
8340           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8341               pr "      char *%s;\n" n
8342           | OptString n ->
8343               (* http://www.perlmonks.org/?node_id=554277
8344                * Note that the implicit handle argument means we have
8345                * to add 1 to the ST(x) operator.
8346                *)
8347               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8348           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8349           | Bool n -> pr "      int %s;\n" n
8350           | Int n -> pr "      int %s;\n" n
8351           | Int64 n -> pr "      int64_t %s;\n" n
8352       ) (snd style);
8353
8354       let do_cleanups () =
8355         List.iter (
8356           function
8357           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8358           | Bool _ | Int _ | Int64 _
8359           | FileIn _ | FileOut _ -> ()
8360           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8361         ) (snd style)
8362       in
8363
8364       (* Code. *)
8365       (match fst style with
8366        | RErr ->
8367            pr "PREINIT:\n";
8368            pr "      int r;\n";
8369            pr " PPCODE:\n";
8370            pr "      r = guestfs_%s " name;
8371            generate_c_call_args ~handle:"g" style;
8372            pr ";\n";
8373            do_cleanups ();
8374            pr "      if (r == -1)\n";
8375            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8376        | RInt n
8377        | RBool n ->
8378            pr "PREINIT:\n";
8379            pr "      int %s;\n" n;
8380            pr "   CODE:\n";
8381            pr "      %s = guestfs_%s " n name;
8382            generate_c_call_args ~handle:"g" style;
8383            pr ";\n";
8384            do_cleanups ();
8385            pr "      if (%s == -1)\n" n;
8386            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8387            pr "      RETVAL = newSViv (%s);\n" n;
8388            pr " OUTPUT:\n";
8389            pr "      RETVAL\n"
8390        | RInt64 n ->
8391            pr "PREINIT:\n";
8392            pr "      int64_t %s;\n" n;
8393            pr "   CODE:\n";
8394            pr "      %s = guestfs_%s " n name;
8395            generate_c_call_args ~handle:"g" style;
8396            pr ";\n";
8397            do_cleanups ();
8398            pr "      if (%s == -1)\n" n;
8399            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8400            pr "      RETVAL = my_newSVll (%s);\n" n;
8401            pr " OUTPUT:\n";
8402            pr "      RETVAL\n"
8403        | RConstString n ->
8404            pr "PREINIT:\n";
8405            pr "      const char *%s;\n" n;
8406            pr "   CODE:\n";
8407            pr "      %s = guestfs_%s " n name;
8408            generate_c_call_args ~handle:"g" style;
8409            pr ";\n";
8410            do_cleanups ();
8411            pr "      if (%s == NULL)\n" n;
8412            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8413            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8414            pr " OUTPUT:\n";
8415            pr "      RETVAL\n"
8416        | RConstOptString n ->
8417            pr "PREINIT:\n";
8418            pr "      const char *%s;\n" n;
8419            pr "   CODE:\n";
8420            pr "      %s = guestfs_%s " n name;
8421            generate_c_call_args ~handle:"g" style;
8422            pr ";\n";
8423            do_cleanups ();
8424            pr "      if (%s == NULL)\n" n;
8425            pr "        RETVAL = &PL_sv_undef;\n";
8426            pr "      else\n";
8427            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8428            pr " OUTPUT:\n";
8429            pr "      RETVAL\n"
8430        | RString n ->
8431            pr "PREINIT:\n";
8432            pr "      char *%s;\n" n;
8433            pr "   CODE:\n";
8434            pr "      %s = guestfs_%s " n name;
8435            generate_c_call_args ~handle:"g" style;
8436            pr ";\n";
8437            do_cleanups ();
8438            pr "      if (%s == NULL)\n" n;
8439            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8440            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8441            pr "      free (%s);\n" n;
8442            pr " OUTPUT:\n";
8443            pr "      RETVAL\n"
8444        | RStringList n | RHashtable n ->
8445            pr "PREINIT:\n";
8446            pr "      char **%s;\n" n;
8447            pr "      int i, n;\n";
8448            pr " PPCODE:\n";
8449            pr "      %s = guestfs_%s " n name;
8450            generate_c_call_args ~handle:"g" style;
8451            pr ";\n";
8452            do_cleanups ();
8453            pr "      if (%s == NULL)\n" n;
8454            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8455            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8456            pr "      EXTEND (SP, n);\n";
8457            pr "      for (i = 0; i < n; ++i) {\n";
8458            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8459            pr "        free (%s[i]);\n" n;
8460            pr "      }\n";
8461            pr "      free (%s);\n" n;
8462        | RStruct (n, typ) ->
8463            let cols = cols_of_struct typ in
8464            generate_perl_struct_code typ cols name style n do_cleanups
8465        | RStructList (n, typ) ->
8466            let cols = cols_of_struct typ in
8467            generate_perl_struct_list_code typ cols name style n do_cleanups
8468        | RBufferOut n ->
8469            pr "PREINIT:\n";
8470            pr "      char *%s;\n" n;
8471            pr "      size_t size;\n";
8472            pr "   CODE:\n";
8473            pr "      %s = guestfs_%s " n name;
8474            generate_c_call_args ~handle:"g" style;
8475            pr ";\n";
8476            do_cleanups ();
8477            pr "      if (%s == NULL)\n" n;
8478            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8479            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8480            pr "      free (%s);\n" n;
8481            pr " OUTPUT:\n";
8482            pr "      RETVAL\n"
8483       );
8484
8485       pr "\n"
8486   ) all_functions
8487
8488 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8489   pr "PREINIT:\n";
8490   pr "      struct guestfs_%s_list *%s;\n" typ n;
8491   pr "      int i;\n";
8492   pr "      HV *hv;\n";
8493   pr " PPCODE:\n";
8494   pr "      %s = guestfs_%s " n name;
8495   generate_c_call_args ~handle:"g" style;
8496   pr ";\n";
8497   do_cleanups ();
8498   pr "      if (%s == NULL)\n" n;
8499   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8500   pr "      EXTEND (SP, %s->len);\n" n;
8501   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8502   pr "        hv = newHV ();\n";
8503   List.iter (
8504     function
8505     | name, FString ->
8506         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8507           name (String.length name) n name
8508     | name, FUUID ->
8509         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8510           name (String.length name) n name
8511     | name, FBuffer ->
8512         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8513           name (String.length name) n name n name
8514     | name, (FBytes|FUInt64) ->
8515         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8516           name (String.length name) n name
8517     | name, FInt64 ->
8518         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8519           name (String.length name) n name
8520     | name, (FInt32|FUInt32) ->
8521         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8522           name (String.length name) n name
8523     | name, FChar ->
8524         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8525           name (String.length name) n name
8526     | name, FOptPercent ->
8527         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8528           name (String.length name) n name
8529   ) cols;
8530   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8531   pr "      }\n";
8532   pr "      guestfs_free_%s_list (%s);\n" typ n
8533
8534 and generate_perl_struct_code typ cols name style n do_cleanups =
8535   pr "PREINIT:\n";
8536   pr "      struct guestfs_%s *%s;\n" typ n;
8537   pr " PPCODE:\n";
8538   pr "      %s = guestfs_%s " n name;
8539   generate_c_call_args ~handle:"g" style;
8540   pr ";\n";
8541   do_cleanups ();
8542   pr "      if (%s == NULL)\n" n;
8543   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8544   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8545   List.iter (
8546     fun ((name, _) as col) ->
8547       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8548
8549       match col with
8550       | name, FString ->
8551           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8552             n name
8553       | name, FBuffer ->
8554           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8555             n name n name
8556       | name, FUUID ->
8557           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8558             n name
8559       | name, (FBytes|FUInt64) ->
8560           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8561             n name
8562       | name, FInt64 ->
8563           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8564             n name
8565       | name, (FInt32|FUInt32) ->
8566           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8567             n name
8568       | name, FChar ->
8569           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8570             n name
8571       | name, FOptPercent ->
8572           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8573             n name
8574   ) cols;
8575   pr "      free (%s);\n" n
8576
8577 (* Generate Sys/Guestfs.pm. *)
8578 and generate_perl_pm () =
8579   generate_header HashStyle LGPLv2plus;
8580
8581   pr "\
8582 =pod
8583
8584 =head1 NAME
8585
8586 Sys::Guestfs - Perl bindings for libguestfs
8587
8588 =head1 SYNOPSIS
8589
8590  use Sys::Guestfs;
8591
8592  my $h = Sys::Guestfs->new ();
8593  $h->add_drive ('guest.img');
8594  $h->launch ();
8595  $h->mount ('/dev/sda1', '/');
8596  $h->touch ('/hello');
8597  $h->sync ();
8598
8599 =head1 DESCRIPTION
8600
8601 The C<Sys::Guestfs> module provides a Perl XS binding to the
8602 libguestfs API for examining and modifying virtual machine
8603 disk images.
8604
8605 Amongst the things this is good for: making batch configuration
8606 changes to guests, getting disk used/free statistics (see also:
8607 virt-df), migrating between virtualization systems (see also:
8608 virt-p2v), performing partial backups, performing partial guest
8609 clones, cloning guests and changing registry/UUID/hostname info, and
8610 much else besides.
8611
8612 Libguestfs uses Linux kernel and qemu code, and can access any type of
8613 guest filesystem that Linux and qemu can, including but not limited
8614 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8615 schemes, qcow, qcow2, vmdk.
8616
8617 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8618 LVs, what filesystem is in each LV, etc.).  It can also run commands
8619 in the context of the guest.  Also you can access filesystems over
8620 FUSE.
8621
8622 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8623 functions for using libguestfs from Perl, including integration
8624 with libvirt.
8625
8626 =head1 ERRORS
8627
8628 All errors turn into calls to C<croak> (see L<Carp(3)>).
8629
8630 =head1 METHODS
8631
8632 =over 4
8633
8634 =cut
8635
8636 package Sys::Guestfs;
8637
8638 use strict;
8639 use warnings;
8640
8641 require XSLoader;
8642 XSLoader::load ('Sys::Guestfs');
8643
8644 =item $h = Sys::Guestfs->new ();
8645
8646 Create a new guestfs handle.
8647
8648 =cut
8649
8650 sub new {
8651   my $proto = shift;
8652   my $class = ref ($proto) || $proto;
8653
8654   my $self = Sys::Guestfs::_create ();
8655   bless $self, $class;
8656   return $self;
8657 }
8658
8659 ";
8660
8661   (* Actions.  We only need to print documentation for these as
8662    * they are pulled in from the XS code automatically.
8663    *)
8664   List.iter (
8665     fun (name, style, _, flags, _, _, longdesc) ->
8666       if not (List.mem NotInDocs flags) then (
8667         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8668         pr "=item ";
8669         generate_perl_prototype name style;
8670         pr "\n\n";
8671         pr "%s\n\n" longdesc;
8672         if List.mem ProtocolLimitWarning flags then
8673           pr "%s\n\n" protocol_limit_warning;
8674         if List.mem DangerWillRobinson flags then
8675           pr "%s\n\n" danger_will_robinson;
8676         match deprecation_notice flags with
8677         | None -> ()
8678         | Some txt -> pr "%s\n\n" txt
8679       )
8680   ) all_functions_sorted;
8681
8682   (* End of file. *)
8683   pr "\
8684 =cut
8685
8686 1;
8687
8688 =back
8689
8690 =head1 COPYRIGHT
8691
8692 Copyright (C) %s Red Hat Inc.
8693
8694 =head1 LICENSE
8695
8696 Please see the file COPYING.LIB for the full license.
8697
8698 =head1 SEE ALSO
8699
8700 L<guestfs(3)>,
8701 L<guestfish(1)>,
8702 L<http://libguestfs.org>,
8703 L<Sys::Guestfs::Lib(3)>.
8704
8705 =cut
8706 " copyright_years
8707
8708 and generate_perl_prototype name style =
8709   (match fst style with
8710    | RErr -> ()
8711    | RBool n
8712    | RInt n
8713    | RInt64 n
8714    | RConstString n
8715    | RConstOptString n
8716    | RString n
8717    | RBufferOut n -> pr "$%s = " n
8718    | RStruct (n,_)
8719    | RHashtable n -> pr "%%%s = " n
8720    | RStringList n
8721    | RStructList (n,_) -> pr "@%s = " n
8722   );
8723   pr "$h->%s (" name;
8724   let comma = ref false in
8725   List.iter (
8726     fun arg ->
8727       if !comma then pr ", ";
8728       comma := true;
8729       match arg with
8730       | Pathname n | Device n | Dev_or_Path n | String n
8731       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8732           pr "$%s" n
8733       | StringList n | DeviceList n ->
8734           pr "\\@%s" n
8735   ) (snd style);
8736   pr ");"
8737
8738 (* Generate Python C module. *)
8739 and generate_python_c () =
8740   generate_header CStyle LGPLv2plus;
8741
8742   pr "\
8743 #include <Python.h>
8744
8745 #include <stdio.h>
8746 #include <stdlib.h>
8747 #include <assert.h>
8748
8749 #include \"guestfs.h\"
8750
8751 typedef struct {
8752   PyObject_HEAD
8753   guestfs_h *g;
8754 } Pyguestfs_Object;
8755
8756 static guestfs_h *
8757 get_handle (PyObject *obj)
8758 {
8759   assert (obj);
8760   assert (obj != Py_None);
8761   return ((Pyguestfs_Object *) obj)->g;
8762 }
8763
8764 static PyObject *
8765 put_handle (guestfs_h *g)
8766 {
8767   assert (g);
8768   return
8769     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8770 }
8771
8772 /* This list should be freed (but not the strings) after use. */
8773 static char **
8774 get_string_list (PyObject *obj)
8775 {
8776   int i, len;
8777   char **r;
8778
8779   assert (obj);
8780
8781   if (!PyList_Check (obj)) {
8782     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8783     return NULL;
8784   }
8785
8786   len = PyList_Size (obj);
8787   r = malloc (sizeof (char *) * (len+1));
8788   if (r == NULL) {
8789     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8790     return NULL;
8791   }
8792
8793   for (i = 0; i < len; ++i)
8794     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8795   r[len] = NULL;
8796
8797   return r;
8798 }
8799
8800 static PyObject *
8801 put_string_list (char * const * const argv)
8802 {
8803   PyObject *list;
8804   int argc, i;
8805
8806   for (argc = 0; argv[argc] != NULL; ++argc)
8807     ;
8808
8809   list = PyList_New (argc);
8810   for (i = 0; i < argc; ++i)
8811     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8812
8813   return list;
8814 }
8815
8816 static PyObject *
8817 put_table (char * const * const argv)
8818 {
8819   PyObject *list, *item;
8820   int argc, i;
8821
8822   for (argc = 0; argv[argc] != NULL; ++argc)
8823     ;
8824
8825   list = PyList_New (argc >> 1);
8826   for (i = 0; i < argc; i += 2) {
8827     item = PyTuple_New (2);
8828     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8829     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8830     PyList_SetItem (list, i >> 1, item);
8831   }
8832
8833   return list;
8834 }
8835
8836 static void
8837 free_strings (char **argv)
8838 {
8839   int argc;
8840
8841   for (argc = 0; argv[argc] != NULL; ++argc)
8842     free (argv[argc]);
8843   free (argv);
8844 }
8845
8846 static PyObject *
8847 py_guestfs_create (PyObject *self, PyObject *args)
8848 {
8849   guestfs_h *g;
8850
8851   g = guestfs_create ();
8852   if (g == NULL) {
8853     PyErr_SetString (PyExc_RuntimeError,
8854                      \"guestfs.create: failed to allocate handle\");
8855     return NULL;
8856   }
8857   guestfs_set_error_handler (g, NULL, NULL);
8858   return put_handle (g);
8859 }
8860
8861 static PyObject *
8862 py_guestfs_close (PyObject *self, PyObject *args)
8863 {
8864   PyObject *py_g;
8865   guestfs_h *g;
8866
8867   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8868     return NULL;
8869   g = get_handle (py_g);
8870
8871   guestfs_close (g);
8872
8873   Py_INCREF (Py_None);
8874   return Py_None;
8875 }
8876
8877 ";
8878
8879   let emit_put_list_function typ =
8880     pr "static PyObject *\n";
8881     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8882     pr "{\n";
8883     pr "  PyObject *list;\n";
8884     pr "  int i;\n";
8885     pr "\n";
8886     pr "  list = PyList_New (%ss->len);\n" typ;
8887     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8888     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8889     pr "  return list;\n";
8890     pr "};\n";
8891     pr "\n"
8892   in
8893
8894   (* Structures, turned into Python dictionaries. *)
8895   List.iter (
8896     fun (typ, cols) ->
8897       pr "static PyObject *\n";
8898       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8899       pr "{\n";
8900       pr "  PyObject *dict;\n";
8901       pr "\n";
8902       pr "  dict = PyDict_New ();\n";
8903       List.iter (
8904         function
8905         | name, FString ->
8906             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8907             pr "                        PyString_FromString (%s->%s));\n"
8908               typ name
8909         | name, FBuffer ->
8910             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8911             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8912               typ name typ name
8913         | name, FUUID ->
8914             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8915             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8916               typ name
8917         | name, (FBytes|FUInt64) ->
8918             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8919             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8920               typ name
8921         | name, FInt64 ->
8922             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8923             pr "                        PyLong_FromLongLong (%s->%s));\n"
8924               typ name
8925         | name, FUInt32 ->
8926             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8927             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8928               typ name
8929         | name, FInt32 ->
8930             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8931             pr "                        PyLong_FromLong (%s->%s));\n"
8932               typ name
8933         | name, FOptPercent ->
8934             pr "  if (%s->%s >= 0)\n" typ name;
8935             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8936             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8937               typ name;
8938             pr "  else {\n";
8939             pr "    Py_INCREF (Py_None);\n";
8940             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8941             pr "  }\n"
8942         | name, FChar ->
8943             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8944             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8945       ) cols;
8946       pr "  return dict;\n";
8947       pr "};\n";
8948       pr "\n";
8949
8950   ) structs;
8951
8952   (* Emit a put_TYPE_list function definition only if that function is used. *)
8953   List.iter (
8954     function
8955     | typ, (RStructListOnly | RStructAndList) ->
8956         (* generate the function for typ *)
8957         emit_put_list_function typ
8958     | typ, _ -> () (* empty *)
8959   ) (rstructs_used_by all_functions);
8960
8961   (* Python wrapper functions. *)
8962   List.iter (
8963     fun (name, style, _, _, _, _, _) ->
8964       pr "static PyObject *\n";
8965       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8966       pr "{\n";
8967
8968       pr "  PyObject *py_g;\n";
8969       pr "  guestfs_h *g;\n";
8970       pr "  PyObject *py_r;\n";
8971
8972       let error_code =
8973         match fst style with
8974         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8975         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8976         | RConstString _ | RConstOptString _ ->
8977             pr "  const char *r;\n"; "NULL"
8978         | RString _ -> pr "  char *r;\n"; "NULL"
8979         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8980         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8981         | RStructList (_, typ) ->
8982             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8983         | RBufferOut _ ->
8984             pr "  char *r;\n";
8985             pr "  size_t size;\n";
8986             "NULL" in
8987
8988       List.iter (
8989         function
8990         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8991             pr "  const char *%s;\n" n
8992         | OptString n -> pr "  const char *%s;\n" n
8993         | StringList n | DeviceList n ->
8994             pr "  PyObject *py_%s;\n" n;
8995             pr "  char **%s;\n" n
8996         | Bool n -> pr "  int %s;\n" n
8997         | Int n -> pr "  int %s;\n" n
8998         | Int64 n -> pr "  long long %s;\n" n
8999       ) (snd style);
9000
9001       pr "\n";
9002
9003       (* Convert the parameters. *)
9004       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9005       List.iter (
9006         function
9007         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9008         | OptString _ -> pr "z"
9009         | StringList _ | DeviceList _ -> pr "O"
9010         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9011         | Int _ -> pr "i"
9012         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9013                              * emulate C's int/long/long long in Python?
9014                              *)
9015       ) (snd style);
9016       pr ":guestfs_%s\",\n" name;
9017       pr "                         &py_g";
9018       List.iter (
9019         function
9020         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9021         | OptString n -> pr ", &%s" n
9022         | StringList n | DeviceList n -> pr ", &py_%s" n
9023         | Bool n -> pr ", &%s" n
9024         | Int n -> pr ", &%s" n
9025         | Int64 n -> pr ", &%s" n
9026       ) (snd style);
9027
9028       pr "))\n";
9029       pr "    return NULL;\n";
9030
9031       pr "  g = get_handle (py_g);\n";
9032       List.iter (
9033         function
9034         | Pathname _ | Device _ | Dev_or_Path _ | String _
9035         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9036         | StringList n | DeviceList n ->
9037             pr "  %s = get_string_list (py_%s);\n" n n;
9038             pr "  if (!%s) return NULL;\n" n
9039       ) (snd style);
9040
9041       pr "\n";
9042
9043       pr "  r = guestfs_%s " name;
9044       generate_c_call_args ~handle:"g" style;
9045       pr ";\n";
9046
9047       List.iter (
9048         function
9049         | Pathname _ | Device _ | Dev_or_Path _ | String _
9050         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9051         | StringList n | DeviceList n ->
9052             pr "  free (%s);\n" n
9053       ) (snd style);
9054
9055       pr "  if (r == %s) {\n" error_code;
9056       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9057       pr "    return NULL;\n";
9058       pr "  }\n";
9059       pr "\n";
9060
9061       (match fst style with
9062        | RErr ->
9063            pr "  Py_INCREF (Py_None);\n";
9064            pr "  py_r = Py_None;\n"
9065        | RInt _
9066        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9067        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9068        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9069        | RConstOptString _ ->
9070            pr "  if (r)\n";
9071            pr "    py_r = PyString_FromString (r);\n";
9072            pr "  else {\n";
9073            pr "    Py_INCREF (Py_None);\n";
9074            pr "    py_r = Py_None;\n";
9075            pr "  }\n"
9076        | RString _ ->
9077            pr "  py_r = PyString_FromString (r);\n";
9078            pr "  free (r);\n"
9079        | RStringList _ ->
9080            pr "  py_r = put_string_list (r);\n";
9081            pr "  free_strings (r);\n"
9082        | RStruct (_, typ) ->
9083            pr "  py_r = put_%s (r);\n" typ;
9084            pr "  guestfs_free_%s (r);\n" typ
9085        | RStructList (_, typ) ->
9086            pr "  py_r = put_%s_list (r);\n" typ;
9087            pr "  guestfs_free_%s_list (r);\n" typ
9088        | RHashtable n ->
9089            pr "  py_r = put_table (r);\n";
9090            pr "  free_strings (r);\n"
9091        | RBufferOut _ ->
9092            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9093            pr "  free (r);\n"
9094       );
9095
9096       pr "  return py_r;\n";
9097       pr "}\n";
9098       pr "\n"
9099   ) all_functions;
9100
9101   (* Table of functions. *)
9102   pr "static PyMethodDef methods[] = {\n";
9103   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9104   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9105   List.iter (
9106     fun (name, _, _, _, _, _, _) ->
9107       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9108         name name
9109   ) all_functions;
9110   pr "  { NULL, NULL, 0, NULL }\n";
9111   pr "};\n";
9112   pr "\n";
9113
9114   (* Init function. *)
9115   pr "\
9116 void
9117 initlibguestfsmod (void)
9118 {
9119   static int initialized = 0;
9120
9121   if (initialized) return;
9122   Py_InitModule ((char *) \"libguestfsmod\", methods);
9123   initialized = 1;
9124 }
9125 "
9126
9127 (* Generate Python module. *)
9128 and generate_python_py () =
9129   generate_header HashStyle LGPLv2plus;
9130
9131   pr "\
9132 u\"\"\"Python bindings for libguestfs
9133
9134 import guestfs
9135 g = guestfs.GuestFS ()
9136 g.add_drive (\"guest.img\")
9137 g.launch ()
9138 parts = g.list_partitions ()
9139
9140 The guestfs module provides a Python binding to the libguestfs API
9141 for examining and modifying virtual machine disk images.
9142
9143 Amongst the things this is good for: making batch configuration
9144 changes to guests, getting disk used/free statistics (see also:
9145 virt-df), migrating between virtualization systems (see also:
9146 virt-p2v), performing partial backups, performing partial guest
9147 clones, cloning guests and changing registry/UUID/hostname info, and
9148 much else besides.
9149
9150 Libguestfs uses Linux kernel and qemu code, and can access any type of
9151 guest filesystem that Linux and qemu can, including but not limited
9152 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9153 schemes, qcow, qcow2, vmdk.
9154
9155 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9156 LVs, what filesystem is in each LV, etc.).  It can also run commands
9157 in the context of the guest.  Also you can access filesystems over
9158 FUSE.
9159
9160 Errors which happen while using the API are turned into Python
9161 RuntimeError exceptions.
9162
9163 To create a guestfs handle you usually have to perform the following
9164 sequence of calls:
9165
9166 # Create the handle, call add_drive at least once, and possibly
9167 # several times if the guest has multiple block devices:
9168 g = guestfs.GuestFS ()
9169 g.add_drive (\"guest.img\")
9170
9171 # Launch the qemu subprocess and wait for it to become ready:
9172 g.launch ()
9173
9174 # Now you can issue commands, for example:
9175 logvols = g.lvs ()
9176
9177 \"\"\"
9178
9179 import libguestfsmod
9180
9181 class GuestFS:
9182     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9183
9184     def __init__ (self):
9185         \"\"\"Create a new libguestfs handle.\"\"\"
9186         self._o = libguestfsmod.create ()
9187
9188     def __del__ (self):
9189         libguestfsmod.close (self._o)
9190
9191 ";
9192
9193   List.iter (
9194     fun (name, style, _, flags, _, _, longdesc) ->
9195       pr "    def %s " name;
9196       generate_py_call_args ~handle:"self" (snd style);
9197       pr ":\n";
9198
9199       if not (List.mem NotInDocs flags) then (
9200         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9201         let doc =
9202           match fst style with
9203           | RErr | RInt _ | RInt64 _ | RBool _
9204           | RConstOptString _ | RConstString _
9205           | RString _ | RBufferOut _ -> doc
9206           | RStringList _ ->
9207               doc ^ "\n\nThis function returns a list of strings."
9208           | RStruct (_, typ) ->
9209               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9210           | RStructList (_, typ) ->
9211               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9212           | RHashtable _ ->
9213               doc ^ "\n\nThis function returns a dictionary." in
9214         let doc =
9215           if List.mem ProtocolLimitWarning flags then
9216             doc ^ "\n\n" ^ protocol_limit_warning
9217           else doc in
9218         let doc =
9219           if List.mem DangerWillRobinson flags then
9220             doc ^ "\n\n" ^ danger_will_robinson
9221           else doc in
9222         let doc =
9223           match deprecation_notice flags with
9224           | None -> doc
9225           | Some txt -> doc ^ "\n\n" ^ txt in
9226         let doc = pod2text ~width:60 name doc in
9227         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9228         let doc = String.concat "\n        " doc in
9229         pr "        u\"\"\"%s\"\"\"\n" doc;
9230       );
9231       pr "        return libguestfsmod.%s " name;
9232       generate_py_call_args ~handle:"self._o" (snd style);
9233       pr "\n";
9234       pr "\n";
9235   ) all_functions
9236
9237 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9238 and generate_py_call_args ~handle args =
9239   pr "(%s" handle;
9240   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9241   pr ")"
9242
9243 (* Useful if you need the longdesc POD text as plain text.  Returns a
9244  * list of lines.
9245  *
9246  * Because this is very slow (the slowest part of autogeneration),
9247  * we memoize the results.
9248  *)
9249 and pod2text ~width name longdesc =
9250   let key = width, name, longdesc in
9251   try Hashtbl.find pod2text_memo key
9252   with Not_found ->
9253     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9254     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9255     close_out chan;
9256     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9257     let chan = open_process_in cmd in
9258     let lines = ref [] in
9259     let rec loop i =
9260       let line = input_line chan in
9261       if i = 1 then             (* discard the first line of output *)
9262         loop (i+1)
9263       else (
9264         let line = triml line in
9265         lines := line :: !lines;
9266         loop (i+1)
9267       ) in
9268     let lines = try loop 1 with End_of_file -> List.rev !lines in
9269     unlink filename;
9270     (match close_process_in chan with
9271      | WEXITED 0 -> ()
9272      | WEXITED i ->
9273          failwithf "pod2text: process exited with non-zero status (%d)" i
9274      | WSIGNALED i | WSTOPPED i ->
9275          failwithf "pod2text: process signalled or stopped by signal %d" i
9276     );
9277     Hashtbl.add pod2text_memo key lines;
9278     pod2text_memo_updated ();
9279     lines
9280
9281 (* Generate ruby bindings. *)
9282 and generate_ruby_c () =
9283   generate_header CStyle LGPLv2plus;
9284
9285   pr "\
9286 #include <stdio.h>
9287 #include <stdlib.h>
9288
9289 #include <ruby.h>
9290
9291 #include \"guestfs.h\"
9292
9293 #include \"extconf.h\"
9294
9295 /* For Ruby < 1.9 */
9296 #ifndef RARRAY_LEN
9297 #define RARRAY_LEN(r) (RARRAY((r))->len)
9298 #endif
9299
9300 static VALUE m_guestfs;                 /* guestfs module */
9301 static VALUE c_guestfs;                 /* guestfs_h handle */
9302 static VALUE e_Error;                   /* used for all errors */
9303
9304 static void ruby_guestfs_free (void *p)
9305 {
9306   if (!p) return;
9307   guestfs_close ((guestfs_h *) p);
9308 }
9309
9310 static VALUE ruby_guestfs_create (VALUE m)
9311 {
9312   guestfs_h *g;
9313
9314   g = guestfs_create ();
9315   if (!g)
9316     rb_raise (e_Error, \"failed to create guestfs handle\");
9317
9318   /* Don't print error messages to stderr by default. */
9319   guestfs_set_error_handler (g, NULL, NULL);
9320
9321   /* Wrap it, and make sure the close function is called when the
9322    * handle goes away.
9323    */
9324   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9325 }
9326
9327 static VALUE ruby_guestfs_close (VALUE gv)
9328 {
9329   guestfs_h *g;
9330   Data_Get_Struct (gv, guestfs_h, g);
9331
9332   ruby_guestfs_free (g);
9333   DATA_PTR (gv) = NULL;
9334
9335   return Qnil;
9336 }
9337
9338 ";
9339
9340   List.iter (
9341     fun (name, style, _, _, _, _, _) ->
9342       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9343       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9344       pr ")\n";
9345       pr "{\n";
9346       pr "  guestfs_h *g;\n";
9347       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9348       pr "  if (!g)\n";
9349       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9350         name;
9351       pr "\n";
9352
9353       List.iter (
9354         function
9355         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9356             pr "  Check_Type (%sv, T_STRING);\n" n;
9357             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9358             pr "  if (!%s)\n" n;
9359             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9360             pr "              \"%s\", \"%s\");\n" n name
9361         | OptString n ->
9362             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9363         | StringList n | DeviceList n ->
9364             pr "  char **%s;\n" n;
9365             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9366             pr "  {\n";
9367             pr "    int i, len;\n";
9368             pr "    len = RARRAY_LEN (%sv);\n" n;
9369             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9370               n;
9371             pr "    for (i = 0; i < len; ++i) {\n";
9372             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9373             pr "      %s[i] = StringValueCStr (v);\n" n;
9374             pr "    }\n";
9375             pr "    %s[len] = NULL;\n" n;
9376             pr "  }\n";
9377         | Bool n ->
9378             pr "  int %s = RTEST (%sv);\n" n n
9379         | Int n ->
9380             pr "  int %s = NUM2INT (%sv);\n" n n
9381         | Int64 n ->
9382             pr "  long long %s = NUM2LL (%sv);\n" n n
9383       ) (snd style);
9384       pr "\n";
9385
9386       let error_code =
9387         match fst style with
9388         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9389         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9390         | RConstString _ | RConstOptString _ ->
9391             pr "  const char *r;\n"; "NULL"
9392         | RString _ -> pr "  char *r;\n"; "NULL"
9393         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9394         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9395         | RStructList (_, typ) ->
9396             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9397         | RBufferOut _ ->
9398             pr "  char *r;\n";
9399             pr "  size_t size;\n";
9400             "NULL" in
9401       pr "\n";
9402
9403       pr "  r = guestfs_%s " name;
9404       generate_c_call_args ~handle:"g" style;
9405       pr ";\n";
9406
9407       List.iter (
9408         function
9409         | Pathname _ | Device _ | Dev_or_Path _ | String _
9410         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9411         | StringList n | DeviceList n ->
9412             pr "  free (%s);\n" n
9413       ) (snd style);
9414
9415       pr "  if (r == %s)\n" error_code;
9416       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9417       pr "\n";
9418
9419       (match fst style with
9420        | RErr ->
9421            pr "  return Qnil;\n"
9422        | RInt _ | RBool _ ->
9423            pr "  return INT2NUM (r);\n"
9424        | RInt64 _ ->
9425            pr "  return ULL2NUM (r);\n"
9426        | RConstString _ ->
9427            pr "  return rb_str_new2 (r);\n";
9428        | RConstOptString _ ->
9429            pr "  if (r)\n";
9430            pr "    return rb_str_new2 (r);\n";
9431            pr "  else\n";
9432            pr "    return Qnil;\n";
9433        | RString _ ->
9434            pr "  VALUE rv = rb_str_new2 (r);\n";
9435            pr "  free (r);\n";
9436            pr "  return rv;\n";
9437        | RStringList _ ->
9438            pr "  int i, len = 0;\n";
9439            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9440            pr "  VALUE rv = rb_ary_new2 (len);\n";
9441            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9442            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9443            pr "    free (r[i]);\n";
9444            pr "  }\n";
9445            pr "  free (r);\n";
9446            pr "  return rv;\n"
9447        | RStruct (_, typ) ->
9448            let cols = cols_of_struct typ in
9449            generate_ruby_struct_code typ cols
9450        | RStructList (_, typ) ->
9451            let cols = cols_of_struct typ in
9452            generate_ruby_struct_list_code typ cols
9453        | RHashtable _ ->
9454            pr "  VALUE rv = rb_hash_new ();\n";
9455            pr "  int i;\n";
9456            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9457            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9458            pr "    free (r[i]);\n";
9459            pr "    free (r[i+1]);\n";
9460            pr "  }\n";
9461            pr "  free (r);\n";
9462            pr "  return rv;\n"
9463        | RBufferOut _ ->
9464            pr "  VALUE rv = rb_str_new (r, size);\n";
9465            pr "  free (r);\n";
9466            pr "  return rv;\n";
9467       );
9468
9469       pr "}\n";
9470       pr "\n"
9471   ) all_functions;
9472
9473   pr "\
9474 /* Initialize the module. */
9475 void Init__guestfs ()
9476 {
9477   m_guestfs = rb_define_module (\"Guestfs\");
9478   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9479   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9480
9481   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9482   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9483
9484 ";
9485   (* Define the rest of the methods. *)
9486   List.iter (
9487     fun (name, style, _, _, _, _, _) ->
9488       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9489       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9490   ) all_functions;
9491
9492   pr "}\n"
9493
9494 (* Ruby code to return a struct. *)
9495 and generate_ruby_struct_code typ cols =
9496   pr "  VALUE rv = rb_hash_new ();\n";
9497   List.iter (
9498     function
9499     | name, FString ->
9500         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9501     | name, FBuffer ->
9502         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9503     | name, FUUID ->
9504         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9505     | name, (FBytes|FUInt64) ->
9506         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9507     | name, FInt64 ->
9508         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9509     | name, FUInt32 ->
9510         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9511     | name, FInt32 ->
9512         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9513     | name, FOptPercent ->
9514         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9515     | name, FChar -> (* XXX wrong? *)
9516         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9517   ) cols;
9518   pr "  guestfs_free_%s (r);\n" typ;
9519   pr "  return rv;\n"
9520
9521 (* Ruby code to return a struct list. *)
9522 and generate_ruby_struct_list_code typ cols =
9523   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9524   pr "  int i;\n";
9525   pr "  for (i = 0; i < r->len; ++i) {\n";
9526   pr "    VALUE hv = rb_hash_new ();\n";
9527   List.iter (
9528     function
9529     | name, FString ->
9530         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9531     | name, FBuffer ->
9532         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
9533     | name, FUUID ->
9534         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9535     | name, (FBytes|FUInt64) ->
9536         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9537     | name, FInt64 ->
9538         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9539     | name, FUInt32 ->
9540         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9541     | name, FInt32 ->
9542         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9543     | name, FOptPercent ->
9544         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9545     | name, FChar -> (* XXX wrong? *)
9546         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9547   ) cols;
9548   pr "    rb_ary_push (rv, hv);\n";
9549   pr "  }\n";
9550   pr "  guestfs_free_%s_list (r);\n" typ;
9551   pr "  return rv;\n"
9552
9553 (* Generate Java bindings GuestFS.java file. *)
9554 and generate_java_java () =
9555   generate_header CStyle LGPLv2plus;
9556
9557   pr "\
9558 package com.redhat.et.libguestfs;
9559
9560 import java.util.HashMap;
9561 import com.redhat.et.libguestfs.LibGuestFSException;
9562 import com.redhat.et.libguestfs.PV;
9563 import com.redhat.et.libguestfs.VG;
9564 import com.redhat.et.libguestfs.LV;
9565 import com.redhat.et.libguestfs.Stat;
9566 import com.redhat.et.libguestfs.StatVFS;
9567 import com.redhat.et.libguestfs.IntBool;
9568 import com.redhat.et.libguestfs.Dirent;
9569
9570 /**
9571  * The GuestFS object is a libguestfs handle.
9572  *
9573  * @author rjones
9574  */
9575 public class GuestFS {
9576   // Load the native code.
9577   static {
9578     System.loadLibrary (\"guestfs_jni\");
9579   }
9580
9581   /**
9582    * The native guestfs_h pointer.
9583    */
9584   long g;
9585
9586   /**
9587    * Create a libguestfs handle.
9588    *
9589    * @throws LibGuestFSException
9590    */
9591   public GuestFS () throws LibGuestFSException
9592   {
9593     g = _create ();
9594   }
9595   private native long _create () throws LibGuestFSException;
9596
9597   /**
9598    * Close a libguestfs handle.
9599    *
9600    * You can also leave handles to be collected by the garbage
9601    * collector, but this method ensures that the resources used
9602    * by the handle are freed up immediately.  If you call any
9603    * other methods after closing the handle, you will get an
9604    * exception.
9605    *
9606    * @throws LibGuestFSException
9607    */
9608   public void close () throws LibGuestFSException
9609   {
9610     if (g != 0)
9611       _close (g);
9612     g = 0;
9613   }
9614   private native void _close (long g) throws LibGuestFSException;
9615
9616   public void finalize () throws LibGuestFSException
9617   {
9618     close ();
9619   }
9620
9621 ";
9622
9623   List.iter (
9624     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9625       if not (List.mem NotInDocs flags); then (
9626         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9627         let doc =
9628           if List.mem ProtocolLimitWarning flags then
9629             doc ^ "\n\n" ^ protocol_limit_warning
9630           else doc in
9631         let doc =
9632           if List.mem DangerWillRobinson flags then
9633             doc ^ "\n\n" ^ danger_will_robinson
9634           else doc in
9635         let doc =
9636           match deprecation_notice flags with
9637           | None -> doc
9638           | Some txt -> doc ^ "\n\n" ^ txt in
9639         let doc = pod2text ~width:60 name doc in
9640         let doc = List.map (            (* RHBZ#501883 *)
9641           function
9642           | "" -> "<p>"
9643           | nonempty -> nonempty
9644         ) doc in
9645         let doc = String.concat "\n   * " doc in
9646
9647         pr "  /**\n";
9648         pr "   * %s\n" shortdesc;
9649         pr "   * <p>\n";
9650         pr "   * %s\n" doc;
9651         pr "   * @throws LibGuestFSException\n";
9652         pr "   */\n";
9653         pr "  ";
9654       );
9655       generate_java_prototype ~public:true ~semicolon:false name style;
9656       pr "\n";
9657       pr "  {\n";
9658       pr "    if (g == 0)\n";
9659       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9660         name;
9661       pr "    ";
9662       if fst style <> RErr then pr "return ";
9663       pr "_%s " name;
9664       generate_java_call_args ~handle:"g" (snd style);
9665       pr ";\n";
9666       pr "  }\n";
9667       pr "  ";
9668       generate_java_prototype ~privat:true ~native:true name style;
9669       pr "\n";
9670       pr "\n";
9671   ) all_functions;
9672
9673   pr "}\n"
9674
9675 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9676 and generate_java_call_args ~handle args =
9677   pr "(%s" handle;
9678   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9679   pr ")"
9680
9681 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9682     ?(semicolon=true) name style =
9683   if privat then pr "private ";
9684   if public then pr "public ";
9685   if native then pr "native ";
9686
9687   (* return type *)
9688   (match fst style with
9689    | RErr -> pr "void ";
9690    | RInt _ -> pr "int ";
9691    | RInt64 _ -> pr "long ";
9692    | RBool _ -> pr "boolean ";
9693    | RConstString _ | RConstOptString _ | RString _
9694    | RBufferOut _ -> pr "String ";
9695    | RStringList _ -> pr "String[] ";
9696    | RStruct (_, typ) ->
9697        let name = java_name_of_struct typ in
9698        pr "%s " name;
9699    | RStructList (_, typ) ->
9700        let name = java_name_of_struct typ in
9701        pr "%s[] " name;
9702    | RHashtable _ -> pr "HashMap<String,String> ";
9703   );
9704
9705   if native then pr "_%s " name else pr "%s " name;
9706   pr "(";
9707   let needs_comma = ref false in
9708   if native then (
9709     pr "long g";
9710     needs_comma := true
9711   );
9712
9713   (* args *)
9714   List.iter (
9715     fun arg ->
9716       if !needs_comma then pr ", ";
9717       needs_comma := true;
9718
9719       match arg with
9720       | Pathname n
9721       | Device n | Dev_or_Path n
9722       | String n
9723       | OptString n
9724       | FileIn n
9725       | FileOut n ->
9726           pr "String %s" n
9727       | StringList n | DeviceList n ->
9728           pr "String[] %s" n
9729       | Bool n ->
9730           pr "boolean %s" n
9731       | Int n ->
9732           pr "int %s" n
9733       | Int64 n ->
9734           pr "long %s" n
9735   ) (snd style);
9736
9737   pr ")\n";
9738   pr "    throws LibGuestFSException";
9739   if semicolon then pr ";"
9740
9741 and generate_java_struct jtyp cols () =
9742   generate_header CStyle LGPLv2plus;
9743
9744   pr "\
9745 package com.redhat.et.libguestfs;
9746
9747 /**
9748  * Libguestfs %s structure.
9749  *
9750  * @author rjones
9751  * @see GuestFS
9752  */
9753 public class %s {
9754 " jtyp jtyp;
9755
9756   List.iter (
9757     function
9758     | name, FString
9759     | name, FUUID
9760     | name, FBuffer -> pr "  public String %s;\n" name
9761     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9762     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9763     | name, FChar -> pr "  public char %s;\n" name
9764     | name, FOptPercent ->
9765         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9766         pr "  public float %s;\n" name
9767   ) cols;
9768
9769   pr "}\n"
9770
9771 and generate_java_c () =
9772   generate_header CStyle LGPLv2plus;
9773
9774   pr "\
9775 #include <stdio.h>
9776 #include <stdlib.h>
9777 #include <string.h>
9778
9779 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9780 #include \"guestfs.h\"
9781
9782 /* Note that this function returns.  The exception is not thrown
9783  * until after the wrapper function returns.
9784  */
9785 static void
9786 throw_exception (JNIEnv *env, const char *msg)
9787 {
9788   jclass cl;
9789   cl = (*env)->FindClass (env,
9790                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9791   (*env)->ThrowNew (env, cl, msg);
9792 }
9793
9794 JNIEXPORT jlong JNICALL
9795 Java_com_redhat_et_libguestfs_GuestFS__1create
9796   (JNIEnv *env, jobject obj)
9797 {
9798   guestfs_h *g;
9799
9800   g = guestfs_create ();
9801   if (g == NULL) {
9802     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9803     return 0;
9804   }
9805   guestfs_set_error_handler (g, NULL, NULL);
9806   return (jlong) (long) g;
9807 }
9808
9809 JNIEXPORT void JNICALL
9810 Java_com_redhat_et_libguestfs_GuestFS__1close
9811   (JNIEnv *env, jobject obj, jlong jg)
9812 {
9813   guestfs_h *g = (guestfs_h *) (long) jg;
9814   guestfs_close (g);
9815 }
9816
9817 ";
9818
9819   List.iter (
9820     fun (name, style, _, _, _, _, _) ->
9821       pr "JNIEXPORT ";
9822       (match fst style with
9823        | RErr -> pr "void ";
9824        | RInt _ -> pr "jint ";
9825        | RInt64 _ -> pr "jlong ";
9826        | RBool _ -> pr "jboolean ";
9827        | RConstString _ | RConstOptString _ | RString _
9828        | RBufferOut _ -> pr "jstring ";
9829        | RStruct _ | RHashtable _ ->
9830            pr "jobject ";
9831        | RStringList _ | RStructList _ ->
9832            pr "jobjectArray ";
9833       );
9834       pr "JNICALL\n";
9835       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9836       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9837       pr "\n";
9838       pr "  (JNIEnv *env, jobject obj, jlong jg";
9839       List.iter (
9840         function
9841         | Pathname n
9842         | Device n | Dev_or_Path n
9843         | String n
9844         | OptString n
9845         | FileIn n
9846         | FileOut n ->
9847             pr ", jstring j%s" n
9848         | StringList n | DeviceList n ->
9849             pr ", jobjectArray j%s" n
9850         | Bool n ->
9851             pr ", jboolean j%s" n
9852         | Int n ->
9853             pr ", jint j%s" n
9854         | Int64 n ->
9855             pr ", jlong j%s" n
9856       ) (snd style);
9857       pr ")\n";
9858       pr "{\n";
9859       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9860       let error_code, no_ret =
9861         match fst style with
9862         | RErr -> pr "  int r;\n"; "-1", ""
9863         | RBool _
9864         | RInt _ -> pr "  int r;\n"; "-1", "0"
9865         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9866         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9867         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9868         | RString _ ->
9869             pr "  jstring jr;\n";
9870             pr "  char *r;\n"; "NULL", "NULL"
9871         | RStringList _ ->
9872             pr "  jobjectArray jr;\n";
9873             pr "  int r_len;\n";
9874             pr "  jclass cl;\n";
9875             pr "  jstring jstr;\n";
9876             pr "  char **r;\n"; "NULL", "NULL"
9877         | RStruct (_, typ) ->
9878             pr "  jobject jr;\n";
9879             pr "  jclass cl;\n";
9880             pr "  jfieldID fl;\n";
9881             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9882         | RStructList (_, typ) ->
9883             pr "  jobjectArray jr;\n";
9884             pr "  jclass cl;\n";
9885             pr "  jfieldID fl;\n";
9886             pr "  jobject jfl;\n";
9887             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9888         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9889         | RBufferOut _ ->
9890             pr "  jstring jr;\n";
9891             pr "  char *r;\n";
9892             pr "  size_t size;\n";
9893             "NULL", "NULL" in
9894       List.iter (
9895         function
9896         | Pathname n
9897         | Device n | Dev_or_Path n
9898         | String n
9899         | OptString n
9900         | FileIn n
9901         | FileOut n ->
9902             pr "  const char *%s;\n" n
9903         | StringList n | DeviceList n ->
9904             pr "  int %s_len;\n" n;
9905             pr "  const char **%s;\n" n
9906         | Bool n
9907         | Int n ->
9908             pr "  int %s;\n" n
9909         | Int64 n ->
9910             pr "  int64_t %s;\n" n
9911       ) (snd style);
9912
9913       let needs_i =
9914         (match fst style with
9915          | RStringList _ | RStructList _ -> true
9916          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9917          | RConstOptString _
9918          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9919           List.exists (function
9920                        | StringList _ -> true
9921                        | DeviceList _ -> true
9922                        | _ -> false) (snd style) in
9923       if needs_i then
9924         pr "  int i;\n";
9925
9926       pr "\n";
9927
9928       (* Get the parameters. *)
9929       List.iter (
9930         function
9931         | Pathname n
9932         | Device n | Dev_or_Path n
9933         | String n
9934         | FileIn n
9935         | FileOut n ->
9936             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9937         | OptString n ->
9938             (* This is completely undocumented, but Java null becomes
9939              * a NULL parameter.
9940              *)
9941             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9942         | StringList n | DeviceList n ->
9943             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9944             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9945             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9946             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9947               n;
9948             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9949             pr "  }\n";
9950             pr "  %s[%s_len] = NULL;\n" n n;
9951         | Bool n
9952         | Int n
9953         | Int64 n ->
9954             pr "  %s = j%s;\n" n n
9955       ) (snd style);
9956
9957       (* Make the call. *)
9958       pr "  r = guestfs_%s " name;
9959       generate_c_call_args ~handle:"g" style;
9960       pr ";\n";
9961
9962       (* Release the parameters. *)
9963       List.iter (
9964         function
9965         | Pathname n
9966         | Device n | Dev_or_Path n
9967         | String n
9968         | FileIn n
9969         | FileOut n ->
9970             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9971         | OptString n ->
9972             pr "  if (j%s)\n" n;
9973             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9974         | StringList n | DeviceList n ->
9975             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9976             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9977               n;
9978             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9979             pr "  }\n";
9980             pr "  free (%s);\n" n
9981         | Bool n
9982         | Int n
9983         | Int64 n -> ()
9984       ) (snd style);
9985
9986       (* Check for errors. *)
9987       pr "  if (r == %s) {\n" error_code;
9988       pr "    throw_exception (env, guestfs_last_error (g));\n";
9989       pr "    return %s;\n" no_ret;
9990       pr "  }\n";
9991
9992       (* Return value. *)
9993       (match fst style with
9994        | RErr -> ()
9995        | RInt _ -> pr "  return (jint) r;\n"
9996        | RBool _ -> pr "  return (jboolean) r;\n"
9997        | RInt64 _ -> pr "  return (jlong) r;\n"
9998        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9999        | RConstOptString _ ->
10000            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10001        | RString _ ->
10002            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10003            pr "  free (r);\n";
10004            pr "  return jr;\n"
10005        | RStringList _ ->
10006            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10007            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10008            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10009            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10010            pr "  for (i = 0; i < r_len; ++i) {\n";
10011            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10012            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10013            pr "    free (r[i]);\n";
10014            pr "  }\n";
10015            pr "  free (r);\n";
10016            pr "  return jr;\n"
10017        | RStruct (_, typ) ->
10018            let jtyp = java_name_of_struct typ in
10019            let cols = cols_of_struct typ in
10020            generate_java_struct_return typ jtyp cols
10021        | RStructList (_, typ) ->
10022            let jtyp = java_name_of_struct typ in
10023            let cols = cols_of_struct typ in
10024            generate_java_struct_list_return typ jtyp cols
10025        | RHashtable _ ->
10026            (* XXX *)
10027            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10028            pr "  return NULL;\n"
10029        | RBufferOut _ ->
10030            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10031            pr "  free (r);\n";
10032            pr "  return jr;\n"
10033       );
10034
10035       pr "}\n";
10036       pr "\n"
10037   ) all_functions
10038
10039 and generate_java_struct_return typ jtyp cols =
10040   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10041   pr "  jr = (*env)->AllocObject (env, cl);\n";
10042   List.iter (
10043     function
10044     | name, FString ->
10045         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10046         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10047     | name, FUUID ->
10048         pr "  {\n";
10049         pr "    char s[33];\n";
10050         pr "    memcpy (s, r->%s, 32);\n" name;
10051         pr "    s[32] = 0;\n";
10052         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10053         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10054         pr "  }\n";
10055     | name, FBuffer ->
10056         pr "  {\n";
10057         pr "    int len = r->%s_len;\n" name;
10058         pr "    char s[len+1];\n";
10059         pr "    memcpy (s, r->%s, len);\n" name;
10060         pr "    s[len] = 0;\n";
10061         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10062         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10063         pr "  }\n";
10064     | name, (FBytes|FUInt64|FInt64) ->
10065         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10066         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10067     | name, (FUInt32|FInt32) ->
10068         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10069         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10070     | name, FOptPercent ->
10071         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10072         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10073     | name, FChar ->
10074         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10075         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10076   ) cols;
10077   pr "  free (r);\n";
10078   pr "  return jr;\n"
10079
10080 and generate_java_struct_list_return typ jtyp cols =
10081   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10082   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10083   pr "  for (i = 0; i < r->len; ++i) {\n";
10084   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10085   List.iter (
10086     function
10087     | name, FString ->
10088         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10089         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10090     | name, FUUID ->
10091         pr "    {\n";
10092         pr "      char s[33];\n";
10093         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10094         pr "      s[32] = 0;\n";
10095         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10096         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10097         pr "    }\n";
10098     | name, FBuffer ->
10099         pr "    {\n";
10100         pr "      int len = r->val[i].%s_len;\n" name;
10101         pr "      char s[len+1];\n";
10102         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10103         pr "      s[len] = 0;\n";
10104         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10105         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10106         pr "    }\n";
10107     | name, (FBytes|FUInt64|FInt64) ->
10108         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10109         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10110     | name, (FUInt32|FInt32) ->
10111         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10112         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10113     | name, FOptPercent ->
10114         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10115         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10116     | name, FChar ->
10117         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10118         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10119   ) cols;
10120   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10121   pr "  }\n";
10122   pr "  guestfs_free_%s_list (r);\n" typ;
10123   pr "  return jr;\n"
10124
10125 and generate_java_makefile_inc () =
10126   generate_header HashStyle GPLv2plus;
10127
10128   pr "java_built_sources = \\\n";
10129   List.iter (
10130     fun (typ, jtyp) ->
10131         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10132   ) java_structs;
10133   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10134
10135 and generate_haskell_hs () =
10136   generate_header HaskellStyle LGPLv2plus;
10137
10138   (* XXX We only know how to generate partial FFI for Haskell
10139    * at the moment.  Please help out!
10140    *)
10141   let can_generate style =
10142     match style with
10143     | RErr, _
10144     | RInt _, _
10145     | RInt64 _, _ -> true
10146     | RBool _, _
10147     | RConstString _, _
10148     | RConstOptString _, _
10149     | RString _, _
10150     | RStringList _, _
10151     | RStruct _, _
10152     | RStructList _, _
10153     | RHashtable _, _
10154     | RBufferOut _, _ -> false in
10155
10156   pr "\
10157 {-# INCLUDE <guestfs.h> #-}
10158 {-# LANGUAGE ForeignFunctionInterface #-}
10159
10160 module Guestfs (
10161   create";
10162
10163   (* List out the names of the actions we want to export. *)
10164   List.iter (
10165     fun (name, style, _, _, _, _, _) ->
10166       if can_generate style then pr ",\n  %s" name
10167   ) all_functions;
10168
10169   pr "
10170   ) where
10171
10172 -- Unfortunately some symbols duplicate ones already present
10173 -- in Prelude.  We don't know which, so we hard-code a list
10174 -- here.
10175 import Prelude hiding (truncate)
10176
10177 import Foreign
10178 import Foreign.C
10179 import Foreign.C.Types
10180 import IO
10181 import Control.Exception
10182 import Data.Typeable
10183
10184 data GuestfsS = GuestfsS            -- represents the opaque C struct
10185 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10186 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10187
10188 -- XXX define properly later XXX
10189 data PV = PV
10190 data VG = VG
10191 data LV = LV
10192 data IntBool = IntBool
10193 data Stat = Stat
10194 data StatVFS = StatVFS
10195 data Hashtable = Hashtable
10196
10197 foreign import ccall unsafe \"guestfs_create\" c_create
10198   :: IO GuestfsP
10199 foreign import ccall unsafe \"&guestfs_close\" c_close
10200   :: FunPtr (GuestfsP -> IO ())
10201 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10202   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10203
10204 create :: IO GuestfsH
10205 create = do
10206   p <- c_create
10207   c_set_error_handler p nullPtr nullPtr
10208   h <- newForeignPtr c_close p
10209   return h
10210
10211 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10212   :: GuestfsP -> IO CString
10213
10214 -- last_error :: GuestfsH -> IO (Maybe String)
10215 -- last_error h = do
10216 --   str <- withForeignPtr h (\\p -> c_last_error p)
10217 --   maybePeek peekCString str
10218
10219 last_error :: GuestfsH -> IO (String)
10220 last_error h = do
10221   str <- withForeignPtr h (\\p -> c_last_error p)
10222   if (str == nullPtr)
10223     then return \"no error\"
10224     else peekCString str
10225
10226 ";
10227
10228   (* Generate wrappers for each foreign function. *)
10229   List.iter (
10230     fun (name, style, _, _, _, _, _) ->
10231       if can_generate style then (
10232         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10233         pr "  :: ";
10234         generate_haskell_prototype ~handle:"GuestfsP" style;
10235         pr "\n";
10236         pr "\n";
10237         pr "%s :: " name;
10238         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10239         pr "\n";
10240         pr "%s %s = do\n" name
10241           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10242         pr "  r <- ";
10243         (* Convert pointer arguments using with* functions. *)
10244         List.iter (
10245           function
10246           | FileIn n
10247           | FileOut n
10248           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10249           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10250           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10251           | Bool _ | Int _ | Int64 _ -> ()
10252         ) (snd style);
10253         (* Convert integer arguments. *)
10254         let args =
10255           List.map (
10256             function
10257             | Bool n -> sprintf "(fromBool %s)" n
10258             | Int n -> sprintf "(fromIntegral %s)" n
10259             | Int64 n -> sprintf "(fromIntegral %s)" n
10260             | FileIn n | FileOut n
10261             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10262           ) (snd style) in
10263         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10264           (String.concat " " ("p" :: args));
10265         (match fst style with
10266          | RErr | RInt _ | RInt64 _ | RBool _ ->
10267              pr "  if (r == -1)\n";
10268              pr "    then do\n";
10269              pr "      err <- last_error h\n";
10270              pr "      fail err\n";
10271          | RConstString _ | RConstOptString _ | RString _
10272          | RStringList _ | RStruct _
10273          | RStructList _ | RHashtable _ | RBufferOut _ ->
10274              pr "  if (r == nullPtr)\n";
10275              pr "    then do\n";
10276              pr "      err <- last_error h\n";
10277              pr "      fail err\n";
10278         );
10279         (match fst style with
10280          | RErr ->
10281              pr "    else return ()\n"
10282          | RInt _ ->
10283              pr "    else return (fromIntegral r)\n"
10284          | RInt64 _ ->
10285              pr "    else return (fromIntegral r)\n"
10286          | RBool _ ->
10287              pr "    else return (toBool r)\n"
10288          | RConstString _
10289          | RConstOptString _
10290          | RString _
10291          | RStringList _
10292          | RStruct _
10293          | RStructList _
10294          | RHashtable _
10295          | RBufferOut _ ->
10296              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10297         );
10298         pr "\n";
10299       )
10300   ) all_functions
10301
10302 and generate_haskell_prototype ~handle ?(hs = false) style =
10303   pr "%s -> " handle;
10304   let string = if hs then "String" else "CString" in
10305   let int = if hs then "Int" else "CInt" in
10306   let bool = if hs then "Bool" else "CInt" in
10307   let int64 = if hs then "Integer" else "Int64" in
10308   List.iter (
10309     fun arg ->
10310       (match arg with
10311        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10312        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10313        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10314        | Bool _ -> pr "%s" bool
10315        | Int _ -> pr "%s" int
10316        | Int64 _ -> pr "%s" int
10317        | FileIn _ -> pr "%s" string
10318        | FileOut _ -> pr "%s" string
10319       );
10320       pr " -> ";
10321   ) (snd style);
10322   pr "IO (";
10323   (match fst style with
10324    | RErr -> if not hs then pr "CInt"
10325    | RInt _ -> pr "%s" int
10326    | RInt64 _ -> pr "%s" int64
10327    | RBool _ -> pr "%s" bool
10328    | RConstString _ -> pr "%s" string
10329    | RConstOptString _ -> pr "Maybe %s" string
10330    | RString _ -> pr "%s" string
10331    | RStringList _ -> pr "[%s]" string
10332    | RStruct (_, typ) ->
10333        let name = java_name_of_struct typ in
10334        pr "%s" name
10335    | RStructList (_, typ) ->
10336        let name = java_name_of_struct typ in
10337        pr "[%s]" name
10338    | RHashtable _ -> pr "Hashtable"
10339    | RBufferOut _ -> pr "%s" string
10340   );
10341   pr ")"
10342
10343 and generate_csharp () =
10344   generate_header CPlusPlusStyle LGPLv2plus;
10345
10346   (* XXX Make this configurable by the C# assembly users. *)
10347   let library = "libguestfs.so.0" in
10348
10349   pr "\
10350 // These C# bindings are highly experimental at present.
10351 //
10352 // Firstly they only work on Linux (ie. Mono).  In order to get them
10353 // to work on Windows (ie. .Net) you would need to port the library
10354 // itself to Windows first.
10355 //
10356 // The second issue is that some calls are known to be incorrect and
10357 // can cause Mono to segfault.  Particularly: calls which pass or
10358 // return string[], or return any structure value.  This is because
10359 // we haven't worked out the correct way to do this from C#.
10360 //
10361 // The third issue is that when compiling you get a lot of warnings.
10362 // We are not sure whether the warnings are important or not.
10363 //
10364 // Fourthly we do not routinely build or test these bindings as part
10365 // of the make && make check cycle, which means that regressions might
10366 // go unnoticed.
10367 //
10368 // Suggestions and patches are welcome.
10369
10370 // To compile:
10371 //
10372 // gmcs Libguestfs.cs
10373 // mono Libguestfs.exe
10374 //
10375 // (You'll probably want to add a Test class / static main function
10376 // otherwise this won't do anything useful).
10377
10378 using System;
10379 using System.IO;
10380 using System.Runtime.InteropServices;
10381 using System.Runtime.Serialization;
10382 using System.Collections;
10383
10384 namespace Guestfs
10385 {
10386   class Error : System.ApplicationException
10387   {
10388     public Error (string message) : base (message) {}
10389     protected Error (SerializationInfo info, StreamingContext context) {}
10390   }
10391
10392   class Guestfs
10393   {
10394     IntPtr _handle;
10395
10396     [DllImport (\"%s\")]
10397     static extern IntPtr guestfs_create ();
10398
10399     public Guestfs ()
10400     {
10401       _handle = guestfs_create ();
10402       if (_handle == IntPtr.Zero)
10403         throw new Error (\"could not create guestfs handle\");
10404     }
10405
10406     [DllImport (\"%s\")]
10407     static extern void guestfs_close (IntPtr h);
10408
10409     ~Guestfs ()
10410     {
10411       guestfs_close (_handle);
10412     }
10413
10414     [DllImport (\"%s\")]
10415     static extern string guestfs_last_error (IntPtr h);
10416
10417 " library library library;
10418
10419   (* Generate C# structure bindings.  We prefix struct names with
10420    * underscore because C# cannot have conflicting struct names and
10421    * method names (eg. "class stat" and "stat").
10422    *)
10423   List.iter (
10424     fun (typ, cols) ->
10425       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10426       pr "    public class _%s {\n" typ;
10427       List.iter (
10428         function
10429         | name, FChar -> pr "      char %s;\n" name
10430         | name, FString -> pr "      string %s;\n" name
10431         | name, FBuffer ->
10432             pr "      uint %s_len;\n" name;
10433             pr "      string %s;\n" name
10434         | name, FUUID ->
10435             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10436             pr "      string %s;\n" name
10437         | name, FUInt32 -> pr "      uint %s;\n" name
10438         | name, FInt32 -> pr "      int %s;\n" name
10439         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10440         | name, FInt64 -> pr "      long %s;\n" name
10441         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10442       ) cols;
10443       pr "    }\n";
10444       pr "\n"
10445   ) structs;
10446
10447   (* Generate C# function bindings. *)
10448   List.iter (
10449     fun (name, style, _, _, _, shortdesc, _) ->
10450       let rec csharp_return_type () =
10451         match fst style with
10452         | RErr -> "void"
10453         | RBool n -> "bool"
10454         | RInt n -> "int"
10455         | RInt64 n -> "long"
10456         | RConstString n
10457         | RConstOptString n
10458         | RString n
10459         | RBufferOut n -> "string"
10460         | RStruct (_,n) -> "_" ^ n
10461         | RHashtable n -> "Hashtable"
10462         | RStringList n -> "string[]"
10463         | RStructList (_,n) -> sprintf "_%s[]" n
10464
10465       and c_return_type () =
10466         match fst style with
10467         | RErr
10468         | RBool _
10469         | RInt _ -> "int"
10470         | RInt64 _ -> "long"
10471         | RConstString _
10472         | RConstOptString _
10473         | RString _
10474         | RBufferOut _ -> "string"
10475         | RStruct (_,n) -> "_" ^ n
10476         | RHashtable _
10477         | RStringList _ -> "string[]"
10478         | RStructList (_,n) -> sprintf "_%s[]" n
10479
10480       and c_error_comparison () =
10481         match fst style with
10482         | RErr
10483         | RBool _
10484         | RInt _
10485         | RInt64 _ -> "== -1"
10486         | RConstString _
10487         | RConstOptString _
10488         | RString _
10489         | RBufferOut _
10490         | RStruct (_,_)
10491         | RHashtable _
10492         | RStringList _
10493         | RStructList (_,_) -> "== null"
10494
10495       and generate_extern_prototype () =
10496         pr "    static extern %s guestfs_%s (IntPtr h"
10497           (c_return_type ()) name;
10498         List.iter (
10499           function
10500           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10501           | FileIn n | FileOut n ->
10502               pr ", [In] string %s" n
10503           | StringList n | DeviceList n ->
10504               pr ", [In] string[] %s" n
10505           | Bool n ->
10506               pr ", bool %s" n
10507           | Int n ->
10508               pr ", int %s" n
10509           | Int64 n ->
10510               pr ", long %s" n
10511         ) (snd style);
10512         pr ");\n"
10513
10514       and generate_public_prototype () =
10515         pr "    public %s %s (" (csharp_return_type ()) name;
10516         let comma = ref false in
10517         let next () =
10518           if !comma then pr ", ";
10519           comma := true
10520         in
10521         List.iter (
10522           function
10523           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10524           | FileIn n | FileOut n ->
10525               next (); pr "string %s" n
10526           | StringList n | DeviceList n ->
10527               next (); pr "string[] %s" n
10528           | Bool n ->
10529               next (); pr "bool %s" n
10530           | Int n ->
10531               next (); pr "int %s" n
10532           | Int64 n ->
10533               next (); pr "long %s" n
10534         ) (snd style);
10535         pr ")\n"
10536
10537       and generate_call () =
10538         pr "guestfs_%s (_handle" name;
10539         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10540         pr ");\n";
10541       in
10542
10543       pr "    [DllImport (\"%s\")]\n" library;
10544       generate_extern_prototype ();
10545       pr "\n";
10546       pr "    /// <summary>\n";
10547       pr "    /// %s\n" shortdesc;
10548       pr "    /// </summary>\n";
10549       generate_public_prototype ();
10550       pr "    {\n";
10551       pr "      %s r;\n" (c_return_type ());
10552       pr "      r = ";
10553       generate_call ();
10554       pr "      if (r %s)\n" (c_error_comparison ());
10555       pr "        throw new Error (guestfs_last_error (_handle));\n";
10556       (match fst style with
10557        | RErr -> ()
10558        | RBool _ ->
10559            pr "      return r != 0 ? true : false;\n"
10560        | RHashtable _ ->
10561            pr "      Hashtable rr = new Hashtable ();\n";
10562            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10563            pr "        rr.Add (r[i], r[i+1]);\n";
10564            pr "      return rr;\n"
10565        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10566        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10567        | RStructList _ ->
10568            pr "      return r;\n"
10569       );
10570       pr "    }\n";
10571       pr "\n";
10572   ) all_functions_sorted;
10573
10574   pr "  }
10575 }
10576 "
10577
10578 and generate_bindtests () =
10579   generate_header CStyle LGPLv2plus;
10580
10581   pr "\
10582 #include <stdio.h>
10583 #include <stdlib.h>
10584 #include <inttypes.h>
10585 #include <string.h>
10586
10587 #include \"guestfs.h\"
10588 #include \"guestfs-internal.h\"
10589 #include \"guestfs-internal-actions.h\"
10590 #include \"guestfs_protocol.h\"
10591
10592 #define error guestfs_error
10593 #define safe_calloc guestfs_safe_calloc
10594 #define safe_malloc guestfs_safe_malloc
10595
10596 static void
10597 print_strings (char *const *argv)
10598 {
10599   int argc;
10600
10601   printf (\"[\");
10602   for (argc = 0; argv[argc] != NULL; ++argc) {
10603     if (argc > 0) printf (\", \");
10604     printf (\"\\\"%%s\\\"\", argv[argc]);
10605   }
10606   printf (\"]\\n\");
10607 }
10608
10609 /* The test0 function prints its parameters to stdout. */
10610 ";
10611
10612   let test0, tests =
10613     match test_functions with
10614     | [] -> assert false
10615     | test0 :: tests -> test0, tests in
10616
10617   let () =
10618     let (name, style, _, _, _, _, _) = test0 in
10619     generate_prototype ~extern:false ~semicolon:false ~newline:true
10620       ~handle:"g" ~prefix:"guestfs__" name style;
10621     pr "{\n";
10622     List.iter (
10623       function
10624       | Pathname n
10625       | Device n | Dev_or_Path n
10626       | String n
10627       | FileIn n
10628       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10629       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10630       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10631       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10632       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10633       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10634     ) (snd style);
10635     pr "  /* Java changes stdout line buffering so we need this: */\n";
10636     pr "  fflush (stdout);\n";
10637     pr "  return 0;\n";
10638     pr "}\n";
10639     pr "\n" in
10640
10641   List.iter (
10642     fun (name, style, _, _, _, _, _) ->
10643       if String.sub name (String.length name - 3) 3 <> "err" then (
10644         pr "/* Test normal return. */\n";
10645         generate_prototype ~extern:false ~semicolon:false ~newline:true
10646           ~handle:"g" ~prefix:"guestfs__" name style;
10647         pr "{\n";
10648         (match fst style with
10649          | RErr ->
10650              pr "  return 0;\n"
10651          | RInt _ ->
10652              pr "  int r;\n";
10653              pr "  sscanf (val, \"%%d\", &r);\n";
10654              pr "  return r;\n"
10655          | RInt64 _ ->
10656              pr "  int64_t r;\n";
10657              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10658              pr "  return r;\n"
10659          | RBool _ ->
10660              pr "  return STREQ (val, \"true\");\n"
10661          | RConstString _
10662          | RConstOptString _ ->
10663              (* Can't return the input string here.  Return a static
10664               * string so we ensure we get a segfault if the caller
10665               * tries to free it.
10666               *)
10667              pr "  return \"static string\";\n"
10668          | RString _ ->
10669              pr "  return strdup (val);\n"
10670          | RStringList _ ->
10671              pr "  char **strs;\n";
10672              pr "  int n, i;\n";
10673              pr "  sscanf (val, \"%%d\", &n);\n";
10674              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10675              pr "  for (i = 0; i < n; ++i) {\n";
10676              pr "    strs[i] = safe_malloc (g, 16);\n";
10677              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10678              pr "  }\n";
10679              pr "  strs[n] = NULL;\n";
10680              pr "  return strs;\n"
10681          | RStruct (_, typ) ->
10682              pr "  struct guestfs_%s *r;\n" typ;
10683              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10684              pr "  return r;\n"
10685          | RStructList (_, typ) ->
10686              pr "  struct guestfs_%s_list *r;\n" typ;
10687              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10688              pr "  sscanf (val, \"%%d\", &r->len);\n";
10689              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10690              pr "  return r;\n"
10691          | RHashtable _ ->
10692              pr "  char **strs;\n";
10693              pr "  int n, i;\n";
10694              pr "  sscanf (val, \"%%d\", &n);\n";
10695              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10696              pr "  for (i = 0; i < n; ++i) {\n";
10697              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10698              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10699              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10700              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10701              pr "  }\n";
10702              pr "  strs[n*2] = NULL;\n";
10703              pr "  return strs;\n"
10704          | RBufferOut _ ->
10705              pr "  return strdup (val);\n"
10706         );
10707         pr "}\n";
10708         pr "\n"
10709       ) else (
10710         pr "/* Test error return. */\n";
10711         generate_prototype ~extern:false ~semicolon:false ~newline:true
10712           ~handle:"g" ~prefix:"guestfs__" name style;
10713         pr "{\n";
10714         pr "  error (g, \"error\");\n";
10715         (match fst style with
10716          | RErr | RInt _ | RInt64 _ | RBool _ ->
10717              pr "  return -1;\n"
10718          | RConstString _ | RConstOptString _
10719          | RString _ | RStringList _ | RStruct _
10720          | RStructList _
10721          | RHashtable _
10722          | RBufferOut _ ->
10723              pr "  return NULL;\n"
10724         );
10725         pr "}\n";
10726         pr "\n"
10727       )
10728   ) tests
10729
10730 and generate_ocaml_bindtests () =
10731   generate_header OCamlStyle GPLv2plus;
10732
10733   pr "\
10734 let () =
10735   let g = Guestfs.create () in
10736 ";
10737
10738   let mkargs args =
10739     String.concat " " (
10740       List.map (
10741         function
10742         | CallString s -> "\"" ^ s ^ "\""
10743         | CallOptString None -> "None"
10744         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10745         | CallStringList xs ->
10746             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10747         | CallInt i when i >= 0 -> string_of_int i
10748         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10749         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10750         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10751         | CallBool b -> string_of_bool b
10752       ) args
10753     )
10754   in
10755
10756   generate_lang_bindtests (
10757     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10758   );
10759
10760   pr "print_endline \"EOF\"\n"
10761
10762 and generate_perl_bindtests () =
10763   pr "#!/usr/bin/perl -w\n";
10764   generate_header HashStyle GPLv2plus;
10765
10766   pr "\
10767 use strict;
10768
10769 use Sys::Guestfs;
10770
10771 my $g = Sys::Guestfs->new ();
10772 ";
10773
10774   let mkargs args =
10775     String.concat ", " (
10776       List.map (
10777         function
10778         | CallString s -> "\"" ^ s ^ "\""
10779         | CallOptString None -> "undef"
10780         | CallOptString (Some s) -> sprintf "\"%s\"" s
10781         | CallStringList xs ->
10782             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10783         | CallInt i -> string_of_int i
10784         | CallInt64 i -> Int64.to_string i
10785         | CallBool b -> if b then "1" else "0"
10786       ) args
10787     )
10788   in
10789
10790   generate_lang_bindtests (
10791     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10792   );
10793
10794   pr "print \"EOF\\n\"\n"
10795
10796 and generate_python_bindtests () =
10797   generate_header HashStyle GPLv2plus;
10798
10799   pr "\
10800 import guestfs
10801
10802 g = guestfs.GuestFS ()
10803 ";
10804
10805   let mkargs args =
10806     String.concat ", " (
10807       List.map (
10808         function
10809         | CallString s -> "\"" ^ s ^ "\""
10810         | CallOptString None -> "None"
10811         | CallOptString (Some s) -> sprintf "\"%s\"" s
10812         | CallStringList xs ->
10813             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10814         | CallInt i -> string_of_int i
10815         | CallInt64 i -> Int64.to_string i
10816         | CallBool b -> if b then "1" else "0"
10817       ) args
10818     )
10819   in
10820
10821   generate_lang_bindtests (
10822     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10823   );
10824
10825   pr "print \"EOF\"\n"
10826
10827 and generate_ruby_bindtests () =
10828   generate_header HashStyle GPLv2plus;
10829
10830   pr "\
10831 require 'guestfs'
10832
10833 g = Guestfs::create()
10834 ";
10835
10836   let mkargs args =
10837     String.concat ", " (
10838       List.map (
10839         function
10840         | CallString s -> "\"" ^ s ^ "\""
10841         | CallOptString None -> "nil"
10842         | CallOptString (Some s) -> sprintf "\"%s\"" s
10843         | CallStringList xs ->
10844             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10845         | CallInt i -> string_of_int i
10846         | CallInt64 i -> Int64.to_string i
10847         | CallBool b -> string_of_bool b
10848       ) args
10849     )
10850   in
10851
10852   generate_lang_bindtests (
10853     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10854   );
10855
10856   pr "print \"EOF\\n\"\n"
10857
10858 and generate_java_bindtests () =
10859   generate_header CStyle GPLv2plus;
10860
10861   pr "\
10862 import com.redhat.et.libguestfs.*;
10863
10864 public class Bindtests {
10865     public static void main (String[] argv)
10866     {
10867         try {
10868             GuestFS g = new GuestFS ();
10869 ";
10870
10871   let mkargs args =
10872     String.concat ", " (
10873       List.map (
10874         function
10875         | CallString s -> "\"" ^ s ^ "\""
10876         | CallOptString None -> "null"
10877         | CallOptString (Some s) -> sprintf "\"%s\"" s
10878         | CallStringList xs ->
10879             "new String[]{" ^
10880               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10881         | CallInt i -> string_of_int i
10882         | CallInt64 i -> Int64.to_string i
10883         | CallBool b -> string_of_bool b
10884       ) args
10885     )
10886   in
10887
10888   generate_lang_bindtests (
10889     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10890   );
10891
10892   pr "
10893             System.out.println (\"EOF\");
10894         }
10895         catch (Exception exn) {
10896             System.err.println (exn);
10897             System.exit (1);
10898         }
10899     }
10900 }
10901 "
10902
10903 and generate_haskell_bindtests () =
10904   generate_header HaskellStyle GPLv2plus;
10905
10906   pr "\
10907 module Bindtests where
10908 import qualified Guestfs
10909
10910 main = do
10911   g <- Guestfs.create
10912 ";
10913
10914   let mkargs args =
10915     String.concat " " (
10916       List.map (
10917         function
10918         | CallString s -> "\"" ^ s ^ "\""
10919         | CallOptString None -> "Nothing"
10920         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10921         | CallStringList xs ->
10922             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10923         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10924         | CallInt i -> string_of_int i
10925         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10926         | CallInt64 i -> Int64.to_string i
10927         | CallBool true -> "True"
10928         | CallBool false -> "False"
10929       ) args
10930     )
10931   in
10932
10933   generate_lang_bindtests (
10934     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10935   );
10936
10937   pr "  putStrLn \"EOF\"\n"
10938
10939 (* Language-independent bindings tests - we do it this way to
10940  * ensure there is parity in testing bindings across all languages.
10941  *)
10942 and generate_lang_bindtests call =
10943   call "test0" [CallString "abc"; CallOptString (Some "def");
10944                 CallStringList []; CallBool false;
10945                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10946   call "test0" [CallString "abc"; CallOptString None;
10947                 CallStringList []; CallBool false;
10948                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10949   call "test0" [CallString ""; CallOptString (Some "def");
10950                 CallStringList []; CallBool false;
10951                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10952   call "test0" [CallString ""; CallOptString (Some "");
10953                 CallStringList []; CallBool false;
10954                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10955   call "test0" [CallString "abc"; CallOptString (Some "def");
10956                 CallStringList ["1"]; CallBool false;
10957                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10958   call "test0" [CallString "abc"; CallOptString (Some "def");
10959                 CallStringList ["1"; "2"]; CallBool false;
10960                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10961   call "test0" [CallString "abc"; CallOptString (Some "def");
10962                 CallStringList ["1"]; CallBool true;
10963                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10964   call "test0" [CallString "abc"; CallOptString (Some "def");
10965                 CallStringList ["1"]; CallBool false;
10966                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10967   call "test0" [CallString "abc"; CallOptString (Some "def");
10968                 CallStringList ["1"]; CallBool false;
10969                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10970   call "test0" [CallString "abc"; CallOptString (Some "def");
10971                 CallStringList ["1"]; CallBool false;
10972                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10973   call "test0" [CallString "abc"; CallOptString (Some "def");
10974                 CallStringList ["1"]; CallBool false;
10975                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10976   call "test0" [CallString "abc"; CallOptString (Some "def");
10977                 CallStringList ["1"]; CallBool false;
10978                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10979   call "test0" [CallString "abc"; CallOptString (Some "def");
10980                 CallStringList ["1"]; CallBool false;
10981                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10982
10983 (* XXX Add here tests of the return and error functions. *)
10984
10985 (* Code to generator bindings for virt-inspector.  Currently only
10986  * implemented for OCaml code (for virt-p2v 2.0).
10987  *)
10988 let rng_input = "inspector/virt-inspector.rng"
10989
10990 (* Read the input file and parse it into internal structures.  This is
10991  * by no means a complete RELAX NG parser, but is just enough to be
10992  * able to parse the specific input file.
10993  *)
10994 type rng =
10995   | Element of string * rng list        (* <element name=name/> *)
10996   | Attribute of string * rng list        (* <attribute name=name/> *)
10997   | Interleave of rng list                (* <interleave/> *)
10998   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10999   | OneOrMore of rng                        (* <oneOrMore/> *)
11000   | Optional of rng                        (* <optional/> *)
11001   | Choice of string list                (* <choice><value/>*</choice> *)
11002   | Value of string                        (* <value>str</value> *)
11003   | Text                                (* <text/> *)
11004
11005 let rec string_of_rng = function
11006   | Element (name, xs) ->
11007       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11008   | Attribute (name, xs) ->
11009       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11010   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11011   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11012   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11013   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11014   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11015   | Value value -> "Value \"" ^ value ^ "\""
11016   | Text -> "Text"
11017
11018 and string_of_rng_list xs =
11019   String.concat ", " (List.map string_of_rng xs)
11020
11021 let rec parse_rng ?defines context = function
11022   | [] -> []
11023   | Xml.Element ("element", ["name", name], children) :: rest ->
11024       Element (name, parse_rng ?defines context children)
11025       :: parse_rng ?defines context rest
11026   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11027       Attribute (name, parse_rng ?defines context children)
11028       :: parse_rng ?defines context rest
11029   | Xml.Element ("interleave", [], children) :: rest ->
11030       Interleave (parse_rng ?defines context children)
11031       :: parse_rng ?defines context rest
11032   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11033       let rng = parse_rng ?defines context [child] in
11034       (match rng with
11035        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11036        | _ ->
11037            failwithf "%s: <zeroOrMore> contains more than one child element"
11038              context
11039       )
11040   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11041       let rng = parse_rng ?defines context [child] in
11042       (match rng with
11043        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11044        | _ ->
11045            failwithf "%s: <oneOrMore> contains more than one child element"
11046              context
11047       )
11048   | Xml.Element ("optional", [], [child]) :: rest ->
11049       let rng = parse_rng ?defines context [child] in
11050       (match rng with
11051        | [child] -> Optional child :: parse_rng ?defines context rest
11052        | _ ->
11053            failwithf "%s: <optional> contains more than one child element"
11054              context
11055       )
11056   | Xml.Element ("choice", [], children) :: rest ->
11057       let values = List.map (
11058         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11059         | _ ->
11060             failwithf "%s: can't handle anything except <value> in <choice>"
11061               context
11062       ) children in
11063       Choice values
11064       :: parse_rng ?defines context rest
11065   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11066       Value value :: parse_rng ?defines context rest
11067   | Xml.Element ("text", [], []) :: rest ->
11068       Text :: parse_rng ?defines context rest
11069   | Xml.Element ("ref", ["name", name], []) :: rest ->
11070       (* Look up the reference.  Because of limitations in this parser,
11071        * we can't handle arbitrarily nested <ref> yet.  You can only
11072        * use <ref> from inside <start>.
11073        *)
11074       (match defines with
11075        | None ->
11076            failwithf "%s: contains <ref>, but no refs are defined yet" context
11077        | Some map ->
11078            let rng = StringMap.find name map in
11079            rng @ parse_rng ?defines context rest
11080       )
11081   | x :: _ ->
11082       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11083
11084 let grammar =
11085   let xml = Xml.parse_file rng_input in
11086   match xml with
11087   | Xml.Element ("grammar", _,
11088                  Xml.Element ("start", _, gram) :: defines) ->
11089       (* The <define/> elements are referenced in the <start> section,
11090        * so build a map of those first.
11091        *)
11092       let defines = List.fold_left (
11093         fun map ->
11094           function Xml.Element ("define", ["name", name], defn) ->
11095             StringMap.add name defn map
11096           | _ ->
11097               failwithf "%s: expected <define name=name/>" rng_input
11098       ) StringMap.empty defines in
11099       let defines = StringMap.mapi parse_rng defines in
11100
11101       (* Parse the <start> clause, passing the defines. *)
11102       parse_rng ~defines "<start>" gram
11103   | _ ->
11104       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11105         rng_input
11106
11107 let name_of_field = function
11108   | Element (name, _) | Attribute (name, _)
11109   | ZeroOrMore (Element (name, _))
11110   | OneOrMore (Element (name, _))
11111   | Optional (Element (name, _)) -> name
11112   | Optional (Attribute (name, _)) -> name
11113   | Text -> (* an unnamed field in an element *)
11114       "data"
11115   | rng ->
11116       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11117
11118 (* At the moment this function only generates OCaml types.  However we
11119  * should parameterize it later so it can generate types/structs in a
11120  * variety of languages.
11121  *)
11122 let generate_types xs =
11123   (* A simple type is one that can be printed out directly, eg.
11124    * "string option".  A complex type is one which has a name and has
11125    * to be defined via another toplevel definition, eg. a struct.
11126    *
11127    * generate_type generates code for either simple or complex types.
11128    * In the simple case, it returns the string ("string option").  In
11129    * the complex case, it returns the name ("mountpoint").  In the
11130    * complex case it has to print out the definition before returning,
11131    * so it should only be called when we are at the beginning of a
11132    * new line (BOL context).
11133    *)
11134   let rec generate_type = function
11135     | Text ->                                (* string *)
11136         "string", true
11137     | Choice values ->                        (* [`val1|`val2|...] *)
11138         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11139     | ZeroOrMore rng ->                        (* <rng> list *)
11140         let t, is_simple = generate_type rng in
11141         t ^ " list (* 0 or more *)", is_simple
11142     | OneOrMore rng ->                        (* <rng> list *)
11143         let t, is_simple = generate_type rng in
11144         t ^ " list (* 1 or more *)", is_simple
11145                                         (* virt-inspector hack: bool *)
11146     | Optional (Attribute (name, [Value "1"])) ->
11147         "bool", true
11148     | Optional rng ->                        (* <rng> list *)
11149         let t, is_simple = generate_type rng in
11150         t ^ " option", is_simple
11151                                         (* type name = { fields ... } *)
11152     | Element (name, fields) when is_attrs_interleave fields ->
11153         generate_type_struct name (get_attrs_interleave fields)
11154     | Element (name, [field])                (* type name = field *)
11155     | Attribute (name, [field]) ->
11156         let t, is_simple = generate_type field in
11157         if is_simple then (t, true)
11158         else (
11159           pr "type %s = %s\n" name t;
11160           name, false
11161         )
11162     | Element (name, fields) ->              (* type name = { fields ... } *)
11163         generate_type_struct name fields
11164     | rng ->
11165         failwithf "generate_type failed at: %s" (string_of_rng rng)
11166
11167   and is_attrs_interleave = function
11168     | [Interleave _] -> true
11169     | Attribute _ :: fields -> is_attrs_interleave fields
11170     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11171     | _ -> false
11172
11173   and get_attrs_interleave = function
11174     | [Interleave fields] -> fields
11175     | ((Attribute _) as field) :: fields
11176     | ((Optional (Attribute _)) as field) :: fields ->
11177         field :: get_attrs_interleave fields
11178     | _ -> assert false
11179
11180   and generate_types xs =
11181     List.iter (fun x -> ignore (generate_type x)) xs
11182
11183   and generate_type_struct name fields =
11184     (* Calculate the types of the fields first.  We have to do this
11185      * before printing anything so we are still in BOL context.
11186      *)
11187     let types = List.map fst (List.map generate_type fields) in
11188
11189     (* Special case of a struct containing just a string and another
11190      * field.  Turn it into an assoc list.
11191      *)
11192     match types with
11193     | ["string"; other] ->
11194         let fname1, fname2 =
11195           match fields with
11196           | [f1; f2] -> name_of_field f1, name_of_field f2
11197           | _ -> assert false in
11198         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11199         name, false
11200
11201     | types ->
11202         pr "type %s = {\n" name;
11203         List.iter (
11204           fun (field, ftype) ->
11205             let fname = name_of_field field in
11206             pr "  %s_%s : %s;\n" name fname ftype
11207         ) (List.combine fields types);
11208         pr "}\n";
11209         (* Return the name of this type, and
11210          * false because it's not a simple type.
11211          *)
11212         name, false
11213   in
11214
11215   generate_types xs
11216
11217 let generate_parsers xs =
11218   (* As for generate_type above, generate_parser makes a parser for
11219    * some type, and returns the name of the parser it has generated.
11220    * Because it (may) need to print something, it should always be
11221    * called in BOL context.
11222    *)
11223   let rec generate_parser = function
11224     | Text ->                                (* string *)
11225         "string_child_or_empty"
11226     | Choice values ->                        (* [`val1|`val2|...] *)
11227         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11228           (String.concat "|"
11229              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11230     | ZeroOrMore rng ->                        (* <rng> list *)
11231         let pa = generate_parser rng in
11232         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11233     | OneOrMore rng ->                        (* <rng> list *)
11234         let pa = generate_parser rng in
11235         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11236                                         (* virt-inspector hack: bool *)
11237     | Optional (Attribute (name, [Value "1"])) ->
11238         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11239     | Optional rng ->                        (* <rng> list *)
11240         let pa = generate_parser rng in
11241         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11242                                         (* type name = { fields ... } *)
11243     | Element (name, fields) when is_attrs_interleave fields ->
11244         generate_parser_struct name (get_attrs_interleave fields)
11245     | Element (name, [field]) ->        (* type name = field *)
11246         let pa = generate_parser field in
11247         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11248         pr "let %s =\n" parser_name;
11249         pr "  %s\n" pa;
11250         pr "let parse_%s = %s\n" name parser_name;
11251         parser_name
11252     | Attribute (name, [field]) ->
11253         let pa = generate_parser field in
11254         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11255         pr "let %s =\n" parser_name;
11256         pr "  %s\n" pa;
11257         pr "let parse_%s = %s\n" name parser_name;
11258         parser_name
11259     | Element (name, fields) ->              (* type name = { fields ... } *)
11260         generate_parser_struct name ([], fields)
11261     | rng ->
11262         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11263
11264   and is_attrs_interleave = function
11265     | [Interleave _] -> true
11266     | Attribute _ :: fields -> is_attrs_interleave fields
11267     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11268     | _ -> false
11269
11270   and get_attrs_interleave = function
11271     | [Interleave fields] -> [], fields
11272     | ((Attribute _) as field) :: fields
11273     | ((Optional (Attribute _)) as field) :: fields ->
11274         let attrs, interleaves = get_attrs_interleave fields in
11275         (field :: attrs), interleaves
11276     | _ -> assert false
11277
11278   and generate_parsers xs =
11279     List.iter (fun x -> ignore (generate_parser x)) xs
11280
11281   and generate_parser_struct name (attrs, interleaves) =
11282     (* Generate parsers for the fields first.  We have to do this
11283      * before printing anything so we are still in BOL context.
11284      *)
11285     let fields = attrs @ interleaves in
11286     let pas = List.map generate_parser fields in
11287
11288     (* Generate an intermediate tuple from all the fields first.
11289      * If the type is just a string + another field, then we will
11290      * return this directly, otherwise it is turned into a record.
11291      *
11292      * RELAX NG note: This code treats <interleave> and plain lists of
11293      * fields the same.  In other words, it doesn't bother enforcing
11294      * any ordering of fields in the XML.
11295      *)
11296     pr "let parse_%s x =\n" name;
11297     pr "  let t = (\n    ";
11298     let comma = ref false in
11299     List.iter (
11300       fun x ->
11301         if !comma then pr ",\n    ";
11302         comma := true;
11303         match x with
11304         | Optional (Attribute (fname, [field])), pa ->
11305             pr "%s x" pa
11306         | Optional (Element (fname, [field])), pa ->
11307             pr "%s (optional_child %S x)" pa fname
11308         | Attribute (fname, [Text]), _ ->
11309             pr "attribute %S x" fname
11310         | (ZeroOrMore _ | OneOrMore _), pa ->
11311             pr "%s x" pa
11312         | Text, pa ->
11313             pr "%s x" pa
11314         | (field, pa) ->
11315             let fname = name_of_field field in
11316             pr "%s (child %S x)" pa fname
11317     ) (List.combine fields pas);
11318     pr "\n  ) in\n";
11319
11320     (match fields with
11321      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11322          pr "  t\n"
11323
11324      | _ ->
11325          pr "  (Obj.magic t : %s)\n" name
11326 (*
11327          List.iter (
11328            function
11329            | (Optional (Attribute (fname, [field])), pa) ->
11330                pr "  %s_%s =\n" name fname;
11331                pr "    %s x;\n" pa
11332            | (Optional (Element (fname, [field])), pa) ->
11333                pr "  %s_%s =\n" name fname;
11334                pr "    (let x = optional_child %S x in\n" fname;
11335                pr "     %s x);\n" pa
11336            | (field, pa) ->
11337                let fname = name_of_field field in
11338                pr "  %s_%s =\n" name fname;
11339                pr "    (let x = child %S x in\n" fname;
11340                pr "     %s x);\n" pa
11341          ) (List.combine fields pas);
11342          pr "}\n"
11343 *)
11344     );
11345     sprintf "parse_%s" name
11346   in
11347
11348   generate_parsers xs
11349
11350 (* Generate ocaml/guestfs_inspector.mli. *)
11351 let generate_ocaml_inspector_mli () =
11352   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11353
11354   pr "\
11355 (** This is an OCaml language binding to the external [virt-inspector]
11356     program.
11357
11358     For more information, please read the man page [virt-inspector(1)].
11359 *)
11360
11361 ";
11362
11363   generate_types grammar;
11364   pr "(** The nested information returned from the {!inspect} function. *)\n";
11365   pr "\n";
11366
11367   pr "\
11368 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11369 (** To inspect a libvirt domain called [name], pass a singleton
11370     list: [inspect [name]].  When using libvirt only, you may
11371     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11372
11373     To inspect a disk image or images, pass a list of the filenames
11374     of the disk images: [inspect filenames]
11375
11376     This function inspects the given guest or disk images and
11377     returns a list of operating system(s) found and a large amount
11378     of information about them.  In the vast majority of cases,
11379     a virtual machine only contains a single operating system.
11380
11381     If the optional [~xml] parameter is given, then this function
11382     skips running the external virt-inspector program and just
11383     parses the given XML directly (which is expected to be XML
11384     produced from a previous run of virt-inspector).  The list of
11385     names and connect URI are ignored in this case.
11386
11387     This function can throw a wide variety of exceptions, for example
11388     if the external virt-inspector program cannot be found, or if
11389     it doesn't generate valid XML.
11390 *)
11391 "
11392
11393 (* Generate ocaml/guestfs_inspector.ml. *)
11394 let generate_ocaml_inspector_ml () =
11395   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11396
11397   pr "open Unix\n";
11398   pr "\n";
11399
11400   generate_types grammar;
11401   pr "\n";
11402
11403   pr "\
11404 (* Misc functions which are used by the parser code below. *)
11405 let first_child = function
11406   | Xml.Element (_, _, c::_) -> c
11407   | Xml.Element (name, _, []) ->
11408       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11409   | Xml.PCData str ->
11410       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11411
11412 let string_child_or_empty = function
11413   | Xml.Element (_, _, [Xml.PCData s]) -> s
11414   | Xml.Element (_, _, []) -> \"\"
11415   | Xml.Element (x, _, _) ->
11416       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11417                 x ^ \" instead\")
11418   | Xml.PCData str ->
11419       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11420
11421 let optional_child name xml =
11422   let children = Xml.children xml in
11423   try
11424     Some (List.find (function
11425                      | Xml.Element (n, _, _) when n = name -> true
11426                      | _ -> false) children)
11427   with
11428     Not_found -> None
11429
11430 let child name xml =
11431   match optional_child name xml with
11432   | Some c -> c
11433   | None ->
11434       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11435
11436 let attribute name xml =
11437   try Xml.attrib xml name
11438   with Xml.No_attribute _ ->
11439     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11440
11441 ";
11442
11443   generate_parsers grammar;
11444   pr "\n";
11445
11446   pr "\
11447 (* Run external virt-inspector, then use parser to parse the XML. *)
11448 let inspect ?connect ?xml names =
11449   let xml =
11450     match xml with
11451     | None ->
11452         if names = [] then invalid_arg \"inspect: no names given\";
11453         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11454           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11455           names in
11456         let cmd = List.map Filename.quote cmd in
11457         let cmd = String.concat \" \" cmd in
11458         let chan = open_process_in cmd in
11459         let xml = Xml.parse_in chan in
11460         (match close_process_in chan with
11461          | WEXITED 0 -> ()
11462          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11463          | WSIGNALED i | WSTOPPED i ->
11464              failwith (\"external virt-inspector command died or stopped on sig \" ^
11465                        string_of_int i)
11466         );
11467         xml
11468     | Some doc ->
11469         Xml.parse_string doc in
11470   parse_operatingsystems xml
11471 "
11472
11473 (* This is used to generate the src/MAX_PROC_NR file which
11474  * contains the maximum procedure number, a surrogate for the
11475  * ABI version number.  See src/Makefile.am for the details.
11476  *)
11477 and generate_max_proc_nr () =
11478   let proc_nrs = List.map (
11479     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11480   ) daemon_functions in
11481
11482   let max_proc_nr = List.fold_left max 0 proc_nrs in
11483
11484   pr "%d\n" max_proc_nr
11485
11486 let output_to filename k =
11487   let filename_new = filename ^ ".new" in
11488   chan := open_out filename_new;
11489   k ();
11490   close_out !chan;
11491   chan := Pervasives.stdout;
11492
11493   (* Is the new file different from the current file? *)
11494   if Sys.file_exists filename && files_equal filename filename_new then
11495     unlink filename_new                 (* same, so skip it *)
11496   else (
11497     (* different, overwrite old one *)
11498     (try chmod filename 0o644 with Unix_error _ -> ());
11499     rename filename_new filename;
11500     chmod filename 0o444;
11501     printf "written %s\n%!" filename;
11502   )
11503
11504 let perror msg = function
11505   | Unix_error (err, _, _) ->
11506       eprintf "%s: %s\n" msg (error_message err)
11507   | exn ->
11508       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11509
11510 (* Main program. *)
11511 let () =
11512   let lock_fd =
11513     try openfile "HACKING" [O_RDWR] 0
11514     with
11515     | Unix_error (ENOENT, _, _) ->
11516         eprintf "\
11517 You are probably running this from the wrong directory.
11518 Run it from the top source directory using the command
11519   src/generator.ml
11520 ";
11521         exit 1
11522     | exn ->
11523         perror "open: HACKING" exn;
11524         exit 1 in
11525
11526   (* Acquire a lock so parallel builds won't try to run the generator
11527    * twice at the same time.  Subsequent builds will wait for the first
11528    * one to finish.  Note the lock is released implicitly when the
11529    * program exits.
11530    *)
11531   (try lockf lock_fd F_LOCK 1
11532    with exn ->
11533      perror "lock: HACKING" exn;
11534      exit 1);
11535
11536   check_functions ();
11537
11538   output_to "src/guestfs_protocol.x" generate_xdr;
11539   output_to "src/guestfs-structs.h" generate_structs_h;
11540   output_to "src/guestfs-actions.h" generate_actions_h;
11541   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11542   output_to "src/guestfs-actions.c" generate_client_actions;
11543   output_to "src/guestfs-bindtests.c" generate_bindtests;
11544   output_to "src/guestfs-structs.pod" generate_structs_pod;
11545   output_to "src/guestfs-actions.pod" generate_actions_pod;
11546   output_to "src/guestfs-availability.pod" generate_availability_pod;
11547   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11548   output_to "src/libguestfs.syms" generate_linker_script;
11549   output_to "daemon/actions.h" generate_daemon_actions_h;
11550   output_to "daemon/stubs.c" generate_daemon_actions;
11551   output_to "daemon/names.c" generate_daemon_names;
11552   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11553   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11554   output_to "capitests/tests.c" generate_tests;
11555   output_to "fish/cmds.c" generate_fish_cmds;
11556   output_to "fish/completion.c" generate_fish_completion;
11557   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11558   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11559   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11560   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11561   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11562   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11563   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11564   output_to "perl/Guestfs.xs" generate_perl_xs;
11565   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11566   output_to "perl/bindtests.pl" generate_perl_bindtests;
11567   output_to "python/guestfs-py.c" generate_python_c;
11568   output_to "python/guestfs.py" generate_python_py;
11569   output_to "python/bindtests.py" generate_python_bindtests;
11570   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11571   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11572   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11573
11574   List.iter (
11575     fun (typ, jtyp) ->
11576       let cols = cols_of_struct typ in
11577       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11578       output_to filename (generate_java_struct jtyp cols);
11579   ) java_structs;
11580
11581   output_to "java/Makefile.inc" generate_java_makefile_inc;
11582   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11583   output_to "java/Bindtests.java" generate_java_bindtests;
11584   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11585   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11586   output_to "csharp/Libguestfs.cs" generate_csharp;
11587
11588   (* Always generate this file last, and unconditionally.  It's used
11589    * by the Makefile to know when we must re-run the generator.
11590    *)
11591   let chan = open_out "src/stamp-generator" in
11592   fprintf chan "1\n";
11593   close_out chan;
11594
11595   printf "generated %d lines of code\n" !lines