Fix documentation for vfs-type to reflect reality.
[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.  In enterprise distributions we backport
811 features from later versions into earlier versions,
812 making this an unreliable way to test for features.
813 Use C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 B<Important note:>
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly.  This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability.  Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
970
971   ("sync", (RErr, []), 2, [],
972    [ InitEmpty, Always, TestRun [["sync"]]],
973    "sync disks, writes are flushed through to the disk image",
974    "\
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
977
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
980
981   ("touch", (RErr, [Pathname "path"]), 3, [],
982    [InitBasicFS, Always, TestOutputTrue (
983       [["touch"; "/new"];
984        ["exists"; "/new"]])],
985    "update file timestamps or create a new file",
986    "\
987 Touch acts like the L<touch(1)> command.  It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
990
991   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992    [InitISOFS, Always, TestOutput (
993       [["cat"; "/known-2"]], "abcdef\n")],
994    "list the contents of a file",
995    "\
996 Return the contents of the file named C<path>.
997
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string).  For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1002
1003   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004    [], (* XXX Tricky to test because it depends on the exact format
1005         * of the 'ls -l' command, which changes between F10 and F11.
1006         *)
1007    "list the files in a directory (long format)",
1008    "\
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1011
1012 This command is mostly useful for interactive sessions.  It
1013 is I<not> intended that you try to parse the output string.");
1014
1015   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016    [InitBasicFS, Always, TestOutputList (
1017       [["touch"; "/new"];
1018        ["touch"; "/newer"];
1019        ["touch"; "/newest"];
1020        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021    "list the files in a directory",
1022    "\
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd).  The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1026
1027 This command is mostly useful for interactive sessions.  Programs
1028 should probably use C<guestfs_readdir> instead.");
1029
1030   ("list_devices", (RStringList "devices", []), 7, [],
1031    [InitEmpty, Always, TestOutputListOfDevices (
1032       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033    "list the block devices",
1034    "\
1035 List all the block devices.
1036
1037 The full block device names are returned, eg. C</dev/sda>");
1038
1039   ("list_partitions", (RStringList "partitions", []), 8, [],
1040    [InitBasicFS, Always, TestOutputListOfDevices (
1041       [["list_partitions"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045    "list the partitions",
1046    "\
1047 List all the partitions detected on all block devices.
1048
1049 The full partition device names are returned, eg. C</dev/sda1>
1050
1051 This does not return logical volumes.  For that you will need to
1052 call C<guestfs_lvs>.");
1053
1054   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056       [["pvs"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["pvcreate"; "/dev/sda1"];
1060        ["pvcreate"; "/dev/sda2"];
1061        ["pvcreate"; "/dev/sda3"];
1062        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063    "list the LVM physical volumes (PVs)",
1064    "\
1065 List all the physical volumes detected.  This is the equivalent
1066 of the L<pvs(8)> command.
1067
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1070
1071 See also C<guestfs_pvs_full>.");
1072
1073   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074    [InitBasicFSonLVM, Always, TestOutputList (
1075       [["vgs"]], ["VG"]);
1076     InitEmpty, Always, TestOutputList (
1077       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078        ["pvcreate"; "/dev/sda1"];
1079        ["pvcreate"; "/dev/sda2"];
1080        ["pvcreate"; "/dev/sda3"];
1081        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082        ["vgcreate"; "VG2"; "/dev/sda3"];
1083        ["vgs"]], ["VG1"; "VG2"])],
1084    "list the LVM volume groups (VGs)",
1085    "\
1086 List all the volumes groups detected.  This is the equivalent
1087 of the L<vgs(8)> command.
1088
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1091
1092 See also C<guestfs_vgs_full>.");
1093
1094   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095    [InitBasicFSonLVM, Always, TestOutputList (
1096       [["lvs"]], ["/dev/VG/LV"]);
1097     InitEmpty, Always, TestOutputList (
1098       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099        ["pvcreate"; "/dev/sda1"];
1100        ["pvcreate"; "/dev/sda2"];
1101        ["pvcreate"; "/dev/sda3"];
1102        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103        ["vgcreate"; "VG2"; "/dev/sda3"];
1104        ["lvcreate"; "LV1"; "VG1"; "50"];
1105        ["lvcreate"; "LV2"; "VG1"; "50"];
1106        ["lvcreate"; "LV3"; "VG2"; "50"];
1107        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108    "list the LVM logical volumes (LVs)",
1109    "\
1110 List all the logical volumes detected.  This is the equivalent
1111 of the L<lvs(8)> command.
1112
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1115
1116 See also C<guestfs_lvs_full>.");
1117
1118   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM physical volumes (PVs)",
1121    "\
1122 List all the physical volumes detected.  This is the equivalent
1123 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM volume groups (VGs)",
1128    "\
1129 List all the volumes groups detected.  This is the equivalent
1130 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM logical volumes (LVs)",
1135    "\
1136 List all the logical volumes detected.  This is the equivalent
1137 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140    [InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142     InitISOFS, Always, TestOutputList (
1143       [["read_lines"; "/empty"]], [])],
1144    "read file as lines",
1145    "\
1146 Return the contents of the file named C<path>.
1147
1148 The file contents are returned as a list of lines.  Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1150
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line).  For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1155
1156   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "create a new Augeas handle",
1159    "\
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1163
1164 You must call this before using any other C<guestfs_aug_*>
1165 commands.
1166
1167 C<root> is the filesystem root.  C<root> must not be NULL,
1168 use C</> instead.
1169
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 integers:
1173
1174 =over 4
1175
1176 =item C<AUG_SAVE_BACKUP> = 1
1177
1178 Keep the original file with a C<.augsave> extension.
1179
1180 =item C<AUG_SAVE_NEWFILE> = 2
1181
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1184
1185 =item C<AUG_TYPE_CHECK> = 4
1186
1187 Typecheck lenses (can be expensive).
1188
1189 =item C<AUG_NO_STDINC> = 8
1190
1191 Do not use standard load path for modules.
1192
1193 =item C<AUG_SAVE_NOOP> = 16
1194
1195 Make save a no-op, just record what would have been changed.
1196
1197 =item C<AUG_NO_LOAD> = 32
1198
1199 Do not load the tree in C<guestfs_aug_init>.
1200
1201 =back
1202
1203 To close the handle, you can call C<guestfs_aug_close>.
1204
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1206
1207   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "close the current Augeas handle",
1210    "\
1211 Close the current Augeas handle and free up any resources
1212 used by it.  After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1215
1216   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "define an Augeas variable",
1219    "\
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1222 undefined.
1223
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226
1227   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "define an Augeas node",
1230    "\
1231 Defines a variable C<name> whose value is the result of
1232 evaluating C<expr>.
1233
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1237
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1241
1242   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "look up the value of an Augeas path",
1245    "\
1246 Look up the value associated with C<path>.  If C<path>
1247 matches exactly one node, the C<value> is returned.");
1248
1249   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "set Augeas path to value",
1252    "\
1253 Set the value associated with C<path> to C<value>.");
1254
1255   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "insert a sibling Augeas node",
1258    "\
1259 Create a new sibling C<label> for C<path>, inserting it into
1260 the tree before or after C<path> (depending on the boolean
1261 flag C<before>).
1262
1263 C<path> must match exactly one existing node in the tree, and
1264 C<label> must be a label, ie. not contain C</>, C<*> or end
1265 with a bracketed index C<[N]>.");
1266
1267   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1268    [], (* XXX Augeas code needs tests. *)
1269    "remove an Augeas path",
1270    "\
1271 Remove C<path> and all of its children.
1272
1273 On success this returns the number of entries which were removed.");
1274
1275   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "move Augeas node",
1278    "\
1279 Move the node C<src> to C<dest>.  C<src> must match exactly
1280 one node.  C<dest> is overwritten if it exists.");
1281
1282   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1283    [], (* XXX Augeas code needs tests. *)
1284    "return Augeas nodes which match augpath",
1285    "\
1286 Returns a list of paths which match the path expression C<path>.
1287 The returned paths are sufficiently qualified so that they match
1288 exactly one node in the current tree.");
1289
1290   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1291    [], (* XXX Augeas code needs tests. *)
1292    "write all pending Augeas changes to disk",
1293    "\
1294 This writes all pending changes to disk.
1295
1296 The flags which were passed to C<guestfs_aug_init> affect exactly
1297 how files are saved.");
1298
1299   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1300    [], (* XXX Augeas code needs tests. *)
1301    "load files into the tree",
1302    "\
1303 Load files into the tree.
1304
1305 See C<aug_load> in the Augeas documentation for the full gory
1306 details.");
1307
1308   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1309    [], (* XXX Augeas code needs tests. *)
1310    "list Augeas nodes under augpath",
1311    "\
1312 This is just a shortcut for listing C<guestfs_aug_match>
1313 C<path/*> and sorting the resulting nodes into alphabetical order.");
1314
1315   ("rm", (RErr, [Pathname "path"]), 29, [],
1316    [InitBasicFS, Always, TestRun
1317       [["touch"; "/new"];
1318        ["rm"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["rm"; "/new"]];
1321     InitBasicFS, Always, TestLastFail
1322       [["mkdir"; "/new"];
1323        ["rm"; "/new"]]],
1324    "remove a file",
1325    "\
1326 Remove the single file C<path>.");
1327
1328   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1329    [InitBasicFS, Always, TestRun
1330       [["mkdir"; "/new"];
1331        ["rmdir"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["rmdir"; "/new"]];
1334     InitBasicFS, Always, TestLastFail
1335       [["touch"; "/new"];
1336        ["rmdir"; "/new"]]],
1337    "remove a directory",
1338    "\
1339 Remove the single directory C<path>.");
1340
1341   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1342    [InitBasicFS, Always, TestOutputFalse
1343       [["mkdir"; "/new"];
1344        ["mkdir"; "/new/foo"];
1345        ["touch"; "/new/foo/bar"];
1346        ["rm_rf"; "/new"];
1347        ["exists"; "/new"]]],
1348    "remove a file or directory recursively",
1349    "\
1350 Remove the file or directory C<path>, recursively removing the
1351 contents if its a directory.  This is like the C<rm -rf> shell
1352 command.");
1353
1354   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1355    [InitBasicFS, Always, TestOutputTrue
1356       [["mkdir"; "/new"];
1357        ["is_dir"; "/new"]];
1358     InitBasicFS, Always, TestLastFail
1359       [["mkdir"; "/new/foo/bar"]]],
1360    "create a directory",
1361    "\
1362 Create a directory named C<path>.");
1363
1364   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1365    [InitBasicFS, Always, TestOutputTrue
1366       [["mkdir_p"; "/new/foo/bar"];
1367        ["is_dir"; "/new/foo/bar"]];
1368     InitBasicFS, Always, TestOutputTrue
1369       [["mkdir_p"; "/new/foo/bar"];
1370        ["is_dir"; "/new/foo"]];
1371     InitBasicFS, Always, TestOutputTrue
1372       [["mkdir_p"; "/new/foo/bar"];
1373        ["is_dir"; "/new"]];
1374     (* Regression tests for RHBZ#503133: *)
1375     InitBasicFS, Always, TestRun
1376       [["mkdir"; "/new"];
1377        ["mkdir_p"; "/new"]];
1378     InitBasicFS, Always, TestLastFail
1379       [["touch"; "/new"];
1380        ["mkdir_p"; "/new"]]],
1381    "create a directory and parents",
1382    "\
1383 Create a directory named C<path>, creating any parent directories
1384 as necessary.  This is like the C<mkdir -p> shell command.");
1385
1386   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1387    [], (* XXX Need stat command to test *)
1388    "change file mode",
1389    "\
1390 Change the mode (permissions) of C<path> to C<mode>.  Only
1391 numeric modes are supported.
1392
1393 I<Note>: When using this command from guestfish, C<mode>
1394 by default would be decimal, unless you prefix it with
1395 C<0> to get octal, ie. use C<0700> not C<700>.
1396
1397 The mode actually set is affected by the umask.");
1398
1399   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1400    [], (* XXX Need stat command to test *)
1401    "change file owner and group",
1402    "\
1403 Change the file owner to C<owner> and group to C<group>.
1404
1405 Only numeric uid and gid are supported.  If you want to use
1406 names, you will need to locate and parse the password file
1407 yourself (Augeas support makes this relatively easy).");
1408
1409   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1410    [InitISOFS, Always, TestOutputTrue (
1411       [["exists"; "/empty"]]);
1412     InitISOFS, Always, TestOutputTrue (
1413       [["exists"; "/directory"]])],
1414    "test if file or directory exists",
1415    "\
1416 This returns C<true> if and only if there is a file, directory
1417 (or anything) with the given C<path> name.
1418
1419 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1420
1421   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1422    [InitISOFS, Always, TestOutputTrue (
1423       [["is_file"; "/known-1"]]);
1424     InitISOFS, Always, TestOutputFalse (
1425       [["is_file"; "/directory"]])],
1426    "test if file exists",
1427    "\
1428 This returns C<true> if and only if there is a file
1429 with the given C<path> name.  Note that it returns false for
1430 other objects like directories.
1431
1432 See also C<guestfs_stat>.");
1433
1434   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1435    [InitISOFS, Always, TestOutputFalse (
1436       [["is_dir"; "/known-3"]]);
1437     InitISOFS, Always, TestOutputTrue (
1438       [["is_dir"; "/directory"]])],
1439    "test if file exists",
1440    "\
1441 This returns C<true> if and only if there is a directory
1442 with the given C<path> name.  Note that it returns false for
1443 other objects like files.
1444
1445 See also C<guestfs_stat>.");
1446
1447   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1448    [InitEmpty, Always, TestOutputListOfDevices (
1449       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1450        ["pvcreate"; "/dev/sda1"];
1451        ["pvcreate"; "/dev/sda2"];
1452        ["pvcreate"; "/dev/sda3"];
1453        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1454    "create an LVM physical volume",
1455    "\
1456 This creates an LVM physical volume on the named C<device>,
1457 where C<device> should usually be a partition name such
1458 as C</dev/sda1>.");
1459
1460   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["vgs"]], ["VG1"; "VG2"])],
1469    "create an LVM volume group",
1470    "\
1471 This creates an LVM volume group called C<volgroup>
1472 from the non-empty list of physical volumes C<physvols>.");
1473
1474   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1475    [InitEmpty, Always, TestOutputList (
1476       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1477        ["pvcreate"; "/dev/sda1"];
1478        ["pvcreate"; "/dev/sda2"];
1479        ["pvcreate"; "/dev/sda3"];
1480        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1481        ["vgcreate"; "VG2"; "/dev/sda3"];
1482        ["lvcreate"; "LV1"; "VG1"; "50"];
1483        ["lvcreate"; "LV2"; "VG1"; "50"];
1484        ["lvcreate"; "LV3"; "VG2"; "50"];
1485        ["lvcreate"; "LV4"; "VG2"; "50"];
1486        ["lvcreate"; "LV5"; "VG2"; "50"];
1487        ["lvs"]],
1488       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1489        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1490    "create an LVM logical volume",
1491    "\
1492 This creates an LVM logical volume called C<logvol>
1493 on the volume group C<volgroup>, with C<size> megabytes.");
1494
1495   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1496    [InitEmpty, Always, TestOutput (
1497       [["part_disk"; "/dev/sda"; "mbr"];
1498        ["mkfs"; "ext2"; "/dev/sda1"];
1499        ["mount_options"; ""; "/dev/sda1"; "/"];
1500        ["write_file"; "/new"; "new file contents"; "0"];
1501        ["cat"; "/new"]], "new file contents")],
1502    "make a filesystem",
1503    "\
1504 This creates a filesystem on C<device> (usually a partition
1505 or LVM logical volume).  The filesystem type is C<fstype>, for
1506 example C<ext3>.");
1507
1508   ("sfdisk", (RErr, [Device "device";
1509                      Int "cyls"; Int "heads"; Int "sectors";
1510                      StringList "lines"]), 43, [DangerWillRobinson],
1511    [],
1512    "create partitions on a block device",
1513    "\
1514 This is a direct interface to the L<sfdisk(8)> program for creating
1515 partitions on block devices.
1516
1517 C<device> should be a block device, for example C</dev/sda>.
1518
1519 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1520 and sectors on the device, which are passed directly to sfdisk as
1521 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1522 of these, then the corresponding parameter is omitted.  Usually for
1523 'large' disks, you can just pass C<0> for these, but for small
1524 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1525 out the right geometry and you will need to tell it.
1526
1527 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1528 information refer to the L<sfdisk(8)> manpage.
1529
1530 To create a single partition occupying the whole disk, you would
1531 pass C<lines> as a single element list, when the single element being
1532 the string C<,> (comma).
1533
1534 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1535 C<guestfs_part_init>");
1536
1537   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1538    [InitBasicFS, Always, TestOutput (
1539       [["write_file"; "/new"; "new file contents"; "0"];
1540        ["cat"; "/new"]], "new file contents");
1541     InitBasicFS, Always, TestOutput (
1542       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1543        ["cat"; "/new"]], "\nnew file contents\n");
1544     InitBasicFS, Always, TestOutput (
1545       [["write_file"; "/new"; "\n\n"; "0"];
1546        ["cat"; "/new"]], "\n\n");
1547     InitBasicFS, Always, TestOutput (
1548       [["write_file"; "/new"; ""; "0"];
1549        ["cat"; "/new"]], "");
1550     InitBasicFS, Always, TestOutput (
1551       [["write_file"; "/new"; "\n\n\n"; "0"];
1552        ["cat"; "/new"]], "\n\n\n");
1553     InitBasicFS, Always, TestOutput (
1554       [["write_file"; "/new"; "\n"; "0"];
1555        ["cat"; "/new"]], "\n")],
1556    "create a file",
1557    "\
1558 This call creates a file called C<path>.  The contents of the
1559 file is the string C<content> (which can contain any 8 bit data),
1560 with length C<size>.
1561
1562 As a special case, if C<size> is C<0>
1563 then the length is calculated using C<strlen> (so in this case
1564 the content cannot contain embedded ASCII NULs).
1565
1566 I<NB.> Owing to a bug, writing content containing ASCII NUL
1567 characters does I<not> work, even if the length is specified.
1568 We hope to resolve this bug in a future version.  In the meantime
1569 use C<guestfs_upload>.");
1570
1571   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1572    [InitEmpty, Always, TestOutputListOfDevices (
1573       [["part_disk"; "/dev/sda"; "mbr"];
1574        ["mkfs"; "ext2"; "/dev/sda1"];
1575        ["mount_options"; ""; "/dev/sda1"; "/"];
1576        ["mounts"]], ["/dev/sda1"]);
1577     InitEmpty, Always, TestOutputList (
1578       [["part_disk"; "/dev/sda"; "mbr"];
1579        ["mkfs"; "ext2"; "/dev/sda1"];
1580        ["mount_options"; ""; "/dev/sda1"; "/"];
1581        ["umount"; "/"];
1582        ["mounts"]], [])],
1583    "unmount a filesystem",
1584    "\
1585 This unmounts the given filesystem.  The filesystem may be
1586 specified either by its mountpoint (path) or the device which
1587 contains the filesystem.");
1588
1589   ("mounts", (RStringList "devices", []), 46, [],
1590    [InitBasicFS, Always, TestOutputListOfDevices (
1591       [["mounts"]], ["/dev/sda1"])],
1592    "show mounted filesystems",
1593    "\
1594 This returns the list of currently mounted filesystems.  It returns
1595 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1596
1597 Some internal mounts are not shown.
1598
1599 See also: C<guestfs_mountpoints>");
1600
1601   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1602    [InitBasicFS, Always, TestOutputList (
1603       [["umount_all"];
1604        ["mounts"]], []);
1605     (* check that umount_all can unmount nested mounts correctly: *)
1606     InitEmpty, Always, TestOutputList (
1607       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1608        ["mkfs"; "ext2"; "/dev/sda1"];
1609        ["mkfs"; "ext2"; "/dev/sda2"];
1610        ["mkfs"; "ext2"; "/dev/sda3"];
1611        ["mount_options"; ""; "/dev/sda1"; "/"];
1612        ["mkdir"; "/mp1"];
1613        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1614        ["mkdir"; "/mp1/mp2"];
1615        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1616        ["mkdir"; "/mp1/mp2/mp3"];
1617        ["umount_all"];
1618        ["mounts"]], [])],
1619    "unmount all filesystems",
1620    "\
1621 This unmounts all mounted filesystems.
1622
1623 Some internal mounts are not unmounted by this call.");
1624
1625   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1626    [],
1627    "remove all LVM LVs, VGs and PVs",
1628    "\
1629 This command removes all LVM logical volumes, volume groups
1630 and physical volumes.");
1631
1632   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1633    [InitISOFS, Always, TestOutput (
1634       [["file"; "/empty"]], "empty");
1635     InitISOFS, Always, TestOutput (
1636       [["file"; "/known-1"]], "ASCII text");
1637     InitISOFS, Always, TestLastFail (
1638       [["file"; "/notexists"]])],
1639    "determine file type",
1640    "\
1641 This call uses the standard L<file(1)> command to determine
1642 the type or contents of the file.  This also works on devices,
1643 for example to find out whether a partition contains a filesystem.
1644
1645 This call will also transparently look inside various types
1646 of compressed file.
1647
1648 The exact command which runs is C<file -zbsL path>.  Note in
1649 particular that the filename is not prepended to the output
1650 (the C<-b> option).");
1651
1652   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1653    [InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 1"]], "Result1");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 2"]], "Result2\n");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 3"]], "\nResult3");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 4"]], "\nResult4\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 5"]], "\nResult5\n\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 7"]], "");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 8"]], "\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 9"]], "\n\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1693     InitBasicFS, Always, TestOutput (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1697     InitBasicFS, Always, TestLastFail (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command"; "/test-command"]])],
1701    "run a command from the guest filesystem",
1702    "\
1703 This call runs a command from the guest filesystem.  The
1704 filesystem must be mounted, and must contain a compatible
1705 operating system (ie. something Linux, with the same
1706 or compatible processor architecture).
1707
1708 The single parameter is an argv-style list of arguments.
1709 The first element is the name of the program to run.
1710 Subsequent elements are parameters.  The list must be
1711 non-empty (ie. must contain a program name).  Note that
1712 the command runs directly, and is I<not> invoked via
1713 the shell (see C<guestfs_sh>).
1714
1715 The return value is anything printed to I<stdout> by
1716 the command.
1717
1718 If the command returns a non-zero exit status, then
1719 this function returns an error message.  The error message
1720 string is the content of I<stderr> from the command.
1721
1722 The C<$PATH> environment variable will contain at least
1723 C</usr/bin> and C</bin>.  If you require a program from
1724 another location, you should provide the full path in the
1725 first parameter.
1726
1727 Shared libraries and data files required by the program
1728 must be available on filesystems which are mounted in the
1729 correct places.  It is the caller's responsibility to ensure
1730 all filesystems that are needed are mounted at the right
1731 locations.");
1732
1733   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1734    [InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 1"]], ["Result1"]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 2"]], ["Result2"]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 7"]], []);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 8"]], [""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 9"]], ["";""]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1774     InitBasicFS, Always, TestOutputList (
1775       [["upload"; "test-command"; "/test-command"];
1776        ["chmod"; "0o755"; "/test-command"];
1777        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1778    "run a command, returning lines",
1779    "\
1780 This is the same as C<guestfs_command>, but splits the
1781 result into a list of lines.
1782
1783 See also: C<guestfs_sh_lines>");
1784
1785   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1786    [InitISOFS, Always, TestOutputStruct (
1787       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1788    "get file information",
1789    "\
1790 Returns file information for the given C<path>.
1791
1792 This is the same as the C<stat(2)> system call.");
1793
1794   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1795    [InitISOFS, Always, TestOutputStruct (
1796       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1797    "get file information for a symbolic link",
1798    "\
1799 Returns file information for the given C<path>.
1800
1801 This is the same as C<guestfs_stat> except that if C<path>
1802 is a symbolic link, then the link is stat-ed, not the file it
1803 refers to.
1804
1805 This is the same as the C<lstat(2)> system call.");
1806
1807   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1808    [InitISOFS, Always, TestOutputStruct (
1809       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1810    "get file system statistics",
1811    "\
1812 Returns file system statistics for any mounted file system.
1813 C<path> should be a file or directory in the mounted file system
1814 (typically it is the mount point itself, but it doesn't need to be).
1815
1816 This is the same as the C<statvfs(2)> system call.");
1817
1818   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1819    [], (* XXX test *)
1820    "get ext2/ext3/ext4 superblock details",
1821    "\
1822 This returns the contents of the ext2, ext3 or ext4 filesystem
1823 superblock on C<device>.
1824
1825 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1826 manpage for more details.  The list of fields returned isn't
1827 clearly defined, and depends on both the version of C<tune2fs>
1828 that libguestfs was built against, and the filesystem itself.");
1829
1830   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1831    [InitEmpty, Always, TestOutputTrue (
1832       [["blockdev_setro"; "/dev/sda"];
1833        ["blockdev_getro"; "/dev/sda"]])],
1834    "set block device to read-only",
1835    "\
1836 Sets the block device named C<device> to read-only.
1837
1838 This uses the L<blockdev(8)> command.");
1839
1840   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1841    [InitEmpty, Always, TestOutputFalse (
1842       [["blockdev_setrw"; "/dev/sda"];
1843        ["blockdev_getro"; "/dev/sda"]])],
1844    "set block device to read-write",
1845    "\
1846 Sets the block device named C<device> to read-write.
1847
1848 This uses the L<blockdev(8)> command.");
1849
1850   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1851    [InitEmpty, Always, TestOutputTrue (
1852       [["blockdev_setro"; "/dev/sda"];
1853        ["blockdev_getro"; "/dev/sda"]])],
1854    "is block device set to read-only",
1855    "\
1856 Returns a boolean indicating if the block device is read-only
1857 (true if read-only, false if not).
1858
1859 This uses the L<blockdev(8)> command.");
1860
1861   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1862    [InitEmpty, Always, TestOutputInt (
1863       [["blockdev_getss"; "/dev/sda"]], 512)],
1864    "get sectorsize of block device",
1865    "\
1866 This returns the size of sectors on a block device.
1867 Usually 512, but can be larger for modern devices.
1868
1869 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1870 for that).
1871
1872 This uses the L<blockdev(8)> command.");
1873
1874   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1875    [InitEmpty, Always, TestOutputInt (
1876       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1877    "get blocksize of block device",
1878    "\
1879 This returns the block size of a device.
1880
1881 (Note this is different from both I<size in blocks> and
1882 I<filesystem block size>).
1883
1884 This uses the L<blockdev(8)> command.");
1885
1886   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1887    [], (* XXX test *)
1888    "set blocksize of block device",
1889    "\
1890 This sets the block size of a device.
1891
1892 (Note this is different from both I<size in blocks> and
1893 I<filesystem block size>).
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1900    "get total size of device in 512-byte sectors",
1901    "\
1902 This returns the size of the device in units of 512-byte sectors
1903 (even if the sectorsize isn't 512 bytes ... weird).
1904
1905 See also C<guestfs_blockdev_getss> for the real sector size of
1906 the device, and C<guestfs_blockdev_getsize64> for the more
1907 useful I<size in bytes>.
1908
1909 This uses the L<blockdev(8)> command.");
1910
1911   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1912    [InitEmpty, Always, TestOutputInt (
1913       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1914    "get total size of device in bytes",
1915    "\
1916 This returns the size of the device in bytes.
1917
1918 See also C<guestfs_blockdev_getsz>.
1919
1920 This uses the L<blockdev(8)> command.");
1921
1922   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1923    [InitEmpty, Always, TestRun
1924       [["blockdev_flushbufs"; "/dev/sda"]]],
1925    "flush device buffers",
1926    "\
1927 This tells the kernel to flush internal buffers associated
1928 with C<device>.
1929
1930 This uses the L<blockdev(8)> command.");
1931
1932   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1933    [InitEmpty, Always, TestRun
1934       [["blockdev_rereadpt"; "/dev/sda"]]],
1935    "reread partition table",
1936    "\
1937 Reread the partition table on C<device>.
1938
1939 This uses the L<blockdev(8)> command.");
1940
1941   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1942    [InitBasicFS, Always, TestOutput (
1943       (* Pick a file from cwd which isn't likely to change. *)
1944       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945        ["checksum"; "md5"; "/COPYING.LIB"]],
1946       Digest.to_hex (Digest.file "COPYING.LIB"))],
1947    "upload a file from the local machine",
1948    "\
1949 Upload local file C<filename> to C<remotefilename> on the
1950 filesystem.
1951
1952 C<filename> can also be a named pipe.
1953
1954 See also C<guestfs_download>.");
1955
1956   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1957    [InitBasicFS, Always, TestOutput (
1958       (* Pick a file from cwd which isn't likely to change. *)
1959       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1960        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1961        ["upload"; "testdownload.tmp"; "/upload"];
1962        ["checksum"; "md5"; "/upload"]],
1963       Digest.to_hex (Digest.file "COPYING.LIB"))],
1964    "download a file to the local machine",
1965    "\
1966 Download file C<remotefilename> and save it as C<filename>
1967 on the local machine.
1968
1969 C<filename> can also be a named pipe.
1970
1971 See also C<guestfs_upload>, C<guestfs_cat>.");
1972
1973   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1974    [InitISOFS, Always, TestOutput (
1975       [["checksum"; "crc"; "/known-3"]], "2891671662");
1976     InitISOFS, Always, TestLastFail (
1977       [["checksum"; "crc"; "/notexists"]]);
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1990    "compute MD5, SHAx or CRC checksum of file",
1991    "\
1992 This call computes the MD5, SHAx or CRC checksum of the
1993 file named C<path>.
1994
1995 The type of checksum to compute is given by the C<csumtype>
1996 parameter which must have one of the following values:
1997
1998 =over 4
1999
2000 =item C<crc>
2001
2002 Compute the cyclic redundancy check (CRC) specified by POSIX
2003 for the C<cksum> command.
2004
2005 =item C<md5>
2006
2007 Compute the MD5 hash (using the C<md5sum> program).
2008
2009 =item C<sha1>
2010
2011 Compute the SHA1 hash (using the C<sha1sum> program).
2012
2013 =item C<sha224>
2014
2015 Compute the SHA224 hash (using the C<sha224sum> program).
2016
2017 =item C<sha256>
2018
2019 Compute the SHA256 hash (using the C<sha256sum> program).
2020
2021 =item C<sha384>
2022
2023 Compute the SHA384 hash (using the C<sha384sum> program).
2024
2025 =item C<sha512>
2026
2027 Compute the SHA512 hash (using the C<sha512sum> program).
2028
2029 =back
2030
2031 The checksum is returned as a printable string.");
2032
2033   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2034    [InitBasicFS, Always, TestOutput (
2035       [["tar_in"; "../images/helloworld.tar"; "/"];
2036        ["cat"; "/hello"]], "hello\n")],
2037    "unpack tarfile to directory",
2038    "\
2039 This command uploads and unpacks local file C<tarfile> (an
2040 I<uncompressed> tar file) into C<directory>.
2041
2042 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2043
2044   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2045    [],
2046    "pack directory into tarfile",
2047    "\
2048 This command packs the contents of C<directory> and downloads
2049 it to local file C<tarfile>.
2050
2051 To download a compressed tarball, use C<guestfs_tgz_out>.");
2052
2053   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2054    [InitBasicFS, Always, TestOutput (
2055       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2056        ["cat"; "/hello"]], "hello\n")],
2057    "unpack compressed tarball to directory",
2058    "\
2059 This command uploads and unpacks local file C<tarball> (a
2060 I<gzip compressed> tar file) into C<directory>.
2061
2062 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2063
2064   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2065    [],
2066    "pack directory into compressed tarball",
2067    "\
2068 This command packs the contents of C<directory> and downloads
2069 it to local file C<tarball>.
2070
2071 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2072
2073   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2074    [InitBasicFS, Always, TestLastFail (
2075       [["umount"; "/"];
2076        ["mount_ro"; "/dev/sda1"; "/"];
2077        ["touch"; "/new"]]);
2078     InitBasicFS, Always, TestOutput (
2079       [["write_file"; "/new"; "data"; "0"];
2080        ["umount"; "/"];
2081        ["mount_ro"; "/dev/sda1"; "/"];
2082        ["cat"; "/new"]], "data")],
2083    "mount a guest disk, read-only",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 mounts the filesystem with the read-only (I<-o ro>) flag.");
2087
2088   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2089    [],
2090    "mount a guest disk with mount options",
2091    "\
2092 This is the same as the C<guestfs_mount> command, but it
2093 allows you to set the mount options as for the
2094 L<mount(8)> I<-o> flag.
2095
2096 If the C<options> parameter is an empty string, then
2097 no options are passed (all options default to whatever
2098 the filesystem uses).");
2099
2100   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2101    [],
2102    "mount a guest disk with mount options and vfstype",
2103    "\
2104 This is the same as the C<guestfs_mount> command, but it
2105 allows you to set both the mount options and the vfstype
2106 as for the L<mount(8)> I<-o> and I<-t> flags.");
2107
2108   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2109    [],
2110    "debugging and internals",
2111    "\
2112 The C<guestfs_debug> command exposes some internals of
2113 C<guestfsd> (the guestfs daemon) that runs inside the
2114 qemu subprocess.
2115
2116 There is no comprehensive help for this command.  You have
2117 to look at the file C<daemon/debug.c> in the libguestfs source
2118 to find out what you can do.");
2119
2120   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2121    [InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG/LV1"];
2128        ["lvs"]], ["/dev/VG/LV2"]);
2129     InitEmpty, Always, TestOutputList (
2130       [["part_disk"; "/dev/sda"; "mbr"];
2131        ["pvcreate"; "/dev/sda1"];
2132        ["vgcreate"; "VG"; "/dev/sda1"];
2133        ["lvcreate"; "LV1"; "VG"; "50"];
2134        ["lvcreate"; "LV2"; "VG"; "50"];
2135        ["lvremove"; "/dev/VG"];
2136        ["lvs"]], []);
2137     InitEmpty, Always, TestOutputList (
2138       [["part_disk"; "/dev/sda"; "mbr"];
2139        ["pvcreate"; "/dev/sda1"];
2140        ["vgcreate"; "VG"; "/dev/sda1"];
2141        ["lvcreate"; "LV1"; "VG"; "50"];
2142        ["lvcreate"; "LV2"; "VG"; "50"];
2143        ["lvremove"; "/dev/VG"];
2144        ["vgs"]], ["VG"])],
2145    "remove an LVM logical volume",
2146    "\
2147 Remove an LVM logical volume C<device>, where C<device> is
2148 the path to the LV, such as C</dev/VG/LV>.
2149
2150 You can also remove all LVs in a volume group by specifying
2151 the VG name, C</dev/VG>.");
2152
2153   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2154    [InitEmpty, Always, TestOutputList (
2155       [["part_disk"; "/dev/sda"; "mbr"];
2156        ["pvcreate"; "/dev/sda1"];
2157        ["vgcreate"; "VG"; "/dev/sda1"];
2158        ["lvcreate"; "LV1"; "VG"; "50"];
2159        ["lvcreate"; "LV2"; "VG"; "50"];
2160        ["vgremove"; "VG"];
2161        ["lvs"]], []);
2162     InitEmpty, Always, TestOutputList (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["vgs"]], [])],
2170    "remove an LVM volume group",
2171    "\
2172 Remove an LVM volume group C<vgname>, (for example C<VG>).
2173
2174 This also forcibly removes all logical volumes in the volume
2175 group (if any).");
2176
2177   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2178    [InitEmpty, Always, TestOutputListOfDevices (
2179       [["part_disk"; "/dev/sda"; "mbr"];
2180        ["pvcreate"; "/dev/sda1"];
2181        ["vgcreate"; "VG"; "/dev/sda1"];
2182        ["lvcreate"; "LV1"; "VG"; "50"];
2183        ["lvcreate"; "LV2"; "VG"; "50"];
2184        ["vgremove"; "VG"];
2185        ["pvremove"; "/dev/sda1"];
2186        ["lvs"]], []);
2187     InitEmpty, Always, TestOutputListOfDevices (
2188       [["part_disk"; "/dev/sda"; "mbr"];
2189        ["pvcreate"; "/dev/sda1"];
2190        ["vgcreate"; "VG"; "/dev/sda1"];
2191        ["lvcreate"; "LV1"; "VG"; "50"];
2192        ["lvcreate"; "LV2"; "VG"; "50"];
2193        ["vgremove"; "VG"];
2194        ["pvremove"; "/dev/sda1"];
2195        ["vgs"]], []);
2196     InitEmpty, Always, TestOutputListOfDevices (
2197       [["part_disk"; "/dev/sda"; "mbr"];
2198        ["pvcreate"; "/dev/sda1"];
2199        ["vgcreate"; "VG"; "/dev/sda1"];
2200        ["lvcreate"; "LV1"; "VG"; "50"];
2201        ["lvcreate"; "LV2"; "VG"; "50"];
2202        ["vgremove"; "VG"];
2203        ["pvremove"; "/dev/sda1"];
2204        ["pvs"]], [])],
2205    "remove an LVM physical volume",
2206    "\
2207 This wipes a physical volume C<device> so that LVM will no longer
2208 recognise it.
2209
2210 The implementation uses the C<pvremove> command which refuses to
2211 wipe physical volumes that contain any volume groups, so you have
2212 to remove those first.");
2213
2214   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2215    [InitBasicFS, Always, TestOutput (
2216       [["set_e2label"; "/dev/sda1"; "testlabel"];
2217        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2218    "set the ext2/3/4 filesystem label",
2219    "\
2220 This sets the ext2/3/4 filesystem label of the filesystem on
2221 C<device> to C<label>.  Filesystem labels are limited to
2222 16 characters.
2223
2224 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2225 to return the existing label on a filesystem.");
2226
2227   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2228    [],
2229    "get the ext2/3/4 filesystem label",
2230    "\
2231 This returns the ext2/3/4 filesystem label of the filesystem on
2232 C<device>.");
2233
2234   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2235    (let uuid = uuidgen () in
2236     [InitBasicFS, Always, TestOutput (
2237        [["set_e2uuid"; "/dev/sda1"; uuid];
2238         ["get_e2uuid"; "/dev/sda1"]], uuid);
2239      InitBasicFS, Always, TestOutput (
2240        [["set_e2uuid"; "/dev/sda1"; "clear"];
2241         ["get_e2uuid"; "/dev/sda1"]], "");
2242      (* We can't predict what UUIDs will be, so just check the commands run. *)
2243      InitBasicFS, Always, TestRun (
2244        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2245      InitBasicFS, Always, TestRun (
2246        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2247    "set the ext2/3/4 filesystem UUID",
2248    "\
2249 This sets the ext2/3/4 filesystem UUID of the filesystem on
2250 C<device> to C<uuid>.  The format of the UUID and alternatives
2251 such as C<clear>, C<random> and C<time> are described in the
2252 L<tune2fs(8)> manpage.
2253
2254 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2255 to return the existing UUID of a filesystem.");
2256
2257   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2258    [],
2259    "get the ext2/3/4 filesystem UUID",
2260    "\
2261 This returns the ext2/3/4 filesystem UUID of the filesystem on
2262 C<device>.");
2263
2264   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2265    [InitBasicFS, Always, TestOutputInt (
2266       [["umount"; "/dev/sda1"];
2267        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2268     InitBasicFS, Always, TestOutputInt (
2269       [["umount"; "/dev/sda1"];
2270        ["zero"; "/dev/sda1"];
2271        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2272    "run the filesystem checker",
2273    "\
2274 This runs the filesystem checker (fsck) on C<device> which
2275 should have filesystem type C<fstype>.
2276
2277 The returned integer is the status.  See L<fsck(8)> for the
2278 list of status codes from C<fsck>.
2279
2280 Notes:
2281
2282 =over 4
2283
2284 =item *
2285
2286 Multiple status codes can be summed together.
2287
2288 =item *
2289
2290 A non-zero return code can mean \"success\", for example if
2291 errors have been corrected on the filesystem.
2292
2293 =item *
2294
2295 Checking or repairing NTFS volumes is not supported
2296 (by linux-ntfs).
2297
2298 =back
2299
2300 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2301
2302   ("zero", (RErr, [Device "device"]), 85, [],
2303    [InitBasicFS, Always, TestOutput (
2304       [["umount"; "/dev/sda1"];
2305        ["zero"; "/dev/sda1"];
2306        ["file"; "/dev/sda1"]], "data")],
2307    "write zeroes to the device",
2308    "\
2309 This command writes zeroes over the first few blocks of C<device>.
2310
2311 How many blocks are zeroed isn't specified (but it's I<not> enough
2312 to securely wipe the device).  It should be sufficient to remove
2313 any partition tables, filesystem superblocks and so on.
2314
2315 See also: C<guestfs_scrub_device>.");
2316
2317   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2318    (* Test disabled because grub-install incompatible with virtio-blk driver.
2319     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2320     *)
2321    [InitBasicFS, Disabled, TestOutputTrue (
2322       [["grub_install"; "/"; "/dev/sda1"];
2323        ["is_dir"; "/boot"]])],
2324    "install GRUB",
2325    "\
2326 This command installs GRUB (the Grand Unified Bootloader) on
2327 C<device>, with the root directory being C<root>.");
2328
2329   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2330    [InitBasicFS, Always, TestOutput (
2331       [["write_file"; "/old"; "file content"; "0"];
2332        ["cp"; "/old"; "/new"];
2333        ["cat"; "/new"]], "file content");
2334     InitBasicFS, Always, TestOutputTrue (
2335       [["write_file"; "/old"; "file content"; "0"];
2336        ["cp"; "/old"; "/new"];
2337        ["is_file"; "/old"]]);
2338     InitBasicFS, Always, TestOutput (
2339       [["write_file"; "/old"; "file content"; "0"];
2340        ["mkdir"; "/dir"];
2341        ["cp"; "/old"; "/dir/new"];
2342        ["cat"; "/dir/new"]], "file content")],
2343    "copy a file",
2344    "\
2345 This copies a file from C<src> to C<dest> where C<dest> is
2346 either a destination filename or destination directory.");
2347
2348   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2349    [InitBasicFS, Always, TestOutput (
2350       [["mkdir"; "/olddir"];
2351        ["mkdir"; "/newdir"];
2352        ["write_file"; "/olddir/file"; "file content"; "0"];
2353        ["cp_a"; "/olddir"; "/newdir"];
2354        ["cat"; "/newdir/olddir/file"]], "file content")],
2355    "copy a file or directory recursively",
2356    "\
2357 This copies a file or directory from C<src> to C<dest>
2358 recursively using the C<cp -a> command.");
2359
2360   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2361    [InitBasicFS, Always, TestOutput (
2362       [["write_file"; "/old"; "file content"; "0"];
2363        ["mv"; "/old"; "/new"];
2364        ["cat"; "/new"]], "file content");
2365     InitBasicFS, Always, TestOutputFalse (
2366       [["write_file"; "/old"; "file content"; "0"];
2367        ["mv"; "/old"; "/new"];
2368        ["is_file"; "/old"]])],
2369    "move a file",
2370    "\
2371 This moves a file from C<src> to C<dest> where C<dest> is
2372 either a destination filename or destination directory.");
2373
2374   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2375    [InitEmpty, Always, TestRun (
2376       [["drop_caches"; "3"]])],
2377    "drop kernel page cache, dentries and inodes",
2378    "\
2379 This instructs the guest kernel to drop its page cache,
2380 and/or dentries and inode caches.  The parameter C<whattodrop>
2381 tells the kernel what precisely to drop, see
2382 L<http://linux-mm.org/Drop_Caches>
2383
2384 Setting C<whattodrop> to 3 should drop everything.
2385
2386 This automatically calls L<sync(2)> before the operation,
2387 so that the maximum guest memory is freed.");
2388
2389   ("dmesg", (RString "kmsgs", []), 91, [],
2390    [InitEmpty, Always, TestRun (
2391       [["dmesg"]])],
2392    "return kernel messages",
2393    "\
2394 This returns the kernel messages (C<dmesg> output) from
2395 the guest kernel.  This is sometimes useful for extended
2396 debugging of problems.
2397
2398 Another way to get the same information is to enable
2399 verbose messages with C<guestfs_set_verbose> or by setting
2400 the environment variable C<LIBGUESTFS_DEBUG=1> before
2401 running the program.");
2402
2403   ("ping_daemon", (RErr, []), 92, [],
2404    [InitEmpty, Always, TestRun (
2405       [["ping_daemon"]])],
2406    "ping the guest daemon",
2407    "\
2408 This is a test probe into the guestfs daemon running inside
2409 the qemu subprocess.  Calling this function checks that the
2410 daemon responds to the ping message, without affecting the daemon
2411 or attached block device(s) in any other way.");
2412
2413   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2414    [InitBasicFS, Always, TestOutputTrue (
2415       [["write_file"; "/file1"; "contents of a file"; "0"];
2416        ["cp"; "/file1"; "/file2"];
2417        ["equal"; "/file1"; "/file2"]]);
2418     InitBasicFS, Always, TestOutputFalse (
2419       [["write_file"; "/file1"; "contents of a file"; "0"];
2420        ["write_file"; "/file2"; "contents of another file"; "0"];
2421        ["equal"; "/file1"; "/file2"]]);
2422     InitBasicFS, Always, TestLastFail (
2423       [["equal"; "/file1"; "/file2"]])],
2424    "test if two files have equal contents",
2425    "\
2426 This compares the two files C<file1> and C<file2> and returns
2427 true if their content is exactly equal, or false otherwise.
2428
2429 The external L<cmp(1)> program is used for the comparison.");
2430
2431   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2432    [InitISOFS, Always, TestOutputList (
2433       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2434     InitISOFS, Always, TestOutputList (
2435       [["strings"; "/empty"]], [])],
2436    "print the printable strings in a file",
2437    "\
2438 This runs the L<strings(1)> command on a file and returns
2439 the list of printable strings found.");
2440
2441   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2442    [InitISOFS, Always, TestOutputList (
2443       [["strings_e"; "b"; "/known-5"]], []);
2444     InitBasicFS, Disabled, TestOutputList (
2445       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2446        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2447    "print the printable strings in a file",
2448    "\
2449 This is like the C<guestfs_strings> command, but allows you to
2450 specify the encoding of strings that are looked for in
2451 the source file C<path>.
2452
2453 Allowed encodings are:
2454
2455 =over 4
2456
2457 =item s
2458
2459 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2460 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2461
2462 =item S
2463
2464 Single 8-bit-byte characters.
2465
2466 =item b
2467
2468 16-bit big endian strings such as those encoded in
2469 UTF-16BE or UCS-2BE.
2470
2471 =item l (lower case letter L)
2472
2473 16-bit little endian such as UTF-16LE and UCS-2LE.
2474 This is useful for examining binaries in Windows guests.
2475
2476 =item B
2477
2478 32-bit big endian such as UCS-4BE.
2479
2480 =item L
2481
2482 32-bit little endian such as UCS-4LE.
2483
2484 =back
2485
2486 The returned strings are transcoded to UTF-8.");
2487
2488   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2489    [InitISOFS, Always, TestOutput (
2490       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2491     (* Test for RHBZ#501888c2 regression which caused large hexdump
2492      * commands to segfault.
2493      *)
2494     InitISOFS, Always, TestRun (
2495       [["hexdump"; "/100krandom"]])],
2496    "dump a file in hexadecimal",
2497    "\
2498 This runs C<hexdump -C> on the given C<path>.  The result is
2499 the human-readable, canonical hex dump of the file.");
2500
2501   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2502    [InitNone, Always, TestOutput (
2503       [["part_disk"; "/dev/sda"; "mbr"];
2504        ["mkfs"; "ext3"; "/dev/sda1"];
2505        ["mount_options"; ""; "/dev/sda1"; "/"];
2506        ["write_file"; "/new"; "test file"; "0"];
2507        ["umount"; "/dev/sda1"];
2508        ["zerofree"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["cat"; "/new"]], "test file")],
2511    "zero unused inodes and disk blocks on ext2/3 filesystem",
2512    "\
2513 This runs the I<zerofree> program on C<device>.  This program
2514 claims to zero unused inodes and disk blocks on an ext2/3
2515 filesystem, thus making it possible to compress the filesystem
2516 more effectively.
2517
2518 You should B<not> run this program if the filesystem is
2519 mounted.
2520
2521 It is possible that using this program can damage the filesystem
2522 or data on the filesystem.");
2523
2524   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2525    [],
2526    "resize an LVM physical volume",
2527    "\
2528 This resizes (expands or shrinks) an existing LVM physical
2529 volume to match the new size of the underlying device.");
2530
2531   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2532                        Int "cyls"; Int "heads"; Int "sectors";
2533                        String "line"]), 99, [DangerWillRobinson],
2534    [],
2535    "modify a single partition on a block device",
2536    "\
2537 This runs L<sfdisk(8)> option to modify just the single
2538 partition C<n> (note: C<n> counts from 1).
2539
2540 For other parameters, see C<guestfs_sfdisk>.  You should usually
2541 pass C<0> for the cyls/heads/sectors parameters.
2542
2543 See also: C<guestfs_part_add>");
2544
2545   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2546    [],
2547    "display the partition table",
2548    "\
2549 This displays the partition table on C<device>, in the
2550 human-readable output of the L<sfdisk(8)> command.  It is
2551 not intended to be parsed.
2552
2553 See also: C<guestfs_part_list>");
2554
2555   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2556    [],
2557    "display the kernel geometry",
2558    "\
2559 This displays the kernel's idea of the geometry of C<device>.
2560
2561 The result is in human-readable format, and not designed to
2562 be parsed.");
2563
2564   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2565    [],
2566    "display the disk geometry from the partition table",
2567    "\
2568 This displays the disk geometry of C<device> read from the
2569 partition table.  Especially in the case where the underlying
2570 block device has been resized, this can be different from the
2571 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2572
2573 The result is in human-readable format, and not designed to
2574 be parsed.");
2575
2576   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2577    [],
2578    "activate or deactivate all volume groups",
2579    "\
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in all volume groups.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2584 then those devices disappear.
2585
2586 This command is the same as running C<vgchange -a y|n>");
2587
2588   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2589    [],
2590    "activate or deactivate some volume groups",
2591    "\
2592 This command activates or (if C<activate> is false) deactivates
2593 all logical volumes in the listed volume groups C<volgroups>.
2594 If activated, then they are made known to the
2595 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2596 then those devices disappear.
2597
2598 This command is the same as running C<vgchange -a y|n volgroups...>
2599
2600 Note that if C<volgroups> is an empty list then B<all> volume groups
2601 are activated or deactivated.");
2602
2603   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2604    [InitNone, Always, TestOutput (
2605       [["part_disk"; "/dev/sda"; "mbr"];
2606        ["pvcreate"; "/dev/sda1"];
2607        ["vgcreate"; "VG"; "/dev/sda1"];
2608        ["lvcreate"; "LV"; "VG"; "10"];
2609        ["mkfs"; "ext2"; "/dev/VG/LV"];
2610        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2611        ["write_file"; "/new"; "test content"; "0"];
2612        ["umount"; "/"];
2613        ["lvresize"; "/dev/VG/LV"; "20"];
2614        ["e2fsck_f"; "/dev/VG/LV"];
2615        ["resize2fs"; "/dev/VG/LV"];
2616        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2617        ["cat"; "/new"]], "test content");
2618     InitNone, Always, TestRun (
2619       (* Make an LV smaller to test RHBZ#587484. *)
2620       [["part_disk"; "/dev/sda"; "mbr"];
2621        ["pvcreate"; "/dev/sda1"];
2622        ["vgcreate"; "VG"; "/dev/sda1"];
2623        ["lvcreate"; "LV"; "VG"; "20"];
2624        ["lvresize"; "/dev/VG/LV"; "10"]])],
2625    "resize an LVM logical volume",
2626    "\
2627 This resizes (expands or shrinks) an existing LVM logical
2628 volume to C<mbytes>.  When reducing, data in the reduced part
2629 is lost.");
2630
2631   ("resize2fs", (RErr, [Device "device"]), 106, [],
2632    [], (* lvresize tests this *)
2633    "resize an ext2/ext3 filesystem",
2634    "\
2635 This resizes an ext2 or ext3 filesystem to match the size of
2636 the underlying device.
2637
2638 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2639 on the C<device> before calling this command.  For unknown reasons
2640 C<resize2fs> sometimes gives an error about this and sometimes not.
2641 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2642 calling this function.");
2643
2644   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2645    [InitBasicFS, Always, TestOutputList (
2646       [["find"; "/"]], ["lost+found"]);
2647     InitBasicFS, Always, TestOutputList (
2648       [["touch"; "/a"];
2649        ["mkdir"; "/b"];
2650        ["touch"; "/b/c"];
2651        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2652     InitBasicFS, Always, TestOutputList (
2653       [["mkdir_p"; "/a/b/c"];
2654        ["touch"; "/a/b/c/d"];
2655        ["find"; "/a/b/"]], ["c"; "c/d"])],
2656    "find all files and directories",
2657    "\
2658 This command lists out all files and directories, recursively,
2659 starting at C<directory>.  It is essentially equivalent to
2660 running the shell command C<find directory -print> but some
2661 post-processing happens on the output, described below.
2662
2663 This returns a list of strings I<without any prefix>.  Thus
2664 if the directory structure was:
2665
2666  /tmp/a
2667  /tmp/b
2668  /tmp/c/d
2669
2670 then the returned list from C<guestfs_find> C</tmp> would be
2671 4 elements:
2672
2673  a
2674  b
2675  c
2676  c/d
2677
2678 If C<directory> is not a directory, then this command returns
2679 an error.
2680
2681 The returned list is sorted.
2682
2683 See also C<guestfs_find0>.");
2684
2685   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2686    [], (* lvresize tests this *)
2687    "check an ext2/ext3 filesystem",
2688    "\
2689 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2690 filesystem checker on C<device>, noninteractively (C<-p>),
2691 even if the filesystem appears to be clean (C<-f>).
2692
2693 This command is only needed because of C<guestfs_resize2fs>
2694 (q.v.).  Normally you should use C<guestfs_fsck>.");
2695
2696   ("sleep", (RErr, [Int "secs"]), 109, [],
2697    [InitNone, Always, TestRun (
2698       [["sleep"; "1"]])],
2699    "sleep for some seconds",
2700    "\
2701 Sleep for C<secs> seconds.");
2702
2703   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2704    [InitNone, Always, TestOutputInt (
2705       [["part_disk"; "/dev/sda"; "mbr"];
2706        ["mkfs"; "ntfs"; "/dev/sda1"];
2707        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2708     InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ext2"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2712    "probe NTFS volume",
2713    "\
2714 This command runs the L<ntfs-3g.probe(8)> command which probes
2715 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2716 be mounted read-write, and some cannot be mounted at all).
2717
2718 C<rw> is a boolean flag.  Set it to true if you want to test
2719 if the volume can be mounted read-write.  Set it to false if
2720 you want to test if the volume can be mounted read-only.
2721
2722 The return value is an integer which C<0> if the operation
2723 would succeed, or some non-zero value documented in the
2724 L<ntfs-3g.probe(8)> manual page.");
2725
2726   ("sh", (RString "output", [String "command"]), 111, [],
2727    [], (* XXX needs tests *)
2728    "run a command via the shell",
2729    "\
2730 This call runs a command from the guest filesystem via the
2731 guest's C</bin/sh>.
2732
2733 This is like C<guestfs_command>, but passes the command to:
2734
2735  /bin/sh -c \"command\"
2736
2737 Depending on the guest's shell, this usually results in
2738 wildcards being expanded, shell expressions being interpolated
2739 and so on.
2740
2741 All the provisos about C<guestfs_command> apply to this call.");
2742
2743   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2744    [], (* XXX needs tests *)
2745    "run a command via the shell returning lines",
2746    "\
2747 This is the same as C<guestfs_sh>, but splits the result
2748 into a list of lines.
2749
2750 See also: C<guestfs_command_lines>");
2751
2752   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2753    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2754     * code in stubs.c, since all valid glob patterns must start with "/".
2755     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2756     *)
2757    [InitBasicFS, Always, TestOutputList (
2758       [["mkdir_p"; "/a/b/c"];
2759        ["touch"; "/a/b/c/d"];
2760        ["touch"; "/a/b/c/e"];
2761        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2762     InitBasicFS, Always, TestOutputList (
2763       [["mkdir_p"; "/a/b/c"];
2764        ["touch"; "/a/b/c/d"];
2765        ["touch"; "/a/b/c/e"];
2766        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2767     InitBasicFS, Always, TestOutputList (
2768       [["mkdir_p"; "/a/b/c"];
2769        ["touch"; "/a/b/c/d"];
2770        ["touch"; "/a/b/c/e"];
2771        ["glob_expand"; "/a/*/x/*"]], [])],
2772    "expand a wildcard path",
2773    "\
2774 This command searches for all the pathnames matching
2775 C<pattern> according to the wildcard expansion rules
2776 used by the shell.
2777
2778 If no paths match, then this returns an empty list
2779 (note: not an error).
2780
2781 It is just a wrapper around the C L<glob(3)> function
2782 with flags C<GLOB_MARK|GLOB_BRACE>.
2783 See that manual page for more details.");
2784
2785   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2786    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2787       [["scrub_device"; "/dev/sdc"]])],
2788    "scrub (securely wipe) a device",
2789    "\
2790 This command writes patterns over C<device> to make data retrieval
2791 more difficult.
2792
2793 It is an interface to the L<scrub(1)> program.  See that
2794 manual page for more details.");
2795
2796   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2797    [InitBasicFS, Always, TestRun (
2798       [["write_file"; "/file"; "content"; "0"];
2799        ["scrub_file"; "/file"]])],
2800    "scrub (securely wipe) a file",
2801    "\
2802 This command writes patterns over a file to make data retrieval
2803 more difficult.
2804
2805 The file is I<removed> after scrubbing.
2806
2807 It is an interface to the L<scrub(1)> program.  See that
2808 manual page for more details.");
2809
2810   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2811    [], (* XXX needs testing *)
2812    "scrub (securely wipe) free space",
2813    "\
2814 This command creates the directory C<dir> and then fills it
2815 with files until the filesystem is full, and scrubs the files
2816 as for C<guestfs_scrub_file>, and deletes them.
2817 The intention is to scrub any free space on the partition
2818 containing C<dir>.
2819
2820 It is an interface to the L<scrub(1)> program.  See that
2821 manual page for more details.");
2822
2823   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2824    [InitBasicFS, Always, TestRun (
2825       [["mkdir"; "/tmp"];
2826        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2827    "create a temporary directory",
2828    "\
2829 This command creates a temporary directory.  The
2830 C<template> parameter should be a full pathname for the
2831 temporary directory name with the final six characters being
2832 \"XXXXXX\".
2833
2834 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2835 the second one being suitable for Windows filesystems.
2836
2837 The name of the temporary directory that was created
2838 is returned.
2839
2840 The temporary directory is created with mode 0700
2841 and is owned by root.
2842
2843 The caller is responsible for deleting the temporary
2844 directory and its contents after use.
2845
2846 See also: L<mkdtemp(3)>");
2847
2848   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2849    [InitISOFS, Always, TestOutputInt (
2850       [["wc_l"; "/10klines"]], 10000)],
2851    "count lines in a file",
2852    "\
2853 This command counts the lines in a file, using the
2854 C<wc -l> external command.");
2855
2856   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2857    [InitISOFS, Always, TestOutputInt (
2858       [["wc_w"; "/10klines"]], 10000)],
2859    "count words in a file",
2860    "\
2861 This command counts the words in a file, using the
2862 C<wc -w> external command.");
2863
2864   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2865    [InitISOFS, Always, TestOutputInt (
2866       [["wc_c"; "/100kallspaces"]], 102400)],
2867    "count characters in a file",
2868    "\
2869 This command counts the characters in a file, using the
2870 C<wc -c> external command.");
2871
2872   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2873    [InitISOFS, Always, TestOutputList (
2874       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2875    "return first 10 lines of a file",
2876    "\
2877 This command returns up to the first 10 lines of a file as
2878 a list of strings.");
2879
2880   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2881    [InitISOFS, Always, TestOutputList (
2882       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2883     InitISOFS, Always, TestOutputList (
2884       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2885     InitISOFS, Always, TestOutputList (
2886       [["head_n"; "0"; "/10klines"]], [])],
2887    "return first N lines of a file",
2888    "\
2889 If the parameter C<nrlines> is a positive number, this returns the first
2890 C<nrlines> lines of the file C<path>.
2891
2892 If the parameter C<nrlines> is a negative number, this returns lines
2893 from the file C<path>, excluding the last C<nrlines> lines.
2894
2895 If the parameter C<nrlines> is zero, this returns an empty list.");
2896
2897   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2898    [InitISOFS, Always, TestOutputList (
2899       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2900    "return last 10 lines of a file",
2901    "\
2902 This command returns up to the last 10 lines of a file as
2903 a list of strings.");
2904
2905   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2906    [InitISOFS, Always, TestOutputList (
2907       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2908     InitISOFS, Always, TestOutputList (
2909       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2910     InitISOFS, Always, TestOutputList (
2911       [["tail_n"; "0"; "/10klines"]], [])],
2912    "return last N lines of a file",
2913    "\
2914 If the parameter C<nrlines> is a positive number, this returns the last
2915 C<nrlines> lines of the file C<path>.
2916
2917 If the parameter C<nrlines> is a negative number, this returns lines
2918 from the file C<path>, starting with the C<-nrlines>th line.
2919
2920 If the parameter C<nrlines> is zero, this returns an empty list.");
2921
2922   ("df", (RString "output", []), 125, [],
2923    [], (* XXX Tricky to test because it depends on the exact format
2924         * of the 'df' command and other imponderables.
2925         *)
2926    "report file system disk space usage",
2927    "\
2928 This command runs the C<df> command to report disk space used.
2929
2930 This command is mostly useful for interactive sessions.  It
2931 is I<not> intended that you try to parse the output string.
2932 Use C<statvfs> from programs.");
2933
2934   ("df_h", (RString "output", []), 126, [],
2935    [], (* XXX Tricky to test because it depends on the exact format
2936         * of the 'df' command and other imponderables.
2937         *)
2938    "report file system disk space usage (human readable)",
2939    "\
2940 This command runs the C<df -h> command to report disk space used
2941 in human-readable format.
2942
2943 This command is mostly useful for interactive sessions.  It
2944 is I<not> intended that you try to parse the output string.
2945 Use C<statvfs> from programs.");
2946
2947   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2948    [InitISOFS, Always, TestOutputInt (
2949       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2950    "estimate file space usage",
2951    "\
2952 This command runs the C<du -s> command to estimate file space
2953 usage for C<path>.
2954
2955 C<path> can be a file or a directory.  If C<path> is a directory
2956 then the estimate includes the contents of the directory and all
2957 subdirectories (recursively).
2958
2959 The result is the estimated size in I<kilobytes>
2960 (ie. units of 1024 bytes).");
2961
2962   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2963    [InitISOFS, Always, TestOutputList (
2964       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2965    "list files in an initrd",
2966    "\
2967 This command lists out files contained in an initrd.
2968
2969 The files are listed without any initial C</> character.  The
2970 files are listed in the order they appear (not necessarily
2971 alphabetical).  Directory names are listed as separate items.
2972
2973 Old Linux kernels (2.4 and earlier) used a compressed ext2
2974 filesystem as initrd.  We I<only> support the newer initramfs
2975 format (compressed cpio files).");
2976
2977   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2978    [],
2979    "mount a file using the loop device",
2980    "\
2981 This command lets you mount C<file> (a filesystem image
2982 in a file) on a mount point.  It is entirely equivalent to
2983 the command C<mount -o loop file mountpoint>.");
2984
2985   ("mkswap", (RErr, [Device "device"]), 130, [],
2986    [InitEmpty, Always, TestRun (
2987       [["part_disk"; "/dev/sda"; "mbr"];
2988        ["mkswap"; "/dev/sda1"]])],
2989    "create a swap partition",
2990    "\
2991 Create a swap partition on C<device>.");
2992
2993   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2994    [InitEmpty, Always, TestRun (
2995       [["part_disk"; "/dev/sda"; "mbr"];
2996        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2997    "create a swap partition with a label",
2998    "\
2999 Create a swap partition on C<device> with label C<label>.
3000
3001 Note that you cannot attach a swap label to a block device
3002 (eg. C</dev/sda>), just to a partition.  This appears to be
3003 a limitation of the kernel or swap tools.");
3004
3005   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3006    (let uuid = uuidgen () in
3007     [InitEmpty, Always, TestRun (
3008        [["part_disk"; "/dev/sda"; "mbr"];
3009         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3010    "create a swap partition with an explicit UUID",
3011    "\
3012 Create a swap partition on C<device> with UUID C<uuid>.");
3013
3014   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3015    [InitBasicFS, Always, TestOutputStruct (
3016       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3017        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3018        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3019     InitBasicFS, Always, TestOutputStruct (
3020       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3021        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3022    "make block, character or FIFO devices",
3023    "\
3024 This call creates block or character special devices, or
3025 named pipes (FIFOs).
3026
3027 The C<mode> parameter should be the mode, using the standard
3028 constants.  C<devmajor> and C<devminor> are the
3029 device major and minor numbers, only used when creating block
3030 and character special devices.
3031
3032 Note that, just like L<mknod(2)>, the mode must be bitwise
3033 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3034 just creates a regular file).  These constants are
3035 available in the standard Linux header files, or you can use
3036 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3037 which are wrappers around this command which bitwise OR
3038 in the appropriate constant for you.
3039
3040 The mode actually set is affected by the umask.");
3041
3042   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3043    [InitBasicFS, Always, TestOutputStruct (
3044       [["mkfifo"; "0o777"; "/node"];
3045        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3046    "make FIFO (named pipe)",
3047    "\
3048 This call creates a FIFO (named pipe) called C<path> with
3049 mode C<mode>.  It is just a convenient wrapper around
3050 C<guestfs_mknod>.
3051
3052 The mode actually set is affected by the umask.");
3053
3054   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3055    [InitBasicFS, Always, TestOutputStruct (
3056       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3057        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3058    "make block device node",
3059    "\
3060 This call creates a block device node called C<path> with
3061 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3062 It is just a convenient wrapper around C<guestfs_mknod>.
3063
3064 The mode actually set is affected by the umask.");
3065
3066   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3067    [InitBasicFS, Always, TestOutputStruct (
3068       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3069        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3070    "make char device node",
3071    "\
3072 This call creates a char device node called C<path> with
3073 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3074 It is just a convenient wrapper around C<guestfs_mknod>.
3075
3076 The mode actually set is affected by the umask.");
3077
3078   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3079    [InitEmpty, Always, TestOutputInt (
3080       [["umask"; "0o22"]], 0o22)],
3081    "set file mode creation mask (umask)",
3082    "\
3083 This function sets the mask used for creating new files and
3084 device nodes to C<mask & 0777>.
3085
3086 Typical umask values would be C<022> which creates new files
3087 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3088 C<002> which creates new files with permissions like
3089 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3090
3091 The default umask is C<022>.  This is important because it
3092 means that directories and device nodes will be created with
3093 C<0644> or C<0755> mode even if you specify C<0777>.
3094
3095 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3096
3097 This call returns the previous umask.");
3098
3099   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3100    [],
3101    "read directories entries",
3102    "\
3103 This returns the list of directory entries in directory C<dir>.
3104
3105 All entries in the directory are returned, including C<.> and
3106 C<..>.  The entries are I<not> sorted, but returned in the same
3107 order as the underlying filesystem.
3108
3109 Also this call returns basic file type information about each
3110 file.  The C<ftyp> field will contain one of the following characters:
3111
3112 =over 4
3113
3114 =item 'b'
3115
3116 Block special
3117
3118 =item 'c'
3119
3120 Char special
3121
3122 =item 'd'
3123
3124 Directory
3125
3126 =item 'f'
3127
3128 FIFO (named pipe)
3129
3130 =item 'l'
3131
3132 Symbolic link
3133
3134 =item 'r'
3135
3136 Regular file
3137
3138 =item 's'
3139
3140 Socket
3141
3142 =item 'u'
3143
3144 Unknown file type
3145
3146 =item '?'
3147
3148 The L<readdir(3)> call returned a C<d_type> field with an
3149 unexpected value
3150
3151 =back
3152
3153 This function is primarily intended for use by programs.  To
3154 get a simple list of names, use C<guestfs_ls>.  To get a printable
3155 directory for human consumption, use C<guestfs_ll>.");
3156
3157   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3158    [],
3159    "create partitions on a block device",
3160    "\
3161 This is a simplified interface to the C<guestfs_sfdisk>
3162 command, where partition sizes are specified in megabytes
3163 only (rounded to the nearest cylinder) and you don't need
3164 to specify the cyls, heads and sectors parameters which
3165 were rarely if ever used anyway.
3166
3167 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3168 and C<guestfs_part_disk>");
3169
3170   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3171    [],
3172    "determine file type inside a compressed file",
3173    "\
3174 This command runs C<file> after first decompressing C<path>
3175 using C<method>.
3176
3177 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3178
3179 Since 1.0.63, use C<guestfs_file> instead which can now
3180 process compressed files.");
3181
3182   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3183    [],
3184    "list extended attributes of a file or directory",
3185    "\
3186 This call lists the extended attributes of the file or directory
3187 C<path>.
3188
3189 At the system call level, this is a combination of the
3190 L<listxattr(2)> and L<getxattr(2)> calls.
3191
3192 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3193
3194   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3195    [],
3196    "list extended attributes of a file or directory",
3197    "\
3198 This is the same as C<guestfs_getxattrs>, but if C<path>
3199 is a symbolic link, then it returns the extended attributes
3200 of the link itself.");
3201
3202   ("setxattr", (RErr, [String "xattr";
3203                        String "val"; Int "vallen"; (* will be BufferIn *)
3204                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3205    [],
3206    "set extended attribute of a file or directory",
3207    "\
3208 This call sets the extended attribute named C<xattr>
3209 of the file C<path> to the value C<val> (of length C<vallen>).
3210 The value is arbitrary 8 bit data.
3211
3212 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3213
3214   ("lsetxattr", (RErr, [String "xattr";
3215                         String "val"; Int "vallen"; (* will be BufferIn *)
3216                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3217    [],
3218    "set extended attribute of a file or directory",
3219    "\
3220 This is the same as C<guestfs_setxattr>, but if C<path>
3221 is a symbolic link, then it sets an extended attribute
3222 of the link itself.");
3223
3224   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3225    [],
3226    "remove extended attribute of a file or directory",
3227    "\
3228 This call removes the extended attribute named C<xattr>
3229 of the file C<path>.
3230
3231 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3232
3233   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3234    [],
3235    "remove extended attribute of a file or directory",
3236    "\
3237 This is the same as C<guestfs_removexattr>, but if C<path>
3238 is a symbolic link, then it removes an extended attribute
3239 of the link itself.");
3240
3241   ("mountpoints", (RHashtable "mps", []), 147, [],
3242    [],
3243    "show mountpoints",
3244    "\
3245 This call is similar to C<guestfs_mounts>.  That call returns
3246 a list of devices.  This one returns a hash table (map) of
3247 device name to directory where the device is mounted.");
3248
3249   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3250    (* This is a special case: while you would expect a parameter
3251     * of type "Pathname", that doesn't work, because it implies
3252     * NEED_ROOT in the generated calling code in stubs.c, and
3253     * this function cannot use NEED_ROOT.
3254     *)
3255    [],
3256    "create a mountpoint",
3257    "\
3258 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3259 specialized calls that can be used to create extra mountpoints
3260 before mounting the first filesystem.
3261
3262 These calls are I<only> necessary in some very limited circumstances,
3263 mainly the case where you want to mount a mix of unrelated and/or
3264 read-only filesystems together.
3265
3266 For example, live CDs often contain a \"Russian doll\" nest of
3267 filesystems, an ISO outer layer, with a squashfs image inside, with
3268 an ext2/3 image inside that.  You can unpack this as follows
3269 in guestfish:
3270
3271  add-ro Fedora-11-i686-Live.iso
3272  run
3273  mkmountpoint /cd
3274  mkmountpoint /squash
3275  mkmountpoint /ext3
3276  mount /dev/sda /cd
3277  mount-loop /cd/LiveOS/squashfs.img /squash
3278  mount-loop /squash/LiveOS/ext3fs.img /ext3
3279
3280 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3281
3282   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3283    [],
3284    "remove a mountpoint",
3285    "\
3286 This calls removes a mountpoint that was previously created
3287 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3288 for full details.");
3289
3290   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3291    [InitISOFS, Always, TestOutputBuffer (
3292       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3293     (* Test various near large, large and too large files (RHBZ#589039). *)
3294     InitBasicFS, Always, TestLastFail (
3295       [["touch"; "/a"];
3296        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3297        ["read_file"; "/a"]]);
3298     InitBasicFS, Always, TestLastFail (
3299       [["touch"; "/a"];
3300        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3301        ["read_file"; "/a"]]);
3302     InitBasicFS, Always, TestLastFail (
3303       [["touch"; "/a"];
3304        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3305        ["read_file"; "/a"]])],
3306    "read a file",
3307    "\
3308 This calls returns the contents of the file C<path> as a
3309 buffer.
3310
3311 Unlike C<guestfs_cat>, this function can correctly
3312 handle files that contain embedded ASCII NUL characters.
3313 However unlike C<guestfs_download>, this function is limited
3314 in the total size of file that can be handled.");
3315
3316   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3317    [InitISOFS, Always, TestOutputList (
3318       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3319     InitISOFS, Always, TestOutputList (
3320       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<grep> program and returns the
3324 matching lines.");
3325
3326   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<egrep> program and returns the
3332 matching lines.");
3333
3334   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3335    [InitISOFS, Always, TestOutputList (
3336       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3337    "return lines matching a pattern",
3338    "\
3339 This calls the external C<fgrep> program and returns the
3340 matching lines.");
3341
3342   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3343    [InitISOFS, Always, TestOutputList (
3344       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3345    "return lines matching a pattern",
3346    "\
3347 This calls the external C<grep -i> program and returns the
3348 matching lines.");
3349
3350   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3351    [InitISOFS, Always, TestOutputList (
3352       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3353    "return lines matching a pattern",
3354    "\
3355 This calls the external C<egrep -i> program and returns the
3356 matching lines.");
3357
3358   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3359    [InitISOFS, Always, TestOutputList (
3360       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3361    "return lines matching a pattern",
3362    "\
3363 This calls the external C<fgrep -i> program and returns the
3364 matching lines.");
3365
3366   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3367    [InitISOFS, Always, TestOutputList (
3368       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3369    "return lines matching a pattern",
3370    "\
3371 This calls the external C<zgrep> program and returns the
3372 matching lines.");
3373
3374   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3375    [InitISOFS, Always, TestOutputList (
3376       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3377    "return lines matching a pattern",
3378    "\
3379 This calls the external C<zegrep> program and returns the
3380 matching lines.");
3381
3382   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3383    [InitISOFS, Always, TestOutputList (
3384       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3385    "return lines matching a pattern",
3386    "\
3387 This calls the external C<zfgrep> program and returns the
3388 matching lines.");
3389
3390   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3391    [InitISOFS, Always, TestOutputList (
3392       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3393    "return lines matching a pattern",
3394    "\
3395 This calls the external C<zgrep -i> program and returns the
3396 matching lines.");
3397
3398   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3399    [InitISOFS, Always, TestOutputList (
3400       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3401    "return lines matching a pattern",
3402    "\
3403 This calls the external C<zegrep -i> program and returns the
3404 matching lines.");
3405
3406   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3407    [InitISOFS, Always, TestOutputList (
3408       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3409    "return lines matching a pattern",
3410    "\
3411 This calls the external C<zfgrep -i> program and returns the
3412 matching lines.");
3413
3414   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3415    [InitISOFS, Always, TestOutput (
3416       [["realpath"; "/../directory"]], "/directory")],
3417    "canonicalized absolute pathname",
3418    "\
3419 Return the canonicalized absolute pathname of C<path>.  The
3420 returned path has no C<.>, C<..> or symbolic link path elements.");
3421
3422   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3423    [InitBasicFS, Always, TestOutputStruct (
3424       [["touch"; "/a"];
3425        ["ln"; "/a"; "/b"];
3426        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3427    "create a hard link",
3428    "\
3429 This command creates a hard link using the C<ln> command.");
3430
3431   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3432    [InitBasicFS, Always, TestOutputStruct (
3433       [["touch"; "/a"];
3434        ["touch"; "/b"];
3435        ["ln_f"; "/a"; "/b"];
3436        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3437    "create a hard link",
3438    "\
3439 This command creates a hard link using the C<ln -f> command.
3440 The C<-f> option removes the link (C<linkname>) if it exists already.");
3441
3442   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3443    [InitBasicFS, Always, TestOutputStruct (
3444       [["touch"; "/a"];
3445        ["ln_s"; "a"; "/b"];
3446        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3447    "create a symbolic link",
3448    "\
3449 This command creates a symbolic link using the C<ln -s> command.");
3450
3451   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3452    [InitBasicFS, Always, TestOutput (
3453       [["mkdir_p"; "/a/b"];
3454        ["touch"; "/a/b/c"];
3455        ["ln_sf"; "../d"; "/a/b/c"];
3456        ["readlink"; "/a/b/c"]], "../d")],
3457    "create a symbolic link",
3458    "\
3459 This command creates a symbolic link using the C<ln -sf> command,
3460 The C<-f> option removes the link (C<linkname>) if it exists already.");
3461
3462   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3463    [] (* XXX tested above *),
3464    "read the target of a symbolic link",
3465    "\
3466 This command reads the target of a symbolic link.");
3467
3468   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3469    [InitBasicFS, Always, TestOutputStruct (
3470       [["fallocate"; "/a"; "1000000"];
3471        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3472    "preallocate a file in the guest filesystem",
3473    "\
3474 This command preallocates a file (containing zero bytes) named
3475 C<path> of size C<len> bytes.  If the file exists already, it
3476 is overwritten.
3477
3478 Do not confuse this with the guestfish-specific
3479 C<alloc> command which allocates a file in the host and
3480 attaches it as a device.");
3481
3482   ("swapon_device", (RErr, [Device "device"]), 170, [],
3483    [InitPartition, Always, TestRun (
3484       [["mkswap"; "/dev/sda1"];
3485        ["swapon_device"; "/dev/sda1"];
3486        ["swapoff_device"; "/dev/sda1"]])],
3487    "enable swap on device",
3488    "\
3489 This command enables the libguestfs appliance to use the
3490 swap device or partition named C<device>.  The increased
3491 memory is made available for all commands, for example
3492 those run using C<guestfs_command> or C<guestfs_sh>.
3493
3494 Note that you should not swap to existing guest swap
3495 partitions unless you know what you are doing.  They may
3496 contain hibernation information, or other information that
3497 the guest doesn't want you to trash.  You also risk leaking
3498 information about the host to the guest this way.  Instead,
3499 attach a new host device to the guest and swap on that.");
3500
3501   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3502    [], (* XXX tested by swapon_device *)
3503    "disable swap on device",
3504    "\
3505 This command disables the libguestfs appliance swap
3506 device or partition named C<device>.
3507 See C<guestfs_swapon_device>.");
3508
3509   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3510    [InitBasicFS, Always, TestRun (
3511       [["fallocate"; "/swap"; "8388608"];
3512        ["mkswap_file"; "/swap"];
3513        ["swapon_file"; "/swap"];
3514        ["swapoff_file"; "/swap"]])],
3515    "enable swap on file",
3516    "\
3517 This command enables swap to a file.
3518 See C<guestfs_swapon_device> for other notes.");
3519
3520   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3521    [], (* XXX tested by swapon_file *)
3522    "disable swap on file",
3523    "\
3524 This command disables the libguestfs appliance swap on file.");
3525
3526   ("swapon_label", (RErr, [String "label"]), 174, [],
3527    [InitEmpty, Always, TestRun (
3528       [["part_disk"; "/dev/sdb"; "mbr"];
3529        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3530        ["swapon_label"; "swapit"];
3531        ["swapoff_label"; "swapit"];
3532        ["zero"; "/dev/sdb"];
3533        ["blockdev_rereadpt"; "/dev/sdb"]])],
3534    "enable swap on labeled swap partition",
3535    "\
3536 This command enables swap to a labeled swap partition.
3537 See C<guestfs_swapon_device> for other notes.");
3538
3539   ("swapoff_label", (RErr, [String "label"]), 175, [],
3540    [], (* XXX tested by swapon_label *)
3541    "disable swap on labeled swap partition",
3542    "\
3543 This command disables the libguestfs appliance swap on
3544 labeled swap partition.");
3545
3546   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3547    (let uuid = uuidgen () in
3548     [InitEmpty, Always, TestRun (
3549        [["mkswap_U"; uuid; "/dev/sdb"];
3550         ["swapon_uuid"; uuid];
3551         ["swapoff_uuid"; uuid]])]),
3552    "enable swap on swap partition by UUID",
3553    "\
3554 This command enables swap to a swap partition with the given UUID.
3555 See C<guestfs_swapon_device> for other notes.");
3556
3557   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3558    [], (* XXX tested by swapon_uuid *)
3559    "disable swap on swap partition by UUID",
3560    "\
3561 This command disables the libguestfs appliance swap partition
3562 with the given UUID.");
3563
3564   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3565    [InitBasicFS, Always, TestRun (
3566       [["fallocate"; "/swap"; "8388608"];
3567        ["mkswap_file"; "/swap"]])],
3568    "create a swap file",
3569    "\
3570 Create a swap file.
3571
3572 This command just writes a swap file signature to an existing
3573 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3574
3575   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3576    [InitISOFS, Always, TestRun (
3577       [["inotify_init"; "0"]])],
3578    "create an inotify handle",
3579    "\
3580 This command creates a new inotify handle.
3581 The inotify subsystem can be used to notify events which happen to
3582 objects in the guest filesystem.
3583
3584 C<maxevents> is the maximum number of events which will be
3585 queued up between calls to C<guestfs_inotify_read> or
3586 C<guestfs_inotify_files>.
3587 If this is passed as C<0>, then the kernel (or previously set)
3588 default is used.  For Linux 2.6.29 the default was 16384 events.
3589 Beyond this limit, the kernel throws away events, but records
3590 the fact that it threw them away by setting a flag
3591 C<IN_Q_OVERFLOW> in the returned structure list (see
3592 C<guestfs_inotify_read>).
3593
3594 Before any events are generated, you have to add some
3595 watches to the internal watch list.  See:
3596 C<guestfs_inotify_add_watch>,
3597 C<guestfs_inotify_rm_watch> and
3598 C<guestfs_inotify_watch_all>.
3599
3600 Queued up events should be read periodically by calling
3601 C<guestfs_inotify_read>
3602 (or C<guestfs_inotify_files> which is just a helpful
3603 wrapper around C<guestfs_inotify_read>).  If you don't
3604 read the events out often enough then you risk the internal
3605 queue overflowing.
3606
3607 The handle should be closed after use by calling
3608 C<guestfs_inotify_close>.  This also removes any
3609 watches automatically.
3610
3611 See also L<inotify(7)> for an overview of the inotify interface
3612 as exposed by the Linux kernel, which is roughly what we expose
3613 via libguestfs.  Note that there is one global inotify handle
3614 per libguestfs instance.");
3615
3616   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3617    [InitBasicFS, Always, TestOutputList (
3618       [["inotify_init"; "0"];
3619        ["inotify_add_watch"; "/"; "1073741823"];
3620        ["touch"; "/a"];
3621        ["touch"; "/b"];
3622        ["inotify_files"]], ["a"; "b"])],
3623    "add an inotify watch",
3624    "\
3625 Watch C<path> for the events listed in C<mask>.
3626
3627 Note that if C<path> is a directory then events within that
3628 directory are watched, but this does I<not> happen recursively
3629 (in subdirectories).
3630
3631 Note for non-C or non-Linux callers: the inotify events are
3632 defined by the Linux kernel ABI and are listed in
3633 C</usr/include/sys/inotify.h>.");
3634
3635   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3636    [],
3637    "remove an inotify watch",
3638    "\
3639 Remove a previously defined inotify watch.
3640 See C<guestfs_inotify_add_watch>.");
3641
3642   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3643    [],
3644    "return list of inotify events",
3645    "\
3646 Return the complete queue of events that have happened
3647 since the previous read call.
3648
3649 If no events have happened, this returns an empty list.
3650
3651 I<Note>: In order to make sure that all events have been
3652 read, you must call this function repeatedly until it
3653 returns an empty list.  The reason is that the call will
3654 read events up to the maximum appliance-to-host message
3655 size and leave remaining events in the queue.");
3656
3657   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3658    [],
3659    "return list of watched files that had events",
3660    "\
3661 This function is a helpful wrapper around C<guestfs_inotify_read>
3662 which just returns a list of pathnames of objects that were
3663 touched.  The returned pathnames are sorted and deduplicated.");
3664
3665   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3666    [],
3667    "close the inotify handle",
3668    "\
3669 This closes the inotify handle which was previously
3670 opened by inotify_init.  It removes all watches, throws
3671 away any pending events, and deallocates all resources.");
3672
3673   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3674    [],
3675    "set SELinux security context",
3676    "\
3677 This sets the SELinux security context of the daemon
3678 to the string C<context>.
3679
3680 See the documentation about SELINUX in L<guestfs(3)>.");
3681
3682   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3683    [],
3684    "get SELinux security context",
3685    "\
3686 This gets the SELinux security context of the daemon.
3687
3688 See the documentation about SELINUX in L<guestfs(3)>,
3689 and C<guestfs_setcon>");
3690
3691   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3692    [InitEmpty, Always, TestOutput (
3693       [["part_disk"; "/dev/sda"; "mbr"];
3694        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3695        ["mount_options"; ""; "/dev/sda1"; "/"];
3696        ["write_file"; "/new"; "new file contents"; "0"];
3697        ["cat"; "/new"]], "new file contents")],
3698    "make a filesystem with block size",
3699    "\
3700 This call is similar to C<guestfs_mkfs>, but it allows you to
3701 control the block size of the resulting filesystem.  Supported
3702 block sizes depend on the filesystem type, but typically they
3703 are C<1024>, C<2048> or C<4096> only.");
3704
3705   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3706    [InitEmpty, Always, TestOutput (
3707       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3708        ["mke2journal"; "4096"; "/dev/sda1"];
3709        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3710        ["mount_options"; ""; "/dev/sda2"; "/"];
3711        ["write_file"; "/new"; "new file contents"; "0"];
3712        ["cat"; "/new"]], "new file contents")],
3713    "make ext2/3/4 external journal",
3714    "\
3715 This creates an ext2 external journal on C<device>.  It is equivalent
3716 to the command:
3717
3718  mke2fs -O journal_dev -b blocksize device");
3719
3720   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3721    [InitEmpty, Always, TestOutput (
3722       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3723        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3724        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3725        ["mount_options"; ""; "/dev/sda2"; "/"];
3726        ["write_file"; "/new"; "new file contents"; "0"];
3727        ["cat"; "/new"]], "new file contents")],
3728    "make ext2/3/4 external journal with label",
3729    "\
3730 This creates an ext2 external journal on C<device> with label C<label>.");
3731
3732   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3733    (let uuid = uuidgen () in
3734     [InitEmpty, Always, TestOutput (
3735        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3736         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3737         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3738         ["mount_options"; ""; "/dev/sda2"; "/"];
3739         ["write_file"; "/new"; "new file contents"; "0"];
3740         ["cat"; "/new"]], "new file contents")]),
3741    "make ext2/3/4 external journal with UUID",
3742    "\
3743 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3744
3745   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3746    [],
3747    "make ext2/3/4 filesystem with external journal",
3748    "\
3749 This creates an ext2/3/4 filesystem on C<device> with
3750 an external journal on C<journal>.  It is equivalent
3751 to the command:
3752
3753  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3754
3755 See also C<guestfs_mke2journal>.");
3756
3757   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3758    [],
3759    "make ext2/3/4 filesystem with external journal",
3760    "\
3761 This creates an ext2/3/4 filesystem on C<device> with
3762 an external journal on the journal labeled C<label>.
3763
3764 See also C<guestfs_mke2journal_L>.");
3765
3766   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3767    [],
3768    "make ext2/3/4 filesystem with external journal",
3769    "\
3770 This creates an ext2/3/4 filesystem on C<device> with
3771 an external journal on the journal with UUID C<uuid>.
3772
3773 See also C<guestfs_mke2journal_U>.");
3774
3775   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3776    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3777    "load a kernel module",
3778    "\
3779 This loads a kernel module in the appliance.
3780
3781 The kernel module must have been whitelisted when libguestfs
3782 was built (see C<appliance/kmod.whitelist.in> in the source).");
3783
3784   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3785    [InitNone, Always, TestOutput (
3786       [["echo_daemon"; "This is a test"]], "This is a test"
3787     )],
3788    "echo arguments back to the client",
3789    "\
3790 This command concatenates the list of C<words> passed with single spaces
3791 between them and returns the resulting string.
3792
3793 You can use this command to test the connection through to the daemon.
3794
3795 See also C<guestfs_ping_daemon>.");
3796
3797   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3798    [], (* There is a regression test for this. *)
3799    "find all files and directories, returning NUL-separated list",
3800    "\
3801 This command lists out all files and directories, recursively,
3802 starting at C<directory>, placing the resulting list in the
3803 external file called C<files>.
3804
3805 This command works the same way as C<guestfs_find> with the
3806 following exceptions:
3807
3808 =over 4
3809
3810 =item *
3811
3812 The resulting list is written to an external file.
3813
3814 =item *
3815
3816 Items (filenames) in the result are separated
3817 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3818
3819 =item *
3820
3821 This command is not limited in the number of names that it
3822 can return.
3823
3824 =item *
3825
3826 The result list is not sorted.
3827
3828 =back");
3829
3830   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3831    [InitISOFS, Always, TestOutput (
3832       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3833     InitISOFS, Always, TestOutput (
3834       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3835     InitISOFS, Always, TestOutput (
3836       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3837     InitISOFS, Always, TestLastFail (
3838       [["case_sensitive_path"; "/Known-1/"]]);
3839     InitBasicFS, Always, TestOutput (
3840       [["mkdir"; "/a"];
3841        ["mkdir"; "/a/bbb"];
3842        ["touch"; "/a/bbb/c"];
3843        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3844     InitBasicFS, Always, TestOutput (
3845       [["mkdir"; "/a"];
3846        ["mkdir"; "/a/bbb"];
3847        ["touch"; "/a/bbb/c"];
3848        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3849     InitBasicFS, Always, TestLastFail (
3850       [["mkdir"; "/a"];
3851        ["mkdir"; "/a/bbb"];
3852        ["touch"; "/a/bbb/c"];
3853        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3854    "return true path on case-insensitive filesystem",
3855    "\
3856 This can be used to resolve case insensitive paths on
3857 a filesystem which is case sensitive.  The use case is
3858 to resolve paths which you have read from Windows configuration
3859 files or the Windows Registry, to the true path.
3860
3861 The command handles a peculiarity of the Linux ntfs-3g
3862 filesystem driver (and probably others), which is that although
3863 the underlying filesystem is case-insensitive, the driver
3864 exports the filesystem to Linux as case-sensitive.
3865
3866 One consequence of this is that special directories such
3867 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3868 (or other things) depending on the precise details of how
3869 they were created.  In Windows itself this would not be
3870 a problem.
3871
3872 Bug or feature?  You decide:
3873 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3874
3875 This function resolves the true case of each element in the
3876 path and returns the case-sensitive path.
3877
3878 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3879 might return C<\"/WINDOWS/system32\"> (the exact return value
3880 would depend on details of how the directories were originally
3881 created under Windows).
3882
3883 I<Note>:
3884 This function does not handle drive names, backslashes etc.
3885
3886 See also C<guestfs_realpath>.");
3887
3888   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3889    [InitBasicFS, Always, TestOutput (
3890       [["vfs_type"; "/dev/sda1"]], "ext2")],
3891    "get the Linux VFS type corresponding to a mounted device",
3892    "\
3893 This command gets the filesystem type corresponding to
3894 the filesystem on C<device>.
3895
3896 For most filesystems, the result is the name of the Linux
3897 VFS module which would be used to mount this filesystem
3898 if you mounted it without specifying the filesystem type.
3899 For example a string such as C<ext3> or C<ntfs>.");
3900
3901   ("truncate", (RErr, [Pathname "path"]), 199, [],
3902    [InitBasicFS, Always, TestOutputStruct (
3903       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3904        ["truncate"; "/test"];
3905        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3906    "truncate a file to zero size",
3907    "\
3908 This command truncates C<path> to a zero-length file.  The
3909 file must exist already.");
3910
3911   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3912    [InitBasicFS, Always, TestOutputStruct (
3913       [["touch"; "/test"];
3914        ["truncate_size"; "/test"; "1000"];
3915        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3916    "truncate a file to a particular size",
3917    "\
3918 This command truncates C<path> to size C<size> bytes.  The file
3919 must exist already.
3920
3921 If the current file size is less than C<size> then
3922 the file is extended to the required size with zero bytes.
3923 This creates a sparse file (ie. disk blocks are not allocated
3924 for the file until you write to it).  To create a non-sparse
3925 file of zeroes, use C<guestfs_fallocate64> instead.");
3926
3927   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3928    [InitBasicFS, Always, TestOutputStruct (
3929       [["touch"; "/test"];
3930        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3931        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3932    "set timestamp of a file with nanosecond precision",
3933    "\
3934 This command sets the timestamps of a file with nanosecond
3935 precision.
3936
3937 C<atsecs, atnsecs> are the last access time (atime) in secs and
3938 nanoseconds from the epoch.
3939
3940 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3941 secs and nanoseconds from the epoch.
3942
3943 If the C<*nsecs> field contains the special value C<-1> then
3944 the corresponding timestamp is set to the current time.  (The
3945 C<*secs> field is ignored in this case).
3946
3947 If the C<*nsecs> field contains the special value C<-2> then
3948 the corresponding timestamp is left unchanged.  (The
3949 C<*secs> field is ignored in this case).");
3950
3951   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3952    [InitBasicFS, Always, TestOutputStruct (
3953       [["mkdir_mode"; "/test"; "0o111"];
3954        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3955    "create a directory with a particular mode",
3956    "\
3957 This command creates a directory, setting the initial permissions
3958 of the directory to C<mode>.
3959
3960 For common Linux filesystems, the actual mode which is set will
3961 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3962 interpret the mode in other ways.
3963
3964 See also C<guestfs_mkdir>, C<guestfs_umask>");
3965
3966   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3967    [], (* XXX *)
3968    "change file owner and group",
3969    "\
3970 Change the file owner to C<owner> and group to C<group>.
3971 This is like C<guestfs_chown> but if C<path> is a symlink then
3972 the link itself is changed, not the target.
3973
3974 Only numeric uid and gid are supported.  If you want to use
3975 names, you will need to locate and parse the password file
3976 yourself (Augeas support makes this relatively easy).");
3977
3978   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3979    [], (* XXX *)
3980    "lstat on multiple files",
3981    "\
3982 This call allows you to perform the C<guestfs_lstat> operation
3983 on multiple files, where all files are in the directory C<path>.
3984 C<names> is the list of files from this directory.
3985
3986 On return you get a list of stat structs, with a one-to-one
3987 correspondence to the C<names> list.  If any name did not exist
3988 or could not be lstat'd, then the C<ino> field of that structure
3989 is set to C<-1>.
3990
3991 This call is intended for programs that want to efficiently
3992 list a directory contents without making many round-trips.
3993 See also C<guestfs_lxattrlist> for a similarly efficient call
3994 for getting extended attributes.  Very long directory listings
3995 might cause the protocol message size to be exceeded, causing
3996 this call to fail.  The caller must split up such requests
3997 into smaller groups of names.");
3998
3999   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4000    [], (* XXX *)
4001    "lgetxattr on multiple files",
4002    "\
4003 This call allows you to get the extended attributes
4004 of multiple files, where all files are in the directory C<path>.
4005 C<names> is the list of files from this directory.
4006
4007 On return you get a flat list of xattr structs which must be
4008 interpreted sequentially.  The first xattr struct always has a zero-length
4009 C<attrname>.  C<attrval> in this struct is zero-length
4010 to indicate there was an error doing C<lgetxattr> for this
4011 file, I<or> is a C string which is a decimal number
4012 (the number of following attributes for this file, which could
4013 be C<\"0\">).  Then after the first xattr struct are the
4014 zero or more attributes for the first named file.
4015 This repeats for the second and subsequent files.
4016
4017 This call is intended for programs that want to efficiently
4018 list a directory contents without making many round-trips.
4019 See also C<guestfs_lstatlist> for a similarly efficient call
4020 for getting standard stats.  Very long directory listings
4021 might cause the protocol message size to be exceeded, causing
4022 this call to fail.  The caller must split up such requests
4023 into smaller groups of names.");
4024
4025   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4026    [], (* XXX *)
4027    "readlink on multiple files",
4028    "\
4029 This call allows you to do a C<readlink> operation
4030 on multiple files, where all files are in the directory C<path>.
4031 C<names> is the list of files from this directory.
4032
4033 On return you get a list of strings, with a one-to-one
4034 correspondence to the C<names> list.  Each string is the
4035 value of the symbolic link.
4036
4037 If the C<readlink(2)> operation fails on any name, then
4038 the corresponding result string is the empty string C<\"\">.
4039 However the whole operation is completed even if there
4040 were C<readlink(2)> errors, and so you can call this
4041 function with names where you don't know if they are
4042 symbolic links already (albeit slightly less efficient).
4043
4044 This call is intended for programs that want to efficiently
4045 list a directory contents without making many round-trips.
4046 Very long directory listings might cause the protocol
4047 message size to be exceeded, causing
4048 this call to fail.  The caller must split up such requests
4049 into smaller groups of names.");
4050
4051   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4052    [InitISOFS, Always, TestOutputBuffer (
4053       [["pread"; "/known-4"; "1"; "3"]], "\n");
4054     InitISOFS, Always, TestOutputBuffer (
4055       [["pread"; "/empty"; "0"; "100"]], "")],
4056    "read part of a file",
4057    "\
4058 This command lets you read part of a file.  It reads C<count>
4059 bytes of the file, starting at C<offset>, from file C<path>.
4060
4061 This may read fewer bytes than requested.  For further details
4062 see the L<pread(2)> system call.");
4063
4064   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4065    [InitEmpty, Always, TestRun (
4066       [["part_init"; "/dev/sda"; "gpt"]])],
4067    "create an empty partition table",
4068    "\
4069 This creates an empty partition table on C<device> of one of the
4070 partition types listed below.  Usually C<parttype> should be
4071 either C<msdos> or C<gpt> (for large disks).
4072
4073 Initially there are no partitions.  Following this, you should
4074 call C<guestfs_part_add> for each partition required.
4075
4076 Possible values for C<parttype> are:
4077
4078 =over 4
4079
4080 =item B<efi> | B<gpt>
4081
4082 Intel EFI / GPT partition table.
4083
4084 This is recommended for >= 2 TB partitions that will be accessed
4085 from Linux and Intel-based Mac OS X.  It also has limited backwards
4086 compatibility with the C<mbr> format.
4087
4088 =item B<mbr> | B<msdos>
4089
4090 The standard PC \"Master Boot Record\" (MBR) format used
4091 by MS-DOS and Windows.  This partition type will B<only> work
4092 for device sizes up to 2 TB.  For large disks we recommend
4093 using C<gpt>.
4094
4095 =back
4096
4097 Other partition table types that may work but are not
4098 supported include:
4099
4100 =over 4
4101
4102 =item B<aix>
4103
4104 AIX disk labels.
4105
4106 =item B<amiga> | B<rdb>
4107
4108 Amiga \"Rigid Disk Block\" format.
4109
4110 =item B<bsd>
4111
4112 BSD disk labels.
4113
4114 =item B<dasd>
4115
4116 DASD, used on IBM mainframes.
4117
4118 =item B<dvh>
4119
4120 MIPS/SGI volumes.
4121
4122 =item B<mac>
4123
4124 Old Mac partition format.  Modern Macs use C<gpt>.
4125
4126 =item B<pc98>
4127
4128 NEC PC-98 format, common in Japan apparently.
4129
4130 =item B<sun>
4131
4132 Sun disk labels.
4133
4134 =back");
4135
4136   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4137    [InitEmpty, Always, TestRun (
4138       [["part_init"; "/dev/sda"; "mbr"];
4139        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4140     InitEmpty, Always, TestRun (
4141       [["part_init"; "/dev/sda"; "gpt"];
4142        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4143        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4144     InitEmpty, Always, TestRun (
4145       [["part_init"; "/dev/sda"; "mbr"];
4146        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4147        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4148        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4149        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4150    "add a partition to the device",
4151    "\
4152 This command adds a partition to C<device>.  If there is no partition
4153 table on the device, call C<guestfs_part_init> first.
4154
4155 The C<prlogex> parameter is the type of partition.  Normally you
4156 should pass C<p> or C<primary> here, but MBR partition tables also
4157 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4158 types.
4159
4160 C<startsect> and C<endsect> are the start and end of the partition
4161 in I<sectors>.  C<endsect> may be negative, which means it counts
4162 backwards from the end of the disk (C<-1> is the last sector).
4163
4164 Creating a partition which covers the whole disk is not so easy.
4165 Use C<guestfs_part_disk> to do that.");
4166
4167   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4168    [InitEmpty, Always, TestRun (
4169       [["part_disk"; "/dev/sda"; "mbr"]]);
4170     InitEmpty, Always, TestRun (
4171       [["part_disk"; "/dev/sda"; "gpt"]])],
4172    "partition whole disk with a single primary partition",
4173    "\
4174 This command is simply a combination of C<guestfs_part_init>
4175 followed by C<guestfs_part_add> to create a single primary partition
4176 covering the whole disk.
4177
4178 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4179 but other possible values are described in C<guestfs_part_init>.");
4180
4181   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4182    [InitEmpty, Always, TestRun (
4183       [["part_disk"; "/dev/sda"; "mbr"];
4184        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4185    "make a partition bootable",
4186    "\
4187 This sets the bootable flag on partition numbered C<partnum> on
4188 device C<device>.  Note that partitions are numbered from 1.
4189
4190 The bootable flag is used by some operating systems (notably
4191 Windows) to determine which partition to boot from.  It is by
4192 no means universally recognized.");
4193
4194   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4195    [InitEmpty, Always, TestRun (
4196       [["part_disk"; "/dev/sda"; "gpt"];
4197        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4198    "set partition name",
4199    "\
4200 This sets the partition name on partition numbered C<partnum> on
4201 device C<device>.  Note that partitions are numbered from 1.
4202
4203 The partition name can only be set on certain types of partition
4204 table.  This works on C<gpt> but not on C<mbr> partitions.");
4205
4206   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4207    [], (* XXX Add a regression test for this. *)
4208    "list partitions on a device",
4209    "\
4210 This command parses the partition table on C<device> and
4211 returns the list of partitions found.
4212
4213 The fields in the returned structure are:
4214
4215 =over 4
4216
4217 =item B<part_num>
4218
4219 Partition number, counting from 1.
4220
4221 =item B<part_start>
4222
4223 Start of the partition I<in bytes>.  To get sectors you have to
4224 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4225
4226 =item B<part_end>
4227
4228 End of the partition in bytes.
4229
4230 =item B<part_size>
4231
4232 Size of the partition in bytes.
4233
4234 =back");
4235
4236   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4237    [InitEmpty, Always, TestOutput (
4238       [["part_disk"; "/dev/sda"; "gpt"];
4239        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4240    "get the partition table type",
4241    "\
4242 This command examines the partition table on C<device> and
4243 returns the partition table type (format) being used.
4244
4245 Common return values include: C<msdos> (a DOS/Windows style MBR
4246 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4247 values are possible, although unusual.  See C<guestfs_part_init>
4248 for a full list.");
4249
4250   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4251    [InitBasicFS, Always, TestOutputBuffer (
4252       [["fill"; "0x63"; "10"; "/test"];
4253        ["read_file"; "/test"]], "cccccccccc")],
4254    "fill a file with octets",
4255    "\
4256 This command creates a new file called C<path>.  The initial
4257 content of the file is C<len> octets of C<c>, where C<c>
4258 must be a number in the range C<[0..255]>.
4259
4260 To fill a file with zero bytes (sparsely), it is
4261 much more efficient to use C<guestfs_truncate_size>.");
4262
4263   ("available", (RErr, [StringList "groups"]), 216, [],
4264    [InitNone, Always, TestRun [["available"; ""]]],
4265    "test availability of some parts of the API",
4266    "\
4267 This command is used to check the availability of some
4268 groups of functionality in the appliance, which not all builds of
4269 the libguestfs appliance will be able to provide.
4270
4271 The libguestfs groups, and the functions that those
4272 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4273
4274 The argument C<groups> is a list of group names, eg:
4275 C<[\"inotify\", \"augeas\"]> would check for the availability of
4276 the Linux inotify functions and Augeas (configuration file
4277 editing) functions.
4278
4279 The command returns no error if I<all> requested groups are available.
4280
4281 It fails with an error if one or more of the requested
4282 groups is unavailable in the appliance.
4283
4284 If an unknown group name is included in the
4285 list of groups then an error is always returned.
4286
4287 I<Notes:>
4288
4289 =over 4
4290
4291 =item *
4292
4293 You must call C<guestfs_launch> before calling this function.
4294
4295 The reason is because we don't know what groups are
4296 supported by the appliance/daemon until it is running and can
4297 be queried.
4298
4299 =item *
4300
4301 If a group of functions is available, this does not necessarily
4302 mean that they will work.  You still have to check for errors
4303 when calling individual API functions even if they are
4304 available.
4305
4306 =item *
4307
4308 It is usually the job of distro packagers to build
4309 complete functionality into the libguestfs appliance.
4310 Upstream libguestfs, if built from source with all
4311 requirements satisfied, will support everything.
4312
4313 =item *
4314
4315 This call was added in version C<1.0.80>.  In previous
4316 versions of libguestfs all you could do would be to speculatively
4317 execute a command to find out if the daemon implemented it.
4318 See also C<guestfs_version>.
4319
4320 =back");
4321
4322   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4323    [InitBasicFS, Always, TestOutputBuffer (
4324       [["write_file"; "/src"; "hello, world"; "0"];
4325        ["dd"; "/src"; "/dest"];
4326        ["read_file"; "/dest"]], "hello, world")],
4327    "copy from source to destination using dd",
4328    "\
4329 This command copies from one source device or file C<src>
4330 to another destination device or file C<dest>.  Normally you
4331 would use this to copy to or from a device or partition, for
4332 example to duplicate a filesystem.
4333
4334 If the destination is a device, it must be as large or larger
4335 than the source file or device, otherwise the copy will fail.
4336 This command cannot do partial copies (see C<guestfs_copy_size>).");
4337
4338   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4339    [InitBasicFS, Always, TestOutputInt (
4340       [["write_file"; "/file"; "hello, world"; "0"];
4341        ["filesize"; "/file"]], 12)],
4342    "return the size of the file in bytes",
4343    "\
4344 This command returns the size of C<file> in bytes.
4345
4346 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4347 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4348 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4349
4350   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4351    [InitBasicFSonLVM, Always, TestOutputList (
4352       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4353        ["lvs"]], ["/dev/VG/LV2"])],
4354    "rename an LVM logical volume",
4355    "\
4356 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4357
4358   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4359    [InitBasicFSonLVM, Always, TestOutputList (
4360       [["umount"; "/"];
4361        ["vg_activate"; "false"; "VG"];
4362        ["vgrename"; "VG"; "VG2"];
4363        ["vg_activate"; "true"; "VG2"];
4364        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4365        ["vgs"]], ["VG2"])],
4366    "rename an LVM volume group",
4367    "\
4368 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4369
4370   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4371    [InitISOFS, Always, TestOutputBuffer (
4372       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4373    "list the contents of a single file in an initrd",
4374    "\
4375 This command unpacks the file C<filename> from the initrd file
4376 called C<initrdpath>.  The filename must be given I<without> the
4377 initial C</> character.
4378
4379 For example, in guestfish you could use the following command
4380 to examine the boot script (usually called C</init>)
4381 contained in a Linux initrd or initramfs image:
4382
4383  initrd-cat /boot/initrd-<version>.img init
4384
4385 See also C<guestfs_initrd_list>.");
4386
4387   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4388    [],
4389    "get the UUID of a physical volume",
4390    "\
4391 This command returns the UUID of the LVM PV C<device>.");
4392
4393   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4394    [],
4395    "get the UUID of a volume group",
4396    "\
4397 This command returns the UUID of the LVM VG named C<vgname>.");
4398
4399   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4400    [],
4401    "get the UUID of a logical volume",
4402    "\
4403 This command returns the UUID of the LVM LV C<device>.");
4404
4405   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4406    [],
4407    "get the PV UUIDs containing the volume group",
4408    "\
4409 Given a VG called C<vgname>, this returns the UUIDs of all
4410 the physical volumes that this volume group resides on.
4411
4412 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4413 calls to associate physical volumes and volume groups.
4414
4415 See also C<guestfs_vglvuuids>.");
4416
4417   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4418    [],
4419    "get the LV UUIDs of all LVs in the volume group",
4420    "\
4421 Given a VG called C<vgname>, this returns the UUIDs of all
4422 the logical volumes created in this volume group.
4423
4424 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4425 calls to associate logical volumes and volume groups.
4426
4427 See also C<guestfs_vgpvuuids>.");
4428
4429   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4430    [InitBasicFS, Always, TestOutputBuffer (
4431       [["write_file"; "/src"; "hello, world"; "0"];
4432        ["copy_size"; "/src"; "/dest"; "5"];
4433        ["read_file"; "/dest"]], "hello")],
4434    "copy size bytes from source to destination using dd",
4435    "\
4436 This command copies exactly C<size> bytes from one source device
4437 or file C<src> to another destination device or file C<dest>.
4438
4439 Note this will fail if the source is too short or if the destination
4440 is not large enough.");
4441
4442   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4443    [InitEmpty, Always, TestRun (
4444       [["part_init"; "/dev/sda"; "mbr"];
4445        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4446        ["part_del"; "/dev/sda"; "1"]])],
4447    "delete a partition",
4448    "\
4449 This command deletes the partition numbered C<partnum> on C<device>.
4450
4451 Note that in the case of MBR partitioning, deleting an
4452 extended partition also deletes any logical partitions
4453 it contains.");
4454
4455   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4456    [InitEmpty, Always, TestOutputTrue (
4457       [["part_init"; "/dev/sda"; "mbr"];
4458        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4459        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4460        ["part_get_bootable"; "/dev/sda"; "1"]])],
4461    "return true if a partition is bootable",
4462    "\
4463 This command returns true if the partition C<partnum> on
4464 C<device> has the bootable flag set.
4465
4466 See also C<guestfs_part_set_bootable>.");
4467
4468   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4469    [InitEmpty, Always, TestOutputInt (
4470       [["part_init"; "/dev/sda"; "mbr"];
4471        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4472        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4473        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4474    "get the MBR type byte (ID byte) from a partition",
4475    "\
4476 Returns the MBR type byte (also known as the ID byte) from
4477 the numbered partition C<partnum>.
4478
4479 Note that only MBR (old DOS-style) partitions have type bytes.
4480 You will get undefined results for other partition table
4481 types (see C<guestfs_part_get_parttype>).");
4482
4483   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4484    [], (* tested by part_get_mbr_id *)
4485    "set the MBR type byte (ID byte) of a partition",
4486    "\
4487 Sets the MBR type byte (also known as the ID byte) of
4488 the numbered partition C<partnum> to C<idbyte>.  Note
4489 that the type bytes quoted in most documentation are
4490 in fact hexadecimal numbers, but usually documented
4491 without any leading \"0x\" which might be confusing.
4492
4493 Note that only MBR (old DOS-style) partitions have type bytes.
4494 You will get undefined results for other partition table
4495 types (see C<guestfs_part_get_parttype>).");
4496
4497 ]
4498
4499 let all_functions = non_daemon_functions @ daemon_functions
4500
4501 (* In some places we want the functions to be displayed sorted
4502  * alphabetically, so this is useful:
4503  *)
4504 let all_functions_sorted =
4505   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4506                compare n1 n2) all_functions
4507
4508 (* Field types for structures. *)
4509 type field =
4510   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4511   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4512   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4513   | FUInt32
4514   | FInt32
4515   | FUInt64
4516   | FInt64
4517   | FBytes                      (* Any int measure that counts bytes. *)
4518   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4519   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4520
4521 (* Because we generate extra parsing code for LVM command line tools,
4522  * we have to pull out the LVM columns separately here.
4523  *)
4524 let lvm_pv_cols = [
4525   "pv_name", FString;
4526   "pv_uuid", FUUID;
4527   "pv_fmt", FString;
4528   "pv_size", FBytes;
4529   "dev_size", FBytes;
4530   "pv_free", FBytes;
4531   "pv_used", FBytes;
4532   "pv_attr", FString (* XXX *);
4533   "pv_pe_count", FInt64;
4534   "pv_pe_alloc_count", FInt64;
4535   "pv_tags", FString;
4536   "pe_start", FBytes;
4537   "pv_mda_count", FInt64;
4538   "pv_mda_free", FBytes;
4539   (* Not in Fedora 10:
4540      "pv_mda_size", FBytes;
4541   *)
4542 ]
4543 let lvm_vg_cols = [
4544   "vg_name", FString;
4545   "vg_uuid", FUUID;
4546   "vg_fmt", FString;
4547   "vg_attr", FString (* XXX *);
4548   "vg_size", FBytes;
4549   "vg_free", FBytes;
4550   "vg_sysid", FString;
4551   "vg_extent_size", FBytes;
4552   "vg_extent_count", FInt64;
4553   "vg_free_count", FInt64;
4554   "max_lv", FInt64;
4555   "max_pv", FInt64;
4556   "pv_count", FInt64;
4557   "lv_count", FInt64;
4558   "snap_count", FInt64;
4559   "vg_seqno", FInt64;
4560   "vg_tags", FString;
4561   "vg_mda_count", FInt64;
4562   "vg_mda_free", FBytes;
4563   (* Not in Fedora 10:
4564      "vg_mda_size", FBytes;
4565   *)
4566 ]
4567 let lvm_lv_cols = [
4568   "lv_name", FString;
4569   "lv_uuid", FUUID;
4570   "lv_attr", FString (* XXX *);
4571   "lv_major", FInt64;
4572   "lv_minor", FInt64;
4573   "lv_kernel_major", FInt64;
4574   "lv_kernel_minor", FInt64;
4575   "lv_size", FBytes;
4576   "seg_count", FInt64;
4577   "origin", FString;
4578   "snap_percent", FOptPercent;
4579   "copy_percent", FOptPercent;
4580   "move_pv", FString;
4581   "lv_tags", FString;
4582   "mirror_log", FString;
4583   "modules", FString;
4584 ]
4585
4586 (* Names and fields in all structures (in RStruct and RStructList)
4587  * that we support.
4588  *)
4589 let structs = [
4590   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4591    * not use this struct in any new code.
4592    *)
4593   "int_bool", [
4594     "i", FInt32;                (* for historical compatibility *)
4595     "b", FInt32;                (* for historical compatibility *)
4596   ];
4597
4598   (* LVM PVs, VGs, LVs. *)
4599   "lvm_pv", lvm_pv_cols;
4600   "lvm_vg", lvm_vg_cols;
4601   "lvm_lv", lvm_lv_cols;
4602
4603   (* Column names and types from stat structures.
4604    * NB. Can't use things like 'st_atime' because glibc header files
4605    * define some of these as macros.  Ugh.
4606    *)
4607   "stat", [
4608     "dev", FInt64;
4609     "ino", FInt64;
4610     "mode", FInt64;
4611     "nlink", FInt64;
4612     "uid", FInt64;
4613     "gid", FInt64;
4614     "rdev", FInt64;
4615     "size", FInt64;
4616     "blksize", FInt64;
4617     "blocks", FInt64;
4618     "atime", FInt64;
4619     "mtime", FInt64;
4620     "ctime", FInt64;
4621   ];
4622   "statvfs", [
4623     "bsize", FInt64;
4624     "frsize", FInt64;
4625     "blocks", FInt64;
4626     "bfree", FInt64;
4627     "bavail", FInt64;
4628     "files", FInt64;
4629     "ffree", FInt64;
4630     "favail", FInt64;
4631     "fsid", FInt64;
4632     "flag", FInt64;
4633     "namemax", FInt64;
4634   ];
4635
4636   (* Column names in dirent structure. *)
4637   "dirent", [
4638     "ino", FInt64;
4639     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4640     "ftyp", FChar;
4641     "name", FString;
4642   ];
4643
4644   (* Version numbers. *)
4645   "version", [
4646     "major", FInt64;
4647     "minor", FInt64;
4648     "release", FInt64;
4649     "extra", FString;
4650   ];
4651
4652   (* Extended attribute. *)
4653   "xattr", [
4654     "attrname", FString;
4655     "attrval", FBuffer;
4656   ];
4657
4658   (* Inotify events. *)
4659   "inotify_event", [
4660     "in_wd", FInt64;
4661     "in_mask", FUInt32;
4662     "in_cookie", FUInt32;
4663     "in_name", FString;
4664   ];
4665
4666   (* Partition table entry. *)
4667   "partition", [
4668     "part_num", FInt32;
4669     "part_start", FBytes;
4670     "part_end", FBytes;
4671     "part_size", FBytes;
4672   ];
4673 ] (* end of structs *)
4674
4675 (* Ugh, Java has to be different ..
4676  * These names are also used by the Haskell bindings.
4677  *)
4678 let java_structs = [
4679   "int_bool", "IntBool";
4680   "lvm_pv", "PV";
4681   "lvm_vg", "VG";
4682   "lvm_lv", "LV";
4683   "stat", "Stat";
4684   "statvfs", "StatVFS";
4685   "dirent", "Dirent";
4686   "version", "Version";
4687   "xattr", "XAttr";
4688   "inotify_event", "INotifyEvent";
4689   "partition", "Partition";
4690 ]
4691
4692 (* What structs are actually returned. *)
4693 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4694
4695 (* Returns a list of RStruct/RStructList structs that are returned
4696  * by any function.  Each element of returned list is a pair:
4697  *
4698  * (structname, RStructOnly)
4699  *    == there exists function which returns RStruct (_, structname)
4700  * (structname, RStructListOnly)
4701  *    == there exists function which returns RStructList (_, structname)
4702  * (structname, RStructAndList)
4703  *    == there are functions returning both RStruct (_, structname)
4704  *                                      and RStructList (_, structname)
4705  *)
4706 let rstructs_used_by functions =
4707   (* ||| is a "logical OR" for rstructs_used_t *)
4708   let (|||) a b =
4709     match a, b with
4710     | RStructAndList, _
4711     | _, RStructAndList -> RStructAndList
4712     | RStructOnly, RStructListOnly
4713     | RStructListOnly, RStructOnly -> RStructAndList
4714     | RStructOnly, RStructOnly -> RStructOnly
4715     | RStructListOnly, RStructListOnly -> RStructListOnly
4716   in
4717
4718   let h = Hashtbl.create 13 in
4719
4720   (* if elem->oldv exists, update entry using ||| operator,
4721    * else just add elem->newv to the hash
4722    *)
4723   let update elem newv =
4724     try  let oldv = Hashtbl.find h elem in
4725          Hashtbl.replace h elem (newv ||| oldv)
4726     with Not_found -> Hashtbl.add h elem newv
4727   in
4728
4729   List.iter (
4730     fun (_, style, _, _, _, _, _) ->
4731       match fst style with
4732       | RStruct (_, structname) -> update structname RStructOnly
4733       | RStructList (_, structname) -> update structname RStructListOnly
4734       | _ -> ()
4735   ) functions;
4736
4737   (* return key->values as a list of (key,value) *)
4738   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4739
4740 (* Used for testing language bindings. *)
4741 type callt =
4742   | CallString of string
4743   | CallOptString of string option
4744   | CallStringList of string list
4745   | CallInt of int
4746   | CallInt64 of int64
4747   | CallBool of bool
4748
4749 (* Used to memoize the result of pod2text. *)
4750 let pod2text_memo_filename = "src/.pod2text.data"
4751 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4752   try
4753     let chan = open_in pod2text_memo_filename in
4754     let v = input_value chan in
4755     close_in chan;
4756     v
4757   with
4758     _ -> Hashtbl.create 13
4759 let pod2text_memo_updated () =
4760   let chan = open_out pod2text_memo_filename in
4761   output_value chan pod2text_memo;
4762   close_out chan
4763
4764 (* Useful functions.
4765  * Note we don't want to use any external OCaml libraries which
4766  * makes this a bit harder than it should be.
4767  *)
4768 module StringMap = Map.Make (String)
4769
4770 let failwithf fs = ksprintf failwith fs
4771
4772 let unique = let i = ref 0 in fun () -> incr i; !i
4773
4774 let replace_char s c1 c2 =
4775   let s2 = String.copy s in
4776   let r = ref false in
4777   for i = 0 to String.length s2 - 1 do
4778     if String.unsafe_get s2 i = c1 then (
4779       String.unsafe_set s2 i c2;
4780       r := true
4781     )
4782   done;
4783   if not !r then s else s2
4784
4785 let isspace c =
4786   c = ' '
4787   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4788
4789 let triml ?(test = isspace) str =
4790   let i = ref 0 in
4791   let n = ref (String.length str) in
4792   while !n > 0 && test str.[!i]; do
4793     decr n;
4794     incr i
4795   done;
4796   if !i = 0 then str
4797   else String.sub str !i !n
4798
4799 let trimr ?(test = isspace) str =
4800   let n = ref (String.length str) in
4801   while !n > 0 && test str.[!n-1]; do
4802     decr n
4803   done;
4804   if !n = String.length str then str
4805   else String.sub str 0 !n
4806
4807 let trim ?(test = isspace) str =
4808   trimr ~test (triml ~test str)
4809
4810 let rec find s sub =
4811   let len = String.length s in
4812   let sublen = String.length sub in
4813   let rec loop i =
4814     if i <= len-sublen then (
4815       let rec loop2 j =
4816         if j < sublen then (
4817           if s.[i+j] = sub.[j] then loop2 (j+1)
4818           else -1
4819         ) else
4820           i (* found *)
4821       in
4822       let r = loop2 0 in
4823       if r = -1 then loop (i+1) else r
4824     ) else
4825       -1 (* not found *)
4826   in
4827   loop 0
4828
4829 let rec replace_str s s1 s2 =
4830   let len = String.length s in
4831   let sublen = String.length s1 in
4832   let i = find s s1 in
4833   if i = -1 then s
4834   else (
4835     let s' = String.sub s 0 i in
4836     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4837     s' ^ s2 ^ replace_str s'' s1 s2
4838   )
4839
4840 let rec string_split sep str =
4841   let len = String.length str in
4842   let seplen = String.length sep in
4843   let i = find str sep in
4844   if i = -1 then [str]
4845   else (
4846     let s' = String.sub str 0 i in
4847     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4848     s' :: string_split sep s''
4849   )
4850
4851 let files_equal n1 n2 =
4852   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4853   match Sys.command cmd with
4854   | 0 -> true
4855   | 1 -> false
4856   | i -> failwithf "%s: failed with error code %d" cmd i
4857
4858 let rec filter_map f = function
4859   | [] -> []
4860   | x :: xs ->
4861       match f x with
4862       | Some y -> y :: filter_map f xs
4863       | None -> filter_map f xs
4864
4865 let rec find_map f = function
4866   | [] -> raise Not_found
4867   | x :: xs ->
4868       match f x with
4869       | Some y -> y
4870       | None -> find_map f xs
4871
4872 let iteri f xs =
4873   let rec loop i = function
4874     | [] -> ()
4875     | x :: xs -> f i x; loop (i+1) xs
4876   in
4877   loop 0 xs
4878
4879 let mapi f xs =
4880   let rec loop i = function
4881     | [] -> []
4882     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4883   in
4884   loop 0 xs
4885
4886 let count_chars c str =
4887   let count = ref 0 in
4888   for i = 0 to String.length str - 1 do
4889     if c = String.unsafe_get str i then incr count
4890   done;
4891   !count
4892
4893 let name_of_argt = function
4894   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4895   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4896   | FileIn n | FileOut n -> n
4897
4898 let java_name_of_struct typ =
4899   try List.assoc typ java_structs
4900   with Not_found ->
4901     failwithf
4902       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4903
4904 let cols_of_struct typ =
4905   try List.assoc typ structs
4906   with Not_found ->
4907     failwithf "cols_of_struct: unknown struct %s" typ
4908
4909 let seq_of_test = function
4910   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4911   | TestOutputListOfDevices (s, _)
4912   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4913   | TestOutputTrue s | TestOutputFalse s
4914   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4915   | TestOutputStruct (s, _)
4916   | TestLastFail s -> s
4917
4918 (* Handling for function flags. *)
4919 let protocol_limit_warning =
4920   "Because of the message protocol, there is a transfer limit
4921 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4922
4923 let danger_will_robinson =
4924   "B<This command is dangerous.  Without careful use you
4925 can easily destroy all your data>."
4926
4927 let deprecation_notice flags =
4928   try
4929     let alt =
4930       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4931     let txt =
4932       sprintf "This function is deprecated.
4933 In new code, use the C<%s> call instead.
4934
4935 Deprecated functions will not be removed from the API, but the
4936 fact that they are deprecated indicates that there are problems
4937 with correct use of these functions." alt in
4938     Some txt
4939   with
4940     Not_found -> None
4941
4942 (* Create list of optional groups. *)
4943 let optgroups =
4944   let h = Hashtbl.create 13 in
4945   List.iter (
4946     fun (name, _, _, flags, _, _, _) ->
4947       List.iter (
4948         function
4949         | Optional group ->
4950             let names = try Hashtbl.find h group with Not_found -> [] in
4951             Hashtbl.replace h group (name :: names)
4952         | _ -> ()
4953       ) flags
4954   ) daemon_functions;
4955   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4956   let groups =
4957     List.map (
4958       fun group -> group, List.sort compare (Hashtbl.find h group)
4959     ) groups in
4960   List.sort (fun x y -> compare (fst x) (fst y)) groups
4961
4962 (* Check function names etc. for consistency. *)
4963 let check_functions () =
4964   let contains_uppercase str =
4965     let len = String.length str in
4966     let rec loop i =
4967       if i >= len then false
4968       else (
4969         let c = str.[i] in
4970         if c >= 'A' && c <= 'Z' then true
4971         else loop (i+1)
4972       )
4973     in
4974     loop 0
4975   in
4976
4977   (* Check function names. *)
4978   List.iter (
4979     fun (name, _, _, _, _, _, _) ->
4980       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4981         failwithf "function name %s does not need 'guestfs' prefix" name;
4982       if name = "" then
4983         failwithf "function name is empty";
4984       if name.[0] < 'a' || name.[0] > 'z' then
4985         failwithf "function name %s must start with lowercase a-z" name;
4986       if String.contains name '-' then
4987         failwithf "function name %s should not contain '-', use '_' instead."
4988           name
4989   ) all_functions;
4990
4991   (* Check function parameter/return names. *)
4992   List.iter (
4993     fun (name, style, _, _, _, _, _) ->
4994       let check_arg_ret_name n =
4995         if contains_uppercase n then
4996           failwithf "%s param/ret %s should not contain uppercase chars"
4997             name n;
4998         if String.contains n '-' || String.contains n '_' then
4999           failwithf "%s param/ret %s should not contain '-' or '_'"
5000             name n;
5001         if n = "value" then
5002           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;
5003         if n = "int" || n = "char" || n = "short" || n = "long" then
5004           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5005         if n = "i" || n = "n" then
5006           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5007         if n = "argv" || n = "args" then
5008           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5009
5010         (* List Haskell, OCaml and C keywords here.
5011          * http://www.haskell.org/haskellwiki/Keywords
5012          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5013          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5014          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5015          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5016          * Omitting _-containing words, since they're handled above.
5017          * Omitting the OCaml reserved word, "val", is ok,
5018          * and saves us from renaming several parameters.
5019          *)
5020         let reserved = [
5021           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5022           "char"; "class"; "const"; "constraint"; "continue"; "data";
5023           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5024           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5025           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5026           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5027           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5028           "interface";
5029           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5030           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5031           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5032           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5033           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5034           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5035           "volatile"; "when"; "where"; "while";
5036           ] in
5037         if List.mem n reserved then
5038           failwithf "%s has param/ret using reserved word %s" name n;
5039       in
5040
5041       (match fst style with
5042        | RErr -> ()
5043        | RInt n | RInt64 n | RBool n
5044        | RConstString n | RConstOptString n | RString n
5045        | RStringList n | RStruct (n, _) | RStructList (n, _)
5046        | RHashtable n | RBufferOut n ->
5047            check_arg_ret_name n
5048       );
5049       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5050   ) all_functions;
5051
5052   (* Check short descriptions. *)
5053   List.iter (
5054     fun (name, _, _, _, _, shortdesc, _) ->
5055       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5056         failwithf "short description of %s should begin with lowercase." name;
5057       let c = shortdesc.[String.length shortdesc-1] in
5058       if c = '\n' || c = '.' then
5059         failwithf "short description of %s should not end with . or \\n." name
5060   ) all_functions;
5061
5062   (* Check long descriptions. *)
5063   List.iter (
5064     fun (name, _, _, _, _, _, longdesc) ->
5065       if longdesc.[String.length longdesc-1] = '\n' then
5066         failwithf "long description of %s should not end with \\n." name
5067   ) all_functions;
5068
5069   (* Check proc_nrs. *)
5070   List.iter (
5071     fun (name, _, proc_nr, _, _, _, _) ->
5072       if proc_nr <= 0 then
5073         failwithf "daemon function %s should have proc_nr > 0" name
5074   ) daemon_functions;
5075
5076   List.iter (
5077     fun (name, _, proc_nr, _, _, _, _) ->
5078       if proc_nr <> -1 then
5079         failwithf "non-daemon function %s should have proc_nr -1" name
5080   ) non_daemon_functions;
5081
5082   let proc_nrs =
5083     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5084       daemon_functions in
5085   let proc_nrs =
5086     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5087   let rec loop = function
5088     | [] -> ()
5089     | [_] -> ()
5090     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5091         loop rest
5092     | (name1,nr1) :: (name2,nr2) :: _ ->
5093         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5094           name1 name2 nr1 nr2
5095   in
5096   loop proc_nrs;
5097
5098   (* Check tests. *)
5099   List.iter (
5100     function
5101       (* Ignore functions that have no tests.  We generate a
5102        * warning when the user does 'make check' instead.
5103        *)
5104     | name, _, _, _, [], _, _ -> ()
5105     | name, _, _, _, tests, _, _ ->
5106         let funcs =
5107           List.map (
5108             fun (_, _, test) ->
5109               match seq_of_test test with
5110               | [] ->
5111                   failwithf "%s has a test containing an empty sequence" name
5112               | cmds -> List.map List.hd cmds
5113           ) tests in
5114         let funcs = List.flatten funcs in
5115
5116         let tested = List.mem name funcs in
5117
5118         if not tested then
5119           failwithf "function %s has tests but does not test itself" name
5120   ) all_functions
5121
5122 (* 'pr' prints to the current output file. *)
5123 let chan = ref Pervasives.stdout
5124 let lines = ref 0
5125 let pr fs =
5126   ksprintf
5127     (fun str ->
5128        let i = count_chars '\n' str in
5129        lines := !lines + i;
5130        output_string !chan str
5131     ) fs
5132
5133 let copyright_years =
5134   let this_year = 1900 + (localtime (time ())).tm_year in
5135   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5136
5137 (* Generate a header block in a number of standard styles. *)
5138 type comment_style =
5139     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5140 type license = GPLv2plus | LGPLv2plus
5141
5142 let generate_header ?(extra_inputs = []) comment license =
5143   let inputs = "src/generator.ml" :: extra_inputs in
5144   let c = match comment with
5145     | CStyle ->         pr "/* "; " *"
5146     | CPlusPlusStyle -> pr "// "; "//"
5147     | HashStyle ->      pr "# ";  "#"
5148     | OCamlStyle ->     pr "(* "; " *"
5149     | HaskellStyle ->   pr "{- "; "  " in
5150   pr "libguestfs generated file\n";
5151   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5152   List.iter (pr "%s   %s\n" c) inputs;
5153   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5154   pr "%s\n" c;
5155   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5156   pr "%s\n" c;
5157   (match license with
5158    | GPLv2plus ->
5159        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5160        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5161        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5162        pr "%s (at your option) any later version.\n" c;
5163        pr "%s\n" c;
5164        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5165        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5166        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5167        pr "%s GNU General Public License for more details.\n" c;
5168        pr "%s\n" c;
5169        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5170        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5171        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5172
5173    | LGPLv2plus ->
5174        pr "%s This library is free software; you can redistribute it and/or\n" c;
5175        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5176        pr "%s License as published by the Free Software Foundation; either\n" c;
5177        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5178        pr "%s\n" c;
5179        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5180        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5181        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5182        pr "%s Lesser General Public License for more details.\n" c;
5183        pr "%s\n" c;
5184        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5185        pr "%s License along with this library; if not, write to the Free Software\n" c;
5186        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5187   );
5188   (match comment with
5189    | CStyle -> pr " */\n"
5190    | CPlusPlusStyle
5191    | HashStyle -> ()
5192    | OCamlStyle -> pr " *)\n"
5193    | HaskellStyle -> pr "-}\n"
5194   );
5195   pr "\n"
5196
5197 (* Start of main code generation functions below this line. *)
5198
5199 (* Generate the pod documentation for the C API. *)
5200 let rec generate_actions_pod () =
5201   List.iter (
5202     fun (shortname, style, _, flags, _, _, longdesc) ->
5203       if not (List.mem NotInDocs flags) then (
5204         let name = "guestfs_" ^ shortname in
5205         pr "=head2 %s\n\n" name;
5206         pr " ";
5207         generate_prototype ~extern:false ~handle:"g" name style;
5208         pr "\n\n";
5209         pr "%s\n\n" longdesc;
5210         (match fst style with
5211          | RErr ->
5212              pr "This function returns 0 on success or -1 on error.\n\n"
5213          | RInt _ ->
5214              pr "On error this function returns -1.\n\n"
5215          | RInt64 _ ->
5216              pr "On error this function returns -1.\n\n"
5217          | RBool _ ->
5218              pr "This function returns a C truth value on success or -1 on error.\n\n"
5219          | RConstString _ ->
5220              pr "This function returns a string, or NULL on error.
5221 The string is owned by the guest handle and must I<not> be freed.\n\n"
5222          | RConstOptString _ ->
5223              pr "This function returns a string which may be NULL.
5224 There is way to return an error from this function.
5225 The string is owned by the guest handle and must I<not> be freed.\n\n"
5226          | RString _ ->
5227              pr "This function returns a string, or NULL on error.
5228 I<The caller must free the returned string after use>.\n\n"
5229          | RStringList _ ->
5230              pr "This function returns a NULL-terminated array of strings
5231 (like L<environ(3)>), or NULL if there was an error.
5232 I<The caller must free the strings and the array after use>.\n\n"
5233          | RStruct (_, typ) ->
5234              pr "This function returns a C<struct guestfs_%s *>,
5235 or NULL if there was an error.
5236 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5237          | RStructList (_, typ) ->
5238              pr "This function returns a C<struct guestfs_%s_list *>
5239 (see E<lt>guestfs-structs.hE<gt>),
5240 or NULL if there was an error.
5241 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5242          | RHashtable _ ->
5243              pr "This function returns a NULL-terminated array of
5244 strings, or NULL if there was an error.
5245 The array of strings will always have length C<2n+1>, where
5246 C<n> keys and values alternate, followed by the trailing NULL entry.
5247 I<The caller must free the strings and the array after use>.\n\n"
5248          | RBufferOut _ ->
5249              pr "This function returns a buffer, or NULL on error.
5250 The size of the returned buffer is written to C<*size_r>.
5251 I<The caller must free the returned buffer after use>.\n\n"
5252         );
5253         if List.mem ProtocolLimitWarning flags then
5254           pr "%s\n\n" protocol_limit_warning;
5255         if List.mem DangerWillRobinson flags then
5256           pr "%s\n\n" danger_will_robinson;
5257         match deprecation_notice flags with
5258         | None -> ()
5259         | Some txt -> pr "%s\n\n" txt
5260       )
5261   ) all_functions_sorted
5262
5263 and generate_structs_pod () =
5264   (* Structs documentation. *)
5265   List.iter (
5266     fun (typ, cols) ->
5267       pr "=head2 guestfs_%s\n" typ;
5268       pr "\n";
5269       pr " struct guestfs_%s {\n" typ;
5270       List.iter (
5271         function
5272         | name, FChar -> pr "   char %s;\n" name
5273         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5274         | name, FInt32 -> pr "   int32_t %s;\n" name
5275         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5276         | name, FInt64 -> pr "   int64_t %s;\n" name
5277         | name, FString -> pr "   char *%s;\n" name
5278         | name, FBuffer ->
5279             pr "   /* The next two fields describe a byte array. */\n";
5280             pr "   uint32_t %s_len;\n" name;
5281             pr "   char *%s;\n" name
5282         | name, FUUID ->
5283             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5284             pr "   char %s[32];\n" name
5285         | name, FOptPercent ->
5286             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5287             pr "   float %s;\n" name
5288       ) cols;
5289       pr " };\n";
5290       pr " \n";
5291       pr " struct guestfs_%s_list {\n" typ;
5292       pr "   uint32_t len; /* Number of elements in list. */\n";
5293       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5294       pr " };\n";
5295       pr " \n";
5296       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5297       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5298         typ typ;
5299       pr "\n"
5300   ) structs
5301
5302 and generate_availability_pod () =
5303   (* Availability documentation. *)
5304   pr "=over 4\n";
5305   pr "\n";
5306   List.iter (
5307     fun (group, functions) ->
5308       pr "=item B<%s>\n" group;
5309       pr "\n";
5310       pr "The following functions:\n";
5311       List.iter (pr "L</guestfs_%s>\n") functions;
5312       pr "\n"
5313   ) optgroups;
5314   pr "=back\n";
5315   pr "\n"
5316
5317 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5318  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5319  *
5320  * We have to use an underscore instead of a dash because otherwise
5321  * rpcgen generates incorrect code.
5322  *
5323  * This header is NOT exported to clients, but see also generate_structs_h.
5324  *)
5325 and generate_xdr () =
5326   generate_header CStyle LGPLv2plus;
5327
5328   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5329   pr "typedef string str<>;\n";
5330   pr "\n";
5331
5332   (* Internal structures. *)
5333   List.iter (
5334     function
5335     | typ, cols ->
5336         pr "struct guestfs_int_%s {\n" typ;
5337         List.iter (function
5338                    | name, FChar -> pr "  char %s;\n" name
5339                    | name, FString -> pr "  string %s<>;\n" name
5340                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5341                    | name, FUUID -> pr "  opaque %s[32];\n" name
5342                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5343                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5344                    | name, FOptPercent -> pr "  float %s;\n" name
5345                   ) cols;
5346         pr "};\n";
5347         pr "\n";
5348         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5349         pr "\n";
5350   ) structs;
5351
5352   List.iter (
5353     fun (shortname, style, _, _, _, _, _) ->
5354       let name = "guestfs_" ^ shortname in
5355
5356       (match snd style with
5357        | [] -> ()
5358        | args ->
5359            pr "struct %s_args {\n" name;
5360            List.iter (
5361              function
5362              | Pathname n | Device n | Dev_or_Path n | String n ->
5363                  pr "  string %s<>;\n" n
5364              | OptString n -> pr "  str *%s;\n" n
5365              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5366              | Bool n -> pr "  bool %s;\n" n
5367              | Int n -> pr "  int %s;\n" n
5368              | Int64 n -> pr "  hyper %s;\n" n
5369              | FileIn _ | FileOut _ -> ()
5370            ) args;
5371            pr "};\n\n"
5372       );
5373       (match fst style with
5374        | RErr -> ()
5375        | RInt n ->
5376            pr "struct %s_ret {\n" name;
5377            pr "  int %s;\n" n;
5378            pr "};\n\n"
5379        | RInt64 n ->
5380            pr "struct %s_ret {\n" name;
5381            pr "  hyper %s;\n" n;
5382            pr "};\n\n"
5383        | RBool n ->
5384            pr "struct %s_ret {\n" name;
5385            pr "  bool %s;\n" n;
5386            pr "};\n\n"
5387        | RConstString _ | RConstOptString _ ->
5388            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5389        | RString n ->
5390            pr "struct %s_ret {\n" name;
5391            pr "  string %s<>;\n" n;
5392            pr "};\n\n"
5393        | RStringList n ->
5394            pr "struct %s_ret {\n" name;
5395            pr "  str %s<>;\n" n;
5396            pr "};\n\n"
5397        | RStruct (n, typ) ->
5398            pr "struct %s_ret {\n" name;
5399            pr "  guestfs_int_%s %s;\n" typ n;
5400            pr "};\n\n"
5401        | RStructList (n, typ) ->
5402            pr "struct %s_ret {\n" name;
5403            pr "  guestfs_int_%s_list %s;\n" typ n;
5404            pr "};\n\n"
5405        | RHashtable n ->
5406            pr "struct %s_ret {\n" name;
5407            pr "  str %s<>;\n" n;
5408            pr "};\n\n"
5409        | RBufferOut n ->
5410            pr "struct %s_ret {\n" name;
5411            pr "  opaque %s<>;\n" n;
5412            pr "};\n\n"
5413       );
5414   ) daemon_functions;
5415
5416   (* Table of procedure numbers. *)
5417   pr "enum guestfs_procedure {\n";
5418   List.iter (
5419     fun (shortname, _, proc_nr, _, _, _, _) ->
5420       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5421   ) daemon_functions;
5422   pr "  GUESTFS_PROC_NR_PROCS\n";
5423   pr "};\n";
5424   pr "\n";
5425
5426   (* Having to choose a maximum message size is annoying for several
5427    * reasons (it limits what we can do in the API), but it (a) makes
5428    * the protocol a lot simpler, and (b) provides a bound on the size
5429    * of the daemon which operates in limited memory space.
5430    *)
5431   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5432   pr "\n";
5433
5434   (* Message header, etc. *)
5435   pr "\
5436 /* The communication protocol is now documented in the guestfs(3)
5437  * manpage.
5438  */
5439
5440 const GUESTFS_PROGRAM = 0x2000F5F5;
5441 const GUESTFS_PROTOCOL_VERSION = 1;
5442
5443 /* These constants must be larger than any possible message length. */
5444 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5445 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5446
5447 enum guestfs_message_direction {
5448   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5449   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5450 };
5451
5452 enum guestfs_message_status {
5453   GUESTFS_STATUS_OK = 0,
5454   GUESTFS_STATUS_ERROR = 1
5455 };
5456
5457 const GUESTFS_ERROR_LEN = 256;
5458
5459 struct guestfs_message_error {
5460   string error_message<GUESTFS_ERROR_LEN>;
5461 };
5462
5463 struct guestfs_message_header {
5464   unsigned prog;                     /* GUESTFS_PROGRAM */
5465   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5466   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5467   guestfs_message_direction direction;
5468   unsigned serial;                   /* message serial number */
5469   guestfs_message_status status;
5470 };
5471
5472 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5473
5474 struct guestfs_chunk {
5475   int cancel;                        /* if non-zero, transfer is cancelled */
5476   /* data size is 0 bytes if the transfer has finished successfully */
5477   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5478 };
5479 "
5480
5481 (* Generate the guestfs-structs.h file. *)
5482 and generate_structs_h () =
5483   generate_header CStyle LGPLv2plus;
5484
5485   (* This is a public exported header file containing various
5486    * structures.  The structures are carefully written to have
5487    * exactly the same in-memory format as the XDR structures that
5488    * we use on the wire to the daemon.  The reason for creating
5489    * copies of these structures here is just so we don't have to
5490    * export the whole of guestfs_protocol.h (which includes much
5491    * unrelated and XDR-dependent stuff that we don't want to be
5492    * public, or required by clients).
5493    *
5494    * To reiterate, we will pass these structures to and from the
5495    * client with a simple assignment or memcpy, so the format
5496    * must be identical to what rpcgen / the RFC defines.
5497    *)
5498
5499   (* Public structures. *)
5500   List.iter (
5501     fun (typ, cols) ->
5502       pr "struct guestfs_%s {\n" typ;
5503       List.iter (
5504         function
5505         | name, FChar -> pr "  char %s;\n" name
5506         | name, FString -> pr "  char *%s;\n" name
5507         | name, FBuffer ->
5508             pr "  uint32_t %s_len;\n" name;
5509             pr "  char *%s;\n" name
5510         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5511         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5512         | name, FInt32 -> pr "  int32_t %s;\n" name
5513         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5514         | name, FInt64 -> pr "  int64_t %s;\n" name
5515         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5516       ) cols;
5517       pr "};\n";
5518       pr "\n";
5519       pr "struct guestfs_%s_list {\n" typ;
5520       pr "  uint32_t len;\n";
5521       pr "  struct guestfs_%s *val;\n" typ;
5522       pr "};\n";
5523       pr "\n";
5524       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5525       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5526       pr "\n"
5527   ) structs
5528
5529 (* Generate the guestfs-actions.h file. *)
5530 and generate_actions_h () =
5531   generate_header CStyle LGPLv2plus;
5532   List.iter (
5533     fun (shortname, style, _, _, _, _, _) ->
5534       let name = "guestfs_" ^ shortname in
5535       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5536         name style
5537   ) all_functions
5538
5539 (* Generate the guestfs-internal-actions.h file. *)
5540 and generate_internal_actions_h () =
5541   generate_header CStyle LGPLv2plus;
5542   List.iter (
5543     fun (shortname, style, _, _, _, _, _) ->
5544       let name = "guestfs__" ^ shortname in
5545       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5546         name style
5547   ) non_daemon_functions
5548
5549 (* Generate the client-side dispatch stubs. *)
5550 and generate_client_actions () =
5551   generate_header CStyle LGPLv2plus;
5552
5553   pr "\
5554 #include <stdio.h>
5555 #include <stdlib.h>
5556 #include <stdint.h>
5557 #include <string.h>
5558 #include <inttypes.h>
5559
5560 #include \"guestfs.h\"
5561 #include \"guestfs-internal.h\"
5562 #include \"guestfs-internal-actions.h\"
5563 #include \"guestfs_protocol.h\"
5564
5565 #define error guestfs_error
5566 //#define perrorf guestfs_perrorf
5567 #define safe_malloc guestfs_safe_malloc
5568 #define safe_realloc guestfs_safe_realloc
5569 //#define safe_strdup guestfs_safe_strdup
5570 #define safe_memdup guestfs_safe_memdup
5571
5572 /* Check the return message from a call for validity. */
5573 static int
5574 check_reply_header (guestfs_h *g,
5575                     const struct guestfs_message_header *hdr,
5576                     unsigned int proc_nr, unsigned int serial)
5577 {
5578   if (hdr->prog != GUESTFS_PROGRAM) {
5579     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5580     return -1;
5581   }
5582   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5583     error (g, \"wrong protocol version (%%d/%%d)\",
5584            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5585     return -1;
5586   }
5587   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5588     error (g, \"unexpected message direction (%%d/%%d)\",
5589            hdr->direction, GUESTFS_DIRECTION_REPLY);
5590     return -1;
5591   }
5592   if (hdr->proc != proc_nr) {
5593     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5594     return -1;
5595   }
5596   if (hdr->serial != serial) {
5597     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5598     return -1;
5599   }
5600
5601   return 0;
5602 }
5603
5604 /* Check we are in the right state to run a high-level action. */
5605 static int
5606 check_state (guestfs_h *g, const char *caller)
5607 {
5608   if (!guestfs__is_ready (g)) {
5609     if (guestfs__is_config (g) || guestfs__is_launching (g))
5610       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5611         caller);
5612     else
5613       error (g, \"%%s called from the wrong state, %%d != READY\",
5614         caller, guestfs__get_state (g));
5615     return -1;
5616   }
5617   return 0;
5618 }
5619
5620 ";
5621
5622   (* Generate code to generate guestfish call traces. *)
5623   let trace_call shortname style =
5624     pr "  if (guestfs__get_trace (g)) {\n";
5625
5626     let needs_i =
5627       List.exists (function
5628                    | StringList _ | DeviceList _ -> true
5629                    | _ -> false) (snd style) in
5630     if needs_i then (
5631       pr "    int i;\n";
5632       pr "\n"
5633     );
5634
5635     pr "    printf (\"%s\");\n" shortname;
5636     List.iter (
5637       function
5638       | String n                        (* strings *)
5639       | Device n
5640       | Pathname n
5641       | Dev_or_Path n
5642       | FileIn n
5643       | FileOut n ->
5644           (* guestfish doesn't support string escaping, so neither do we *)
5645           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5646       | OptString n ->                  (* string option *)
5647           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5648           pr "    else printf (\" null\");\n"
5649       | StringList n
5650       | DeviceList n ->                 (* string list *)
5651           pr "    putchar (' ');\n";
5652           pr "    putchar ('\"');\n";
5653           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5654           pr "      if (i > 0) putchar (' ');\n";
5655           pr "      fputs (%s[i], stdout);\n" n;
5656           pr "    }\n";
5657           pr "    putchar ('\"');\n";
5658       | Bool n ->                       (* boolean *)
5659           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5660       | Int n ->                        (* int *)
5661           pr "    printf (\" %%d\", %s);\n" n
5662       | Int64 n ->
5663           pr "    printf (\" %%\" PRIi64, %s);\n" n
5664     ) (snd style);
5665     pr "    putchar ('\\n');\n";
5666     pr "  }\n";
5667     pr "\n";
5668   in
5669
5670   (* For non-daemon functions, generate a wrapper around each function. *)
5671   List.iter (
5672     fun (shortname, style, _, _, _, _, _) ->
5673       let name = "guestfs_" ^ shortname in
5674
5675       generate_prototype ~extern:false ~semicolon:false ~newline:true
5676         ~handle:"g" name style;
5677       pr "{\n";
5678       trace_call shortname style;
5679       pr "  return guestfs__%s " shortname;
5680       generate_c_call_args ~handle:"g" style;
5681       pr ";\n";
5682       pr "}\n";
5683       pr "\n"
5684   ) non_daemon_functions;
5685
5686   (* Client-side stubs for each function. *)
5687   List.iter (
5688     fun (shortname, style, _, _, _, _, _) ->
5689       let name = "guestfs_" ^ shortname in
5690
5691       (* Generate the action stub. *)
5692       generate_prototype ~extern:false ~semicolon:false ~newline:true
5693         ~handle:"g" name style;
5694
5695       let error_code =
5696         match fst style with
5697         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5698         | RConstString _ | RConstOptString _ ->
5699             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5700         | RString _ | RStringList _
5701         | RStruct _ | RStructList _
5702         | RHashtable _ | RBufferOut _ ->
5703             "NULL" in
5704
5705       pr "{\n";
5706
5707       (match snd style with
5708        | [] -> ()
5709        | _ -> pr "  struct %s_args args;\n" name
5710       );
5711
5712       pr "  guestfs_message_header hdr;\n";
5713       pr "  guestfs_message_error err;\n";
5714       let has_ret =
5715         match fst style with
5716         | RErr -> false
5717         | RConstString _ | RConstOptString _ ->
5718             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5719         | RInt _ | RInt64 _
5720         | RBool _ | RString _ | RStringList _
5721         | RStruct _ | RStructList _
5722         | RHashtable _ | RBufferOut _ ->
5723             pr "  struct %s_ret ret;\n" name;
5724             true in
5725
5726       pr "  int serial;\n";
5727       pr "  int r;\n";
5728       pr "\n";
5729       trace_call shortname style;
5730       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5731       pr "  guestfs___set_busy (g);\n";
5732       pr "\n";
5733
5734       (* Send the main header and arguments. *)
5735       (match snd style with
5736        | [] ->
5737            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5738              (String.uppercase shortname)
5739        | args ->
5740            List.iter (
5741              function
5742              | Pathname n | Device n | Dev_or_Path n | String n ->
5743                  pr "  args.%s = (char *) %s;\n" n n
5744              | OptString n ->
5745                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5746              | StringList n | DeviceList n ->
5747                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5748                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5749              | Bool n ->
5750                  pr "  args.%s = %s;\n" n n
5751              | Int n ->
5752                  pr "  args.%s = %s;\n" n n
5753              | Int64 n ->
5754                  pr "  args.%s = %s;\n" n n
5755              | FileIn _ | FileOut _ -> ()
5756            ) args;
5757            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5758              (String.uppercase shortname);
5759            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5760              name;
5761       );
5762       pr "  if (serial == -1) {\n";
5763       pr "    guestfs___end_busy (g);\n";
5764       pr "    return %s;\n" error_code;
5765       pr "  }\n";
5766       pr "\n";
5767
5768       (* Send any additional files (FileIn) requested. *)
5769       let need_read_reply_label = ref false in
5770       List.iter (
5771         function
5772         | FileIn n ->
5773             pr "  r = guestfs___send_file (g, %s);\n" n;
5774             pr "  if (r == -1) {\n";
5775             pr "    guestfs___end_busy (g);\n";
5776             pr "    return %s;\n" error_code;
5777             pr "  }\n";
5778             pr "  if (r == -2) /* daemon cancelled */\n";
5779             pr "    goto read_reply;\n";
5780             need_read_reply_label := true;
5781             pr "\n";
5782         | _ -> ()
5783       ) (snd style);
5784
5785       (* Wait for the reply from the remote end. *)
5786       if !need_read_reply_label then pr " read_reply:\n";
5787       pr "  memset (&hdr, 0, sizeof hdr);\n";
5788       pr "  memset (&err, 0, sizeof err);\n";
5789       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5790       pr "\n";
5791       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5792       if not has_ret then
5793         pr "NULL, NULL"
5794       else
5795         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5796       pr ");\n";
5797
5798       pr "  if (r == -1) {\n";
5799       pr "    guestfs___end_busy (g);\n";
5800       pr "    return %s;\n" error_code;
5801       pr "  }\n";
5802       pr "\n";
5803
5804       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5805         (String.uppercase shortname);
5806       pr "    guestfs___end_busy (g);\n";
5807       pr "    return %s;\n" error_code;
5808       pr "  }\n";
5809       pr "\n";
5810
5811       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5812       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5813       pr "    free (err.error_message);\n";
5814       pr "    guestfs___end_busy (g);\n";
5815       pr "    return %s;\n" error_code;
5816       pr "  }\n";
5817       pr "\n";
5818
5819       (* Expecting to receive further files (FileOut)? *)
5820       List.iter (
5821         function
5822         | FileOut n ->
5823             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5824             pr "    guestfs___end_busy (g);\n";
5825             pr "    return %s;\n" error_code;
5826             pr "  }\n";
5827             pr "\n";
5828         | _ -> ()
5829       ) (snd style);
5830
5831       pr "  guestfs___end_busy (g);\n";
5832
5833       (match fst style with
5834        | RErr -> pr "  return 0;\n"
5835        | RInt n | RInt64 n | RBool n ->
5836            pr "  return ret.%s;\n" n
5837        | RConstString _ | RConstOptString _ ->
5838            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5839        | RString n ->
5840            pr "  return ret.%s; /* caller will free */\n" n
5841        | RStringList n | RHashtable n ->
5842            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5843            pr "  ret.%s.%s_val =\n" n n;
5844            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5845            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5846              n n;
5847            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5848            pr "  return ret.%s.%s_val;\n" n n
5849        | RStruct (n, _) ->
5850            pr "  /* caller will free this */\n";
5851            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5852        | RStructList (n, _) ->
5853            pr "  /* caller will free this */\n";
5854            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5855        | RBufferOut n ->
5856            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5857            pr "   * _val might be NULL here.  To make the API saner for\n";
5858            pr "   * callers, we turn this case into a unique pointer (using\n";
5859            pr "   * malloc(1)).\n";
5860            pr "   */\n";
5861            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5862            pr "    *size_r = ret.%s.%s_len;\n" n n;
5863            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5864            pr "  } else {\n";
5865            pr "    free (ret.%s.%s_val);\n" n n;
5866            pr "    char *p = safe_malloc (g, 1);\n";
5867            pr "    *size_r = ret.%s.%s_len;\n" n n;
5868            pr "    return p;\n";
5869            pr "  }\n";
5870       );
5871
5872       pr "}\n\n"
5873   ) daemon_functions;
5874
5875   (* Functions to free structures. *)
5876   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5877   pr " * structure format is identical to the XDR format.  See note in\n";
5878   pr " * generator.ml.\n";
5879   pr " */\n";
5880   pr "\n";
5881
5882   List.iter (
5883     fun (typ, _) ->
5884       pr "void\n";
5885       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5886       pr "{\n";
5887       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5888       pr "  free (x);\n";
5889       pr "}\n";
5890       pr "\n";
5891
5892       pr "void\n";
5893       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5894       pr "{\n";
5895       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5896       pr "  free (x);\n";
5897       pr "}\n";
5898       pr "\n";
5899
5900   ) structs;
5901
5902 (* Generate daemon/actions.h. *)
5903 and generate_daemon_actions_h () =
5904   generate_header CStyle GPLv2plus;
5905
5906   pr "#include \"../src/guestfs_protocol.h\"\n";
5907   pr "\n";
5908
5909   List.iter (
5910     fun (name, style, _, _, _, _, _) ->
5911       generate_prototype
5912         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5913         name style;
5914   ) daemon_functions
5915
5916 (* Generate the linker script which controls the visibility of
5917  * symbols in the public ABI and ensures no other symbols get
5918  * exported accidentally.
5919  *)
5920 and generate_linker_script () =
5921   generate_header HashStyle GPLv2plus;
5922
5923   let globals = [
5924     "guestfs_create";
5925     "guestfs_close";
5926     "guestfs_get_error_handler";
5927     "guestfs_get_out_of_memory_handler";
5928     "guestfs_last_error";
5929     "guestfs_set_error_handler";
5930     "guestfs_set_launch_done_callback";
5931     "guestfs_set_log_message_callback";
5932     "guestfs_set_out_of_memory_handler";
5933     "guestfs_set_subprocess_quit_callback";
5934
5935     (* Unofficial parts of the API: the bindings code use these
5936      * functions, so it is useful to export them.
5937      *)
5938     "guestfs_safe_calloc";
5939     "guestfs_safe_malloc";
5940   ] in
5941   let functions =
5942     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5943       all_functions in
5944   let structs =
5945     List.concat (
5946       List.map (fun (typ, _) ->
5947                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5948         structs
5949     ) in
5950   let globals = List.sort compare (globals @ functions @ structs) in
5951
5952   pr "{\n";
5953   pr "    global:\n";
5954   List.iter (pr "        %s;\n") globals;
5955   pr "\n";
5956
5957   pr "    local:\n";
5958   pr "        *;\n";
5959   pr "};\n"
5960
5961 (* Generate the server-side stubs. *)
5962 and generate_daemon_actions () =
5963   generate_header CStyle GPLv2plus;
5964
5965   pr "#include <config.h>\n";
5966   pr "\n";
5967   pr "#include <stdio.h>\n";
5968   pr "#include <stdlib.h>\n";
5969   pr "#include <string.h>\n";
5970   pr "#include <inttypes.h>\n";
5971   pr "#include <rpc/types.h>\n";
5972   pr "#include <rpc/xdr.h>\n";
5973   pr "\n";
5974   pr "#include \"daemon.h\"\n";
5975   pr "#include \"c-ctype.h\"\n";
5976   pr "#include \"../src/guestfs_protocol.h\"\n";
5977   pr "#include \"actions.h\"\n";
5978   pr "\n";
5979
5980   List.iter (
5981     fun (name, style, _, _, _, _, _) ->
5982       (* Generate server-side stubs. *)
5983       pr "static void %s_stub (XDR *xdr_in)\n" name;
5984       pr "{\n";
5985       let error_code =
5986         match fst style with
5987         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5988         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5989         | RBool _ -> pr "  int r;\n"; "-1"
5990         | RConstString _ | RConstOptString _ ->
5991             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5992         | RString _ -> pr "  char *r;\n"; "NULL"
5993         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5994         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5995         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5996         | RBufferOut _ ->
5997             pr "  size_t size = 1;\n";
5998             pr "  char *r;\n";
5999             "NULL" in
6000
6001       (match snd style with
6002        | [] -> ()
6003        | args ->
6004            pr "  struct guestfs_%s_args args;\n" name;
6005            List.iter (
6006              function
6007              | Device n | Dev_or_Path n
6008              | Pathname n
6009              | String n -> ()
6010              | OptString n -> pr "  char *%s;\n" n
6011              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6012              | Bool n -> pr "  int %s;\n" n
6013              | Int n -> pr "  int %s;\n" n
6014              | Int64 n -> pr "  int64_t %s;\n" n
6015              | FileIn _ | FileOut _ -> ()
6016            ) args
6017       );
6018       pr "\n";
6019
6020       (match snd style with
6021        | [] -> ()
6022        | args ->
6023            pr "  memset (&args, 0, sizeof args);\n";
6024            pr "\n";
6025            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6026            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6027            pr "    return;\n";
6028            pr "  }\n";
6029            let pr_args n =
6030              pr "  char *%s = args.%s;\n" n n
6031            in
6032            let pr_list_handling_code n =
6033              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6034              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6035              pr "  if (%s == NULL) {\n" n;
6036              pr "    reply_with_perror (\"realloc\");\n";
6037              pr "    goto done;\n";
6038              pr "  }\n";
6039              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6040              pr "  args.%s.%s_val = %s;\n" n n n;
6041            in
6042            List.iter (
6043              function
6044              | Pathname n ->
6045                  pr_args n;
6046                  pr "  ABS_PATH (%s, goto done);\n" n;
6047              | Device n ->
6048                  pr_args n;
6049                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6050              | Dev_or_Path n ->
6051                  pr_args n;
6052                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6053              | String n -> pr_args n
6054              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6055              | StringList n ->
6056                  pr_list_handling_code n;
6057              | DeviceList n ->
6058                  pr_list_handling_code n;
6059                  pr "  /* Ensure that each is a device,\n";
6060                  pr "   * and perform device name translation. */\n";
6061                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6062                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6063                  pr "  }\n";
6064              | Bool n -> pr "  %s = args.%s;\n" n n
6065              | Int n -> pr "  %s = args.%s;\n" n n
6066              | Int64 n -> pr "  %s = args.%s;\n" n n
6067              | FileIn _ | FileOut _ -> ()
6068            ) args;
6069            pr "\n"
6070       );
6071
6072
6073       (* this is used at least for do_equal *)
6074       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6075         (* Emit NEED_ROOT just once, even when there are two or
6076            more Pathname args *)
6077         pr "  NEED_ROOT (goto done);\n";
6078       );
6079
6080       (* Don't want to call the impl with any FileIn or FileOut
6081        * parameters, since these go "outside" the RPC protocol.
6082        *)
6083       let args' =
6084         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6085           (snd style) in
6086       pr "  r = do_%s " name;
6087       generate_c_call_args (fst style, args');
6088       pr ";\n";
6089
6090       (match fst style with
6091        | RErr | RInt _ | RInt64 _ | RBool _
6092        | RConstString _ | RConstOptString _
6093        | RString _ | RStringList _ | RHashtable _
6094        | RStruct (_, _) | RStructList (_, _) ->
6095            pr "  if (r == %s)\n" error_code;
6096            pr "    /* do_%s has already called reply_with_error */\n" name;
6097            pr "    goto done;\n";
6098            pr "\n"
6099        | RBufferOut _ ->
6100            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6101            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6102            pr "   */\n";
6103            pr "  if (size == 1 && r == %s)\n" error_code;
6104            pr "    /* do_%s has already called reply_with_error */\n" name;
6105            pr "    goto done;\n";
6106            pr "\n"
6107       );
6108
6109       (* If there are any FileOut parameters, then the impl must
6110        * send its own reply.
6111        *)
6112       let no_reply =
6113         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6114       if no_reply then
6115         pr "  /* do_%s has already sent a reply */\n" name
6116       else (
6117         match fst style with
6118         | RErr -> pr "  reply (NULL, NULL);\n"
6119         | RInt n | RInt64 n | RBool n ->
6120             pr "  struct guestfs_%s_ret ret;\n" name;
6121             pr "  ret.%s = r;\n" n;
6122             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6123               name
6124         | RConstString _ | RConstOptString _ ->
6125             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6126         | RString n ->
6127             pr "  struct guestfs_%s_ret ret;\n" name;
6128             pr "  ret.%s = r;\n" n;
6129             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6130               name;
6131             pr "  free (r);\n"
6132         | RStringList n | RHashtable n ->
6133             pr "  struct guestfs_%s_ret ret;\n" name;
6134             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6135             pr "  ret.%s.%s_val = r;\n" n n;
6136             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6137               name;
6138             pr "  free_strings (r);\n"
6139         | RStruct (n, _) ->
6140             pr "  struct guestfs_%s_ret ret;\n" name;
6141             pr "  ret.%s = *r;\n" n;
6142             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6143               name;
6144             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6145               name
6146         | RStructList (n, _) ->
6147             pr "  struct guestfs_%s_ret ret;\n" name;
6148             pr "  ret.%s = *r;\n" n;
6149             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6150               name;
6151             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6152               name
6153         | RBufferOut n ->
6154             pr "  struct guestfs_%s_ret ret;\n" name;
6155             pr "  ret.%s.%s_val = r;\n" n n;
6156             pr "  ret.%s.%s_len = size;\n" n n;
6157             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6158               name;
6159             pr "  free (r);\n"
6160       );
6161
6162       (* Free the args. *)
6163       (match snd style with
6164        | [] ->
6165            pr "done: ;\n";
6166        | _ ->
6167            pr "done:\n";
6168            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6169              name
6170       );
6171
6172       pr "}\n\n";
6173   ) daemon_functions;
6174
6175   (* Dispatch function. *)
6176   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6177   pr "{\n";
6178   pr "  switch (proc_nr) {\n";
6179
6180   List.iter (
6181     fun (name, style, _, _, _, _, _) ->
6182       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6183       pr "      %s_stub (xdr_in);\n" name;
6184       pr "      break;\n"
6185   ) daemon_functions;
6186
6187   pr "    default:\n";
6188   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";
6189   pr "  }\n";
6190   pr "}\n";
6191   pr "\n";
6192
6193   (* LVM columns and tokenization functions. *)
6194   (* XXX This generates crap code.  We should rethink how we
6195    * do this parsing.
6196    *)
6197   List.iter (
6198     function
6199     | typ, cols ->
6200         pr "static const char *lvm_%s_cols = \"%s\";\n"
6201           typ (String.concat "," (List.map fst cols));
6202         pr "\n";
6203
6204         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6205         pr "{\n";
6206         pr "  char *tok, *p, *next;\n";
6207         pr "  int i, j;\n";
6208         pr "\n";
6209         (*
6210           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6211           pr "\n";
6212         *)
6213         pr "  if (!str) {\n";
6214         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6215         pr "    return -1;\n";
6216         pr "  }\n";
6217         pr "  if (!*str || c_isspace (*str)) {\n";
6218         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6219         pr "    return -1;\n";
6220         pr "  }\n";
6221         pr "  tok = str;\n";
6222         List.iter (
6223           fun (name, coltype) ->
6224             pr "  if (!tok) {\n";
6225             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6226             pr "    return -1;\n";
6227             pr "  }\n";
6228             pr "  p = strchrnul (tok, ',');\n";
6229             pr "  if (*p) next = p+1; else next = NULL;\n";
6230             pr "  *p = '\\0';\n";
6231             (match coltype with
6232              | FString ->
6233                  pr "  r->%s = strdup (tok);\n" name;
6234                  pr "  if (r->%s == NULL) {\n" name;
6235                  pr "    perror (\"strdup\");\n";
6236                  pr "    return -1;\n";
6237                  pr "  }\n"
6238              | FUUID ->
6239                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6240                  pr "    if (tok[j] == '\\0') {\n";
6241                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6242                  pr "      return -1;\n";
6243                  pr "    } else if (tok[j] != '-')\n";
6244                  pr "      r->%s[i++] = tok[j];\n" name;
6245                  pr "  }\n";
6246              | FBytes ->
6247                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6248                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6249                  pr "    return -1;\n";
6250                  pr "  }\n";
6251              | FInt64 ->
6252                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6253                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6254                  pr "    return -1;\n";
6255                  pr "  }\n";
6256              | FOptPercent ->
6257                  pr "  if (tok[0] == '\\0')\n";
6258                  pr "    r->%s = -1;\n" name;
6259                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6260                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6261                  pr "    return -1;\n";
6262                  pr "  }\n";
6263              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6264                  assert false (* can never be an LVM column *)
6265             );
6266             pr "  tok = next;\n";
6267         ) cols;
6268
6269         pr "  if (tok != NULL) {\n";
6270         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6271         pr "    return -1;\n";
6272         pr "  }\n";
6273         pr "  return 0;\n";
6274         pr "}\n";
6275         pr "\n";
6276
6277         pr "guestfs_int_lvm_%s_list *\n" typ;
6278         pr "parse_command_line_%ss (void)\n" typ;
6279         pr "{\n";
6280         pr "  char *out, *err;\n";
6281         pr "  char *p, *pend;\n";
6282         pr "  int r, i;\n";
6283         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6284         pr "  void *newp;\n";
6285         pr "\n";
6286         pr "  ret = malloc (sizeof *ret);\n";
6287         pr "  if (!ret) {\n";
6288         pr "    reply_with_perror (\"malloc\");\n";
6289         pr "    return NULL;\n";
6290         pr "  }\n";
6291         pr "\n";
6292         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6293         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6294         pr "\n";
6295         pr "  r = command (&out, &err,\n";
6296         pr "           \"lvm\", \"%ss\",\n" typ;
6297         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6298         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6299         pr "  if (r == -1) {\n";
6300         pr "    reply_with_error (\"%%s\", err);\n";
6301         pr "    free (out);\n";
6302         pr "    free (err);\n";
6303         pr "    free (ret);\n";
6304         pr "    return NULL;\n";
6305         pr "  }\n";
6306         pr "\n";
6307         pr "  free (err);\n";
6308         pr "\n";
6309         pr "  /* Tokenize each line of the output. */\n";
6310         pr "  p = out;\n";
6311         pr "  i = 0;\n";
6312         pr "  while (p) {\n";
6313         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6314         pr "    if (pend) {\n";
6315         pr "      *pend = '\\0';\n";
6316         pr "      pend++;\n";
6317         pr "    }\n";
6318         pr "\n";
6319         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6320         pr "      p++;\n";
6321         pr "\n";
6322         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6323         pr "      p = pend;\n";
6324         pr "      continue;\n";
6325         pr "    }\n";
6326         pr "\n";
6327         pr "    /* Allocate some space to store this next entry. */\n";
6328         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6329         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6330         pr "    if (newp == NULL) {\n";
6331         pr "      reply_with_perror (\"realloc\");\n";
6332         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6333         pr "      free (ret);\n";
6334         pr "      free (out);\n";
6335         pr "      return NULL;\n";
6336         pr "    }\n";
6337         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6338         pr "\n";
6339         pr "    /* Tokenize the next entry. */\n";
6340         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6341         pr "    if (r == -1) {\n";
6342         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6343         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6344         pr "      free (ret);\n";
6345         pr "      free (out);\n";
6346         pr "      return NULL;\n";
6347         pr "    }\n";
6348         pr "\n";
6349         pr "    ++i;\n";
6350         pr "    p = pend;\n";
6351         pr "  }\n";
6352         pr "\n";
6353         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6354         pr "\n";
6355         pr "  free (out);\n";
6356         pr "  return ret;\n";
6357         pr "}\n"
6358
6359   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6360
6361 (* Generate a list of function names, for debugging in the daemon.. *)
6362 and generate_daemon_names () =
6363   generate_header CStyle GPLv2plus;
6364
6365   pr "#include <config.h>\n";
6366   pr "\n";
6367   pr "#include \"daemon.h\"\n";
6368   pr "\n";
6369
6370   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6371   pr "const char *function_names[] = {\n";
6372   List.iter (
6373     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6374   ) daemon_functions;
6375   pr "};\n";
6376
6377 (* Generate the optional groups for the daemon to implement
6378  * guestfs_available.
6379  *)
6380 and generate_daemon_optgroups_c () =
6381   generate_header CStyle GPLv2plus;
6382
6383   pr "#include <config.h>\n";
6384   pr "\n";
6385   pr "#include \"daemon.h\"\n";
6386   pr "#include \"optgroups.h\"\n";
6387   pr "\n";
6388
6389   pr "struct optgroup optgroups[] = {\n";
6390   List.iter (
6391     fun (group, _) ->
6392       pr "  { \"%s\", optgroup_%s_available },\n" group group
6393   ) optgroups;
6394   pr "  { NULL, NULL }\n";
6395   pr "};\n"
6396
6397 and generate_daemon_optgroups_h () =
6398   generate_header CStyle GPLv2plus;
6399
6400   List.iter (
6401     fun (group, _) ->
6402       pr "extern int optgroup_%s_available (void);\n" group
6403   ) optgroups
6404
6405 (* Generate the tests. *)
6406 and generate_tests () =
6407   generate_header CStyle GPLv2plus;
6408
6409   pr "\
6410 #include <stdio.h>
6411 #include <stdlib.h>
6412 #include <string.h>
6413 #include <unistd.h>
6414 #include <sys/types.h>
6415 #include <fcntl.h>
6416
6417 #include \"guestfs.h\"
6418 #include \"guestfs-internal.h\"
6419
6420 static guestfs_h *g;
6421 static int suppress_error = 0;
6422
6423 static void print_error (guestfs_h *g, void *data, const char *msg)
6424 {
6425   if (!suppress_error)
6426     fprintf (stderr, \"%%s\\n\", msg);
6427 }
6428
6429 /* FIXME: nearly identical code appears in fish.c */
6430 static void print_strings (char *const *argv)
6431 {
6432   int argc;
6433
6434   for (argc = 0; argv[argc] != NULL; ++argc)
6435     printf (\"\\t%%s\\n\", argv[argc]);
6436 }
6437
6438 /*
6439 static void print_table (char const *const *argv)
6440 {
6441   int i;
6442
6443   for (i = 0; argv[i] != NULL; i += 2)
6444     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6445 }
6446 */
6447
6448 ";
6449
6450   (* Generate a list of commands which are not tested anywhere. *)
6451   pr "static void no_test_warnings (void)\n";
6452   pr "{\n";
6453
6454   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6455   List.iter (
6456     fun (_, _, _, _, tests, _, _) ->
6457       let tests = filter_map (
6458         function
6459         | (_, (Always|If _|Unless _), test) -> Some test
6460         | (_, Disabled, _) -> None
6461       ) tests in
6462       let seq = List.concat (List.map seq_of_test tests) in
6463       let cmds_tested = List.map List.hd seq in
6464       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6465   ) all_functions;
6466
6467   List.iter (
6468     fun (name, _, _, _, _, _, _) ->
6469       if not (Hashtbl.mem hash name) then
6470         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6471   ) all_functions;
6472
6473   pr "}\n";
6474   pr "\n";
6475
6476   (* Generate the actual tests.  Note that we generate the tests
6477    * in reverse order, deliberately, so that (in general) the
6478    * newest tests run first.  This makes it quicker and easier to
6479    * debug them.
6480    *)
6481   let test_names =
6482     List.map (
6483       fun (name, _, _, flags, tests, _, _) ->
6484         mapi (generate_one_test name flags) tests
6485     ) (List.rev all_functions) in
6486   let test_names = List.concat test_names in
6487   let nr_tests = List.length test_names in
6488
6489   pr "\
6490 int main (int argc, char *argv[])
6491 {
6492   char c = 0;
6493   unsigned long int n_failed = 0;
6494   const char *filename;
6495   int fd;
6496   int nr_tests, test_num = 0;
6497
6498   setbuf (stdout, NULL);
6499
6500   no_test_warnings ();
6501
6502   g = guestfs_create ();
6503   if (g == NULL) {
6504     printf (\"guestfs_create FAILED\\n\");
6505     exit (EXIT_FAILURE);
6506   }
6507
6508   guestfs_set_error_handler (g, print_error, NULL);
6509
6510   guestfs_set_path (g, \"../appliance\");
6511
6512   filename = \"test1.img\";
6513   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6514   if (fd == -1) {
6515     perror (filename);
6516     exit (EXIT_FAILURE);
6517   }
6518   if (lseek (fd, %d, SEEK_SET) == -1) {
6519     perror (\"lseek\");
6520     close (fd);
6521     unlink (filename);
6522     exit (EXIT_FAILURE);
6523   }
6524   if (write (fd, &c, 1) == -1) {
6525     perror (\"write\");
6526     close (fd);
6527     unlink (filename);
6528     exit (EXIT_FAILURE);
6529   }
6530   if (close (fd) == -1) {
6531     perror (filename);
6532     unlink (filename);
6533     exit (EXIT_FAILURE);
6534   }
6535   if (guestfs_add_drive (g, filename) == -1) {
6536     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6537     exit (EXIT_FAILURE);
6538   }
6539
6540   filename = \"test2.img\";
6541   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6542   if (fd == -1) {
6543     perror (filename);
6544     exit (EXIT_FAILURE);
6545   }
6546   if (lseek (fd, %d, SEEK_SET) == -1) {
6547     perror (\"lseek\");
6548     close (fd);
6549     unlink (filename);
6550     exit (EXIT_FAILURE);
6551   }
6552   if (write (fd, &c, 1) == -1) {
6553     perror (\"write\");
6554     close (fd);
6555     unlink (filename);
6556     exit (EXIT_FAILURE);
6557   }
6558   if (close (fd) == -1) {
6559     perror (filename);
6560     unlink (filename);
6561     exit (EXIT_FAILURE);
6562   }
6563   if (guestfs_add_drive (g, filename) == -1) {
6564     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6565     exit (EXIT_FAILURE);
6566   }
6567
6568   filename = \"test3.img\";
6569   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6570   if (fd == -1) {
6571     perror (filename);
6572     exit (EXIT_FAILURE);
6573   }
6574   if (lseek (fd, %d, SEEK_SET) == -1) {
6575     perror (\"lseek\");
6576     close (fd);
6577     unlink (filename);
6578     exit (EXIT_FAILURE);
6579   }
6580   if (write (fd, &c, 1) == -1) {
6581     perror (\"write\");
6582     close (fd);
6583     unlink (filename);
6584     exit (EXIT_FAILURE);
6585   }
6586   if (close (fd) == -1) {
6587     perror (filename);
6588     unlink (filename);
6589     exit (EXIT_FAILURE);
6590   }
6591   if (guestfs_add_drive (g, filename) == -1) {
6592     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6593     exit (EXIT_FAILURE);
6594   }
6595
6596   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6597     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6598     exit (EXIT_FAILURE);
6599   }
6600
6601   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6602   alarm (600);
6603
6604   if (guestfs_launch (g) == -1) {
6605     printf (\"guestfs_launch FAILED\\n\");
6606     exit (EXIT_FAILURE);
6607   }
6608
6609   /* Cancel previous alarm. */
6610   alarm (0);
6611
6612   nr_tests = %d;
6613
6614 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6615
6616   iteri (
6617     fun i test_name ->
6618       pr "  test_num++;\n";
6619       pr "  if (guestfs_get_verbose (g))\n";
6620       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6621       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6622       pr "  if (%s () == -1) {\n" test_name;
6623       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6624       pr "    n_failed++;\n";
6625       pr "  }\n";
6626   ) test_names;
6627   pr "\n";
6628
6629   pr "  guestfs_close (g);\n";
6630   pr "  unlink (\"test1.img\");\n";
6631   pr "  unlink (\"test2.img\");\n";
6632   pr "  unlink (\"test3.img\");\n";
6633   pr "\n";
6634
6635   pr "  if (n_failed > 0) {\n";
6636   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6637   pr "    exit (EXIT_FAILURE);\n";
6638   pr "  }\n";
6639   pr "\n";
6640
6641   pr "  exit (EXIT_SUCCESS);\n";
6642   pr "}\n"
6643
6644 and generate_one_test name flags i (init, prereq, test) =
6645   let test_name = sprintf "test_%s_%d" name i in
6646
6647   pr "\
6648 static int %s_skip (void)
6649 {
6650   const char *str;
6651
6652   str = getenv (\"TEST_ONLY\");
6653   if (str)
6654     return strstr (str, \"%s\") == NULL;
6655   str = getenv (\"SKIP_%s\");
6656   if (str && STREQ (str, \"1\")) return 1;
6657   str = getenv (\"SKIP_TEST_%s\");
6658   if (str && STREQ (str, \"1\")) return 1;
6659   return 0;
6660 }
6661
6662 " test_name name (String.uppercase test_name) (String.uppercase name);
6663
6664   (match prereq with
6665    | Disabled | Always -> ()
6666    | If code | Unless code ->
6667        pr "static int %s_prereq (void)\n" test_name;
6668        pr "{\n";
6669        pr "  %s\n" code;
6670        pr "}\n";
6671        pr "\n";
6672   );
6673
6674   pr "\
6675 static int %s (void)
6676 {
6677   if (%s_skip ()) {
6678     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6679     return 0;
6680   }
6681
6682 " test_name test_name test_name;
6683
6684   (* Optional functions should only be tested if the relevant
6685    * support is available in the daemon.
6686    *)
6687   List.iter (
6688     function
6689     | Optional group ->
6690         pr "  {\n";
6691         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6692         pr "    int r;\n";
6693         pr "    suppress_error = 1;\n";
6694         pr "    r = guestfs_available (g, (char **) groups);\n";
6695         pr "    suppress_error = 0;\n";
6696         pr "    if (r == -1) {\n";
6697         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6698         pr "      return 0;\n";
6699         pr "    }\n";
6700         pr "  }\n";
6701     | _ -> ()
6702   ) flags;
6703
6704   (match prereq with
6705    | Disabled ->
6706        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6707    | If _ ->
6708        pr "  if (! %s_prereq ()) {\n" test_name;
6709        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6710        pr "    return 0;\n";
6711        pr "  }\n";
6712        pr "\n";
6713        generate_one_test_body name i test_name init test;
6714    | Unless _ ->
6715        pr "  if (%s_prereq ()) {\n" test_name;
6716        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6717        pr "    return 0;\n";
6718        pr "  }\n";
6719        pr "\n";
6720        generate_one_test_body name i test_name init test;
6721    | Always ->
6722        generate_one_test_body name i test_name init test
6723   );
6724
6725   pr "  return 0;\n";
6726   pr "}\n";
6727   pr "\n";
6728   test_name
6729
6730 and generate_one_test_body name i test_name init test =
6731   (match init with
6732    | InitNone (* XXX at some point, InitNone and InitEmpty became
6733                * folded together as the same thing.  Really we should
6734                * make InitNone do nothing at all, but the tests may
6735                * need to be checked to make sure this is OK.
6736                *)
6737    | InitEmpty ->
6738        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6739        List.iter (generate_test_command_call test_name)
6740          [["blockdev_setrw"; "/dev/sda"];
6741           ["umount_all"];
6742           ["lvm_remove_all"]]
6743    | InitPartition ->
6744        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6745        List.iter (generate_test_command_call test_name)
6746          [["blockdev_setrw"; "/dev/sda"];
6747           ["umount_all"];
6748           ["lvm_remove_all"];
6749           ["part_disk"; "/dev/sda"; "mbr"]]
6750    | InitBasicFS ->
6751        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6752        List.iter (generate_test_command_call test_name)
6753          [["blockdev_setrw"; "/dev/sda"];
6754           ["umount_all"];
6755           ["lvm_remove_all"];
6756           ["part_disk"; "/dev/sda"; "mbr"];
6757           ["mkfs"; "ext2"; "/dev/sda1"];
6758           ["mount_options"; ""; "/dev/sda1"; "/"]]
6759    | InitBasicFSonLVM ->
6760        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6761          test_name;
6762        List.iter (generate_test_command_call test_name)
6763          [["blockdev_setrw"; "/dev/sda"];
6764           ["umount_all"];
6765           ["lvm_remove_all"];
6766           ["part_disk"; "/dev/sda"; "mbr"];
6767           ["pvcreate"; "/dev/sda1"];
6768           ["vgcreate"; "VG"; "/dev/sda1"];
6769           ["lvcreate"; "LV"; "VG"; "8"];
6770           ["mkfs"; "ext2"; "/dev/VG/LV"];
6771           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6772    | InitISOFS ->
6773        pr "  /* InitISOFS for %s */\n" test_name;
6774        List.iter (generate_test_command_call test_name)
6775          [["blockdev_setrw"; "/dev/sda"];
6776           ["umount_all"];
6777           ["lvm_remove_all"];
6778           ["mount_ro"; "/dev/sdd"; "/"]]
6779   );
6780
6781   let get_seq_last = function
6782     | [] ->
6783         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6784           test_name
6785     | seq ->
6786         let seq = List.rev seq in
6787         List.rev (List.tl seq), List.hd seq
6788   in
6789
6790   match test with
6791   | TestRun seq ->
6792       pr "  /* TestRun for %s (%d) */\n" name i;
6793       List.iter (generate_test_command_call test_name) seq
6794   | TestOutput (seq, expected) ->
6795       pr "  /* TestOutput for %s (%d) */\n" name i;
6796       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6797       let seq, last = get_seq_last seq in
6798       let test () =
6799         pr "    if (STRNEQ (r, expected)) {\n";
6800         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6801         pr "      return -1;\n";
6802         pr "    }\n"
6803       in
6804       List.iter (generate_test_command_call test_name) seq;
6805       generate_test_command_call ~test test_name last
6806   | TestOutputList (seq, expected) ->
6807       pr "  /* TestOutputList for %s (%d) */\n" name i;
6808       let seq, last = get_seq_last seq in
6809       let test () =
6810         iteri (
6811           fun i str ->
6812             pr "    if (!r[%d]) {\n" i;
6813             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6814             pr "      print_strings (r);\n";
6815             pr "      return -1;\n";
6816             pr "    }\n";
6817             pr "    {\n";
6818             pr "      const char *expected = \"%s\";\n" (c_quote str);
6819             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6820             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6821             pr "        return -1;\n";
6822             pr "      }\n";
6823             pr "    }\n"
6824         ) expected;
6825         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6826         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6827           test_name;
6828         pr "      print_strings (r);\n";
6829         pr "      return -1;\n";
6830         pr "    }\n"
6831       in
6832       List.iter (generate_test_command_call test_name) seq;
6833       generate_test_command_call ~test test_name last
6834   | TestOutputListOfDevices (seq, expected) ->
6835       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6836       let seq, last = get_seq_last seq in
6837       let test () =
6838         iteri (
6839           fun i str ->
6840             pr "    if (!r[%d]) {\n" i;
6841             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6842             pr "      print_strings (r);\n";
6843             pr "      return -1;\n";
6844             pr "    }\n";
6845             pr "    {\n";
6846             pr "      const char *expected = \"%s\";\n" (c_quote str);
6847             pr "      r[%d][5] = 's';\n" i;
6848             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6849             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6850             pr "        return -1;\n";
6851             pr "      }\n";
6852             pr "    }\n"
6853         ) expected;
6854         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6855         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6856           test_name;
6857         pr "      print_strings (r);\n";
6858         pr "      return -1;\n";
6859         pr "    }\n"
6860       in
6861       List.iter (generate_test_command_call test_name) seq;
6862       generate_test_command_call ~test test_name last
6863   | TestOutputInt (seq, expected) ->
6864       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6865       let seq, last = get_seq_last seq in
6866       let test () =
6867         pr "    if (r != %d) {\n" expected;
6868         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6869           test_name expected;
6870         pr "               (int) r);\n";
6871         pr "      return -1;\n";
6872         pr "    }\n"
6873       in
6874       List.iter (generate_test_command_call test_name) seq;
6875       generate_test_command_call ~test test_name last
6876   | TestOutputIntOp (seq, op, expected) ->
6877       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6878       let seq, last = get_seq_last seq in
6879       let test () =
6880         pr "    if (! (r %s %d)) {\n" op expected;
6881         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6882           test_name op expected;
6883         pr "               (int) r);\n";
6884         pr "      return -1;\n";
6885         pr "    }\n"
6886       in
6887       List.iter (generate_test_command_call test_name) seq;
6888       generate_test_command_call ~test test_name last
6889   | TestOutputTrue seq ->
6890       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6891       let seq, last = get_seq_last seq in
6892       let test () =
6893         pr "    if (!r) {\n";
6894         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6895           test_name;
6896         pr "      return -1;\n";
6897         pr "    }\n"
6898       in
6899       List.iter (generate_test_command_call test_name) seq;
6900       generate_test_command_call ~test test_name last
6901   | TestOutputFalse seq ->
6902       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6903       let seq, last = get_seq_last seq in
6904       let test () =
6905         pr "    if (r) {\n";
6906         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6907           test_name;
6908         pr "      return -1;\n";
6909         pr "    }\n"
6910       in
6911       List.iter (generate_test_command_call test_name) seq;
6912       generate_test_command_call ~test test_name last
6913   | TestOutputLength (seq, expected) ->
6914       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6915       let seq, last = get_seq_last seq in
6916       let test () =
6917         pr "    int j;\n";
6918         pr "    for (j = 0; j < %d; ++j)\n" expected;
6919         pr "      if (r[j] == NULL) {\n";
6920         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6921           test_name;
6922         pr "        print_strings (r);\n";
6923         pr "        return -1;\n";
6924         pr "      }\n";
6925         pr "    if (r[j] != NULL) {\n";
6926         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6927           test_name;
6928         pr "      print_strings (r);\n";
6929         pr "      return -1;\n";
6930         pr "    }\n"
6931       in
6932       List.iter (generate_test_command_call test_name) seq;
6933       generate_test_command_call ~test test_name last
6934   | TestOutputBuffer (seq, expected) ->
6935       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6936       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6937       let seq, last = get_seq_last seq in
6938       let len = String.length expected in
6939       let test () =
6940         pr "    if (size != %d) {\n" len;
6941         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6942         pr "      return -1;\n";
6943         pr "    }\n";
6944         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6945         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6946         pr "      return -1;\n";
6947         pr "    }\n"
6948       in
6949       List.iter (generate_test_command_call test_name) seq;
6950       generate_test_command_call ~test test_name last
6951   | TestOutputStruct (seq, checks) ->
6952       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6953       let seq, last = get_seq_last seq in
6954       let test () =
6955         List.iter (
6956           function
6957           | CompareWithInt (field, expected) ->
6958               pr "    if (r->%s != %d) {\n" field expected;
6959               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6960                 test_name field expected;
6961               pr "               (int) r->%s);\n" field;
6962               pr "      return -1;\n";
6963               pr "    }\n"
6964           | CompareWithIntOp (field, op, expected) ->
6965               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6966               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6967                 test_name field op expected;
6968               pr "               (int) r->%s);\n" field;
6969               pr "      return -1;\n";
6970               pr "    }\n"
6971           | CompareWithString (field, expected) ->
6972               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6973               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6974                 test_name field expected;
6975               pr "               r->%s);\n" field;
6976               pr "      return -1;\n";
6977               pr "    }\n"
6978           | CompareFieldsIntEq (field1, field2) ->
6979               pr "    if (r->%s != r->%s) {\n" field1 field2;
6980               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6981                 test_name field1 field2;
6982               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6983               pr "      return -1;\n";
6984               pr "    }\n"
6985           | CompareFieldsStrEq (field1, field2) ->
6986               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6987               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6988                 test_name field1 field2;
6989               pr "               r->%s, r->%s);\n" field1 field2;
6990               pr "      return -1;\n";
6991               pr "    }\n"
6992         ) checks
6993       in
6994       List.iter (generate_test_command_call test_name) seq;
6995       generate_test_command_call ~test test_name last
6996   | TestLastFail seq ->
6997       pr "  /* TestLastFail for %s (%d) */\n" name i;
6998       let seq, last = get_seq_last seq in
6999       List.iter (generate_test_command_call test_name) seq;
7000       generate_test_command_call test_name ~expect_error:true last
7001
7002 (* Generate the code to run a command, leaving the result in 'r'.
7003  * If you expect to get an error then you should set expect_error:true.
7004  *)
7005 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7006   match cmd with
7007   | [] -> assert false
7008   | name :: args ->
7009       (* Look up the command to find out what args/ret it has. *)
7010       let style =
7011         try
7012           let _, style, _, _, _, _, _ =
7013             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7014           style
7015         with Not_found ->
7016           failwithf "%s: in test, command %s was not found" test_name name in
7017
7018       if List.length (snd style) <> List.length args then
7019         failwithf "%s: in test, wrong number of args given to %s"
7020           test_name name;
7021
7022       pr "  {\n";
7023
7024       List.iter (
7025         function
7026         | OptString n, "NULL" -> ()
7027         | Pathname n, arg
7028         | Device n, arg
7029         | Dev_or_Path n, arg
7030         | String n, arg
7031         | OptString n, arg ->
7032             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7033         | Int _, _
7034         | Int64 _, _
7035         | Bool _, _
7036         | FileIn _, _ | FileOut _, _ -> ()
7037         | StringList n, "" | DeviceList n, "" ->
7038             pr "    const char *const %s[1] = { NULL };\n" n
7039         | StringList n, arg | DeviceList n, arg ->
7040             let strs = string_split " " arg in
7041             iteri (
7042               fun i str ->
7043                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7044             ) strs;
7045             pr "    const char *const %s[] = {\n" n;
7046             iteri (
7047               fun i _ -> pr "      %s_%d,\n" n i
7048             ) strs;
7049             pr "      NULL\n";
7050             pr "    };\n";
7051       ) (List.combine (snd style) args);
7052
7053       let error_code =
7054         match fst style with
7055         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7056         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7057         | RConstString _ | RConstOptString _ ->
7058             pr "    const char *r;\n"; "NULL"
7059         | RString _ -> pr "    char *r;\n"; "NULL"
7060         | RStringList _ | RHashtable _ ->
7061             pr "    char **r;\n";
7062             pr "    int i;\n";
7063             "NULL"
7064         | RStruct (_, typ) ->
7065             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7066         | RStructList (_, typ) ->
7067             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7068         | RBufferOut _ ->
7069             pr "    char *r;\n";
7070             pr "    size_t size;\n";
7071             "NULL" in
7072
7073       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7074       pr "    r = guestfs_%s (g" name;
7075
7076       (* Generate the parameters. *)
7077       List.iter (
7078         function
7079         | OptString _, "NULL" -> pr ", NULL"
7080         | Pathname n, _
7081         | Device n, _ | Dev_or_Path n, _
7082         | String n, _
7083         | OptString n, _ ->
7084             pr ", %s" n
7085         | FileIn _, arg | FileOut _, arg ->
7086             pr ", \"%s\"" (c_quote arg)
7087         | StringList n, _ | DeviceList n, _ ->
7088             pr ", (char **) %s" n
7089         | Int _, arg ->
7090             let i =
7091               try int_of_string arg
7092               with Failure "int_of_string" ->
7093                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7094             pr ", %d" i
7095         | Int64 _, arg ->
7096             let i =
7097               try Int64.of_string arg
7098               with Failure "int_of_string" ->
7099                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7100             pr ", %Ld" i
7101         | Bool _, arg ->
7102             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7103       ) (List.combine (snd style) args);
7104
7105       (match fst style with
7106        | RBufferOut _ -> pr ", &size"
7107        | _ -> ()
7108       );
7109
7110       pr ");\n";
7111
7112       if not expect_error then
7113         pr "    if (r == %s)\n" error_code
7114       else
7115         pr "    if (r != %s)\n" error_code;
7116       pr "      return -1;\n";
7117
7118       (* Insert the test code. *)
7119       (match test with
7120        | None -> ()
7121        | Some f -> f ()
7122       );
7123
7124       (match fst style with
7125        | RErr | RInt _ | RInt64 _ | RBool _
7126        | RConstString _ | RConstOptString _ -> ()
7127        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7128        | RStringList _ | RHashtable _ ->
7129            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7130            pr "      free (r[i]);\n";
7131            pr "    free (r);\n"
7132        | RStruct (_, typ) ->
7133            pr "    guestfs_free_%s (r);\n" typ
7134        | RStructList (_, typ) ->
7135            pr "    guestfs_free_%s_list (r);\n" typ
7136       );
7137
7138       pr "  }\n"
7139
7140 and c_quote str =
7141   let str = replace_str str "\r" "\\r" in
7142   let str = replace_str str "\n" "\\n" in
7143   let str = replace_str str "\t" "\\t" in
7144   let str = replace_str str "\000" "\\0" in
7145   str
7146
7147 (* Generate a lot of different functions for guestfish. *)
7148 and generate_fish_cmds () =
7149   generate_header CStyle GPLv2plus;
7150
7151   let all_functions =
7152     List.filter (
7153       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7154     ) all_functions in
7155   let all_functions_sorted =
7156     List.filter (
7157       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7158     ) all_functions_sorted in
7159
7160   pr "#include <config.h>\n";
7161   pr "\n";
7162   pr "#include <stdio.h>\n";
7163   pr "#include <stdlib.h>\n";
7164   pr "#include <string.h>\n";
7165   pr "#include <inttypes.h>\n";
7166   pr "\n";
7167   pr "#include <guestfs.h>\n";
7168   pr "#include \"c-ctype.h\"\n";
7169   pr "#include \"full-write.h\"\n";
7170   pr "#include \"xstrtol.h\"\n";
7171   pr "#include \"fish.h\"\n";
7172   pr "\n";
7173
7174   (* list_commands function, which implements guestfish -h *)
7175   pr "void list_commands (void)\n";
7176   pr "{\n";
7177   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7178   pr "  list_builtin_commands ();\n";
7179   List.iter (
7180     fun (name, _, _, flags, _, shortdesc, _) ->
7181       let name = replace_char name '_' '-' in
7182       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7183         name shortdesc
7184   ) all_functions_sorted;
7185   pr "  printf (\"    %%s\\n\",";
7186   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7187   pr "}\n";
7188   pr "\n";
7189
7190   (* display_command function, which implements guestfish -h cmd *)
7191   pr "void display_command (const char *cmd)\n";
7192   pr "{\n";
7193   List.iter (
7194     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7195       let name2 = replace_char name '_' '-' in
7196       let alias =
7197         try find_map (function FishAlias n -> Some n | _ -> None) flags
7198         with Not_found -> name in
7199       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7200       let synopsis =
7201         match snd style with
7202         | [] -> name2
7203         | args ->
7204             sprintf "%s %s"
7205               name2 (String.concat " " (List.map name_of_argt args)) in
7206
7207       let warnings =
7208         if List.mem ProtocolLimitWarning flags then
7209           ("\n\n" ^ protocol_limit_warning)
7210         else "" in
7211
7212       (* For DangerWillRobinson commands, we should probably have
7213        * guestfish prompt before allowing you to use them (especially
7214        * in interactive mode). XXX
7215        *)
7216       let warnings =
7217         warnings ^
7218           if List.mem DangerWillRobinson flags then
7219             ("\n\n" ^ danger_will_robinson)
7220           else "" in
7221
7222       let warnings =
7223         warnings ^
7224           match deprecation_notice flags with
7225           | None -> ""
7226           | Some txt -> "\n\n" ^ txt in
7227
7228       let describe_alias =
7229         if name <> alias then
7230           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7231         else "" in
7232
7233       pr "  if (";
7234       pr "STRCASEEQ (cmd, \"%s\")" name;
7235       if name <> name2 then
7236         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7237       if name <> alias then
7238         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7239       pr ")\n";
7240       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7241         name2 shortdesc
7242         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7243          "=head1 DESCRIPTION\n\n" ^
7244          longdesc ^ warnings ^ describe_alias);
7245       pr "  else\n"
7246   ) all_functions;
7247   pr "    display_builtin_command (cmd);\n";
7248   pr "}\n";
7249   pr "\n";
7250
7251   let emit_print_list_function typ =
7252     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7253       typ typ typ;
7254     pr "{\n";
7255     pr "  unsigned int i;\n";
7256     pr "\n";
7257     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7258     pr "    printf (\"[%%d] = {\\n\", i);\n";
7259     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7260     pr "    printf (\"}\\n\");\n";
7261     pr "  }\n";
7262     pr "}\n";
7263     pr "\n";
7264   in
7265
7266   (* print_* functions *)
7267   List.iter (
7268     fun (typ, cols) ->
7269       let needs_i =
7270         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7271
7272       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7273       pr "{\n";
7274       if needs_i then (
7275         pr "  unsigned int i;\n";
7276         pr "\n"
7277       );
7278       List.iter (
7279         function
7280         | name, FString ->
7281             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7282         | name, FUUID ->
7283             pr "  printf (\"%%s%s: \", indent);\n" name;
7284             pr "  for (i = 0; i < 32; ++i)\n";
7285             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7286             pr "  printf (\"\\n\");\n"
7287         | name, FBuffer ->
7288             pr "  printf (\"%%s%s: \", indent);\n" name;
7289             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7290             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7291             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7292             pr "    else\n";
7293             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7294             pr "  printf (\"\\n\");\n"
7295         | name, (FUInt64|FBytes) ->
7296             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7297               name typ name
7298         | name, FInt64 ->
7299             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7300               name typ name
7301         | name, FUInt32 ->
7302             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7303               name typ name
7304         | name, FInt32 ->
7305             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7306               name typ name
7307         | name, FChar ->
7308             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7309               name typ name
7310         | name, FOptPercent ->
7311             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7312               typ name name typ name;
7313             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7314       ) cols;
7315       pr "}\n";
7316       pr "\n";
7317   ) structs;
7318
7319   (* Emit a print_TYPE_list function definition only if that function is used. *)
7320   List.iter (
7321     function
7322     | typ, (RStructListOnly | RStructAndList) ->
7323         (* generate the function for typ *)
7324         emit_print_list_function typ
7325     | typ, _ -> () (* empty *)
7326   ) (rstructs_used_by all_functions);
7327
7328   (* Emit a print_TYPE function definition only if that function is used. *)
7329   List.iter (
7330     function
7331     | typ, (RStructOnly | RStructAndList) ->
7332         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7333         pr "{\n";
7334         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7335         pr "}\n";
7336         pr "\n";
7337     | typ, _ -> () (* empty *)
7338   ) (rstructs_used_by all_functions);
7339
7340   (* run_<action> actions *)
7341   List.iter (
7342     fun (name, style, _, flags, _, _, _) ->
7343       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7344       pr "{\n";
7345       (match fst style with
7346        | RErr
7347        | RInt _
7348        | RBool _ -> pr "  int r;\n"
7349        | RInt64 _ -> pr "  int64_t r;\n"
7350        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7351        | RString _ -> pr "  char *r;\n"
7352        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7353        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7354        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7355        | RBufferOut _ ->
7356            pr "  char *r;\n";
7357            pr "  size_t size;\n";
7358       );
7359       List.iter (
7360         function
7361         | Device n
7362         | String n
7363         | OptString n
7364         | FileIn n
7365         | FileOut n -> pr "  const char *%s;\n" n
7366         | Pathname n
7367         | Dev_or_Path n -> pr "  char *%s;\n" n
7368         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7369         | Bool n -> pr "  int %s;\n" n
7370         | Int n -> pr "  int %s;\n" n
7371         | Int64 n -> pr "  int64_t %s;\n" n
7372       ) (snd style);
7373
7374       (* Check and convert parameters. *)
7375       let argc_expected = List.length (snd style) in
7376       pr "  if (argc != %d) {\n" argc_expected;
7377       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7378         argc_expected;
7379       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7380       pr "    return -1;\n";
7381       pr "  }\n";
7382
7383       let parse_integer fn fntyp rtyp range name i =
7384         pr "  {\n";
7385         pr "    strtol_error xerr;\n";
7386         pr "    %s r;\n" fntyp;
7387         pr "\n";
7388         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7389         pr "    if (xerr != LONGINT_OK) {\n";
7390         pr "      fprintf (stderr,\n";
7391         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7392         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7393         pr "      return -1;\n";
7394         pr "    }\n";
7395         (match range with
7396          | None -> ()
7397          | Some (min, max, comment) ->
7398              pr "    /* %s */\n" comment;
7399              pr "    if (r < %s || r > %s) {\n" min max;
7400              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7401                name;
7402              pr "      return -1;\n";
7403              pr "    }\n";
7404              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7405         );
7406         pr "    %s = r;\n" name;
7407         pr "  }\n";
7408       in
7409
7410       iteri (
7411         fun i ->
7412           function
7413           | Device name
7414           | String name ->
7415               pr "  %s = argv[%d];\n" name i
7416           | Pathname name
7417           | Dev_or_Path name ->
7418               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7419               pr "  if (%s == NULL) return -1;\n" name
7420           | OptString name ->
7421               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7422                 name i i
7423           | FileIn name ->
7424               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7425                 name i i
7426           | FileOut name ->
7427               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7428                 name i i
7429           | StringList name | DeviceList name ->
7430               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7431               pr "  if (%s == NULL) return -1;\n" name;
7432           | Bool name ->
7433               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7434           | Int name ->
7435               let range =
7436                 let min = "(-(2LL<<30))"
7437                 and max = "((2LL<<30)-1)"
7438                 and comment =
7439                   "The Int type in the generator is a signed 31 bit int." in
7440                 Some (min, max, comment) in
7441               parse_integer "xstrtoll" "long long" "int" range name i
7442           | Int64 name ->
7443               parse_integer "xstrtoll" "long long" "int64_t" None name i
7444       ) (snd style);
7445
7446       (* Call C API function. *)
7447       let fn =
7448         try find_map (function FishAction n -> Some n | _ -> None) flags
7449         with Not_found -> sprintf "guestfs_%s" name in
7450       pr "  r = %s " fn;
7451       generate_c_call_args ~handle:"g" style;
7452       pr ";\n";
7453
7454       List.iter (
7455         function
7456         | Device name | String name
7457         | OptString name | FileIn name | FileOut name | Bool name
7458         | Int name | Int64 name -> ()
7459         | Pathname name | Dev_or_Path name ->
7460             pr "  free (%s);\n" name
7461         | StringList name | DeviceList name ->
7462             pr "  free_strings (%s);\n" name
7463       ) (snd style);
7464
7465       (* Check return value for errors and display command results. *)
7466       (match fst style with
7467        | RErr -> pr "  return r;\n"
7468        | RInt _ ->
7469            pr "  if (r == -1) return -1;\n";
7470            pr "  printf (\"%%d\\n\", r);\n";
7471            pr "  return 0;\n"
7472        | RInt64 _ ->
7473            pr "  if (r == -1) return -1;\n";
7474            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7475            pr "  return 0;\n"
7476        | RBool _ ->
7477            pr "  if (r == -1) return -1;\n";
7478            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7479            pr "  return 0;\n"
7480        | RConstString _ ->
7481            pr "  if (r == NULL) return -1;\n";
7482            pr "  printf (\"%%s\\n\", r);\n";
7483            pr "  return 0;\n"
7484        | RConstOptString _ ->
7485            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7486            pr "  return 0;\n"
7487        | RString _ ->
7488            pr "  if (r == NULL) return -1;\n";
7489            pr "  printf (\"%%s\\n\", r);\n";
7490            pr "  free (r);\n";
7491            pr "  return 0;\n"
7492        | RStringList _ ->
7493            pr "  if (r == NULL) return -1;\n";
7494            pr "  print_strings (r);\n";
7495            pr "  free_strings (r);\n";
7496            pr "  return 0;\n"
7497        | RStruct (_, typ) ->
7498            pr "  if (r == NULL) return -1;\n";
7499            pr "  print_%s (r);\n" typ;
7500            pr "  guestfs_free_%s (r);\n" typ;
7501            pr "  return 0;\n"
7502        | RStructList (_, typ) ->
7503            pr "  if (r == NULL) return -1;\n";
7504            pr "  print_%s_list (r);\n" typ;
7505            pr "  guestfs_free_%s_list (r);\n" typ;
7506            pr "  return 0;\n"
7507        | RHashtable _ ->
7508            pr "  if (r == NULL) return -1;\n";
7509            pr "  print_table (r);\n";
7510            pr "  free_strings (r);\n";
7511            pr "  return 0;\n"
7512        | RBufferOut _ ->
7513            pr "  if (r == NULL) return -1;\n";
7514            pr "  if (full_write (1, r, size) != size) {\n";
7515            pr "    perror (\"write\");\n";
7516            pr "    free (r);\n";
7517            pr "    return -1;\n";
7518            pr "  }\n";
7519            pr "  free (r);\n";
7520            pr "  return 0;\n"
7521       );
7522       pr "}\n";
7523       pr "\n"
7524   ) all_functions;
7525
7526   (* run_action function *)
7527   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7528   pr "{\n";
7529   List.iter (
7530     fun (name, _, _, flags, _, _, _) ->
7531       let name2 = replace_char name '_' '-' in
7532       let alias =
7533         try find_map (function FishAlias n -> Some n | _ -> None) flags
7534         with Not_found -> name in
7535       pr "  if (";
7536       pr "STRCASEEQ (cmd, \"%s\")" name;
7537       if name <> name2 then
7538         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7539       if name <> alias then
7540         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7541       pr ")\n";
7542       pr "    return run_%s (cmd, argc, argv);\n" name;
7543       pr "  else\n";
7544   ) all_functions;
7545   pr "    {\n";
7546   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7547   pr "      if (command_num == 1)\n";
7548   pr "        extended_help_message ();\n";
7549   pr "      return -1;\n";
7550   pr "    }\n";
7551   pr "  return 0;\n";
7552   pr "}\n";
7553   pr "\n"
7554
7555 (* Readline completion for guestfish. *)
7556 and generate_fish_completion () =
7557   generate_header CStyle GPLv2plus;
7558
7559   let all_functions =
7560     List.filter (
7561       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7562     ) all_functions in
7563
7564   pr "\
7565 #include <config.h>
7566
7567 #include <stdio.h>
7568 #include <stdlib.h>
7569 #include <string.h>
7570
7571 #ifdef HAVE_LIBREADLINE
7572 #include <readline/readline.h>
7573 #endif
7574
7575 #include \"fish.h\"
7576
7577 #ifdef HAVE_LIBREADLINE
7578
7579 static const char *const commands[] = {
7580   BUILTIN_COMMANDS_FOR_COMPLETION,
7581 ";
7582
7583   (* Get the commands, including the aliases.  They don't need to be
7584    * sorted - the generator() function just does a dumb linear search.
7585    *)
7586   let commands =
7587     List.map (
7588       fun (name, _, _, flags, _, _, _) ->
7589         let name2 = replace_char name '_' '-' in
7590         let alias =
7591           try find_map (function FishAlias n -> Some n | _ -> None) flags
7592           with Not_found -> name in
7593
7594         if name <> alias then [name2; alias] else [name2]
7595     ) all_functions in
7596   let commands = List.flatten commands in
7597
7598   List.iter (pr "  \"%s\",\n") commands;
7599
7600   pr "  NULL
7601 };
7602
7603 static char *
7604 generator (const char *text, int state)
7605 {
7606   static int index, len;
7607   const char *name;
7608
7609   if (!state) {
7610     index = 0;
7611     len = strlen (text);
7612   }
7613
7614   rl_attempted_completion_over = 1;
7615
7616   while ((name = commands[index]) != NULL) {
7617     index++;
7618     if (STRCASEEQLEN (name, text, len))
7619       return strdup (name);
7620   }
7621
7622   return NULL;
7623 }
7624
7625 #endif /* HAVE_LIBREADLINE */
7626
7627 #ifdef HAVE_RL_COMPLETION_MATCHES
7628 #define RL_COMPLETION_MATCHES rl_completion_matches
7629 #else
7630 #ifdef HAVE_COMPLETION_MATCHES
7631 #define RL_COMPLETION_MATCHES completion_matches
7632 #endif
7633 #endif /* else just fail if we don't have either symbol */
7634
7635 char **
7636 do_completion (const char *text, int start, int end)
7637 {
7638   char **matches = NULL;
7639
7640 #ifdef HAVE_LIBREADLINE
7641   rl_completion_append_character = ' ';
7642
7643   if (start == 0)
7644     matches = RL_COMPLETION_MATCHES (text, generator);
7645   else if (complete_dest_paths)
7646     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7647 #endif
7648
7649   return matches;
7650 }
7651 ";
7652
7653 (* Generate the POD documentation for guestfish. *)
7654 and generate_fish_actions_pod () =
7655   let all_functions_sorted =
7656     List.filter (
7657       fun (_, _, _, flags, _, _, _) ->
7658         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7659     ) all_functions_sorted in
7660
7661   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7662
7663   List.iter (
7664     fun (name, style, _, flags, _, _, longdesc) ->
7665       let longdesc =
7666         Str.global_substitute rex (
7667           fun s ->
7668             let sub =
7669               try Str.matched_group 1 s
7670               with Not_found ->
7671                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7672             "C<" ^ replace_char sub '_' '-' ^ ">"
7673         ) longdesc in
7674       let name = replace_char name '_' '-' in
7675       let alias =
7676         try find_map (function FishAlias n -> Some n | _ -> None) flags
7677         with Not_found -> name in
7678
7679       pr "=head2 %s" name;
7680       if name <> alias then
7681         pr " | %s" alias;
7682       pr "\n";
7683       pr "\n";
7684       pr " %s" name;
7685       List.iter (
7686         function
7687         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7688         | OptString n -> pr " %s" n
7689         | StringList n | DeviceList n -> pr " '%s ...'" n
7690         | Bool _ -> pr " true|false"
7691         | Int n -> pr " %s" n
7692         | Int64 n -> pr " %s" n
7693         | FileIn n | FileOut n -> pr " (%s|-)" n
7694       ) (snd style);
7695       pr "\n";
7696       pr "\n";
7697       pr "%s\n\n" longdesc;
7698
7699       if List.exists (function FileIn _ | FileOut _ -> true
7700                       | _ -> false) (snd style) then
7701         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7702
7703       if List.mem ProtocolLimitWarning flags then
7704         pr "%s\n\n" protocol_limit_warning;
7705
7706       if List.mem DangerWillRobinson flags then
7707         pr "%s\n\n" danger_will_robinson;
7708
7709       match deprecation_notice flags with
7710       | None -> ()
7711       | Some txt -> pr "%s\n\n" txt
7712   ) all_functions_sorted
7713
7714 (* Generate a C function prototype. *)
7715 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7716     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7717     ?(prefix = "")
7718     ?handle name style =
7719   if extern then pr "extern ";
7720   if static then pr "static ";
7721   (match fst style with
7722    | RErr -> pr "int "
7723    | RInt _ -> pr "int "
7724    | RInt64 _ -> pr "int64_t "
7725    | RBool _ -> pr "int "
7726    | RConstString _ | RConstOptString _ -> pr "const char *"
7727    | RString _ | RBufferOut _ -> pr "char *"
7728    | RStringList _ | RHashtable _ -> pr "char **"
7729    | RStruct (_, typ) ->
7730        if not in_daemon then pr "struct guestfs_%s *" typ
7731        else pr "guestfs_int_%s *" typ
7732    | RStructList (_, typ) ->
7733        if not in_daemon then pr "struct guestfs_%s_list *" typ
7734        else pr "guestfs_int_%s_list *" typ
7735   );
7736   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7737   pr "%s%s (" prefix name;
7738   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7739     pr "void"
7740   else (
7741     let comma = ref false in
7742     (match handle with
7743      | None -> ()
7744      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7745     );
7746     let next () =
7747       if !comma then (
7748         if single_line then pr ", " else pr ",\n\t\t"
7749       );
7750       comma := true
7751     in
7752     List.iter (
7753       function
7754       | Pathname n
7755       | Device n | Dev_or_Path n
7756       | String n
7757       | OptString n ->
7758           next ();
7759           pr "const char *%s" n
7760       | StringList n | DeviceList n ->
7761           next ();
7762           pr "char *const *%s" n
7763       | Bool n -> next (); pr "int %s" n
7764       | Int n -> next (); pr "int %s" n
7765       | Int64 n -> next (); pr "int64_t %s" n
7766       | FileIn n
7767       | FileOut n ->
7768           if not in_daemon then (next (); pr "const char *%s" n)
7769     ) (snd style);
7770     if is_RBufferOut then (next (); pr "size_t *size_r");
7771   );
7772   pr ")";
7773   if semicolon then pr ";";
7774   if newline then pr "\n"
7775
7776 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7777 and generate_c_call_args ?handle ?(decl = false) style =
7778   pr "(";
7779   let comma = ref false in
7780   let next () =
7781     if !comma then pr ", ";
7782     comma := true
7783   in
7784   (match handle with
7785    | None -> ()
7786    | Some handle -> pr "%s" handle; comma := true
7787   );
7788   List.iter (
7789     fun arg ->
7790       next ();
7791       pr "%s" (name_of_argt arg)
7792   ) (snd style);
7793   (* For RBufferOut calls, add implicit &size parameter. *)
7794   if not decl then (
7795     match fst style with
7796     | RBufferOut _ ->
7797         next ();
7798         pr "&size"
7799     | _ -> ()
7800   );
7801   pr ")"
7802
7803 (* Generate the OCaml bindings interface. *)
7804 and generate_ocaml_mli () =
7805   generate_header OCamlStyle LGPLv2plus;
7806
7807   pr "\
7808 (** For API documentation you should refer to the C API
7809     in the guestfs(3) manual page.  The OCaml API uses almost
7810     exactly the same calls. *)
7811
7812 type t
7813 (** A [guestfs_h] handle. *)
7814
7815 exception Error of string
7816 (** This exception is raised when there is an error. *)
7817
7818 exception Handle_closed of string
7819 (** This exception is raised if you use a {!Guestfs.t} handle
7820     after calling {!close} on it.  The string is the name of
7821     the function. *)
7822
7823 val create : unit -> t
7824 (** Create a {!Guestfs.t} handle. *)
7825
7826 val close : t -> unit
7827 (** Close the {!Guestfs.t} handle and free up all resources used
7828     by it immediately.
7829
7830     Handles are closed by the garbage collector when they become
7831     unreferenced, but callers can call this in order to provide
7832     predictable cleanup. *)
7833
7834 ";
7835   generate_ocaml_structure_decls ();
7836
7837   (* The actions. *)
7838   List.iter (
7839     fun (name, style, _, _, _, shortdesc, _) ->
7840       generate_ocaml_prototype name style;
7841       pr "(** %s *)\n" shortdesc;
7842       pr "\n"
7843   ) all_functions_sorted
7844
7845 (* Generate the OCaml bindings implementation. *)
7846 and generate_ocaml_ml () =
7847   generate_header OCamlStyle LGPLv2plus;
7848
7849   pr "\
7850 type t
7851
7852 exception Error of string
7853 exception Handle_closed of string
7854
7855 external create : unit -> t = \"ocaml_guestfs_create\"
7856 external close : t -> unit = \"ocaml_guestfs_close\"
7857
7858 (* Give the exceptions names, so they can be raised from the C code. *)
7859 let () =
7860   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7861   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7862
7863 ";
7864
7865   generate_ocaml_structure_decls ();
7866
7867   (* The actions. *)
7868   List.iter (
7869     fun (name, style, _, _, _, shortdesc, _) ->
7870       generate_ocaml_prototype ~is_external:true name style;
7871   ) all_functions_sorted
7872
7873 (* Generate the OCaml bindings C implementation. *)
7874 and generate_ocaml_c () =
7875   generate_header CStyle LGPLv2plus;
7876
7877   pr "\
7878 #include <stdio.h>
7879 #include <stdlib.h>
7880 #include <string.h>
7881
7882 #include <caml/config.h>
7883 #include <caml/alloc.h>
7884 #include <caml/callback.h>
7885 #include <caml/fail.h>
7886 #include <caml/memory.h>
7887 #include <caml/mlvalues.h>
7888 #include <caml/signals.h>
7889
7890 #include <guestfs.h>
7891
7892 #include \"guestfs_c.h\"
7893
7894 /* Copy a hashtable of string pairs into an assoc-list.  We return
7895  * the list in reverse order, but hashtables aren't supposed to be
7896  * ordered anyway.
7897  */
7898 static CAMLprim value
7899 copy_table (char * const * argv)
7900 {
7901   CAMLparam0 ();
7902   CAMLlocal5 (rv, pairv, kv, vv, cons);
7903   int i;
7904
7905   rv = Val_int (0);
7906   for (i = 0; argv[i] != NULL; i += 2) {
7907     kv = caml_copy_string (argv[i]);
7908     vv = caml_copy_string (argv[i+1]);
7909     pairv = caml_alloc (2, 0);
7910     Store_field (pairv, 0, kv);
7911     Store_field (pairv, 1, vv);
7912     cons = caml_alloc (2, 0);
7913     Store_field (cons, 1, rv);
7914     rv = cons;
7915     Store_field (cons, 0, pairv);
7916   }
7917
7918   CAMLreturn (rv);
7919 }
7920
7921 ";
7922
7923   (* Struct copy functions. *)
7924
7925   let emit_ocaml_copy_list_function typ =
7926     pr "static CAMLprim value\n";
7927     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7928     pr "{\n";
7929     pr "  CAMLparam0 ();\n";
7930     pr "  CAMLlocal2 (rv, v);\n";
7931     pr "  unsigned int i;\n";
7932     pr "\n";
7933     pr "  if (%ss->len == 0)\n" typ;
7934     pr "    CAMLreturn (Atom (0));\n";
7935     pr "  else {\n";
7936     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7937     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7938     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7939     pr "      caml_modify (&Field (rv, i), v);\n";
7940     pr "    }\n";
7941     pr "    CAMLreturn (rv);\n";
7942     pr "  }\n";
7943     pr "}\n";
7944     pr "\n";
7945   in
7946
7947   List.iter (
7948     fun (typ, cols) ->
7949       let has_optpercent_col =
7950         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7951
7952       pr "static CAMLprim value\n";
7953       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7954       pr "{\n";
7955       pr "  CAMLparam0 ();\n";
7956       if has_optpercent_col then
7957         pr "  CAMLlocal3 (rv, v, v2);\n"
7958       else
7959         pr "  CAMLlocal2 (rv, v);\n";
7960       pr "\n";
7961       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7962       iteri (
7963         fun i col ->
7964           (match col with
7965            | name, FString ->
7966                pr "  v = caml_copy_string (%s->%s);\n" typ name
7967            | name, FBuffer ->
7968                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7969                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7970                  typ name typ name
7971            | name, FUUID ->
7972                pr "  v = caml_alloc_string (32);\n";
7973                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7974            | name, (FBytes|FInt64|FUInt64) ->
7975                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7976            | name, (FInt32|FUInt32) ->
7977                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7978            | name, FOptPercent ->
7979                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7980                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7981                pr "    v = caml_alloc (1, 0);\n";
7982                pr "    Store_field (v, 0, v2);\n";
7983                pr "  } else /* None */\n";
7984                pr "    v = Val_int (0);\n";
7985            | name, FChar ->
7986                pr "  v = Val_int (%s->%s);\n" typ name
7987           );
7988           pr "  Store_field (rv, %d, v);\n" i
7989       ) cols;
7990       pr "  CAMLreturn (rv);\n";
7991       pr "}\n";
7992       pr "\n";
7993   ) structs;
7994
7995   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7996   List.iter (
7997     function
7998     | typ, (RStructListOnly | RStructAndList) ->
7999         (* generate the function for typ *)
8000         emit_ocaml_copy_list_function typ
8001     | typ, _ -> () (* empty *)
8002   ) (rstructs_used_by all_functions);
8003
8004   (* The wrappers. *)
8005   List.iter (
8006     fun (name, style, _, _, _, _, _) ->
8007       pr "/* Automatically generated wrapper for function\n";
8008       pr " * ";
8009       generate_ocaml_prototype name style;
8010       pr " */\n";
8011       pr "\n";
8012
8013       let params =
8014         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8015
8016       let needs_extra_vs =
8017         match fst style with RConstOptString _ -> true | _ -> false in
8018
8019       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8020       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8021       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8022       pr "\n";
8023
8024       pr "CAMLprim value\n";
8025       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8026       List.iter (pr ", value %s") (List.tl params);
8027       pr ")\n";
8028       pr "{\n";
8029
8030       (match params with
8031        | [p1; p2; p3; p4; p5] ->
8032            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8033        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8034            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8035            pr "  CAMLxparam%d (%s);\n"
8036              (List.length rest) (String.concat ", " rest)
8037        | ps ->
8038            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8039       );
8040       if not needs_extra_vs then
8041         pr "  CAMLlocal1 (rv);\n"
8042       else
8043         pr "  CAMLlocal3 (rv, v, v2);\n";
8044       pr "\n";
8045
8046       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8047       pr "  if (g == NULL)\n";
8048       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8049       pr "\n";
8050
8051       List.iter (
8052         function
8053         | Pathname n
8054         | Device n | Dev_or_Path n
8055         | String n
8056         | FileIn n
8057         | FileOut n ->
8058             pr "  const char *%s = String_val (%sv);\n" n n
8059         | OptString n ->
8060             pr "  const char *%s =\n" n;
8061             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8062               n n
8063         | StringList n | DeviceList n ->
8064             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8065         | Bool n ->
8066             pr "  int %s = Bool_val (%sv);\n" n n
8067         | Int n ->
8068             pr "  int %s = Int_val (%sv);\n" n n
8069         | Int64 n ->
8070             pr "  int64_t %s = Int64_val (%sv);\n" n n
8071       ) (snd style);
8072       let error_code =
8073         match fst style with
8074         | RErr -> pr "  int r;\n"; "-1"
8075         | RInt _ -> pr "  int r;\n"; "-1"
8076         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8077         | RBool _ -> pr "  int r;\n"; "-1"
8078         | RConstString _ | RConstOptString _ ->
8079             pr "  const char *r;\n"; "NULL"
8080         | RString _ -> pr "  char *r;\n"; "NULL"
8081         | RStringList _ ->
8082             pr "  int i;\n";
8083             pr "  char **r;\n";
8084             "NULL"
8085         | RStruct (_, typ) ->
8086             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8087         | RStructList (_, typ) ->
8088             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8089         | RHashtable _ ->
8090             pr "  int i;\n";
8091             pr "  char **r;\n";
8092             "NULL"
8093         | RBufferOut _ ->
8094             pr "  char *r;\n";
8095             pr "  size_t size;\n";
8096             "NULL" in
8097       pr "\n";
8098
8099       pr "  caml_enter_blocking_section ();\n";
8100       pr "  r = guestfs_%s " name;
8101       generate_c_call_args ~handle:"g" style;
8102       pr ";\n";
8103       pr "  caml_leave_blocking_section ();\n";
8104
8105       List.iter (
8106         function
8107         | StringList n | DeviceList n ->
8108             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8109         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8110         | Bool _ | Int _ | Int64 _
8111         | FileIn _ | FileOut _ -> ()
8112       ) (snd style);
8113
8114       pr "  if (r == %s)\n" error_code;
8115       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8116       pr "\n";
8117
8118       (match fst style with
8119        | RErr -> pr "  rv = Val_unit;\n"
8120        | RInt _ -> pr "  rv = Val_int (r);\n"
8121        | RInt64 _ ->
8122            pr "  rv = caml_copy_int64 (r);\n"
8123        | RBool _ -> pr "  rv = Val_bool (r);\n"
8124        | RConstString _ ->
8125            pr "  rv = caml_copy_string (r);\n"
8126        | RConstOptString _ ->
8127            pr "  if (r) { /* Some string */\n";
8128            pr "    v = caml_alloc (1, 0);\n";
8129            pr "    v2 = caml_copy_string (r);\n";
8130            pr "    Store_field (v, 0, v2);\n";
8131            pr "  } else /* None */\n";
8132            pr "    v = Val_int (0);\n";
8133        | RString _ ->
8134            pr "  rv = caml_copy_string (r);\n";
8135            pr "  free (r);\n"
8136        | RStringList _ ->
8137            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8138            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8139            pr "  free (r);\n"
8140        | RStruct (_, typ) ->
8141            pr "  rv = copy_%s (r);\n" typ;
8142            pr "  guestfs_free_%s (r);\n" typ;
8143        | RStructList (_, typ) ->
8144            pr "  rv = copy_%s_list (r);\n" typ;
8145            pr "  guestfs_free_%s_list (r);\n" typ;
8146        | RHashtable _ ->
8147            pr "  rv = copy_table (r);\n";
8148            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8149            pr "  free (r);\n";
8150        | RBufferOut _ ->
8151            pr "  rv = caml_alloc_string (size);\n";
8152            pr "  memcpy (String_val (rv), r, size);\n";
8153       );
8154
8155       pr "  CAMLreturn (rv);\n";
8156       pr "}\n";
8157       pr "\n";
8158
8159       if List.length params > 5 then (
8160         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8161         pr "CAMLprim value ";
8162         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8163         pr "CAMLprim value\n";
8164         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8165         pr "{\n";
8166         pr "  return ocaml_guestfs_%s (argv[0]" name;
8167         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8168         pr ");\n";
8169         pr "}\n";
8170         pr "\n"
8171       )
8172   ) all_functions_sorted
8173
8174 and generate_ocaml_structure_decls () =
8175   List.iter (
8176     fun (typ, cols) ->
8177       pr "type %s = {\n" typ;
8178       List.iter (
8179         function
8180         | name, FString -> pr "  %s : string;\n" name
8181         | name, FBuffer -> pr "  %s : string;\n" name
8182         | name, FUUID -> pr "  %s : string;\n" name
8183         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8184         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8185         | name, FChar -> pr "  %s : char;\n" name
8186         | name, FOptPercent -> pr "  %s : float option;\n" name
8187       ) cols;
8188       pr "}\n";
8189       pr "\n"
8190   ) structs
8191
8192 and generate_ocaml_prototype ?(is_external = false) name style =
8193   if is_external then pr "external " else pr "val ";
8194   pr "%s : t -> " name;
8195   List.iter (
8196     function
8197     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8198     | OptString _ -> pr "string option -> "
8199     | StringList _ | DeviceList _ -> pr "string array -> "
8200     | Bool _ -> pr "bool -> "
8201     | Int _ -> pr "int -> "
8202     | Int64 _ -> pr "int64 -> "
8203   ) (snd style);
8204   (match fst style with
8205    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8206    | RInt _ -> pr "int"
8207    | RInt64 _ -> pr "int64"
8208    | RBool _ -> pr "bool"
8209    | RConstString _ -> pr "string"
8210    | RConstOptString _ -> pr "string option"
8211    | RString _ | RBufferOut _ -> pr "string"
8212    | RStringList _ -> pr "string array"
8213    | RStruct (_, typ) -> pr "%s" typ
8214    | RStructList (_, typ) -> pr "%s array" typ
8215    | RHashtable _ -> pr "(string * string) list"
8216   );
8217   if is_external then (
8218     pr " = ";
8219     if List.length (snd style) + 1 > 5 then
8220       pr "\"ocaml_guestfs_%s_byte\" " name;
8221     pr "\"ocaml_guestfs_%s\"" name
8222   );
8223   pr "\n"
8224
8225 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8226 and generate_perl_xs () =
8227   generate_header CStyle LGPLv2plus;
8228
8229   pr "\
8230 #include \"EXTERN.h\"
8231 #include \"perl.h\"
8232 #include \"XSUB.h\"
8233
8234 #include <guestfs.h>
8235
8236 #ifndef PRId64
8237 #define PRId64 \"lld\"
8238 #endif
8239
8240 static SV *
8241 my_newSVll(long long val) {
8242 #ifdef USE_64_BIT_ALL
8243   return newSViv(val);
8244 #else
8245   char buf[100];
8246   int len;
8247   len = snprintf(buf, 100, \"%%\" PRId64, val);
8248   return newSVpv(buf, len);
8249 #endif
8250 }
8251
8252 #ifndef PRIu64
8253 #define PRIu64 \"llu\"
8254 #endif
8255
8256 static SV *
8257 my_newSVull(unsigned long long val) {
8258 #ifdef USE_64_BIT_ALL
8259   return newSVuv(val);
8260 #else
8261   char buf[100];
8262   int len;
8263   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8264   return newSVpv(buf, len);
8265 #endif
8266 }
8267
8268 /* http://www.perlmonks.org/?node_id=680842 */
8269 static char **
8270 XS_unpack_charPtrPtr (SV *arg) {
8271   char **ret;
8272   AV *av;
8273   I32 i;
8274
8275   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8276     croak (\"array reference expected\");
8277
8278   av = (AV *)SvRV (arg);
8279   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8280   if (!ret)
8281     croak (\"malloc failed\");
8282
8283   for (i = 0; i <= av_len (av); i++) {
8284     SV **elem = av_fetch (av, i, 0);
8285
8286     if (!elem || !*elem)
8287       croak (\"missing element in list\");
8288
8289     ret[i] = SvPV_nolen (*elem);
8290   }
8291
8292   ret[i] = NULL;
8293
8294   return ret;
8295 }
8296
8297 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8298
8299 PROTOTYPES: ENABLE
8300
8301 guestfs_h *
8302 _create ()
8303    CODE:
8304       RETVAL = guestfs_create ();
8305       if (!RETVAL)
8306         croak (\"could not create guestfs handle\");
8307       guestfs_set_error_handler (RETVAL, NULL, NULL);
8308  OUTPUT:
8309       RETVAL
8310
8311 void
8312 DESTROY (g)
8313       guestfs_h *g;
8314  PPCODE:
8315       guestfs_close (g);
8316
8317 ";
8318
8319   List.iter (
8320     fun (name, style, _, _, _, _, _) ->
8321       (match fst style with
8322        | RErr -> pr "void\n"
8323        | RInt _ -> pr "SV *\n"
8324        | RInt64 _ -> pr "SV *\n"
8325        | RBool _ -> pr "SV *\n"
8326        | RConstString _ -> pr "SV *\n"
8327        | RConstOptString _ -> pr "SV *\n"
8328        | RString _ -> pr "SV *\n"
8329        | RBufferOut _ -> pr "SV *\n"
8330        | RStringList _
8331        | RStruct _ | RStructList _
8332        | RHashtable _ ->
8333            pr "void\n" (* all lists returned implictly on the stack *)
8334       );
8335       (* Call and arguments. *)
8336       pr "%s " name;
8337       generate_c_call_args ~handle:"g" ~decl:true style;
8338       pr "\n";
8339       pr "      guestfs_h *g;\n";
8340       iteri (
8341         fun i ->
8342           function
8343           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8344               pr "      char *%s;\n" n
8345           | OptString n ->
8346               (* http://www.perlmonks.org/?node_id=554277
8347                * Note that the implicit handle argument means we have
8348                * to add 1 to the ST(x) operator.
8349                *)
8350               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8351           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8352           | Bool n -> pr "      int %s;\n" n
8353           | Int n -> pr "      int %s;\n" n
8354           | Int64 n -> pr "      int64_t %s;\n" n
8355       ) (snd style);
8356
8357       let do_cleanups () =
8358         List.iter (
8359           function
8360           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8361           | Bool _ | Int _ | Int64 _
8362           | FileIn _ | FileOut _ -> ()
8363           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8364         ) (snd style)
8365       in
8366
8367       (* Code. *)
8368       (match fst style with
8369        | RErr ->
8370            pr "PREINIT:\n";
8371            pr "      int r;\n";
8372            pr " PPCODE:\n";
8373            pr "      r = guestfs_%s " name;
8374            generate_c_call_args ~handle:"g" style;
8375            pr ";\n";
8376            do_cleanups ();
8377            pr "      if (r == -1)\n";
8378            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8379        | RInt n
8380        | RBool n ->
8381            pr "PREINIT:\n";
8382            pr "      int %s;\n" n;
8383            pr "   CODE:\n";
8384            pr "      %s = guestfs_%s " n name;
8385            generate_c_call_args ~handle:"g" style;
8386            pr ";\n";
8387            do_cleanups ();
8388            pr "      if (%s == -1)\n" n;
8389            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8390            pr "      RETVAL = newSViv (%s);\n" n;
8391            pr " OUTPUT:\n";
8392            pr "      RETVAL\n"
8393        | RInt64 n ->
8394            pr "PREINIT:\n";
8395            pr "      int64_t %s;\n" n;
8396            pr "   CODE:\n";
8397            pr "      %s = guestfs_%s " n name;
8398            generate_c_call_args ~handle:"g" style;
8399            pr ";\n";
8400            do_cleanups ();
8401            pr "      if (%s == -1)\n" n;
8402            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8403            pr "      RETVAL = my_newSVll (%s);\n" n;
8404            pr " OUTPUT:\n";
8405            pr "      RETVAL\n"
8406        | RConstString n ->
8407            pr "PREINIT:\n";
8408            pr "      const char *%s;\n" n;
8409            pr "   CODE:\n";
8410            pr "      %s = guestfs_%s " n name;
8411            generate_c_call_args ~handle:"g" style;
8412            pr ";\n";
8413            do_cleanups ();
8414            pr "      if (%s == NULL)\n" n;
8415            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8416            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8417            pr " OUTPUT:\n";
8418            pr "      RETVAL\n"
8419        | RConstOptString n ->
8420            pr "PREINIT:\n";
8421            pr "      const char *%s;\n" n;
8422            pr "   CODE:\n";
8423            pr "      %s = guestfs_%s " n name;
8424            generate_c_call_args ~handle:"g" style;
8425            pr ";\n";
8426            do_cleanups ();
8427            pr "      if (%s == NULL)\n" n;
8428            pr "        RETVAL = &PL_sv_undef;\n";
8429            pr "      else\n";
8430            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8431            pr " OUTPUT:\n";
8432            pr "      RETVAL\n"
8433        | RString n ->
8434            pr "PREINIT:\n";
8435            pr "      char *%s;\n" n;
8436            pr "   CODE:\n";
8437            pr "      %s = guestfs_%s " n name;
8438            generate_c_call_args ~handle:"g" style;
8439            pr ";\n";
8440            do_cleanups ();
8441            pr "      if (%s == NULL)\n" n;
8442            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8443            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8444            pr "      free (%s);\n" n;
8445            pr " OUTPUT:\n";
8446            pr "      RETVAL\n"
8447        | RStringList n | RHashtable n ->
8448            pr "PREINIT:\n";
8449            pr "      char **%s;\n" n;
8450            pr "      int i, n;\n";
8451            pr " PPCODE:\n";
8452            pr "      %s = guestfs_%s " n name;
8453            generate_c_call_args ~handle:"g" style;
8454            pr ";\n";
8455            do_cleanups ();
8456            pr "      if (%s == NULL)\n" n;
8457            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8458            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8459            pr "      EXTEND (SP, n);\n";
8460            pr "      for (i = 0; i < n; ++i) {\n";
8461            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8462            pr "        free (%s[i]);\n" n;
8463            pr "      }\n";
8464            pr "      free (%s);\n" n;
8465        | RStruct (n, typ) ->
8466            let cols = cols_of_struct typ in
8467            generate_perl_struct_code typ cols name style n do_cleanups
8468        | RStructList (n, typ) ->
8469            let cols = cols_of_struct typ in
8470            generate_perl_struct_list_code typ cols name style n do_cleanups
8471        | RBufferOut n ->
8472            pr "PREINIT:\n";
8473            pr "      char *%s;\n" n;
8474            pr "      size_t size;\n";
8475            pr "   CODE:\n";
8476            pr "      %s = guestfs_%s " n name;
8477            generate_c_call_args ~handle:"g" style;
8478            pr ";\n";
8479            do_cleanups ();
8480            pr "      if (%s == NULL)\n" n;
8481            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8482            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8483            pr "      free (%s);\n" n;
8484            pr " OUTPUT:\n";
8485            pr "      RETVAL\n"
8486       );
8487
8488       pr "\n"
8489   ) all_functions
8490
8491 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8492   pr "PREINIT:\n";
8493   pr "      struct guestfs_%s_list *%s;\n" typ n;
8494   pr "      int i;\n";
8495   pr "      HV *hv;\n";
8496   pr " PPCODE:\n";
8497   pr "      %s = guestfs_%s " n name;
8498   generate_c_call_args ~handle:"g" style;
8499   pr ";\n";
8500   do_cleanups ();
8501   pr "      if (%s == NULL)\n" n;
8502   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8503   pr "      EXTEND (SP, %s->len);\n" n;
8504   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8505   pr "        hv = newHV ();\n";
8506   List.iter (
8507     function
8508     | name, FString ->
8509         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8510           name (String.length name) n name
8511     | name, FUUID ->
8512         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8513           name (String.length name) n name
8514     | name, FBuffer ->
8515         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8516           name (String.length name) n name n name
8517     | name, (FBytes|FUInt64) ->
8518         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8519           name (String.length name) n name
8520     | name, FInt64 ->
8521         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8522           name (String.length name) n name
8523     | name, (FInt32|FUInt32) ->
8524         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8525           name (String.length name) n name
8526     | name, FChar ->
8527         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8528           name (String.length name) n name
8529     | name, FOptPercent ->
8530         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8531           name (String.length name) n name
8532   ) cols;
8533   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8534   pr "      }\n";
8535   pr "      guestfs_free_%s_list (%s);\n" typ n
8536
8537 and generate_perl_struct_code typ cols name style n do_cleanups =
8538   pr "PREINIT:\n";
8539   pr "      struct guestfs_%s *%s;\n" typ n;
8540   pr " PPCODE:\n";
8541   pr "      %s = guestfs_%s " n name;
8542   generate_c_call_args ~handle:"g" style;
8543   pr ";\n";
8544   do_cleanups ();
8545   pr "      if (%s == NULL)\n" n;
8546   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8547   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8548   List.iter (
8549     fun ((name, _) as col) ->
8550       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8551
8552       match col with
8553       | name, FString ->
8554           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8555             n name
8556       | name, FBuffer ->
8557           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8558             n name n name
8559       | name, FUUID ->
8560           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8561             n name
8562       | name, (FBytes|FUInt64) ->
8563           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8564             n name
8565       | name, FInt64 ->
8566           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8567             n name
8568       | name, (FInt32|FUInt32) ->
8569           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8570             n name
8571       | name, FChar ->
8572           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8573             n name
8574       | name, FOptPercent ->
8575           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8576             n name
8577   ) cols;
8578   pr "      free (%s);\n" n
8579
8580 (* Generate Sys/Guestfs.pm. *)
8581 and generate_perl_pm () =
8582   generate_header HashStyle LGPLv2plus;
8583
8584   pr "\
8585 =pod
8586
8587 =head1 NAME
8588
8589 Sys::Guestfs - Perl bindings for libguestfs
8590
8591 =head1 SYNOPSIS
8592
8593  use Sys::Guestfs;
8594
8595  my $h = Sys::Guestfs->new ();
8596  $h->add_drive ('guest.img');
8597  $h->launch ();
8598  $h->mount ('/dev/sda1', '/');
8599  $h->touch ('/hello');
8600  $h->sync ();
8601
8602 =head1 DESCRIPTION
8603
8604 The C<Sys::Guestfs> module provides a Perl XS binding to the
8605 libguestfs API for examining and modifying virtual machine
8606 disk images.
8607
8608 Amongst the things this is good for: making batch configuration
8609 changes to guests, getting disk used/free statistics (see also:
8610 virt-df), migrating between virtualization systems (see also:
8611 virt-p2v), performing partial backups, performing partial guest
8612 clones, cloning guests and changing registry/UUID/hostname info, and
8613 much else besides.
8614
8615 Libguestfs uses Linux kernel and qemu code, and can access any type of
8616 guest filesystem that Linux and qemu can, including but not limited
8617 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8618 schemes, qcow, qcow2, vmdk.
8619
8620 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8621 LVs, what filesystem is in each LV, etc.).  It can also run commands
8622 in the context of the guest.  Also you can access filesystems over
8623 FUSE.
8624
8625 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8626 functions for using libguestfs from Perl, including integration
8627 with libvirt.
8628
8629 =head1 ERRORS
8630
8631 All errors turn into calls to C<croak> (see L<Carp(3)>).
8632
8633 =head1 METHODS
8634
8635 =over 4
8636
8637 =cut
8638
8639 package Sys::Guestfs;
8640
8641 use strict;
8642 use warnings;
8643
8644 require XSLoader;
8645 XSLoader::load ('Sys::Guestfs');
8646
8647 =item $h = Sys::Guestfs->new ();
8648
8649 Create a new guestfs handle.
8650
8651 =cut
8652
8653 sub new {
8654   my $proto = shift;
8655   my $class = ref ($proto) || $proto;
8656
8657   my $self = Sys::Guestfs::_create ();
8658   bless $self, $class;
8659   return $self;
8660 }
8661
8662 ";
8663
8664   (* Actions.  We only need to print documentation for these as
8665    * they are pulled in from the XS code automatically.
8666    *)
8667   List.iter (
8668     fun (name, style, _, flags, _, _, longdesc) ->
8669       if not (List.mem NotInDocs flags) then (
8670         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8671         pr "=item ";
8672         generate_perl_prototype name style;
8673         pr "\n\n";
8674         pr "%s\n\n" longdesc;
8675         if List.mem ProtocolLimitWarning flags then
8676           pr "%s\n\n" protocol_limit_warning;
8677         if List.mem DangerWillRobinson flags then
8678           pr "%s\n\n" danger_will_robinson;
8679         match deprecation_notice flags with
8680         | None -> ()
8681         | Some txt -> pr "%s\n\n" txt
8682       )
8683   ) all_functions_sorted;
8684
8685   (* End of file. *)
8686   pr "\
8687 =cut
8688
8689 1;
8690
8691 =back
8692
8693 =head1 COPYRIGHT
8694
8695 Copyright (C) %s Red Hat Inc.
8696
8697 =head1 LICENSE
8698
8699 Please see the file COPYING.LIB for the full license.
8700
8701 =head1 SEE ALSO
8702
8703 L<guestfs(3)>,
8704 L<guestfish(1)>,
8705 L<http://libguestfs.org>,
8706 L<Sys::Guestfs::Lib(3)>.
8707
8708 =cut
8709 " copyright_years
8710
8711 and generate_perl_prototype name style =
8712   (match fst style with
8713    | RErr -> ()
8714    | RBool n
8715    | RInt n
8716    | RInt64 n
8717    | RConstString n
8718    | RConstOptString n
8719    | RString n
8720    | RBufferOut n -> pr "$%s = " n
8721    | RStruct (n,_)
8722    | RHashtable n -> pr "%%%s = " n
8723    | RStringList n
8724    | RStructList (n,_) -> pr "@%s = " n
8725   );
8726   pr "$h->%s (" name;
8727   let comma = ref false in
8728   List.iter (
8729     fun arg ->
8730       if !comma then pr ", ";
8731       comma := true;
8732       match arg with
8733       | Pathname n | Device n | Dev_or_Path n | String n
8734       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8735           pr "$%s" n
8736       | StringList n | DeviceList n ->
8737           pr "\\@%s" n
8738   ) (snd style);
8739   pr ");"
8740
8741 (* Generate Python C module. *)
8742 and generate_python_c () =
8743   generate_header CStyle LGPLv2plus;
8744
8745   pr "\
8746 #include <Python.h>
8747
8748 #include <stdio.h>
8749 #include <stdlib.h>
8750 #include <assert.h>
8751
8752 #include \"guestfs.h\"
8753
8754 typedef struct {
8755   PyObject_HEAD
8756   guestfs_h *g;
8757 } Pyguestfs_Object;
8758
8759 static guestfs_h *
8760 get_handle (PyObject *obj)
8761 {
8762   assert (obj);
8763   assert (obj != Py_None);
8764   return ((Pyguestfs_Object *) obj)->g;
8765 }
8766
8767 static PyObject *
8768 put_handle (guestfs_h *g)
8769 {
8770   assert (g);
8771   return
8772     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8773 }
8774
8775 /* This list should be freed (but not the strings) after use. */
8776 static char **
8777 get_string_list (PyObject *obj)
8778 {
8779   int i, len;
8780   char **r;
8781
8782   assert (obj);
8783
8784   if (!PyList_Check (obj)) {
8785     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8786     return NULL;
8787   }
8788
8789   len = PyList_Size (obj);
8790   r = malloc (sizeof (char *) * (len+1));
8791   if (r == NULL) {
8792     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8793     return NULL;
8794   }
8795
8796   for (i = 0; i < len; ++i)
8797     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8798   r[len] = NULL;
8799
8800   return r;
8801 }
8802
8803 static PyObject *
8804 put_string_list (char * const * const argv)
8805 {
8806   PyObject *list;
8807   int argc, i;
8808
8809   for (argc = 0; argv[argc] != NULL; ++argc)
8810     ;
8811
8812   list = PyList_New (argc);
8813   for (i = 0; i < argc; ++i)
8814     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8815
8816   return list;
8817 }
8818
8819 static PyObject *
8820 put_table (char * const * const argv)
8821 {
8822   PyObject *list, *item;
8823   int argc, i;
8824
8825   for (argc = 0; argv[argc] != NULL; ++argc)
8826     ;
8827
8828   list = PyList_New (argc >> 1);
8829   for (i = 0; i < argc; i += 2) {
8830     item = PyTuple_New (2);
8831     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8832     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8833     PyList_SetItem (list, i >> 1, item);
8834   }
8835
8836   return list;
8837 }
8838
8839 static void
8840 free_strings (char **argv)
8841 {
8842   int argc;
8843
8844   for (argc = 0; argv[argc] != NULL; ++argc)
8845     free (argv[argc]);
8846   free (argv);
8847 }
8848
8849 static PyObject *
8850 py_guestfs_create (PyObject *self, PyObject *args)
8851 {
8852   guestfs_h *g;
8853
8854   g = guestfs_create ();
8855   if (g == NULL) {
8856     PyErr_SetString (PyExc_RuntimeError,
8857                      \"guestfs.create: failed to allocate handle\");
8858     return NULL;
8859   }
8860   guestfs_set_error_handler (g, NULL, NULL);
8861   return put_handle (g);
8862 }
8863
8864 static PyObject *
8865 py_guestfs_close (PyObject *self, PyObject *args)
8866 {
8867   PyObject *py_g;
8868   guestfs_h *g;
8869
8870   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8871     return NULL;
8872   g = get_handle (py_g);
8873
8874   guestfs_close (g);
8875
8876   Py_INCREF (Py_None);
8877   return Py_None;
8878 }
8879
8880 ";
8881
8882   let emit_put_list_function typ =
8883     pr "static PyObject *\n";
8884     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8885     pr "{\n";
8886     pr "  PyObject *list;\n";
8887     pr "  int i;\n";
8888     pr "\n";
8889     pr "  list = PyList_New (%ss->len);\n" typ;
8890     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8891     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8892     pr "  return list;\n";
8893     pr "};\n";
8894     pr "\n"
8895   in
8896
8897   (* Structures, turned into Python dictionaries. *)
8898   List.iter (
8899     fun (typ, cols) ->
8900       pr "static PyObject *\n";
8901       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8902       pr "{\n";
8903       pr "  PyObject *dict;\n";
8904       pr "\n";
8905       pr "  dict = PyDict_New ();\n";
8906       List.iter (
8907         function
8908         | name, FString ->
8909             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8910             pr "                        PyString_FromString (%s->%s));\n"
8911               typ name
8912         | name, FBuffer ->
8913             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8914             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8915               typ name typ name
8916         | name, FUUID ->
8917             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8918             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8919               typ name
8920         | name, (FBytes|FUInt64) ->
8921             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8922             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8923               typ name
8924         | name, FInt64 ->
8925             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8926             pr "                        PyLong_FromLongLong (%s->%s));\n"
8927               typ name
8928         | name, FUInt32 ->
8929             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8930             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8931               typ name
8932         | name, FInt32 ->
8933             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8934             pr "                        PyLong_FromLong (%s->%s));\n"
8935               typ name
8936         | name, FOptPercent ->
8937             pr "  if (%s->%s >= 0)\n" typ name;
8938             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8939             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8940               typ name;
8941             pr "  else {\n";
8942             pr "    Py_INCREF (Py_None);\n";
8943             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8944             pr "  }\n"
8945         | name, FChar ->
8946             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8947             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8948       ) cols;
8949       pr "  return dict;\n";
8950       pr "};\n";
8951       pr "\n";
8952
8953   ) structs;
8954
8955   (* Emit a put_TYPE_list function definition only if that function is used. *)
8956   List.iter (
8957     function
8958     | typ, (RStructListOnly | RStructAndList) ->
8959         (* generate the function for typ *)
8960         emit_put_list_function typ
8961     | typ, _ -> () (* empty *)
8962   ) (rstructs_used_by all_functions);
8963
8964   (* Python wrapper functions. *)
8965   List.iter (
8966     fun (name, style, _, _, _, _, _) ->
8967       pr "static PyObject *\n";
8968       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8969       pr "{\n";
8970
8971       pr "  PyObject *py_g;\n";
8972       pr "  guestfs_h *g;\n";
8973       pr "  PyObject *py_r;\n";
8974
8975       let error_code =
8976         match fst style with
8977         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8978         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8979         | RConstString _ | RConstOptString _ ->
8980             pr "  const char *r;\n"; "NULL"
8981         | RString _ -> pr "  char *r;\n"; "NULL"
8982         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8983         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8984         | RStructList (_, typ) ->
8985             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8986         | RBufferOut _ ->
8987             pr "  char *r;\n";
8988             pr "  size_t size;\n";
8989             "NULL" in
8990
8991       List.iter (
8992         function
8993         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8994             pr "  const char *%s;\n" n
8995         | OptString n -> pr "  const char *%s;\n" n
8996         | StringList n | DeviceList n ->
8997             pr "  PyObject *py_%s;\n" n;
8998             pr "  char **%s;\n" n
8999         | Bool n -> pr "  int %s;\n" n
9000         | Int n -> pr "  int %s;\n" n
9001         | Int64 n -> pr "  long long %s;\n" n
9002       ) (snd style);
9003
9004       pr "\n";
9005
9006       (* Convert the parameters. *)
9007       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9008       List.iter (
9009         function
9010         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9011         | OptString _ -> pr "z"
9012         | StringList _ | DeviceList _ -> pr "O"
9013         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9014         | Int _ -> pr "i"
9015         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9016                              * emulate C's int/long/long long in Python?
9017                              *)
9018       ) (snd style);
9019       pr ":guestfs_%s\",\n" name;
9020       pr "                         &py_g";
9021       List.iter (
9022         function
9023         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9024         | OptString n -> pr ", &%s" n
9025         | StringList n | DeviceList n -> pr ", &py_%s" n
9026         | Bool n -> pr ", &%s" n
9027         | Int n -> pr ", &%s" n
9028         | Int64 n -> pr ", &%s" n
9029       ) (snd style);
9030
9031       pr "))\n";
9032       pr "    return NULL;\n";
9033
9034       pr "  g = get_handle (py_g);\n";
9035       List.iter (
9036         function
9037         | Pathname _ | Device _ | Dev_or_Path _ | String _
9038         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9039         | StringList n | DeviceList n ->
9040             pr "  %s = get_string_list (py_%s);\n" n n;
9041             pr "  if (!%s) return NULL;\n" n
9042       ) (snd style);
9043
9044       pr "\n";
9045
9046       pr "  r = guestfs_%s " name;
9047       generate_c_call_args ~handle:"g" style;
9048       pr ";\n";
9049
9050       List.iter (
9051         function
9052         | Pathname _ | Device _ | Dev_or_Path _ | String _
9053         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9054         | StringList n | DeviceList n ->
9055             pr "  free (%s);\n" n
9056       ) (snd style);
9057
9058       pr "  if (r == %s) {\n" error_code;
9059       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9060       pr "    return NULL;\n";
9061       pr "  }\n";
9062       pr "\n";
9063
9064       (match fst style with
9065        | RErr ->
9066            pr "  Py_INCREF (Py_None);\n";
9067            pr "  py_r = Py_None;\n"
9068        | RInt _
9069        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9070        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9071        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9072        | RConstOptString _ ->
9073            pr "  if (r)\n";
9074            pr "    py_r = PyString_FromString (r);\n";
9075            pr "  else {\n";
9076            pr "    Py_INCREF (Py_None);\n";
9077            pr "    py_r = Py_None;\n";
9078            pr "  }\n"
9079        | RString _ ->
9080            pr "  py_r = PyString_FromString (r);\n";
9081            pr "  free (r);\n"
9082        | RStringList _ ->
9083            pr "  py_r = put_string_list (r);\n";
9084            pr "  free_strings (r);\n"
9085        | RStruct (_, typ) ->
9086            pr "  py_r = put_%s (r);\n" typ;
9087            pr "  guestfs_free_%s (r);\n" typ
9088        | RStructList (_, typ) ->
9089            pr "  py_r = put_%s_list (r);\n" typ;
9090            pr "  guestfs_free_%s_list (r);\n" typ
9091        | RHashtable n ->
9092            pr "  py_r = put_table (r);\n";
9093            pr "  free_strings (r);\n"
9094        | RBufferOut _ ->
9095            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9096            pr "  free (r);\n"
9097       );
9098
9099       pr "  return py_r;\n";
9100       pr "}\n";
9101       pr "\n"
9102   ) all_functions;
9103
9104   (* Table of functions. *)
9105   pr "static PyMethodDef methods[] = {\n";
9106   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9107   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9108   List.iter (
9109     fun (name, _, _, _, _, _, _) ->
9110       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9111         name name
9112   ) all_functions;
9113   pr "  { NULL, NULL, 0, NULL }\n";
9114   pr "};\n";
9115   pr "\n";
9116
9117   (* Init function. *)
9118   pr "\
9119 void
9120 initlibguestfsmod (void)
9121 {
9122   static int initialized = 0;
9123
9124   if (initialized) return;
9125   Py_InitModule ((char *) \"libguestfsmod\", methods);
9126   initialized = 1;
9127 }
9128 "
9129
9130 (* Generate Python module. *)
9131 and generate_python_py () =
9132   generate_header HashStyle LGPLv2plus;
9133
9134   pr "\
9135 u\"\"\"Python bindings for libguestfs
9136
9137 import guestfs
9138 g = guestfs.GuestFS ()
9139 g.add_drive (\"guest.img\")
9140 g.launch ()
9141 parts = g.list_partitions ()
9142
9143 The guestfs module provides a Python binding to the libguestfs API
9144 for examining and modifying virtual machine disk images.
9145
9146 Amongst the things this is good for: making batch configuration
9147 changes to guests, getting disk used/free statistics (see also:
9148 virt-df), migrating between virtualization systems (see also:
9149 virt-p2v), performing partial backups, performing partial guest
9150 clones, cloning guests and changing registry/UUID/hostname info, and
9151 much else besides.
9152
9153 Libguestfs uses Linux kernel and qemu code, and can access any type of
9154 guest filesystem that Linux and qemu can, including but not limited
9155 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9156 schemes, qcow, qcow2, vmdk.
9157
9158 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9159 LVs, what filesystem is in each LV, etc.).  It can also run commands
9160 in the context of the guest.  Also you can access filesystems over
9161 FUSE.
9162
9163 Errors which happen while using the API are turned into Python
9164 RuntimeError exceptions.
9165
9166 To create a guestfs handle you usually have to perform the following
9167 sequence of calls:
9168
9169 # Create the handle, call add_drive at least once, and possibly
9170 # several times if the guest has multiple block devices:
9171 g = guestfs.GuestFS ()
9172 g.add_drive (\"guest.img\")
9173
9174 # Launch the qemu subprocess and wait for it to become ready:
9175 g.launch ()
9176
9177 # Now you can issue commands, for example:
9178 logvols = g.lvs ()
9179
9180 \"\"\"
9181
9182 import libguestfsmod
9183
9184 class GuestFS:
9185     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9186
9187     def __init__ (self):
9188         \"\"\"Create a new libguestfs handle.\"\"\"
9189         self._o = libguestfsmod.create ()
9190
9191     def __del__ (self):
9192         libguestfsmod.close (self._o)
9193
9194 ";
9195
9196   List.iter (
9197     fun (name, style, _, flags, _, _, longdesc) ->
9198       pr "    def %s " name;
9199       generate_py_call_args ~handle:"self" (snd style);
9200       pr ":\n";
9201
9202       if not (List.mem NotInDocs flags) then (
9203         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9204         let doc =
9205           match fst style with
9206           | RErr | RInt _ | RInt64 _ | RBool _
9207           | RConstOptString _ | RConstString _
9208           | RString _ | RBufferOut _ -> doc
9209           | RStringList _ ->
9210               doc ^ "\n\nThis function returns a list of strings."
9211           | RStruct (_, typ) ->
9212               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9213           | RStructList (_, typ) ->
9214               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9215           | RHashtable _ ->
9216               doc ^ "\n\nThis function returns a dictionary." in
9217         let doc =
9218           if List.mem ProtocolLimitWarning flags then
9219             doc ^ "\n\n" ^ protocol_limit_warning
9220           else doc in
9221         let doc =
9222           if List.mem DangerWillRobinson flags then
9223             doc ^ "\n\n" ^ danger_will_robinson
9224           else doc in
9225         let doc =
9226           match deprecation_notice flags with
9227           | None -> doc
9228           | Some txt -> doc ^ "\n\n" ^ txt in
9229         let doc = pod2text ~width:60 name doc in
9230         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9231         let doc = String.concat "\n        " doc in
9232         pr "        u\"\"\"%s\"\"\"\n" doc;
9233       );
9234       pr "        return libguestfsmod.%s " name;
9235       generate_py_call_args ~handle:"self._o" (snd style);
9236       pr "\n";
9237       pr "\n";
9238   ) all_functions
9239
9240 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9241 and generate_py_call_args ~handle args =
9242   pr "(%s" handle;
9243   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9244   pr ")"
9245
9246 (* Useful if you need the longdesc POD text as plain text.  Returns a
9247  * list of lines.
9248  *
9249  * Because this is very slow (the slowest part of autogeneration),
9250  * we memoize the results.
9251  *)
9252 and pod2text ~width name longdesc =
9253   let key = width, name, longdesc in
9254   try Hashtbl.find pod2text_memo key
9255   with Not_found ->
9256     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9257     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9258     close_out chan;
9259     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9260     let chan = open_process_in cmd in
9261     let lines = ref [] in
9262     let rec loop i =
9263       let line = input_line chan in
9264       if i = 1 then             (* discard the first line of output *)
9265         loop (i+1)
9266       else (
9267         let line = triml line in
9268         lines := line :: !lines;
9269         loop (i+1)
9270       ) in
9271     let lines = try loop 1 with End_of_file -> List.rev !lines in
9272     unlink filename;
9273     (match close_process_in chan with
9274      | WEXITED 0 -> ()
9275      | WEXITED i ->
9276          failwithf "pod2text: process exited with non-zero status (%d)" i
9277      | WSIGNALED i | WSTOPPED i ->
9278          failwithf "pod2text: process signalled or stopped by signal %d" i
9279     );
9280     Hashtbl.add pod2text_memo key lines;
9281     pod2text_memo_updated ();
9282     lines
9283
9284 (* Generate ruby bindings. *)
9285 and generate_ruby_c () =
9286   generate_header CStyle LGPLv2plus;
9287
9288   pr "\
9289 #include <stdio.h>
9290 #include <stdlib.h>
9291
9292 #include <ruby.h>
9293
9294 #include \"guestfs.h\"
9295
9296 #include \"extconf.h\"
9297
9298 /* For Ruby < 1.9 */
9299 #ifndef RARRAY_LEN
9300 #define RARRAY_LEN(r) (RARRAY((r))->len)
9301 #endif
9302
9303 static VALUE m_guestfs;                 /* guestfs module */
9304 static VALUE c_guestfs;                 /* guestfs_h handle */
9305 static VALUE e_Error;                   /* used for all errors */
9306
9307 static void ruby_guestfs_free (void *p)
9308 {
9309   if (!p) return;
9310   guestfs_close ((guestfs_h *) p);
9311 }
9312
9313 static VALUE ruby_guestfs_create (VALUE m)
9314 {
9315   guestfs_h *g;
9316
9317   g = guestfs_create ();
9318   if (!g)
9319     rb_raise (e_Error, \"failed to create guestfs handle\");
9320
9321   /* Don't print error messages to stderr by default. */
9322   guestfs_set_error_handler (g, NULL, NULL);
9323
9324   /* Wrap it, and make sure the close function is called when the
9325    * handle goes away.
9326    */
9327   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9328 }
9329
9330 static VALUE ruby_guestfs_close (VALUE gv)
9331 {
9332   guestfs_h *g;
9333   Data_Get_Struct (gv, guestfs_h, g);
9334
9335   ruby_guestfs_free (g);
9336   DATA_PTR (gv) = NULL;
9337
9338   return Qnil;
9339 }
9340
9341 ";
9342
9343   List.iter (
9344     fun (name, style, _, _, _, _, _) ->
9345       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9346       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9347       pr ")\n";
9348       pr "{\n";
9349       pr "  guestfs_h *g;\n";
9350       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9351       pr "  if (!g)\n";
9352       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9353         name;
9354       pr "\n";
9355
9356       List.iter (
9357         function
9358         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9359             pr "  Check_Type (%sv, T_STRING);\n" n;
9360             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9361             pr "  if (!%s)\n" n;
9362             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9363             pr "              \"%s\", \"%s\");\n" n name
9364         | OptString n ->
9365             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9366         | StringList n | DeviceList n ->
9367             pr "  char **%s;\n" n;
9368             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9369             pr "  {\n";
9370             pr "    int i, len;\n";
9371             pr "    len = RARRAY_LEN (%sv);\n" n;
9372             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9373               n;
9374             pr "    for (i = 0; i < len; ++i) {\n";
9375             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9376             pr "      %s[i] = StringValueCStr (v);\n" n;
9377             pr "    }\n";
9378             pr "    %s[len] = NULL;\n" n;
9379             pr "  }\n";
9380         | Bool n ->
9381             pr "  int %s = RTEST (%sv);\n" n n
9382         | Int n ->
9383             pr "  int %s = NUM2INT (%sv);\n" n n
9384         | Int64 n ->
9385             pr "  long long %s = NUM2LL (%sv);\n" n n
9386       ) (snd style);
9387       pr "\n";
9388
9389       let error_code =
9390         match fst style with
9391         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9392         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9393         | RConstString _ | RConstOptString _ ->
9394             pr "  const char *r;\n"; "NULL"
9395         | RString _ -> pr "  char *r;\n"; "NULL"
9396         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9397         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9398         | RStructList (_, typ) ->
9399             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9400         | RBufferOut _ ->
9401             pr "  char *r;\n";
9402             pr "  size_t size;\n";
9403             "NULL" in
9404       pr "\n";
9405
9406       pr "  r = guestfs_%s " name;
9407       generate_c_call_args ~handle:"g" style;
9408       pr ";\n";
9409
9410       List.iter (
9411         function
9412         | Pathname _ | Device _ | Dev_or_Path _ | String _
9413         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9414         | StringList n | DeviceList n ->
9415             pr "  free (%s);\n" n
9416       ) (snd style);
9417
9418       pr "  if (r == %s)\n" error_code;
9419       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9420       pr "\n";
9421
9422       (match fst style with
9423        | RErr ->
9424            pr "  return Qnil;\n"
9425        | RInt _ | RBool _ ->
9426            pr "  return INT2NUM (r);\n"
9427        | RInt64 _ ->
9428            pr "  return ULL2NUM (r);\n"
9429        | RConstString _ ->
9430            pr "  return rb_str_new2 (r);\n";
9431        | RConstOptString _ ->
9432            pr "  if (r)\n";
9433            pr "    return rb_str_new2 (r);\n";
9434            pr "  else\n";
9435            pr "    return Qnil;\n";
9436        | RString _ ->
9437            pr "  VALUE rv = rb_str_new2 (r);\n";
9438            pr "  free (r);\n";
9439            pr "  return rv;\n";
9440        | RStringList _ ->
9441            pr "  int i, len = 0;\n";
9442            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9443            pr "  VALUE rv = rb_ary_new2 (len);\n";
9444            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9445            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9446            pr "    free (r[i]);\n";
9447            pr "  }\n";
9448            pr "  free (r);\n";
9449            pr "  return rv;\n"
9450        | RStruct (_, typ) ->
9451            let cols = cols_of_struct typ in
9452            generate_ruby_struct_code typ cols
9453        | RStructList (_, typ) ->
9454            let cols = cols_of_struct typ in
9455            generate_ruby_struct_list_code typ cols
9456        | RHashtable _ ->
9457            pr "  VALUE rv = rb_hash_new ();\n";
9458            pr "  int i;\n";
9459            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9460            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9461            pr "    free (r[i]);\n";
9462            pr "    free (r[i+1]);\n";
9463            pr "  }\n";
9464            pr "  free (r);\n";
9465            pr "  return rv;\n"
9466        | RBufferOut _ ->
9467            pr "  VALUE rv = rb_str_new (r, size);\n";
9468            pr "  free (r);\n";
9469            pr "  return rv;\n";
9470       );
9471
9472       pr "}\n";
9473       pr "\n"
9474   ) all_functions;
9475
9476   pr "\
9477 /* Initialize the module. */
9478 void Init__guestfs ()
9479 {
9480   m_guestfs = rb_define_module (\"Guestfs\");
9481   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9482   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9483
9484   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9485   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9486
9487 ";
9488   (* Define the rest of the methods. *)
9489   List.iter (
9490     fun (name, style, _, _, _, _, _) ->
9491       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9492       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9493   ) all_functions;
9494
9495   pr "}\n"
9496
9497 (* Ruby code to return a struct. *)
9498 and generate_ruby_struct_code typ cols =
9499   pr "  VALUE rv = rb_hash_new ();\n";
9500   List.iter (
9501     function
9502     | name, FString ->
9503         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9504     | name, FBuffer ->
9505         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9506     | name, FUUID ->
9507         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9508     | name, (FBytes|FUInt64) ->
9509         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9510     | name, FInt64 ->
9511         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9512     | name, FUInt32 ->
9513         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9514     | name, FInt32 ->
9515         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9516     | name, FOptPercent ->
9517         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9518     | name, FChar -> (* XXX wrong? *)
9519         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9520   ) cols;
9521   pr "  guestfs_free_%s (r);\n" typ;
9522   pr "  return rv;\n"
9523
9524 (* Ruby code to return a struct list. *)
9525 and generate_ruby_struct_list_code typ cols =
9526   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9527   pr "  int i;\n";
9528   pr "  for (i = 0; i < r->len; ++i) {\n";
9529   pr "    VALUE hv = rb_hash_new ();\n";
9530   List.iter (
9531     function
9532     | name, FString ->
9533         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9534     | name, FBuffer ->
9535         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
9536     | name, FUUID ->
9537         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9538     | name, (FBytes|FUInt64) ->
9539         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9540     | name, FInt64 ->
9541         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9542     | name, FUInt32 ->
9543         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9544     | name, FInt32 ->
9545         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9546     | name, FOptPercent ->
9547         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9548     | name, FChar -> (* XXX wrong? *)
9549         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9550   ) cols;
9551   pr "    rb_ary_push (rv, hv);\n";
9552   pr "  }\n";
9553   pr "  guestfs_free_%s_list (r);\n" typ;
9554   pr "  return rv;\n"
9555
9556 (* Generate Java bindings GuestFS.java file. *)
9557 and generate_java_java () =
9558   generate_header CStyle LGPLv2plus;
9559
9560   pr "\
9561 package com.redhat.et.libguestfs;
9562
9563 import java.util.HashMap;
9564 import com.redhat.et.libguestfs.LibGuestFSException;
9565 import com.redhat.et.libguestfs.PV;
9566 import com.redhat.et.libguestfs.VG;
9567 import com.redhat.et.libguestfs.LV;
9568 import com.redhat.et.libguestfs.Stat;
9569 import com.redhat.et.libguestfs.StatVFS;
9570 import com.redhat.et.libguestfs.IntBool;
9571 import com.redhat.et.libguestfs.Dirent;
9572
9573 /**
9574  * The GuestFS object is a libguestfs handle.
9575  *
9576  * @author rjones
9577  */
9578 public class GuestFS {
9579   // Load the native code.
9580   static {
9581     System.loadLibrary (\"guestfs_jni\");
9582   }
9583
9584   /**
9585    * The native guestfs_h pointer.
9586    */
9587   long g;
9588
9589   /**
9590    * Create a libguestfs handle.
9591    *
9592    * @throws LibGuestFSException
9593    */
9594   public GuestFS () throws LibGuestFSException
9595   {
9596     g = _create ();
9597   }
9598   private native long _create () throws LibGuestFSException;
9599
9600   /**
9601    * Close a libguestfs handle.
9602    *
9603    * You can also leave handles to be collected by the garbage
9604    * collector, but this method ensures that the resources used
9605    * by the handle are freed up immediately.  If you call any
9606    * other methods after closing the handle, you will get an
9607    * exception.
9608    *
9609    * @throws LibGuestFSException
9610    */
9611   public void close () throws LibGuestFSException
9612   {
9613     if (g != 0)
9614       _close (g);
9615     g = 0;
9616   }
9617   private native void _close (long g) throws LibGuestFSException;
9618
9619   public void finalize () throws LibGuestFSException
9620   {
9621     close ();
9622   }
9623
9624 ";
9625
9626   List.iter (
9627     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9628       if not (List.mem NotInDocs flags); then (
9629         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9630         let doc =
9631           if List.mem ProtocolLimitWarning flags then
9632             doc ^ "\n\n" ^ protocol_limit_warning
9633           else doc in
9634         let doc =
9635           if List.mem DangerWillRobinson flags then
9636             doc ^ "\n\n" ^ danger_will_robinson
9637           else doc in
9638         let doc =
9639           match deprecation_notice flags with
9640           | None -> doc
9641           | Some txt -> doc ^ "\n\n" ^ txt in
9642         let doc = pod2text ~width:60 name doc in
9643         let doc = List.map (            (* RHBZ#501883 *)
9644           function
9645           | "" -> "<p>"
9646           | nonempty -> nonempty
9647         ) doc in
9648         let doc = String.concat "\n   * " doc in
9649
9650         pr "  /**\n";
9651         pr "   * %s\n" shortdesc;
9652         pr "   * <p>\n";
9653         pr "   * %s\n" doc;
9654         pr "   * @throws LibGuestFSException\n";
9655         pr "   */\n";
9656         pr "  ";
9657       );
9658       generate_java_prototype ~public:true ~semicolon:false name style;
9659       pr "\n";
9660       pr "  {\n";
9661       pr "    if (g == 0)\n";
9662       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9663         name;
9664       pr "    ";
9665       if fst style <> RErr then pr "return ";
9666       pr "_%s " name;
9667       generate_java_call_args ~handle:"g" (snd style);
9668       pr ";\n";
9669       pr "  }\n";
9670       pr "  ";
9671       generate_java_prototype ~privat:true ~native:true name style;
9672       pr "\n";
9673       pr "\n";
9674   ) all_functions;
9675
9676   pr "}\n"
9677
9678 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9679 and generate_java_call_args ~handle args =
9680   pr "(%s" handle;
9681   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9682   pr ")"
9683
9684 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9685     ?(semicolon=true) name style =
9686   if privat then pr "private ";
9687   if public then pr "public ";
9688   if native then pr "native ";
9689
9690   (* return type *)
9691   (match fst style with
9692    | RErr -> pr "void ";
9693    | RInt _ -> pr "int ";
9694    | RInt64 _ -> pr "long ";
9695    | RBool _ -> pr "boolean ";
9696    | RConstString _ | RConstOptString _ | RString _
9697    | RBufferOut _ -> pr "String ";
9698    | RStringList _ -> pr "String[] ";
9699    | RStruct (_, typ) ->
9700        let name = java_name_of_struct typ in
9701        pr "%s " name;
9702    | RStructList (_, typ) ->
9703        let name = java_name_of_struct typ in
9704        pr "%s[] " name;
9705    | RHashtable _ -> pr "HashMap<String,String> ";
9706   );
9707
9708   if native then pr "_%s " name else pr "%s " name;
9709   pr "(";
9710   let needs_comma = ref false in
9711   if native then (
9712     pr "long g";
9713     needs_comma := true
9714   );
9715
9716   (* args *)
9717   List.iter (
9718     fun arg ->
9719       if !needs_comma then pr ", ";
9720       needs_comma := true;
9721
9722       match arg with
9723       | Pathname n
9724       | Device n | Dev_or_Path n
9725       | String n
9726       | OptString n
9727       | FileIn n
9728       | FileOut n ->
9729           pr "String %s" n
9730       | StringList n | DeviceList n ->
9731           pr "String[] %s" n
9732       | Bool n ->
9733           pr "boolean %s" n
9734       | Int n ->
9735           pr "int %s" n
9736       | Int64 n ->
9737           pr "long %s" n
9738   ) (snd style);
9739
9740   pr ")\n";
9741   pr "    throws LibGuestFSException";
9742   if semicolon then pr ";"
9743
9744 and generate_java_struct jtyp cols () =
9745   generate_header CStyle LGPLv2plus;
9746
9747   pr "\
9748 package com.redhat.et.libguestfs;
9749
9750 /**
9751  * Libguestfs %s structure.
9752  *
9753  * @author rjones
9754  * @see GuestFS
9755  */
9756 public class %s {
9757 " jtyp jtyp;
9758
9759   List.iter (
9760     function
9761     | name, FString
9762     | name, FUUID
9763     | name, FBuffer -> pr "  public String %s;\n" name
9764     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9765     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9766     | name, FChar -> pr "  public char %s;\n" name
9767     | name, FOptPercent ->
9768         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9769         pr "  public float %s;\n" name
9770   ) cols;
9771
9772   pr "}\n"
9773
9774 and generate_java_c () =
9775   generate_header CStyle LGPLv2plus;
9776
9777   pr "\
9778 #include <stdio.h>
9779 #include <stdlib.h>
9780 #include <string.h>
9781
9782 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9783 #include \"guestfs.h\"
9784
9785 /* Note that this function returns.  The exception is not thrown
9786  * until after the wrapper function returns.
9787  */
9788 static void
9789 throw_exception (JNIEnv *env, const char *msg)
9790 {
9791   jclass cl;
9792   cl = (*env)->FindClass (env,
9793                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9794   (*env)->ThrowNew (env, cl, msg);
9795 }
9796
9797 JNIEXPORT jlong JNICALL
9798 Java_com_redhat_et_libguestfs_GuestFS__1create
9799   (JNIEnv *env, jobject obj)
9800 {
9801   guestfs_h *g;
9802
9803   g = guestfs_create ();
9804   if (g == NULL) {
9805     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9806     return 0;
9807   }
9808   guestfs_set_error_handler (g, NULL, NULL);
9809   return (jlong) (long) g;
9810 }
9811
9812 JNIEXPORT void JNICALL
9813 Java_com_redhat_et_libguestfs_GuestFS__1close
9814   (JNIEnv *env, jobject obj, jlong jg)
9815 {
9816   guestfs_h *g = (guestfs_h *) (long) jg;
9817   guestfs_close (g);
9818 }
9819
9820 ";
9821
9822   List.iter (
9823     fun (name, style, _, _, _, _, _) ->
9824       pr "JNIEXPORT ";
9825       (match fst style with
9826        | RErr -> pr "void ";
9827        | RInt _ -> pr "jint ";
9828        | RInt64 _ -> pr "jlong ";
9829        | RBool _ -> pr "jboolean ";
9830        | RConstString _ | RConstOptString _ | RString _
9831        | RBufferOut _ -> pr "jstring ";
9832        | RStruct _ | RHashtable _ ->
9833            pr "jobject ";
9834        | RStringList _ | RStructList _ ->
9835            pr "jobjectArray ";
9836       );
9837       pr "JNICALL\n";
9838       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9839       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9840       pr "\n";
9841       pr "  (JNIEnv *env, jobject obj, jlong jg";
9842       List.iter (
9843         function
9844         | Pathname n
9845         | Device n | Dev_or_Path n
9846         | String n
9847         | OptString n
9848         | FileIn n
9849         | FileOut n ->
9850             pr ", jstring j%s" n
9851         | StringList n | DeviceList n ->
9852             pr ", jobjectArray j%s" n
9853         | Bool n ->
9854             pr ", jboolean j%s" n
9855         | Int n ->
9856             pr ", jint j%s" n
9857         | Int64 n ->
9858             pr ", jlong j%s" n
9859       ) (snd style);
9860       pr ")\n";
9861       pr "{\n";
9862       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9863       let error_code, no_ret =
9864         match fst style with
9865         | RErr -> pr "  int r;\n"; "-1", ""
9866         | RBool _
9867         | RInt _ -> pr "  int r;\n"; "-1", "0"
9868         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9869         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9870         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9871         | RString _ ->
9872             pr "  jstring jr;\n";
9873             pr "  char *r;\n"; "NULL", "NULL"
9874         | RStringList _ ->
9875             pr "  jobjectArray jr;\n";
9876             pr "  int r_len;\n";
9877             pr "  jclass cl;\n";
9878             pr "  jstring jstr;\n";
9879             pr "  char **r;\n"; "NULL", "NULL"
9880         | RStruct (_, typ) ->
9881             pr "  jobject jr;\n";
9882             pr "  jclass cl;\n";
9883             pr "  jfieldID fl;\n";
9884             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9885         | RStructList (_, typ) ->
9886             pr "  jobjectArray jr;\n";
9887             pr "  jclass cl;\n";
9888             pr "  jfieldID fl;\n";
9889             pr "  jobject jfl;\n";
9890             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9891         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9892         | RBufferOut _ ->
9893             pr "  jstring jr;\n";
9894             pr "  char *r;\n";
9895             pr "  size_t size;\n";
9896             "NULL", "NULL" in
9897       List.iter (
9898         function
9899         | Pathname n
9900         | Device n | Dev_or_Path n
9901         | String n
9902         | OptString n
9903         | FileIn n
9904         | FileOut n ->
9905             pr "  const char *%s;\n" n
9906         | StringList n | DeviceList n ->
9907             pr "  int %s_len;\n" n;
9908             pr "  const char **%s;\n" n
9909         | Bool n
9910         | Int n ->
9911             pr "  int %s;\n" n
9912         | Int64 n ->
9913             pr "  int64_t %s;\n" n
9914       ) (snd style);
9915
9916       let needs_i =
9917         (match fst style with
9918          | RStringList _ | RStructList _ -> true
9919          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9920          | RConstOptString _
9921          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9922           List.exists (function
9923                        | StringList _ -> true
9924                        | DeviceList _ -> true
9925                        | _ -> false) (snd style) in
9926       if needs_i then
9927         pr "  int i;\n";
9928
9929       pr "\n";
9930
9931       (* Get the parameters. *)
9932       List.iter (
9933         function
9934         | Pathname n
9935         | Device n | Dev_or_Path n
9936         | String n
9937         | FileIn n
9938         | FileOut n ->
9939             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9940         | OptString n ->
9941             (* This is completely undocumented, but Java null becomes
9942              * a NULL parameter.
9943              *)
9944             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9945         | StringList n | DeviceList n ->
9946             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9947             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9948             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9949             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9950               n;
9951             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9952             pr "  }\n";
9953             pr "  %s[%s_len] = NULL;\n" n n;
9954         | Bool n
9955         | Int n
9956         | Int64 n ->
9957             pr "  %s = j%s;\n" n n
9958       ) (snd style);
9959
9960       (* Make the call. *)
9961       pr "  r = guestfs_%s " name;
9962       generate_c_call_args ~handle:"g" style;
9963       pr ";\n";
9964
9965       (* Release the parameters. *)
9966       List.iter (
9967         function
9968         | Pathname n
9969         | Device n | Dev_or_Path n
9970         | String n
9971         | FileIn n
9972         | FileOut n ->
9973             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9974         | OptString n ->
9975             pr "  if (j%s)\n" n;
9976             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9977         | StringList n | DeviceList n ->
9978             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9979             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9980               n;
9981             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9982             pr "  }\n";
9983             pr "  free (%s);\n" n
9984         | Bool n
9985         | Int n
9986         | Int64 n -> ()
9987       ) (snd style);
9988
9989       (* Check for errors. *)
9990       pr "  if (r == %s) {\n" error_code;
9991       pr "    throw_exception (env, guestfs_last_error (g));\n";
9992       pr "    return %s;\n" no_ret;
9993       pr "  }\n";
9994
9995       (* Return value. *)
9996       (match fst style with
9997        | RErr -> ()
9998        | RInt _ -> pr "  return (jint) r;\n"
9999        | RBool _ -> pr "  return (jboolean) r;\n"
10000        | RInt64 _ -> pr "  return (jlong) r;\n"
10001        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10002        | RConstOptString _ ->
10003            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10004        | RString _ ->
10005            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10006            pr "  free (r);\n";
10007            pr "  return jr;\n"
10008        | RStringList _ ->
10009            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10010            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10011            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10012            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10013            pr "  for (i = 0; i < r_len; ++i) {\n";
10014            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10015            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10016            pr "    free (r[i]);\n";
10017            pr "  }\n";
10018            pr "  free (r);\n";
10019            pr "  return jr;\n"
10020        | RStruct (_, typ) ->
10021            let jtyp = java_name_of_struct typ in
10022            let cols = cols_of_struct typ in
10023            generate_java_struct_return typ jtyp cols
10024        | RStructList (_, typ) ->
10025            let jtyp = java_name_of_struct typ in
10026            let cols = cols_of_struct typ in
10027            generate_java_struct_list_return typ jtyp cols
10028        | RHashtable _ ->
10029            (* XXX *)
10030            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10031            pr "  return NULL;\n"
10032        | RBufferOut _ ->
10033            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10034            pr "  free (r);\n";
10035            pr "  return jr;\n"
10036       );
10037
10038       pr "}\n";
10039       pr "\n"
10040   ) all_functions
10041
10042 and generate_java_struct_return typ jtyp cols =
10043   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10044   pr "  jr = (*env)->AllocObject (env, cl);\n";
10045   List.iter (
10046     function
10047     | name, FString ->
10048         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10049         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10050     | name, FUUID ->
10051         pr "  {\n";
10052         pr "    char s[33];\n";
10053         pr "    memcpy (s, r->%s, 32);\n" name;
10054         pr "    s[32] = 0;\n";
10055         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10056         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10057         pr "  }\n";
10058     | name, FBuffer ->
10059         pr "  {\n";
10060         pr "    int len = r->%s_len;\n" name;
10061         pr "    char s[len+1];\n";
10062         pr "    memcpy (s, r->%s, len);\n" name;
10063         pr "    s[len] = 0;\n";
10064         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10065         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10066         pr "  }\n";
10067     | name, (FBytes|FUInt64|FInt64) ->
10068         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10069         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10070     | name, (FUInt32|FInt32) ->
10071         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10072         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10073     | name, FOptPercent ->
10074         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10075         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10076     | name, FChar ->
10077         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10078         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10079   ) cols;
10080   pr "  free (r);\n";
10081   pr "  return jr;\n"
10082
10083 and generate_java_struct_list_return typ jtyp cols =
10084   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10085   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10086   pr "  for (i = 0; i < r->len; ++i) {\n";
10087   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10088   List.iter (
10089     function
10090     | name, FString ->
10091         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10092         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10093     | name, FUUID ->
10094         pr "    {\n";
10095         pr "      char s[33];\n";
10096         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10097         pr "      s[32] = 0;\n";
10098         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10099         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10100         pr "    }\n";
10101     | name, FBuffer ->
10102         pr "    {\n";
10103         pr "      int len = r->val[i].%s_len;\n" name;
10104         pr "      char s[len+1];\n";
10105         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10106         pr "      s[len] = 0;\n";
10107         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10108         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10109         pr "    }\n";
10110     | name, (FBytes|FUInt64|FInt64) ->
10111         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10112         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10113     | name, (FUInt32|FInt32) ->
10114         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10115         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10116     | name, FOptPercent ->
10117         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10118         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10119     | name, FChar ->
10120         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10121         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10122   ) cols;
10123   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10124   pr "  }\n";
10125   pr "  guestfs_free_%s_list (r);\n" typ;
10126   pr "  return jr;\n"
10127
10128 and generate_java_makefile_inc () =
10129   generate_header HashStyle GPLv2plus;
10130
10131   pr "java_built_sources = \\\n";
10132   List.iter (
10133     fun (typ, jtyp) ->
10134         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10135   ) java_structs;
10136   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10137
10138 and generate_haskell_hs () =
10139   generate_header HaskellStyle LGPLv2plus;
10140
10141   (* XXX We only know how to generate partial FFI for Haskell
10142    * at the moment.  Please help out!
10143    *)
10144   let can_generate style =
10145     match style with
10146     | RErr, _
10147     | RInt _, _
10148     | RInt64 _, _ -> true
10149     | RBool _, _
10150     | RConstString _, _
10151     | RConstOptString _, _
10152     | RString _, _
10153     | RStringList _, _
10154     | RStruct _, _
10155     | RStructList _, _
10156     | RHashtable _, _
10157     | RBufferOut _, _ -> false in
10158
10159   pr "\
10160 {-# INCLUDE <guestfs.h> #-}
10161 {-# LANGUAGE ForeignFunctionInterface #-}
10162
10163 module Guestfs (
10164   create";
10165
10166   (* List out the names of the actions we want to export. *)
10167   List.iter (
10168     fun (name, style, _, _, _, _, _) ->
10169       if can_generate style then pr ",\n  %s" name
10170   ) all_functions;
10171
10172   pr "
10173   ) where
10174
10175 -- Unfortunately some symbols duplicate ones already present
10176 -- in Prelude.  We don't know which, so we hard-code a list
10177 -- here.
10178 import Prelude hiding (truncate)
10179
10180 import Foreign
10181 import Foreign.C
10182 import Foreign.C.Types
10183 import IO
10184 import Control.Exception
10185 import Data.Typeable
10186
10187 data GuestfsS = GuestfsS            -- represents the opaque C struct
10188 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10189 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10190
10191 -- XXX define properly later XXX
10192 data PV = PV
10193 data VG = VG
10194 data LV = LV
10195 data IntBool = IntBool
10196 data Stat = Stat
10197 data StatVFS = StatVFS
10198 data Hashtable = Hashtable
10199
10200 foreign import ccall unsafe \"guestfs_create\" c_create
10201   :: IO GuestfsP
10202 foreign import ccall unsafe \"&guestfs_close\" c_close
10203   :: FunPtr (GuestfsP -> IO ())
10204 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10205   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10206
10207 create :: IO GuestfsH
10208 create = do
10209   p <- c_create
10210   c_set_error_handler p nullPtr nullPtr
10211   h <- newForeignPtr c_close p
10212   return h
10213
10214 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10215   :: GuestfsP -> IO CString
10216
10217 -- last_error :: GuestfsH -> IO (Maybe String)
10218 -- last_error h = do
10219 --   str <- withForeignPtr h (\\p -> c_last_error p)
10220 --   maybePeek peekCString str
10221
10222 last_error :: GuestfsH -> IO (String)
10223 last_error h = do
10224   str <- withForeignPtr h (\\p -> c_last_error p)
10225   if (str == nullPtr)
10226     then return \"no error\"
10227     else peekCString str
10228
10229 ";
10230
10231   (* Generate wrappers for each foreign function. *)
10232   List.iter (
10233     fun (name, style, _, _, _, _, _) ->
10234       if can_generate style then (
10235         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10236         pr "  :: ";
10237         generate_haskell_prototype ~handle:"GuestfsP" style;
10238         pr "\n";
10239         pr "\n";
10240         pr "%s :: " name;
10241         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10242         pr "\n";
10243         pr "%s %s = do\n" name
10244           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10245         pr "  r <- ";
10246         (* Convert pointer arguments using with* functions. *)
10247         List.iter (
10248           function
10249           | FileIn n
10250           | FileOut n
10251           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10252           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10253           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10254           | Bool _ | Int _ | Int64 _ -> ()
10255         ) (snd style);
10256         (* Convert integer arguments. *)
10257         let args =
10258           List.map (
10259             function
10260             | Bool n -> sprintf "(fromBool %s)" n
10261             | Int n -> sprintf "(fromIntegral %s)" n
10262             | Int64 n -> sprintf "(fromIntegral %s)" n
10263             | FileIn n | FileOut n
10264             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10265           ) (snd style) in
10266         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10267           (String.concat " " ("p" :: args));
10268         (match fst style with
10269          | RErr | RInt _ | RInt64 _ | RBool _ ->
10270              pr "  if (r == -1)\n";
10271              pr "    then do\n";
10272              pr "      err <- last_error h\n";
10273              pr "      fail err\n";
10274          | RConstString _ | RConstOptString _ | RString _
10275          | RStringList _ | RStruct _
10276          | RStructList _ | RHashtable _ | RBufferOut _ ->
10277              pr "  if (r == nullPtr)\n";
10278              pr "    then do\n";
10279              pr "      err <- last_error h\n";
10280              pr "      fail err\n";
10281         );
10282         (match fst style with
10283          | RErr ->
10284              pr "    else return ()\n"
10285          | RInt _ ->
10286              pr "    else return (fromIntegral r)\n"
10287          | RInt64 _ ->
10288              pr "    else return (fromIntegral r)\n"
10289          | RBool _ ->
10290              pr "    else return (toBool r)\n"
10291          | RConstString _
10292          | RConstOptString _
10293          | RString _
10294          | RStringList _
10295          | RStruct _
10296          | RStructList _
10297          | RHashtable _
10298          | RBufferOut _ ->
10299              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10300         );
10301         pr "\n";
10302       )
10303   ) all_functions
10304
10305 and generate_haskell_prototype ~handle ?(hs = false) style =
10306   pr "%s -> " handle;
10307   let string = if hs then "String" else "CString" in
10308   let int = if hs then "Int" else "CInt" in
10309   let bool = if hs then "Bool" else "CInt" in
10310   let int64 = if hs then "Integer" else "Int64" in
10311   List.iter (
10312     fun arg ->
10313       (match arg with
10314        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10315        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10316        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10317        | Bool _ -> pr "%s" bool
10318        | Int _ -> pr "%s" int
10319        | Int64 _ -> pr "%s" int
10320        | FileIn _ -> pr "%s" string
10321        | FileOut _ -> pr "%s" string
10322       );
10323       pr " -> ";
10324   ) (snd style);
10325   pr "IO (";
10326   (match fst style with
10327    | RErr -> if not hs then pr "CInt"
10328    | RInt _ -> pr "%s" int
10329    | RInt64 _ -> pr "%s" int64
10330    | RBool _ -> pr "%s" bool
10331    | RConstString _ -> pr "%s" string
10332    | RConstOptString _ -> pr "Maybe %s" string
10333    | RString _ -> pr "%s" string
10334    | RStringList _ -> pr "[%s]" string
10335    | RStruct (_, typ) ->
10336        let name = java_name_of_struct typ in
10337        pr "%s" name
10338    | RStructList (_, typ) ->
10339        let name = java_name_of_struct typ in
10340        pr "[%s]" name
10341    | RHashtable _ -> pr "Hashtable"
10342    | RBufferOut _ -> pr "%s" string
10343   );
10344   pr ")"
10345
10346 and generate_csharp () =
10347   generate_header CPlusPlusStyle LGPLv2plus;
10348
10349   (* XXX Make this configurable by the C# assembly users. *)
10350   let library = "libguestfs.so.0" in
10351
10352   pr "\
10353 // These C# bindings are highly experimental at present.
10354 //
10355 // Firstly they only work on Linux (ie. Mono).  In order to get them
10356 // to work on Windows (ie. .Net) you would need to port the library
10357 // itself to Windows first.
10358 //
10359 // The second issue is that some calls are known to be incorrect and
10360 // can cause Mono to segfault.  Particularly: calls which pass or
10361 // return string[], or return any structure value.  This is because
10362 // we haven't worked out the correct way to do this from C#.
10363 //
10364 // The third issue is that when compiling you get a lot of warnings.
10365 // We are not sure whether the warnings are important or not.
10366 //
10367 // Fourthly we do not routinely build or test these bindings as part
10368 // of the make && make check cycle, which means that regressions might
10369 // go unnoticed.
10370 //
10371 // Suggestions and patches are welcome.
10372
10373 // To compile:
10374 //
10375 // gmcs Libguestfs.cs
10376 // mono Libguestfs.exe
10377 //
10378 // (You'll probably want to add a Test class / static main function
10379 // otherwise this won't do anything useful).
10380
10381 using System;
10382 using System.IO;
10383 using System.Runtime.InteropServices;
10384 using System.Runtime.Serialization;
10385 using System.Collections;
10386
10387 namespace Guestfs
10388 {
10389   class Error : System.ApplicationException
10390   {
10391     public Error (string message) : base (message) {}
10392     protected Error (SerializationInfo info, StreamingContext context) {}
10393   }
10394
10395   class Guestfs
10396   {
10397     IntPtr _handle;
10398
10399     [DllImport (\"%s\")]
10400     static extern IntPtr guestfs_create ();
10401
10402     public Guestfs ()
10403     {
10404       _handle = guestfs_create ();
10405       if (_handle == IntPtr.Zero)
10406         throw new Error (\"could not create guestfs handle\");
10407     }
10408
10409     [DllImport (\"%s\")]
10410     static extern void guestfs_close (IntPtr h);
10411
10412     ~Guestfs ()
10413     {
10414       guestfs_close (_handle);
10415     }
10416
10417     [DllImport (\"%s\")]
10418     static extern string guestfs_last_error (IntPtr h);
10419
10420 " library library library;
10421
10422   (* Generate C# structure bindings.  We prefix struct names with
10423    * underscore because C# cannot have conflicting struct names and
10424    * method names (eg. "class stat" and "stat").
10425    *)
10426   List.iter (
10427     fun (typ, cols) ->
10428       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10429       pr "    public class _%s {\n" typ;
10430       List.iter (
10431         function
10432         | name, FChar -> pr "      char %s;\n" name
10433         | name, FString -> pr "      string %s;\n" name
10434         | name, FBuffer ->
10435             pr "      uint %s_len;\n" name;
10436             pr "      string %s;\n" name
10437         | name, FUUID ->
10438             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10439             pr "      string %s;\n" name
10440         | name, FUInt32 -> pr "      uint %s;\n" name
10441         | name, FInt32 -> pr "      int %s;\n" name
10442         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10443         | name, FInt64 -> pr "      long %s;\n" name
10444         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10445       ) cols;
10446       pr "    }\n";
10447       pr "\n"
10448   ) structs;
10449
10450   (* Generate C# function bindings. *)
10451   List.iter (
10452     fun (name, style, _, _, _, shortdesc, _) ->
10453       let rec csharp_return_type () =
10454         match fst style with
10455         | RErr -> "void"
10456         | RBool n -> "bool"
10457         | RInt n -> "int"
10458         | RInt64 n -> "long"
10459         | RConstString n
10460         | RConstOptString n
10461         | RString n
10462         | RBufferOut n -> "string"
10463         | RStruct (_,n) -> "_" ^ n
10464         | RHashtable n -> "Hashtable"
10465         | RStringList n -> "string[]"
10466         | RStructList (_,n) -> sprintf "_%s[]" n
10467
10468       and c_return_type () =
10469         match fst style with
10470         | RErr
10471         | RBool _
10472         | RInt _ -> "int"
10473         | RInt64 _ -> "long"
10474         | RConstString _
10475         | RConstOptString _
10476         | RString _
10477         | RBufferOut _ -> "string"
10478         | RStruct (_,n) -> "_" ^ n
10479         | RHashtable _
10480         | RStringList _ -> "string[]"
10481         | RStructList (_,n) -> sprintf "_%s[]" n
10482
10483       and c_error_comparison () =
10484         match fst style with
10485         | RErr
10486         | RBool _
10487         | RInt _
10488         | RInt64 _ -> "== -1"
10489         | RConstString _
10490         | RConstOptString _
10491         | RString _
10492         | RBufferOut _
10493         | RStruct (_,_)
10494         | RHashtable _
10495         | RStringList _
10496         | RStructList (_,_) -> "== null"
10497
10498       and generate_extern_prototype () =
10499         pr "    static extern %s guestfs_%s (IntPtr h"
10500           (c_return_type ()) name;
10501         List.iter (
10502           function
10503           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10504           | FileIn n | FileOut n ->
10505               pr ", [In] string %s" n
10506           | StringList n | DeviceList n ->
10507               pr ", [In] string[] %s" n
10508           | Bool n ->
10509               pr ", bool %s" n
10510           | Int n ->
10511               pr ", int %s" n
10512           | Int64 n ->
10513               pr ", long %s" n
10514         ) (snd style);
10515         pr ");\n"
10516
10517       and generate_public_prototype () =
10518         pr "    public %s %s (" (csharp_return_type ()) name;
10519         let comma = ref false in
10520         let next () =
10521           if !comma then pr ", ";
10522           comma := true
10523         in
10524         List.iter (
10525           function
10526           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10527           | FileIn n | FileOut n ->
10528               next (); pr "string %s" n
10529           | StringList n | DeviceList n ->
10530               next (); pr "string[] %s" n
10531           | Bool n ->
10532               next (); pr "bool %s" n
10533           | Int n ->
10534               next (); pr "int %s" n
10535           | Int64 n ->
10536               next (); pr "long %s" n
10537         ) (snd style);
10538         pr ")\n"
10539
10540       and generate_call () =
10541         pr "guestfs_%s (_handle" name;
10542         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10543         pr ");\n";
10544       in
10545
10546       pr "    [DllImport (\"%s\")]\n" library;
10547       generate_extern_prototype ();
10548       pr "\n";
10549       pr "    /// <summary>\n";
10550       pr "    /// %s\n" shortdesc;
10551       pr "    /// </summary>\n";
10552       generate_public_prototype ();
10553       pr "    {\n";
10554       pr "      %s r;\n" (c_return_type ());
10555       pr "      r = ";
10556       generate_call ();
10557       pr "      if (r %s)\n" (c_error_comparison ());
10558       pr "        throw new Error (guestfs_last_error (_handle));\n";
10559       (match fst style with
10560        | RErr -> ()
10561        | RBool _ ->
10562            pr "      return r != 0 ? true : false;\n"
10563        | RHashtable _ ->
10564            pr "      Hashtable rr = new Hashtable ();\n";
10565            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10566            pr "        rr.Add (r[i], r[i+1]);\n";
10567            pr "      return rr;\n"
10568        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10569        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10570        | RStructList _ ->
10571            pr "      return r;\n"
10572       );
10573       pr "    }\n";
10574       pr "\n";
10575   ) all_functions_sorted;
10576
10577   pr "  }
10578 }
10579 "
10580
10581 and generate_bindtests () =
10582   generate_header CStyle LGPLv2plus;
10583
10584   pr "\
10585 #include <stdio.h>
10586 #include <stdlib.h>
10587 #include <inttypes.h>
10588 #include <string.h>
10589
10590 #include \"guestfs.h\"
10591 #include \"guestfs-internal.h\"
10592 #include \"guestfs-internal-actions.h\"
10593 #include \"guestfs_protocol.h\"
10594
10595 #define error guestfs_error
10596 #define safe_calloc guestfs_safe_calloc
10597 #define safe_malloc guestfs_safe_malloc
10598
10599 static void
10600 print_strings (char *const *argv)
10601 {
10602   int argc;
10603
10604   printf (\"[\");
10605   for (argc = 0; argv[argc] != NULL; ++argc) {
10606     if (argc > 0) printf (\", \");
10607     printf (\"\\\"%%s\\\"\", argv[argc]);
10608   }
10609   printf (\"]\\n\");
10610 }
10611
10612 /* The test0 function prints its parameters to stdout. */
10613 ";
10614
10615   let test0, tests =
10616     match test_functions with
10617     | [] -> assert false
10618     | test0 :: tests -> test0, tests in
10619
10620   let () =
10621     let (name, style, _, _, _, _, _) = test0 in
10622     generate_prototype ~extern:false ~semicolon:false ~newline:true
10623       ~handle:"g" ~prefix:"guestfs__" name style;
10624     pr "{\n";
10625     List.iter (
10626       function
10627       | Pathname n
10628       | Device n | Dev_or_Path n
10629       | String n
10630       | FileIn n
10631       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10632       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10633       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10634       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10635       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10636       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10637     ) (snd style);
10638     pr "  /* Java changes stdout line buffering so we need this: */\n";
10639     pr "  fflush (stdout);\n";
10640     pr "  return 0;\n";
10641     pr "}\n";
10642     pr "\n" in
10643
10644   List.iter (
10645     fun (name, style, _, _, _, _, _) ->
10646       if String.sub name (String.length name - 3) 3 <> "err" then (
10647         pr "/* Test normal return. */\n";
10648         generate_prototype ~extern:false ~semicolon:false ~newline:true
10649           ~handle:"g" ~prefix:"guestfs__" name style;
10650         pr "{\n";
10651         (match fst style with
10652          | RErr ->
10653              pr "  return 0;\n"
10654          | RInt _ ->
10655              pr "  int r;\n";
10656              pr "  sscanf (val, \"%%d\", &r);\n";
10657              pr "  return r;\n"
10658          | RInt64 _ ->
10659              pr "  int64_t r;\n";
10660              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10661              pr "  return r;\n"
10662          | RBool _ ->
10663              pr "  return STREQ (val, \"true\");\n"
10664          | RConstString _
10665          | RConstOptString _ ->
10666              (* Can't return the input string here.  Return a static
10667               * string so we ensure we get a segfault if the caller
10668               * tries to free it.
10669               *)
10670              pr "  return \"static string\";\n"
10671          | RString _ ->
10672              pr "  return strdup (val);\n"
10673          | RStringList _ ->
10674              pr "  char **strs;\n";
10675              pr "  int n, i;\n";
10676              pr "  sscanf (val, \"%%d\", &n);\n";
10677              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10678              pr "  for (i = 0; i < n; ++i) {\n";
10679              pr "    strs[i] = safe_malloc (g, 16);\n";
10680              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10681              pr "  }\n";
10682              pr "  strs[n] = NULL;\n";
10683              pr "  return strs;\n"
10684          | RStruct (_, typ) ->
10685              pr "  struct guestfs_%s *r;\n" typ;
10686              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10687              pr "  return r;\n"
10688          | RStructList (_, typ) ->
10689              pr "  struct guestfs_%s_list *r;\n" typ;
10690              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10691              pr "  sscanf (val, \"%%d\", &r->len);\n";
10692              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10693              pr "  return r;\n"
10694          | RHashtable _ ->
10695              pr "  char **strs;\n";
10696              pr "  int n, i;\n";
10697              pr "  sscanf (val, \"%%d\", &n);\n";
10698              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10699              pr "  for (i = 0; i < n; ++i) {\n";
10700              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10701              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10702              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10703              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10704              pr "  }\n";
10705              pr "  strs[n*2] = NULL;\n";
10706              pr "  return strs;\n"
10707          | RBufferOut _ ->
10708              pr "  return strdup (val);\n"
10709         );
10710         pr "}\n";
10711         pr "\n"
10712       ) else (
10713         pr "/* Test error return. */\n";
10714         generate_prototype ~extern:false ~semicolon:false ~newline:true
10715           ~handle:"g" ~prefix:"guestfs__" name style;
10716         pr "{\n";
10717         pr "  error (g, \"error\");\n";
10718         (match fst style with
10719          | RErr | RInt _ | RInt64 _ | RBool _ ->
10720              pr "  return -1;\n"
10721          | RConstString _ | RConstOptString _
10722          | RString _ | RStringList _ | RStruct _
10723          | RStructList _
10724          | RHashtable _
10725          | RBufferOut _ ->
10726              pr "  return NULL;\n"
10727         );
10728         pr "}\n";
10729         pr "\n"
10730       )
10731   ) tests
10732
10733 and generate_ocaml_bindtests () =
10734   generate_header OCamlStyle GPLv2plus;
10735
10736   pr "\
10737 let () =
10738   let g = Guestfs.create () in
10739 ";
10740
10741   let mkargs args =
10742     String.concat " " (
10743       List.map (
10744         function
10745         | CallString s -> "\"" ^ s ^ "\""
10746         | CallOptString None -> "None"
10747         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10748         | CallStringList xs ->
10749             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10750         | CallInt i when i >= 0 -> string_of_int i
10751         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10752         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10753         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10754         | CallBool b -> string_of_bool b
10755       ) args
10756     )
10757   in
10758
10759   generate_lang_bindtests (
10760     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10761   );
10762
10763   pr "print_endline \"EOF\"\n"
10764
10765 and generate_perl_bindtests () =
10766   pr "#!/usr/bin/perl -w\n";
10767   generate_header HashStyle GPLv2plus;
10768
10769   pr "\
10770 use strict;
10771
10772 use Sys::Guestfs;
10773
10774 my $g = Sys::Guestfs->new ();
10775 ";
10776
10777   let mkargs args =
10778     String.concat ", " (
10779       List.map (
10780         function
10781         | CallString s -> "\"" ^ s ^ "\""
10782         | CallOptString None -> "undef"
10783         | CallOptString (Some s) -> sprintf "\"%s\"" s
10784         | CallStringList xs ->
10785             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10786         | CallInt i -> string_of_int i
10787         | CallInt64 i -> Int64.to_string i
10788         | CallBool b -> if b then "1" else "0"
10789       ) args
10790     )
10791   in
10792
10793   generate_lang_bindtests (
10794     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10795   );
10796
10797   pr "print \"EOF\\n\"\n"
10798
10799 and generate_python_bindtests () =
10800   generate_header HashStyle GPLv2plus;
10801
10802   pr "\
10803 import guestfs
10804
10805 g = guestfs.GuestFS ()
10806 ";
10807
10808   let mkargs args =
10809     String.concat ", " (
10810       List.map (
10811         function
10812         | CallString s -> "\"" ^ s ^ "\""
10813         | CallOptString None -> "None"
10814         | CallOptString (Some s) -> sprintf "\"%s\"" s
10815         | CallStringList xs ->
10816             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10817         | CallInt i -> string_of_int i
10818         | CallInt64 i -> Int64.to_string i
10819         | CallBool b -> if b then "1" else "0"
10820       ) args
10821     )
10822   in
10823
10824   generate_lang_bindtests (
10825     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10826   );
10827
10828   pr "print \"EOF\"\n"
10829
10830 and generate_ruby_bindtests () =
10831   generate_header HashStyle GPLv2plus;
10832
10833   pr "\
10834 require 'guestfs'
10835
10836 g = Guestfs::create()
10837 ";
10838
10839   let mkargs args =
10840     String.concat ", " (
10841       List.map (
10842         function
10843         | CallString s -> "\"" ^ s ^ "\""
10844         | CallOptString None -> "nil"
10845         | CallOptString (Some s) -> sprintf "\"%s\"" s
10846         | CallStringList xs ->
10847             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10848         | CallInt i -> string_of_int i
10849         | CallInt64 i -> Int64.to_string i
10850         | CallBool b -> string_of_bool b
10851       ) args
10852     )
10853   in
10854
10855   generate_lang_bindtests (
10856     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10857   );
10858
10859   pr "print \"EOF\\n\"\n"
10860
10861 and generate_java_bindtests () =
10862   generate_header CStyle GPLv2plus;
10863
10864   pr "\
10865 import com.redhat.et.libguestfs.*;
10866
10867 public class Bindtests {
10868     public static void main (String[] argv)
10869     {
10870         try {
10871             GuestFS g = new GuestFS ();
10872 ";
10873
10874   let mkargs args =
10875     String.concat ", " (
10876       List.map (
10877         function
10878         | CallString s -> "\"" ^ s ^ "\""
10879         | CallOptString None -> "null"
10880         | CallOptString (Some s) -> sprintf "\"%s\"" s
10881         | CallStringList xs ->
10882             "new String[]{" ^
10883               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10884         | CallInt i -> string_of_int i
10885         | CallInt64 i -> Int64.to_string i
10886         | CallBool b -> string_of_bool b
10887       ) args
10888     )
10889   in
10890
10891   generate_lang_bindtests (
10892     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10893   );
10894
10895   pr "
10896             System.out.println (\"EOF\");
10897         }
10898         catch (Exception exn) {
10899             System.err.println (exn);
10900             System.exit (1);
10901         }
10902     }
10903 }
10904 "
10905
10906 and generate_haskell_bindtests () =
10907   generate_header HaskellStyle GPLv2plus;
10908
10909   pr "\
10910 module Bindtests where
10911 import qualified Guestfs
10912
10913 main = do
10914   g <- Guestfs.create
10915 ";
10916
10917   let mkargs args =
10918     String.concat " " (
10919       List.map (
10920         function
10921         | CallString s -> "\"" ^ s ^ "\""
10922         | CallOptString None -> "Nothing"
10923         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10924         | CallStringList xs ->
10925             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10926         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10927         | CallInt i -> string_of_int i
10928         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10929         | CallInt64 i -> Int64.to_string i
10930         | CallBool true -> "True"
10931         | CallBool false -> "False"
10932       ) args
10933     )
10934   in
10935
10936   generate_lang_bindtests (
10937     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10938   );
10939
10940   pr "  putStrLn \"EOF\"\n"
10941
10942 (* Language-independent bindings tests - we do it this way to
10943  * ensure there is parity in testing bindings across all languages.
10944  *)
10945 and generate_lang_bindtests call =
10946   call "test0" [CallString "abc"; CallOptString (Some "def");
10947                 CallStringList []; CallBool false;
10948                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10949   call "test0" [CallString "abc"; CallOptString None;
10950                 CallStringList []; CallBool false;
10951                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10952   call "test0" [CallString ""; CallOptString (Some "def");
10953                 CallStringList []; CallBool false;
10954                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10955   call "test0" [CallString ""; CallOptString (Some "");
10956                 CallStringList []; CallBool false;
10957                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10958   call "test0" [CallString "abc"; CallOptString (Some "def");
10959                 CallStringList ["1"]; CallBool false;
10960                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10961   call "test0" [CallString "abc"; CallOptString (Some "def");
10962                 CallStringList ["1"; "2"]; CallBool false;
10963                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10964   call "test0" [CallString "abc"; CallOptString (Some "def");
10965                 CallStringList ["1"]; CallBool true;
10966                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10967   call "test0" [CallString "abc"; CallOptString (Some "def");
10968                 CallStringList ["1"]; CallBool false;
10969                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10970   call "test0" [CallString "abc"; CallOptString (Some "def");
10971                 CallStringList ["1"]; CallBool false;
10972                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10973   call "test0" [CallString "abc"; CallOptString (Some "def");
10974                 CallStringList ["1"]; CallBool false;
10975                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10976   call "test0" [CallString "abc"; CallOptString (Some "def");
10977                 CallStringList ["1"]; CallBool false;
10978                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10979   call "test0" [CallString "abc"; CallOptString (Some "def");
10980                 CallStringList ["1"]; CallBool false;
10981                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10982   call "test0" [CallString "abc"; CallOptString (Some "def");
10983                 CallStringList ["1"]; CallBool false;
10984                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10985
10986 (* XXX Add here tests of the return and error functions. *)
10987
10988 (* Code to generator bindings for virt-inspector.  Currently only
10989  * implemented for OCaml code (for virt-p2v 2.0).
10990  *)
10991 let rng_input = "inspector/virt-inspector.rng"
10992
10993 (* Read the input file and parse it into internal structures.  This is
10994  * by no means a complete RELAX NG parser, but is just enough to be
10995  * able to parse the specific input file.
10996  *)
10997 type rng =
10998   | Element of string * rng list        (* <element name=name/> *)
10999   | Attribute of string * rng list        (* <attribute name=name/> *)
11000   | Interleave of rng list                (* <interleave/> *)
11001   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11002   | OneOrMore of rng                        (* <oneOrMore/> *)
11003   | Optional of rng                        (* <optional/> *)
11004   | Choice of string list                (* <choice><value/>*</choice> *)
11005   | Value of string                        (* <value>str</value> *)
11006   | Text                                (* <text/> *)
11007
11008 let rec string_of_rng = function
11009   | Element (name, xs) ->
11010       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11011   | Attribute (name, xs) ->
11012       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11013   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11014   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11015   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11016   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11017   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11018   | Value value -> "Value \"" ^ value ^ "\""
11019   | Text -> "Text"
11020
11021 and string_of_rng_list xs =
11022   String.concat ", " (List.map string_of_rng xs)
11023
11024 let rec parse_rng ?defines context = function
11025   | [] -> []
11026   | Xml.Element ("element", ["name", name], children) :: rest ->
11027       Element (name, parse_rng ?defines context children)
11028       :: parse_rng ?defines context rest
11029   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11030       Attribute (name, parse_rng ?defines context children)
11031       :: parse_rng ?defines context rest
11032   | Xml.Element ("interleave", [], children) :: rest ->
11033       Interleave (parse_rng ?defines context children)
11034       :: parse_rng ?defines context rest
11035   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11036       let rng = parse_rng ?defines context [child] in
11037       (match rng with
11038        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11039        | _ ->
11040            failwithf "%s: <zeroOrMore> contains more than one child element"
11041              context
11042       )
11043   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11044       let rng = parse_rng ?defines context [child] in
11045       (match rng with
11046        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11047        | _ ->
11048            failwithf "%s: <oneOrMore> contains more than one child element"
11049              context
11050       )
11051   | Xml.Element ("optional", [], [child]) :: rest ->
11052       let rng = parse_rng ?defines context [child] in
11053       (match rng with
11054        | [child] -> Optional child :: parse_rng ?defines context rest
11055        | _ ->
11056            failwithf "%s: <optional> contains more than one child element"
11057              context
11058       )
11059   | Xml.Element ("choice", [], children) :: rest ->
11060       let values = List.map (
11061         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11062         | _ ->
11063             failwithf "%s: can't handle anything except <value> in <choice>"
11064               context
11065       ) children in
11066       Choice values
11067       :: parse_rng ?defines context rest
11068   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11069       Value value :: parse_rng ?defines context rest
11070   | Xml.Element ("text", [], []) :: rest ->
11071       Text :: parse_rng ?defines context rest
11072   | Xml.Element ("ref", ["name", name], []) :: rest ->
11073       (* Look up the reference.  Because of limitations in this parser,
11074        * we can't handle arbitrarily nested <ref> yet.  You can only
11075        * use <ref> from inside <start>.
11076        *)
11077       (match defines with
11078        | None ->
11079            failwithf "%s: contains <ref>, but no refs are defined yet" context
11080        | Some map ->
11081            let rng = StringMap.find name map in
11082            rng @ parse_rng ?defines context rest
11083       )
11084   | x :: _ ->
11085       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11086
11087 let grammar =
11088   let xml = Xml.parse_file rng_input in
11089   match xml with
11090   | Xml.Element ("grammar", _,
11091                  Xml.Element ("start", _, gram) :: defines) ->
11092       (* The <define/> elements are referenced in the <start> section,
11093        * so build a map of those first.
11094        *)
11095       let defines = List.fold_left (
11096         fun map ->
11097           function Xml.Element ("define", ["name", name], defn) ->
11098             StringMap.add name defn map
11099           | _ ->
11100               failwithf "%s: expected <define name=name/>" rng_input
11101       ) StringMap.empty defines in
11102       let defines = StringMap.mapi parse_rng defines in
11103
11104       (* Parse the <start> clause, passing the defines. *)
11105       parse_rng ~defines "<start>" gram
11106   | _ ->
11107       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11108         rng_input
11109
11110 let name_of_field = function
11111   | Element (name, _) | Attribute (name, _)
11112   | ZeroOrMore (Element (name, _))
11113   | OneOrMore (Element (name, _))
11114   | Optional (Element (name, _)) -> name
11115   | Optional (Attribute (name, _)) -> name
11116   | Text -> (* an unnamed field in an element *)
11117       "data"
11118   | rng ->
11119       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11120
11121 (* At the moment this function only generates OCaml types.  However we
11122  * should parameterize it later so it can generate types/structs in a
11123  * variety of languages.
11124  *)
11125 let generate_types xs =
11126   (* A simple type is one that can be printed out directly, eg.
11127    * "string option".  A complex type is one which has a name and has
11128    * to be defined via another toplevel definition, eg. a struct.
11129    *
11130    * generate_type generates code for either simple or complex types.
11131    * In the simple case, it returns the string ("string option").  In
11132    * the complex case, it returns the name ("mountpoint").  In the
11133    * complex case it has to print out the definition before returning,
11134    * so it should only be called when we are at the beginning of a
11135    * new line (BOL context).
11136    *)
11137   let rec generate_type = function
11138     | Text ->                                (* string *)
11139         "string", true
11140     | Choice values ->                        (* [`val1|`val2|...] *)
11141         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11142     | ZeroOrMore rng ->                        (* <rng> list *)
11143         let t, is_simple = generate_type rng in
11144         t ^ " list (* 0 or more *)", is_simple
11145     | OneOrMore rng ->                        (* <rng> list *)
11146         let t, is_simple = generate_type rng in
11147         t ^ " list (* 1 or more *)", is_simple
11148                                         (* virt-inspector hack: bool *)
11149     | Optional (Attribute (name, [Value "1"])) ->
11150         "bool", true
11151     | Optional rng ->                        (* <rng> list *)
11152         let t, is_simple = generate_type rng in
11153         t ^ " option", is_simple
11154                                         (* type name = { fields ... } *)
11155     | Element (name, fields) when is_attrs_interleave fields ->
11156         generate_type_struct name (get_attrs_interleave fields)
11157     | Element (name, [field])                (* type name = field *)
11158     | Attribute (name, [field]) ->
11159         let t, is_simple = generate_type field in
11160         if is_simple then (t, true)
11161         else (
11162           pr "type %s = %s\n" name t;
11163           name, false
11164         )
11165     | Element (name, fields) ->              (* type name = { fields ... } *)
11166         generate_type_struct name fields
11167     | rng ->
11168         failwithf "generate_type failed at: %s" (string_of_rng rng)
11169
11170   and is_attrs_interleave = function
11171     | [Interleave _] -> true
11172     | Attribute _ :: fields -> is_attrs_interleave fields
11173     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11174     | _ -> false
11175
11176   and get_attrs_interleave = function
11177     | [Interleave fields] -> fields
11178     | ((Attribute _) as field) :: fields
11179     | ((Optional (Attribute _)) as field) :: fields ->
11180         field :: get_attrs_interleave fields
11181     | _ -> assert false
11182
11183   and generate_types xs =
11184     List.iter (fun x -> ignore (generate_type x)) xs
11185
11186   and generate_type_struct name fields =
11187     (* Calculate the types of the fields first.  We have to do this
11188      * before printing anything so we are still in BOL context.
11189      *)
11190     let types = List.map fst (List.map generate_type fields) in
11191
11192     (* Special case of a struct containing just a string and another
11193      * field.  Turn it into an assoc list.
11194      *)
11195     match types with
11196     | ["string"; other] ->
11197         let fname1, fname2 =
11198           match fields with
11199           | [f1; f2] -> name_of_field f1, name_of_field f2
11200           | _ -> assert false in
11201         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11202         name, false
11203
11204     | types ->
11205         pr "type %s = {\n" name;
11206         List.iter (
11207           fun (field, ftype) ->
11208             let fname = name_of_field field in
11209             pr "  %s_%s : %s;\n" name fname ftype
11210         ) (List.combine fields types);
11211         pr "}\n";
11212         (* Return the name of this type, and
11213          * false because it's not a simple type.
11214          *)
11215         name, false
11216   in
11217
11218   generate_types xs
11219
11220 let generate_parsers xs =
11221   (* As for generate_type above, generate_parser makes a parser for
11222    * some type, and returns the name of the parser it has generated.
11223    * Because it (may) need to print something, it should always be
11224    * called in BOL context.
11225    *)
11226   let rec generate_parser = function
11227     | Text ->                                (* string *)
11228         "string_child_or_empty"
11229     | Choice values ->                        (* [`val1|`val2|...] *)
11230         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11231           (String.concat "|"
11232              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11233     | ZeroOrMore rng ->                        (* <rng> list *)
11234         let pa = generate_parser rng in
11235         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11236     | OneOrMore rng ->                        (* <rng> list *)
11237         let pa = generate_parser rng in
11238         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11239                                         (* virt-inspector hack: bool *)
11240     | Optional (Attribute (name, [Value "1"])) ->
11241         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11242     | Optional rng ->                        (* <rng> list *)
11243         let pa = generate_parser rng in
11244         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11245                                         (* type name = { fields ... } *)
11246     | Element (name, fields) when is_attrs_interleave fields ->
11247         generate_parser_struct name (get_attrs_interleave fields)
11248     | Element (name, [field]) ->        (* type name = field *)
11249         let pa = generate_parser field in
11250         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11251         pr "let %s =\n" parser_name;
11252         pr "  %s\n" pa;
11253         pr "let parse_%s = %s\n" name parser_name;
11254         parser_name
11255     | Attribute (name, [field]) ->
11256         let pa = generate_parser field in
11257         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11258         pr "let %s =\n" parser_name;
11259         pr "  %s\n" pa;
11260         pr "let parse_%s = %s\n" name parser_name;
11261         parser_name
11262     | Element (name, fields) ->              (* type name = { fields ... } *)
11263         generate_parser_struct name ([], fields)
11264     | rng ->
11265         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11266
11267   and is_attrs_interleave = function
11268     | [Interleave _] -> true
11269     | Attribute _ :: fields -> is_attrs_interleave fields
11270     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11271     | _ -> false
11272
11273   and get_attrs_interleave = function
11274     | [Interleave fields] -> [], fields
11275     | ((Attribute _) as field) :: fields
11276     | ((Optional (Attribute _)) as field) :: fields ->
11277         let attrs, interleaves = get_attrs_interleave fields in
11278         (field :: attrs), interleaves
11279     | _ -> assert false
11280
11281   and generate_parsers xs =
11282     List.iter (fun x -> ignore (generate_parser x)) xs
11283
11284   and generate_parser_struct name (attrs, interleaves) =
11285     (* Generate parsers for the fields first.  We have to do this
11286      * before printing anything so we are still in BOL context.
11287      *)
11288     let fields = attrs @ interleaves in
11289     let pas = List.map generate_parser fields in
11290
11291     (* Generate an intermediate tuple from all the fields first.
11292      * If the type is just a string + another field, then we will
11293      * return this directly, otherwise it is turned into a record.
11294      *
11295      * RELAX NG note: This code treats <interleave> and plain lists of
11296      * fields the same.  In other words, it doesn't bother enforcing
11297      * any ordering of fields in the XML.
11298      *)
11299     pr "let parse_%s x =\n" name;
11300     pr "  let t = (\n    ";
11301     let comma = ref false in
11302     List.iter (
11303       fun x ->
11304         if !comma then pr ",\n    ";
11305         comma := true;
11306         match x with
11307         | Optional (Attribute (fname, [field])), pa ->
11308             pr "%s x" pa
11309         | Optional (Element (fname, [field])), pa ->
11310             pr "%s (optional_child %S x)" pa fname
11311         | Attribute (fname, [Text]), _ ->
11312             pr "attribute %S x" fname
11313         | (ZeroOrMore _ | OneOrMore _), pa ->
11314             pr "%s x" pa
11315         | Text, pa ->
11316             pr "%s x" pa
11317         | (field, pa) ->
11318             let fname = name_of_field field in
11319             pr "%s (child %S x)" pa fname
11320     ) (List.combine fields pas);
11321     pr "\n  ) in\n";
11322
11323     (match fields with
11324      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11325          pr "  t\n"
11326
11327      | _ ->
11328          pr "  (Obj.magic t : %s)\n" name
11329 (*
11330          List.iter (
11331            function
11332            | (Optional (Attribute (fname, [field])), pa) ->
11333                pr "  %s_%s =\n" name fname;
11334                pr "    %s x;\n" pa
11335            | (Optional (Element (fname, [field])), pa) ->
11336                pr "  %s_%s =\n" name fname;
11337                pr "    (let x = optional_child %S x in\n" fname;
11338                pr "     %s x);\n" pa
11339            | (field, pa) ->
11340                let fname = name_of_field field in
11341                pr "  %s_%s =\n" name fname;
11342                pr "    (let x = child %S x in\n" fname;
11343                pr "     %s x);\n" pa
11344          ) (List.combine fields pas);
11345          pr "}\n"
11346 *)
11347     );
11348     sprintf "parse_%s" name
11349   in
11350
11351   generate_parsers xs
11352
11353 (* Generate ocaml/guestfs_inspector.mli. *)
11354 let generate_ocaml_inspector_mli () =
11355   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11356
11357   pr "\
11358 (** This is an OCaml language binding to the external [virt-inspector]
11359     program.
11360
11361     For more information, please read the man page [virt-inspector(1)].
11362 *)
11363
11364 ";
11365
11366   generate_types grammar;
11367   pr "(** The nested information returned from the {!inspect} function. *)\n";
11368   pr "\n";
11369
11370   pr "\
11371 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11372 (** To inspect a libvirt domain called [name], pass a singleton
11373     list: [inspect [name]].  When using libvirt only, you may
11374     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11375
11376     To inspect a disk image or images, pass a list of the filenames
11377     of the disk images: [inspect filenames]
11378
11379     This function inspects the given guest or disk images and
11380     returns a list of operating system(s) found and a large amount
11381     of information about them.  In the vast majority of cases,
11382     a virtual machine only contains a single operating system.
11383
11384     If the optional [~xml] parameter is given, then this function
11385     skips running the external virt-inspector program and just
11386     parses the given XML directly (which is expected to be XML
11387     produced from a previous run of virt-inspector).  The list of
11388     names and connect URI are ignored in this case.
11389
11390     This function can throw a wide variety of exceptions, for example
11391     if the external virt-inspector program cannot be found, or if
11392     it doesn't generate valid XML.
11393 *)
11394 "
11395
11396 (* Generate ocaml/guestfs_inspector.ml. *)
11397 let generate_ocaml_inspector_ml () =
11398   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11399
11400   pr "open Unix\n";
11401   pr "\n";
11402
11403   generate_types grammar;
11404   pr "\n";
11405
11406   pr "\
11407 (* Misc functions which are used by the parser code below. *)
11408 let first_child = function
11409   | Xml.Element (_, _, c::_) -> c
11410   | Xml.Element (name, _, []) ->
11411       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11412   | Xml.PCData str ->
11413       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11414
11415 let string_child_or_empty = function
11416   | Xml.Element (_, _, [Xml.PCData s]) -> s
11417   | Xml.Element (_, _, []) -> \"\"
11418   | Xml.Element (x, _, _) ->
11419       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11420                 x ^ \" instead\")
11421   | Xml.PCData str ->
11422       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11423
11424 let optional_child name xml =
11425   let children = Xml.children xml in
11426   try
11427     Some (List.find (function
11428                      | Xml.Element (n, _, _) when n = name -> true
11429                      | _ -> false) children)
11430   with
11431     Not_found -> None
11432
11433 let child name xml =
11434   match optional_child name xml with
11435   | Some c -> c
11436   | None ->
11437       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11438
11439 let attribute name xml =
11440   try Xml.attrib xml name
11441   with Xml.No_attribute _ ->
11442     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11443
11444 ";
11445
11446   generate_parsers grammar;
11447   pr "\n";
11448
11449   pr "\
11450 (* Run external virt-inspector, then use parser to parse the XML. *)
11451 let inspect ?connect ?xml names =
11452   let xml =
11453     match xml with
11454     | None ->
11455         if names = [] then invalid_arg \"inspect: no names given\";
11456         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11457           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11458           names in
11459         let cmd = List.map Filename.quote cmd in
11460         let cmd = String.concat \" \" cmd in
11461         let chan = open_process_in cmd in
11462         let xml = Xml.parse_in chan in
11463         (match close_process_in chan with
11464          | WEXITED 0 -> ()
11465          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11466          | WSIGNALED i | WSTOPPED i ->
11467              failwith (\"external virt-inspector command died or stopped on sig \" ^
11468                        string_of_int i)
11469         );
11470         xml
11471     | Some doc ->
11472         Xml.parse_string doc in
11473   parse_operatingsystems xml
11474 "
11475
11476 (* This is used to generate the src/MAX_PROC_NR file which
11477  * contains the maximum procedure number, a surrogate for the
11478  * ABI version number.  See src/Makefile.am for the details.
11479  *)
11480 and generate_max_proc_nr () =
11481   let proc_nrs = List.map (
11482     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11483   ) daemon_functions in
11484
11485   let max_proc_nr = List.fold_left max 0 proc_nrs in
11486
11487   pr "%d\n" max_proc_nr
11488
11489 let output_to filename k =
11490   let filename_new = filename ^ ".new" in
11491   chan := open_out filename_new;
11492   k ();
11493   close_out !chan;
11494   chan := Pervasives.stdout;
11495
11496   (* Is the new file different from the current file? *)
11497   if Sys.file_exists filename && files_equal filename filename_new then
11498     unlink filename_new                 (* same, so skip it *)
11499   else (
11500     (* different, overwrite old one *)
11501     (try chmod filename 0o644 with Unix_error _ -> ());
11502     rename filename_new filename;
11503     chmod filename 0o444;
11504     printf "written %s\n%!" filename;
11505   )
11506
11507 let perror msg = function
11508   | Unix_error (err, _, _) ->
11509       eprintf "%s: %s\n" msg (error_message err)
11510   | exn ->
11511       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11512
11513 (* Main program. *)
11514 let () =
11515   let lock_fd =
11516     try openfile "HACKING" [O_RDWR] 0
11517     with
11518     | Unix_error (ENOENT, _, _) ->
11519         eprintf "\
11520 You are probably running this from the wrong directory.
11521 Run it from the top source directory using the command
11522   src/generator.ml
11523 ";
11524         exit 1
11525     | exn ->
11526         perror "open: HACKING" exn;
11527         exit 1 in
11528
11529   (* Acquire a lock so parallel builds won't try to run the generator
11530    * twice at the same time.  Subsequent builds will wait for the first
11531    * one to finish.  Note the lock is released implicitly when the
11532    * program exits.
11533    *)
11534   (try lockf lock_fd F_LOCK 1
11535    with exn ->
11536      perror "lock: HACKING" exn;
11537      exit 1);
11538
11539   check_functions ();
11540
11541   output_to "src/guestfs_protocol.x" generate_xdr;
11542   output_to "src/guestfs-structs.h" generate_structs_h;
11543   output_to "src/guestfs-actions.h" generate_actions_h;
11544   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11545   output_to "src/guestfs-actions.c" generate_client_actions;
11546   output_to "src/guestfs-bindtests.c" generate_bindtests;
11547   output_to "src/guestfs-structs.pod" generate_structs_pod;
11548   output_to "src/guestfs-actions.pod" generate_actions_pod;
11549   output_to "src/guestfs-availability.pod" generate_availability_pod;
11550   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11551   output_to "src/libguestfs.syms" generate_linker_script;
11552   output_to "daemon/actions.h" generate_daemon_actions_h;
11553   output_to "daemon/stubs.c" generate_daemon_actions;
11554   output_to "daemon/names.c" generate_daemon_names;
11555   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11556   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11557   output_to "capitests/tests.c" generate_tests;
11558   output_to "fish/cmds.c" generate_fish_cmds;
11559   output_to "fish/completion.c" generate_fish_completion;
11560   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11561   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11562   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11563   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11564   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11565   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11566   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11567   output_to "perl/Guestfs.xs" generate_perl_xs;
11568   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11569   output_to "perl/bindtests.pl" generate_perl_bindtests;
11570   output_to "python/guestfs-py.c" generate_python_c;
11571   output_to "python/guestfs.py" generate_python_py;
11572   output_to "python/bindtests.py" generate_python_bindtests;
11573   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11574   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11575   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11576
11577   List.iter (
11578     fun (typ, jtyp) ->
11579       let cols = cols_of_struct typ in
11580       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11581       output_to filename (generate_java_struct jtyp cols);
11582   ) java_structs;
11583
11584   output_to "java/Makefile.inc" generate_java_makefile_inc;
11585   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11586   output_to "java/Bindtests.java" generate_java_bindtests;
11587   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11588   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11589   output_to "csharp/Libguestfs.cs" generate_csharp;
11590
11591   (* Always generate this file last, and unconditionally.  It's used
11592    * by the Makefile to know when we must re-run the generator.
11593    *)
11594   let chan = open_out "src/stamp-generator" in
11595   fprintf chan "1\n";
11596   close_out chan;
11597
11598   printf "generated %d lines of code\n" !lines