New API: ntfsresize.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.");
1384
1385   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386    [], (* XXX Need stat command to test *)
1387    "change file owner and group",
1388    "\
1389 Change the file owner to C<owner> and group to C<group>.
1390
1391 Only numeric uid and gid are supported.  If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1394
1395   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396    [InitISOFS, Always, TestOutputTrue (
1397       [["exists"; "/empty"]]);
1398     InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/directory"]])],
1400    "test if file or directory exists",
1401    "\
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1404
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406
1407   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["is_file"; "/known-1"]]);
1410     InitISOFS, Always, TestOutputFalse (
1411       [["is_file"; "/directory"]])],
1412    "test if file exists",
1413    "\
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name.  Note that it returns false for
1416 other objects like directories.
1417
1418 See also C<guestfs_stat>.");
1419
1420   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421    [InitISOFS, Always, TestOutputFalse (
1422       [["is_dir"; "/known-3"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["is_dir"; "/directory"]])],
1425    "test if file exists",
1426    "\
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name.  Note that it returns false for
1429 other objects like files.
1430
1431 See also C<guestfs_stat>.");
1432
1433   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436        ["pvcreate"; "/dev/sda1"];
1437        ["pvcreate"; "/dev/sda2"];
1438        ["pvcreate"; "/dev/sda3"];
1439        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440    "create an LVM physical volume",
1441    "\
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1444 as C</dev/sda1>.");
1445
1446   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447    [InitEmpty, Always, TestOutputList (
1448       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449        ["pvcreate"; "/dev/sda1"];
1450        ["pvcreate"; "/dev/sda2"];
1451        ["pvcreate"; "/dev/sda3"];
1452        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453        ["vgcreate"; "VG2"; "/dev/sda3"];
1454        ["vgs"]], ["VG1"; "VG2"])],
1455    "create an LVM volume group",
1456    "\
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1459
1460   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["lvcreate"; "LV1"; "VG1"; "50"];
1469        ["lvcreate"; "LV2"; "VG1"; "50"];
1470        ["lvcreate"; "LV3"; "VG2"; "50"];
1471        ["lvcreate"; "LV4"; "VG2"; "50"];
1472        ["lvcreate"; "LV5"; "VG2"; "50"];
1473        ["lvs"]],
1474       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476    "create an LVM volume group",
1477    "\
1478 This creates an LVM volume group called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1480
1481   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482    [InitEmpty, Always, TestOutput (
1483       [["part_disk"; "/dev/sda"; "mbr"];
1484        ["mkfs"; "ext2"; "/dev/sda1"];
1485        ["mount_options"; ""; "/dev/sda1"; "/"];
1486        ["write_file"; "/new"; "new file contents"; "0"];
1487        ["cat"; "/new"]], "new file contents")],
1488    "make a filesystem",
1489    "\
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume).  The filesystem type is C<fstype>, for
1492 example C<ext3>.");
1493
1494   ("sfdisk", (RErr, [Device "device";
1495                      Int "cyls"; Int "heads"; Int "sectors";
1496                      StringList "lines"]), 43, [DangerWillRobinson],
1497    [],
1498    "create partitions on a block device",
1499    "\
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1502
1503 C<device> should be a block device, for example C</dev/sda>.
1504
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted.  Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1512
1513 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1514 information refer to the L<sfdisk(8)> manpage.
1515
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1519
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1522
1523   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524    [InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "new file contents"; "0"];
1526        ["cat"; "/new"]], "new file contents");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529        ["cat"; "/new"]], "\nnew file contents\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; "\n\n"; "0"];
1532        ["cat"; "/new"]], "\n\n");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; ""; "0"];
1535        ["cat"; "/new"]], "");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n\n\n"; "0"];
1538        ["cat"; "/new"]], "\n\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n"; "0"];
1541        ["cat"; "/new"]], "\n")],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version.  In the meantime
1555 use C<guestfs_upload>.");
1556
1557   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558    [InitEmpty, Always, TestOutputListOfDevices (
1559       [["part_disk"; "/dev/sda"; "mbr"];
1560        ["mkfs"; "ext2"; "/dev/sda1"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mounts"]], ["/dev/sda1"]);
1563     InitEmpty, Always, TestOutputList (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["umount"; "/"];
1568        ["mounts"]], [])],
1569    "unmount a filesystem",
1570    "\
1571 This unmounts the given filesystem.  The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1574
1575   ("mounts", (RStringList "devices", []), 46, [],
1576    [InitBasicFS, Always, TestOutputListOfDevices (
1577       [["mounts"]], ["/dev/sda1"])],
1578    "show mounted filesystems",
1579    "\
1580 This returns the list of currently mounted filesystems.  It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582
1583 Some internal mounts are not shown.
1584
1585 See also: C<guestfs_mountpoints>");
1586
1587   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588    [InitBasicFS, Always, TestOutputList (
1589       [["umount_all"];
1590        ["mounts"]], []);
1591     (* check that umount_all can unmount nested mounts correctly: *)
1592     InitEmpty, Always, TestOutputList (
1593       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594        ["mkfs"; "ext2"; "/dev/sda1"];
1595        ["mkfs"; "ext2"; "/dev/sda2"];
1596        ["mkfs"; "ext2"; "/dev/sda3"];
1597        ["mount_options"; ""; "/dev/sda1"; "/"];
1598        ["mkdir"; "/mp1"];
1599        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600        ["mkdir"; "/mp1/mp2"];
1601        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602        ["mkdir"; "/mp1/mp2/mp3"];
1603        ["umount_all"];
1604        ["mounts"]], [])],
1605    "unmount all filesystems",
1606    "\
1607 This unmounts all mounted filesystems.
1608
1609 Some internal mounts are not unmounted by this call.");
1610
1611   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612    [],
1613    "remove all LVM LVs, VGs and PVs",
1614    "\
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1617
1618   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619    [InitISOFS, Always, TestOutput (
1620       [["file"; "/empty"]], "empty");
1621     InitISOFS, Always, TestOutput (
1622       [["file"; "/known-1"]], "ASCII text");
1623     InitISOFS, Always, TestLastFail (
1624       [["file"; "/notexists"]])],
1625    "determine file type",
1626    "\
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file.  This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1630
1631 This call will also transparently look inside various types
1632 of compressed file.
1633
1634 The exact command which runs is C<file -zbsL path>.  Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1637
1638   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639    [InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 1"]], "Result1");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 2"]], "Result2\n");
1647     InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 3"]], "\nResult3");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 4"]], "\nResult4\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 5"]], "\nResult5\n\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 7"]], "");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 8"]], "\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 9"]], "\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683     InitBasicFS, Always, TestLastFail (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command"]])],
1687    "run a command from the guest filesystem",
1688    "\
1689 This call runs a command from the guest filesystem.  The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1693
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters.  The list must be
1697 non-empty (ie. must contain a program name).  Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1700
1701 The return value is anything printed to I<stdout> by
1702 the command.
1703
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message.  The error message
1706 string is the content of I<stderr> from the command.
1707
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>.  If you require a program from
1710 another location, you should provide the full path in the
1711 first parameter.
1712
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places.  It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1717 locations.");
1718
1719   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720    [InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 1"]], ["Result1"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 2"]], ["Result2"]);
1728     InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 7"]], []);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 8"]], [""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 9"]], ["";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764    "run a command, returning lines",
1765    "\
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1768
1769 See also: C<guestfs_sh_lines>");
1770
1771   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772    [InitISOFS, Always, TestOutputStruct (
1773       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774    "get file information",
1775    "\
1776 Returns file information for the given C<path>.
1777
1778 This is the same as the C<stat(2)> system call.");
1779
1780   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information for a symbolic link",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1789 refers to.
1790
1791 This is the same as the C<lstat(2)> system call.");
1792
1793   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796    "get file system statistics",
1797    "\
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1801
1802 This is the same as the C<statvfs(2)> system call.");
1803
1804   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805    [], (* XXX test *)
1806    "get ext2/ext3/ext4 superblock details",
1807    "\
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1810
1811 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1812 manpage for more details.  The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1815
1816   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817    [InitEmpty, Always, TestOutputTrue (
1818       [["blockdev_setro"; "/dev/sda"];
1819        ["blockdev_getro"; "/dev/sda"]])],
1820    "set block device to read-only",
1821    "\
1822 Sets the block device named C<device> to read-only.
1823
1824 This uses the L<blockdev(8)> command.");
1825
1826   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827    [InitEmpty, Always, TestOutputFalse (
1828       [["blockdev_setrw"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-write",
1831    "\
1832 Sets the block device named C<device> to read-write.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837    [InitEmpty, Always, TestOutputTrue (
1838       [["blockdev_setro"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "is block device set to read-only",
1841    "\
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getss"; "/dev/sda"]], 512)],
1850    "get sectorsize of block device",
1851    "\
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1854
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1856 for that).
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861    [InitEmpty, Always, TestOutputInt (
1862       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863    "get blocksize of block device",
1864    "\
1865 This returns the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873    [], (* XXX test *)
1874    "set blocksize of block device",
1875    "\
1876 This sets the block size of a device.
1877
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1880
1881 This uses the L<blockdev(8)> command.");
1882
1883   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884    [InitEmpty, Always, TestOutputInt (
1885       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886    "get total size of device in 512-byte sectors",
1887    "\
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1890
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900    "get total size of device in bytes",
1901    "\
1902 This returns the size of the device in bytes.
1903
1904 See also C<guestfs_blockdev_getsz>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909    [InitEmpty, Always, TestRun
1910       [["blockdev_flushbufs"; "/dev/sda"]]],
1911    "flush device buffers",
1912    "\
1913 This tells the kernel to flush internal buffers associated
1914 with C<device>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_rereadpt"; "/dev/sda"]]],
1921    "reread partition table",
1922    "\
1923 Reread the partition table on C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928    [InitBasicFS, Always, TestOutput (
1929       (* Pick a file from cwd which isn't likely to change. *)
1930       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931        ["checksum"; "md5"; "/COPYING.LIB"]],
1932       Digest.to_hex (Digest.file "COPYING.LIB"))],
1933    "upload a file from the local machine",
1934    "\
1935 Upload local file C<filename> to C<remotefilename> on the
1936 filesystem.
1937
1938 C<filename> can also be a named pipe.
1939
1940 See also C<guestfs_download>.");
1941
1942   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943    [InitBasicFS, Always, TestOutput (
1944       (* Pick a file from cwd which isn't likely to change. *)
1945       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947        ["upload"; "testdownload.tmp"; "/upload"];
1948        ["checksum"; "md5"; "/upload"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "download a file to the local machine",
1951    "\
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1958
1959   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960    [InitISOFS, Always, TestOutput (
1961       [["checksum"; "crc"; "/known-3"]], "2891671662");
1962     InitISOFS, Always, TestLastFail (
1963       [["checksum"; "crc"; "/notexists"]]);
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976    "compute MD5, SHAx or CRC checksum of file",
1977    "\
1978 This call computes the MD5, SHAx or CRC checksum of the
1979 file named C<path>.
1980
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1983
1984 =over 4
1985
1986 =item C<crc>
1987
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1990
1991 =item C<md5>
1992
1993 Compute the MD5 hash (using the C<md5sum> program).
1994
1995 =item C<sha1>
1996
1997 Compute the SHA1 hash (using the C<sha1sum> program).
1998
1999 =item C<sha224>
2000
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2002
2003 =item C<sha256>
2004
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2006
2007 =item C<sha384>
2008
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2010
2011 =item C<sha512>
2012
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2014
2015 =back
2016
2017 The checksum is returned as a printable string.");
2018
2019   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020    [InitBasicFS, Always, TestOutput (
2021       [["tar_in"; "../images/helloworld.tar"; "/"];
2022        ["cat"; "/hello"]], "hello\n")],
2023    "unpack tarfile to directory",
2024    "\
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2027
2028 To upload a compressed tarball, use C<guestfs_tgz_in>
2029 or C<guestfs_txz_in>.");
2030
2031   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2032    [],
2033    "pack directory into tarfile",
2034    "\
2035 This command packs the contents of C<directory> and downloads
2036 it to local file C<tarfile>.
2037
2038 To download a compressed tarball, use C<guestfs_tgz_out>
2039 or C<guestfs_txz_out>.");
2040
2041   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2042    [InitBasicFS, Always, TestOutput (
2043       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2044        ["cat"; "/hello"]], "hello\n")],
2045    "unpack compressed tarball to directory",
2046    "\
2047 This command uploads and unpacks local file C<tarball> (a
2048 I<gzip compressed> tar file) into C<directory>.
2049
2050 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2051
2052   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2053    [],
2054    "pack directory into compressed tarball",
2055    "\
2056 This command packs the contents of C<directory> and downloads
2057 it to local file C<tarball>.
2058
2059 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2060
2061   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2062    [InitBasicFS, Always, TestLastFail (
2063       [["umount"; "/"];
2064        ["mount_ro"; "/dev/sda1"; "/"];
2065        ["touch"; "/new"]]);
2066     InitBasicFS, Always, TestOutput (
2067       [["write_file"; "/new"; "data"; "0"];
2068        ["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["cat"; "/new"]], "data")],
2071    "mount a guest disk, read-only",
2072    "\
2073 This is the same as the C<guestfs_mount> command, but it
2074 mounts the filesystem with the read-only (I<-o ro>) flag.");
2075
2076   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2077    [],
2078    "mount a guest disk with mount options",
2079    "\
2080 This is the same as the C<guestfs_mount> command, but it
2081 allows you to set the mount options as for the
2082 L<mount(8)> I<-o> flag.");
2083
2084   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2085    [],
2086    "mount a guest disk with mount options and vfstype",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set both the mount options and the vfstype
2090 as for the L<mount(8)> I<-o> and I<-t> flags.");
2091
2092   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2093    [],
2094    "debugging and internals",
2095    "\
2096 The C<guestfs_debug> command exposes some internals of
2097 C<guestfsd> (the guestfs daemon) that runs inside the
2098 qemu subprocess.
2099
2100 There is no comprehensive help for this command.  You have
2101 to look at the file C<daemon/debug.c> in the libguestfs source
2102 to find out what you can do.");
2103
2104   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2105    [InitEmpty, Always, TestOutputList (
2106       [["part_disk"; "/dev/sda"; "mbr"];
2107        ["pvcreate"; "/dev/sda1"];
2108        ["vgcreate"; "VG"; "/dev/sda1"];
2109        ["lvcreate"; "LV1"; "VG"; "50"];
2110        ["lvcreate"; "LV2"; "VG"; "50"];
2111        ["lvremove"; "/dev/VG/LV1"];
2112        ["lvs"]], ["/dev/VG/LV2"]);
2113     InitEmpty, Always, TestOutputList (
2114       [["part_disk"; "/dev/sda"; "mbr"];
2115        ["pvcreate"; "/dev/sda1"];
2116        ["vgcreate"; "VG"; "/dev/sda1"];
2117        ["lvcreate"; "LV1"; "VG"; "50"];
2118        ["lvcreate"; "LV2"; "VG"; "50"];
2119        ["lvremove"; "/dev/VG"];
2120        ["lvs"]], []);
2121     InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG"];
2128        ["vgs"]], ["VG"])],
2129    "remove an LVM logical volume",
2130    "\
2131 Remove an LVM logical volume C<device>, where C<device> is
2132 the path to the LV, such as C</dev/VG/LV>.
2133
2134 You can also remove all LVs in a volume group by specifying
2135 the VG name, C</dev/VG>.");
2136
2137   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["vgremove"; "VG"];
2145        ["lvs"]], []);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["vgremove"; "VG"];
2153        ["vgs"]], [])],
2154    "remove an LVM volume group",
2155    "\
2156 Remove an LVM volume group C<vgname>, (for example C<VG>).
2157
2158 This also forcibly removes all logical volumes in the volume
2159 group (if any).");
2160
2161   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2162    [InitEmpty, Always, TestOutputListOfDevices (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["pvremove"; "/dev/sda1"];
2170        ["lvs"]], []);
2171     InitEmpty, Always, TestOutputListOfDevices (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["pvremove"; "/dev/sda1"];
2179        ["vgs"]], []);
2180     InitEmpty, Always, TestOutputListOfDevices (
2181       [["part_disk"; "/dev/sda"; "mbr"];
2182        ["pvcreate"; "/dev/sda1"];
2183        ["vgcreate"; "VG"; "/dev/sda1"];
2184        ["lvcreate"; "LV1"; "VG"; "50"];
2185        ["lvcreate"; "LV2"; "VG"; "50"];
2186        ["vgremove"; "VG"];
2187        ["pvremove"; "/dev/sda1"];
2188        ["pvs"]], [])],
2189    "remove an LVM physical volume",
2190    "\
2191 This wipes a physical volume C<device> so that LVM will no longer
2192 recognise it.
2193
2194 The implementation uses the C<pvremove> command which refuses to
2195 wipe physical volumes that contain any volume groups, so you have
2196 to remove those first.");
2197
2198   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2199    [InitBasicFS, Always, TestOutput (
2200       [["set_e2label"; "/dev/sda1"; "testlabel"];
2201        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2202    "set the ext2/3/4 filesystem label",
2203    "\
2204 This sets the ext2/3/4 filesystem label of the filesystem on
2205 C<device> to C<label>.  Filesystem labels are limited to
2206 16 characters.
2207
2208 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2209 to return the existing label on a filesystem.");
2210
2211   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2212    [],
2213    "get the ext2/3/4 filesystem label",
2214    "\
2215 This returns the ext2/3/4 filesystem label of the filesystem on
2216 C<device>.");
2217
2218   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2219    (let uuid = uuidgen () in
2220     [InitBasicFS, Always, TestOutput (
2221        [["set_e2uuid"; "/dev/sda1"; uuid];
2222         ["get_e2uuid"; "/dev/sda1"]], uuid);
2223      InitBasicFS, Always, TestOutput (
2224        [["set_e2uuid"; "/dev/sda1"; "clear"];
2225         ["get_e2uuid"; "/dev/sda1"]], "");
2226      (* We can't predict what UUIDs will be, so just check the commands run. *)
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2229      InitBasicFS, Always, TestRun (
2230        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2231    "set the ext2/3/4 filesystem UUID",
2232    "\
2233 This sets the ext2/3/4 filesystem UUID of the filesystem on
2234 C<device> to C<uuid>.  The format of the UUID and alternatives
2235 such as C<clear>, C<random> and C<time> are described in the
2236 L<tune2fs(8)> manpage.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2239 to return the existing UUID of a filesystem.");
2240
2241   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2242    [],
2243    "get the ext2/3/4 filesystem UUID",
2244    "\
2245 This returns the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device>.");
2247
2248   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2249    [InitBasicFS, Always, TestOutputInt (
2250       [["umount"; "/dev/sda1"];
2251        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2252     InitBasicFS, Always, TestOutputInt (
2253       [["umount"; "/dev/sda1"];
2254        ["zero"; "/dev/sda1"];
2255        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2256    "run the filesystem checker",
2257    "\
2258 This runs the filesystem checker (fsck) on C<device> which
2259 should have filesystem type C<fstype>.
2260
2261 The returned integer is the status.  See L<fsck(8)> for the
2262 list of status codes from C<fsck>.
2263
2264 Notes:
2265
2266 =over 4
2267
2268 =item *
2269
2270 Multiple status codes can be summed together.
2271
2272 =item *
2273
2274 A non-zero return code can mean \"success\", for example if
2275 errors have been corrected on the filesystem.
2276
2277 =item *
2278
2279 Checking or repairing NTFS volumes is not supported
2280 (by linux-ntfs).
2281
2282 =back
2283
2284 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2285
2286   ("zero", (RErr, [Device "device"]), 85, [],
2287    [InitBasicFS, Always, TestOutput (
2288       [["umount"; "/dev/sda1"];
2289        ["zero"; "/dev/sda1"];
2290        ["file"; "/dev/sda1"]], "data")],
2291    "write zeroes to the device",
2292    "\
2293 This command writes zeroes over the first few blocks of C<device>.
2294
2295 How many blocks are zeroed isn't specified (but it's I<not> enough
2296 to securely wipe the device).  It should be sufficient to remove
2297 any partition tables, filesystem superblocks and so on.
2298
2299 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2300
2301   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2302    (* Test disabled because grub-install incompatible with virtio-blk driver.
2303     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2304     *)
2305    [InitBasicFS, Disabled, TestOutputTrue (
2306       [["grub_install"; "/"; "/dev/sda1"];
2307        ["is_dir"; "/boot"]])],
2308    "install GRUB",
2309    "\
2310 This command installs GRUB (the Grand Unified Bootloader) on
2311 C<device>, with the root directory being C<root>.");
2312
2313   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2314    [InitBasicFS, Always, TestOutput (
2315       [["write_file"; "/old"; "file content"; "0"];
2316        ["cp"; "/old"; "/new"];
2317        ["cat"; "/new"]], "file content");
2318     InitBasicFS, Always, TestOutputTrue (
2319       [["write_file"; "/old"; "file content"; "0"];
2320        ["cp"; "/old"; "/new"];
2321        ["is_file"; "/old"]]);
2322     InitBasicFS, Always, TestOutput (
2323       [["write_file"; "/old"; "file content"; "0"];
2324        ["mkdir"; "/dir"];
2325        ["cp"; "/old"; "/dir/new"];
2326        ["cat"; "/dir/new"]], "file content")],
2327    "copy a file",
2328    "\
2329 This copies a file from C<src> to C<dest> where C<dest> is
2330 either a destination filename or destination directory.");
2331
2332   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2333    [InitBasicFS, Always, TestOutput (
2334       [["mkdir"; "/olddir"];
2335        ["mkdir"; "/newdir"];
2336        ["write_file"; "/olddir/file"; "file content"; "0"];
2337        ["cp_a"; "/olddir"; "/newdir"];
2338        ["cat"; "/newdir/olddir/file"]], "file content")],
2339    "copy a file or directory recursively",
2340    "\
2341 This copies a file or directory from C<src> to C<dest>
2342 recursively using the C<cp -a> command.");
2343
2344   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["write_file"; "/old"; "file content"; "0"];
2347        ["mv"; "/old"; "/new"];
2348        ["cat"; "/new"]], "file content");
2349     InitBasicFS, Always, TestOutputFalse (
2350       [["write_file"; "/old"; "file content"; "0"];
2351        ["mv"; "/old"; "/new"];
2352        ["is_file"; "/old"]])],
2353    "move a file",
2354    "\
2355 This moves a file from C<src> to C<dest> where C<dest> is
2356 either a destination filename or destination directory.");
2357
2358   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2359    [InitEmpty, Always, TestRun (
2360       [["drop_caches"; "3"]])],
2361    "drop kernel page cache, dentries and inodes",
2362    "\
2363 This instructs the guest kernel to drop its page cache,
2364 and/or dentries and inode caches.  The parameter C<whattodrop>
2365 tells the kernel what precisely to drop, see
2366 L<http://linux-mm.org/Drop_Caches>
2367
2368 Setting C<whattodrop> to 3 should drop everything.
2369
2370 This automatically calls L<sync(2)> before the operation,
2371 so that the maximum guest memory is freed.");
2372
2373   ("dmesg", (RString "kmsgs", []), 91, [],
2374    [InitEmpty, Always, TestRun (
2375       [["dmesg"]])],
2376    "return kernel messages",
2377    "\
2378 This returns the kernel messages (C<dmesg> output) from
2379 the guest kernel.  This is sometimes useful for extended
2380 debugging of problems.
2381
2382 Another way to get the same information is to enable
2383 verbose messages with C<guestfs_set_verbose> or by setting
2384 the environment variable C<LIBGUESTFS_DEBUG=1> before
2385 running the program.");
2386
2387   ("ping_daemon", (RErr, []), 92, [],
2388    [InitEmpty, Always, TestRun (
2389       [["ping_daemon"]])],
2390    "ping the guest daemon",
2391    "\
2392 This is a test probe into the guestfs daemon running inside
2393 the qemu subprocess.  Calling this function checks that the
2394 daemon responds to the ping message, without affecting the daemon
2395 or attached block device(s) in any other way.");
2396
2397   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2398    [InitBasicFS, Always, TestOutputTrue (
2399       [["write_file"; "/file1"; "contents of a file"; "0"];
2400        ["cp"; "/file1"; "/file2"];
2401        ["equal"; "/file1"; "/file2"]]);
2402     InitBasicFS, Always, TestOutputFalse (
2403       [["write_file"; "/file1"; "contents of a file"; "0"];
2404        ["write_file"; "/file2"; "contents of another file"; "0"];
2405        ["equal"; "/file1"; "/file2"]]);
2406     InitBasicFS, Always, TestLastFail (
2407       [["equal"; "/file1"; "/file2"]])],
2408    "test if two files have equal contents",
2409    "\
2410 This compares the two files C<file1> and C<file2> and returns
2411 true if their content is exactly equal, or false otherwise.
2412
2413 The external L<cmp(1)> program is used for the comparison.");
2414
2415   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2416    [InitISOFS, Always, TestOutputList (
2417       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2418     InitISOFS, Always, TestOutputList (
2419       [["strings"; "/empty"]], [])],
2420    "print the printable strings in a file",
2421    "\
2422 This runs the L<strings(1)> command on a file and returns
2423 the list of printable strings found.");
2424
2425   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings_e"; "b"; "/known-5"]], []);
2428     InitBasicFS, Disabled, TestOutputList (
2429       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2430        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2431    "print the printable strings in a file",
2432    "\
2433 This is like the C<guestfs_strings> command, but allows you to
2434 specify the encoding.
2435
2436 See the L<strings(1)> manpage for the full list of encodings.
2437
2438 Commonly useful encodings are C<l> (lower case L) which will
2439 show strings inside Windows/x86 files.
2440
2441 The returned strings are transcoded to UTF-8.");
2442
2443   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2444    [InitISOFS, Always, TestOutput (
2445       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2446     (* Test for RHBZ#501888c2 regression which caused large hexdump
2447      * commands to segfault.
2448      *)
2449     InitISOFS, Always, TestRun (
2450       [["hexdump"; "/100krandom"]])],
2451    "dump a file in hexadecimal",
2452    "\
2453 This runs C<hexdump -C> on the given C<path>.  The result is
2454 the human-readable, canonical hex dump of the file.");
2455
2456   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2457    [InitNone, Always, TestOutput (
2458       [["part_disk"; "/dev/sda"; "mbr"];
2459        ["mkfs"; "ext3"; "/dev/sda1"];
2460        ["mount_options"; ""; "/dev/sda1"; "/"];
2461        ["write_file"; "/new"; "test file"; "0"];
2462        ["umount"; "/dev/sda1"];
2463        ["zerofree"; "/dev/sda1"];
2464        ["mount_options"; ""; "/dev/sda1"; "/"];
2465        ["cat"; "/new"]], "test file")],
2466    "zero unused inodes and disk blocks on ext2/3 filesystem",
2467    "\
2468 This runs the I<zerofree> program on C<device>.  This program
2469 claims to zero unused inodes and disk blocks on an ext2/3
2470 filesystem, thus making it possible to compress the filesystem
2471 more effectively.
2472
2473 You should B<not> run this program if the filesystem is
2474 mounted.
2475
2476 It is possible that using this program can damage the filesystem
2477 or data on the filesystem.");
2478
2479   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2480    [],
2481    "resize an LVM physical volume",
2482    "\
2483 This resizes (expands or shrinks) an existing LVM physical
2484 volume to match the new size of the underlying device.");
2485
2486   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2487                        Int "cyls"; Int "heads"; Int "sectors";
2488                        String "line"]), 99, [DangerWillRobinson],
2489    [],
2490    "modify a single partition on a block device",
2491    "\
2492 This runs L<sfdisk(8)> option to modify just the single
2493 partition C<n> (note: C<n> counts from 1).
2494
2495 For other parameters, see C<guestfs_sfdisk>.  You should usually
2496 pass C<0> for the cyls/heads/sectors parameters.
2497
2498 See also: C<guestfs_part_add>");
2499
2500   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2501    [],
2502    "display the partition table",
2503    "\
2504 This displays the partition table on C<device>, in the
2505 human-readable output of the L<sfdisk(8)> command.  It is
2506 not intended to be parsed.
2507
2508 See also: C<guestfs_part_list>");
2509
2510   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2511    [],
2512    "display the kernel geometry",
2513    "\
2514 This displays the kernel's idea of the geometry of C<device>.
2515
2516 The result is in human-readable format, and not designed to
2517 be parsed.");
2518
2519   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2520    [],
2521    "display the disk geometry from the partition table",
2522    "\
2523 This displays the disk geometry of C<device> read from the
2524 partition table.  Especially in the case where the underlying
2525 block device has been resized, this can be different from the
2526 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2527
2528 The result is in human-readable format, and not designed to
2529 be parsed.");
2530
2531   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2532    [],
2533    "activate or deactivate all volume groups",
2534    "\
2535 This command activates or (if C<activate> is false) deactivates
2536 all logical volumes in all volume groups.
2537 If activated, then they are made known to the
2538 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2539 then those devices disappear.
2540
2541 This command is the same as running C<vgchange -a y|n>");
2542
2543   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2544    [],
2545    "activate or deactivate some volume groups",
2546    "\
2547 This command activates or (if C<activate> is false) deactivates
2548 all logical volumes in the listed volume groups C<volgroups>.
2549 If activated, then they are made known to the
2550 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2551 then those devices disappear.
2552
2553 This command is the same as running C<vgchange -a y|n volgroups...>
2554
2555 Note that if C<volgroups> is an empty list then B<all> volume groups
2556 are activated or deactivated.");
2557
2558   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2559    [InitNone, Always, TestOutput (
2560       [["part_disk"; "/dev/sda"; "mbr"];
2561        ["pvcreate"; "/dev/sda1"];
2562        ["vgcreate"; "VG"; "/dev/sda1"];
2563        ["lvcreate"; "LV"; "VG"; "10"];
2564        ["mkfs"; "ext2"; "/dev/VG/LV"];
2565        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2566        ["write_file"; "/new"; "test content"; "0"];
2567        ["umount"; "/"];
2568        ["lvresize"; "/dev/VG/LV"; "20"];
2569        ["e2fsck_f"; "/dev/VG/LV"];
2570        ["resize2fs"; "/dev/VG/LV"];
2571        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2572        ["cat"; "/new"]], "test content")],
2573    "resize an LVM logical volume",
2574    "\
2575 This resizes (expands or shrinks) an existing LVM logical
2576 volume to C<mbytes>.  When reducing, data in the reduced part
2577 is lost.");
2578
2579   ("resize2fs", (RErr, [Device "device"]), 106, [],
2580    [], (* lvresize tests this *)
2581    "resize an ext2/ext3 filesystem",
2582    "\
2583 This resizes an ext2 or ext3 filesystem to match the size of
2584 the underlying device.
2585
2586 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2587 on the C<device> before calling this command.  For unknown reasons
2588 C<resize2fs> sometimes gives an error about this and sometimes not.
2589 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2590 calling this function.");
2591
2592   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2593    [InitBasicFS, Always, TestOutputList (
2594       [["find"; "/"]], ["lost+found"]);
2595     InitBasicFS, Always, TestOutputList (
2596       [["touch"; "/a"];
2597        ["mkdir"; "/b"];
2598        ["touch"; "/b/c"];
2599        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2600     InitBasicFS, Always, TestOutputList (
2601       [["mkdir_p"; "/a/b/c"];
2602        ["touch"; "/a/b/c/d"];
2603        ["find"; "/a/b/"]], ["c"; "c/d"])],
2604    "find all files and directories",
2605    "\
2606 This command lists out all files and directories, recursively,
2607 starting at C<directory>.  It is essentially equivalent to
2608 running the shell command C<find directory -print> but some
2609 post-processing happens on the output, described below.
2610
2611 This returns a list of strings I<without any prefix>.  Thus
2612 if the directory structure was:
2613
2614  /tmp/a
2615  /tmp/b
2616  /tmp/c/d
2617
2618 then the returned list from C<guestfs_find> C</tmp> would be
2619 4 elements:
2620
2621  a
2622  b
2623  c
2624  c/d
2625
2626 If C<directory> is not a directory, then this command returns
2627 an error.
2628
2629 The returned list is sorted.
2630
2631 See also C<guestfs_find0>.");
2632
2633   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2634    [], (* lvresize tests this *)
2635    "check an ext2/ext3 filesystem",
2636    "\
2637 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2638 filesystem checker on C<device>, noninteractively (C<-p>),
2639 even if the filesystem appears to be clean (C<-f>).
2640
2641 This command is only needed because of C<guestfs_resize2fs>
2642 (q.v.).  Normally you should use C<guestfs_fsck>.");
2643
2644   ("sleep", (RErr, [Int "secs"]), 109, [],
2645    [InitNone, Always, TestRun (
2646       [["sleep"; "1"]])],
2647    "sleep for some seconds",
2648    "\
2649 Sleep for C<secs> seconds.");
2650
2651   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2652    [InitNone, Always, TestOutputInt (
2653       [["part_disk"; "/dev/sda"; "mbr"];
2654        ["mkfs"; "ntfs"; "/dev/sda1"];
2655        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2656     InitNone, Always, TestOutputInt (
2657       [["part_disk"; "/dev/sda"; "mbr"];
2658        ["mkfs"; "ext2"; "/dev/sda1"];
2659        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2660    "probe NTFS volume",
2661    "\
2662 This command runs the L<ntfs-3g.probe(8)> command which probes
2663 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2664 be mounted read-write, and some cannot be mounted at all).
2665
2666 C<rw> is a boolean flag.  Set it to true if you want to test
2667 if the volume can be mounted read-write.  Set it to false if
2668 you want to test if the volume can be mounted read-only.
2669
2670 The return value is an integer which C<0> if the operation
2671 would succeed, or some non-zero value documented in the
2672 L<ntfs-3g.probe(8)> manual page.");
2673
2674   ("sh", (RString "output", [String "command"]), 111, [],
2675    [], (* XXX needs tests *)
2676    "run a command via the shell",
2677    "\
2678 This call runs a command from the guest filesystem via the
2679 guest's C</bin/sh>.
2680
2681 This is like C<guestfs_command>, but passes the command to:
2682
2683  /bin/sh -c \"command\"
2684
2685 Depending on the guest's shell, this usually results in
2686 wildcards being expanded, shell expressions being interpolated
2687 and so on.
2688
2689 All the provisos about C<guestfs_command> apply to this call.");
2690
2691   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2692    [], (* XXX needs tests *)
2693    "run a command via the shell returning lines",
2694    "\
2695 This is the same as C<guestfs_sh>, but splits the result
2696 into a list of lines.
2697
2698 See also: C<guestfs_command_lines>");
2699
2700   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2701    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2702     * code in stubs.c, since all valid glob patterns must start with "/".
2703     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2704     *)
2705    [InitBasicFS, Always, TestOutputList (
2706       [["mkdir_p"; "/a/b/c"];
2707        ["touch"; "/a/b/c/d"];
2708        ["touch"; "/a/b/c/e"];
2709        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2710     InitBasicFS, Always, TestOutputList (
2711       [["mkdir_p"; "/a/b/c"];
2712        ["touch"; "/a/b/c/d"];
2713        ["touch"; "/a/b/c/e"];
2714        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2715     InitBasicFS, Always, TestOutputList (
2716       [["mkdir_p"; "/a/b/c"];
2717        ["touch"; "/a/b/c/d"];
2718        ["touch"; "/a/b/c/e"];
2719        ["glob_expand"; "/a/*/x/*"]], [])],
2720    "expand a wildcard path",
2721    "\
2722 This command searches for all the pathnames matching
2723 C<pattern> according to the wildcard expansion rules
2724 used by the shell.
2725
2726 If no paths match, then this returns an empty list
2727 (note: not an error).
2728
2729 It is just a wrapper around the C L<glob(3)> function
2730 with flags C<GLOB_MARK|GLOB_BRACE>.
2731 See that manual page for more details.");
2732
2733   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2734    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2735       [["scrub_device"; "/dev/sdc"]])],
2736    "scrub (securely wipe) a device",
2737    "\
2738 This command writes patterns over C<device> to make data retrieval
2739 more difficult.
2740
2741 It is an interface to the L<scrub(1)> program.  See that
2742 manual page for more details.");
2743
2744   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2745    [InitBasicFS, Always, TestRun (
2746       [["write_file"; "/file"; "content"; "0"];
2747        ["scrub_file"; "/file"]])],
2748    "scrub (securely wipe) a file",
2749    "\
2750 This command writes patterns over a file to make data retrieval
2751 more difficult.
2752
2753 The file is I<removed> after scrubbing.
2754
2755 It is an interface to the L<scrub(1)> program.  See that
2756 manual page for more details.");
2757
2758   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2759    [], (* XXX needs testing *)
2760    "scrub (securely wipe) free space",
2761    "\
2762 This command creates the directory C<dir> and then fills it
2763 with files until the filesystem is full, and scrubs the files
2764 as for C<guestfs_scrub_file>, and deletes them.
2765 The intention is to scrub any free space on the partition
2766 containing C<dir>.
2767
2768 It is an interface to the L<scrub(1)> program.  See that
2769 manual page for more details.");
2770
2771   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2772    [InitBasicFS, Always, TestRun (
2773       [["mkdir"; "/tmp"];
2774        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2775    "create a temporary directory",
2776    "\
2777 This command creates a temporary directory.  The
2778 C<template> parameter should be a full pathname for the
2779 temporary directory name with the final six characters being
2780 \"XXXXXX\".
2781
2782 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2783 the second one being suitable for Windows filesystems.
2784
2785 The name of the temporary directory that was created
2786 is returned.
2787
2788 The temporary directory is created with mode 0700
2789 and is owned by root.
2790
2791 The caller is responsible for deleting the temporary
2792 directory and its contents after use.
2793
2794 See also: L<mkdtemp(3)>");
2795
2796   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2797    [InitISOFS, Always, TestOutputInt (
2798       [["wc_l"; "/10klines"]], 10000)],
2799    "count lines in a file",
2800    "\
2801 This command counts the lines in a file, using the
2802 C<wc -l> external command.");
2803
2804   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2805    [InitISOFS, Always, TestOutputInt (
2806       [["wc_w"; "/10klines"]], 10000)],
2807    "count words in a file",
2808    "\
2809 This command counts the words in a file, using the
2810 C<wc -w> external command.");
2811
2812   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2813    [InitISOFS, Always, TestOutputInt (
2814       [["wc_c"; "/100kallspaces"]], 102400)],
2815    "count characters in a file",
2816    "\
2817 This command counts the characters in a file, using the
2818 C<wc -c> external command.");
2819
2820   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2821    [InitISOFS, Always, TestOutputList (
2822       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2823    "return first 10 lines of a file",
2824    "\
2825 This command returns up to the first 10 lines of a file as
2826 a list of strings.");
2827
2828   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2829    [InitISOFS, Always, TestOutputList (
2830       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2833     InitISOFS, Always, TestOutputList (
2834       [["head_n"; "0"; "/10klines"]], [])],
2835    "return first N lines of a file",
2836    "\
2837 If the parameter C<nrlines> is a positive number, this returns the first
2838 C<nrlines> lines of the file C<path>.
2839
2840 If the parameter C<nrlines> is a negative number, this returns lines
2841 from the file C<path>, excluding the last C<nrlines> lines.
2842
2843 If the parameter C<nrlines> is zero, this returns an empty list.");
2844
2845   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2846    [InitISOFS, Always, TestOutputList (
2847       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2848    "return last 10 lines of a file",
2849    "\
2850 This command returns up to the last 10 lines of a file as
2851 a list of strings.");
2852
2853   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2854    [InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2858     InitISOFS, Always, TestOutputList (
2859       [["tail_n"; "0"; "/10klines"]], [])],
2860    "return last N lines of a file",
2861    "\
2862 If the parameter C<nrlines> is a positive number, this returns the last
2863 C<nrlines> lines of the file C<path>.
2864
2865 If the parameter C<nrlines> is a negative number, this returns lines
2866 from the file C<path>, starting with the C<-nrlines>th line.
2867
2868 If the parameter C<nrlines> is zero, this returns an empty list.");
2869
2870   ("df", (RString "output", []), 125, [],
2871    [], (* XXX Tricky to test because it depends on the exact format
2872         * of the 'df' command and other imponderables.
2873         *)
2874    "report file system disk space usage",
2875    "\
2876 This command runs the C<df> command to report disk space used.
2877
2878 This command is mostly useful for interactive sessions.  It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2881
2882   ("df_h", (RString "output", []), 126, [],
2883    [], (* XXX Tricky to test because it depends on the exact format
2884         * of the 'df' command and other imponderables.
2885         *)
2886    "report file system disk space usage (human readable)",
2887    "\
2888 This command runs the C<df -h> command to report disk space used
2889 in human-readable format.
2890
2891 This command is mostly useful for interactive sessions.  It
2892 is I<not> intended that you try to parse the output string.
2893 Use C<statvfs> from programs.");
2894
2895   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2896    [InitISOFS, Always, TestOutputInt (
2897       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2898    "estimate file space usage",
2899    "\
2900 This command runs the C<du -s> command to estimate file space
2901 usage for C<path>.
2902
2903 C<path> can be a file or a directory.  If C<path> is a directory
2904 then the estimate includes the contents of the directory and all
2905 subdirectories (recursively).
2906
2907 The result is the estimated size in I<kilobytes>
2908 (ie. units of 1024 bytes).");
2909
2910   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2911    [InitISOFS, Always, TestOutputList (
2912       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2913    "list files in an initrd",
2914    "\
2915 This command lists out files contained in an initrd.
2916
2917 The files are listed without any initial C</> character.  The
2918 files are listed in the order they appear (not necessarily
2919 alphabetical).  Directory names are listed as separate items.
2920
2921 Old Linux kernels (2.4 and earlier) used a compressed ext2
2922 filesystem as initrd.  We I<only> support the newer initramfs
2923 format (compressed cpio files).");
2924
2925   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2926    [],
2927    "mount a file using the loop device",
2928    "\
2929 This command lets you mount C<file> (a filesystem image
2930 in a file) on a mount point.  It is entirely equivalent to
2931 the command C<mount -o loop file mountpoint>.");
2932
2933   ("mkswap", (RErr, [Device "device"]), 130, [],
2934    [InitEmpty, Always, TestRun (
2935       [["part_disk"; "/dev/sda"; "mbr"];
2936        ["mkswap"; "/dev/sda1"]])],
2937    "create a swap partition",
2938    "\
2939 Create a swap partition on C<device>.");
2940
2941   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2942    [InitEmpty, Always, TestRun (
2943       [["part_disk"; "/dev/sda"; "mbr"];
2944        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2945    "create a swap partition with a label",
2946    "\
2947 Create a swap partition on C<device> with label C<label>.
2948
2949 Note that you cannot attach a swap label to a block device
2950 (eg. C</dev/sda>), just to a partition.  This appears to be
2951 a limitation of the kernel or swap tools.");
2952
2953   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2954    (let uuid = uuidgen () in
2955     [InitEmpty, Always, TestRun (
2956        [["part_disk"; "/dev/sda"; "mbr"];
2957         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2958    "create a swap partition with an explicit UUID",
2959    "\
2960 Create a swap partition on C<device> with UUID C<uuid>.");
2961
2962   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2963    [InitBasicFS, Always, TestOutputStruct (
2964       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2965        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2966        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2967     InitBasicFS, Always, TestOutputStruct (
2968       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2969        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2970    "make block, character or FIFO devices",
2971    "\
2972 This call creates block or character special devices, or
2973 named pipes (FIFOs).
2974
2975 The C<mode> parameter should be the mode, using the standard
2976 constants.  C<devmajor> and C<devminor> are the
2977 device major and minor numbers, only used when creating block
2978 and character special devices.");
2979
2980   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2981    [InitBasicFS, Always, TestOutputStruct (
2982       [["mkfifo"; "0o777"; "/node"];
2983        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2984    "make FIFO (named pipe)",
2985    "\
2986 This call creates a FIFO (named pipe) called C<path> with
2987 mode C<mode>.  It is just a convenient wrapper around
2988 C<guestfs_mknod>.");
2989
2990   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2991    [InitBasicFS, Always, TestOutputStruct (
2992       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2993        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2994    "make block device node",
2995    "\
2996 This call creates a block device node called C<path> with
2997 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2998 It is just a convenient wrapper around C<guestfs_mknod>.");
2999
3000   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3001    [InitBasicFS, Always, TestOutputStruct (
3002       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3004    "make char device node",
3005    "\
3006 This call creates a char device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3009
3010   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3011    [], (* XXX umask is one of those stateful things that we should
3012         * reset between each test.
3013         *)
3014    "set file mode creation mask (umask)",
3015    "\
3016 This function sets the mask used for creating new files and
3017 device nodes to C<mask & 0777>.
3018
3019 Typical umask values would be C<022> which creates new files
3020 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3021 C<002> which creates new files with permissions like
3022 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3023
3024 The default umask is C<022>.  This is important because it
3025 means that directories and device nodes will be created with
3026 C<0644> or C<0755> mode even if you specify C<0777>.
3027
3028 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3029
3030 This call returns the previous umask.");
3031
3032   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3033    [],
3034    "read directories entries",
3035    "\
3036 This returns the list of directory entries in directory C<dir>.
3037
3038 All entries in the directory are returned, including C<.> and
3039 C<..>.  The entries are I<not> sorted, but returned in the same
3040 order as the underlying filesystem.
3041
3042 Also this call returns basic file type information about each
3043 file.  The C<ftyp> field will contain one of the following characters:
3044
3045 =over 4
3046
3047 =item 'b'
3048
3049 Block special
3050
3051 =item 'c'
3052
3053 Char special
3054
3055 =item 'd'
3056
3057 Directory
3058
3059 =item 'f'
3060
3061 FIFO (named pipe)
3062
3063 =item 'l'
3064
3065 Symbolic link
3066
3067 =item 'r'
3068
3069 Regular file
3070
3071 =item 's'
3072
3073 Socket
3074
3075 =item 'u'
3076
3077 Unknown file type
3078
3079 =item '?'
3080
3081 The L<readdir(3)> returned a C<d_type> field with an
3082 unexpected value
3083
3084 =back
3085
3086 This function is primarily intended for use by programs.  To
3087 get a simple list of names, use C<guestfs_ls>.  To get a printable
3088 directory for human consumption, use C<guestfs_ll>.");
3089
3090   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3091    [],
3092    "create partitions on a block device",
3093    "\
3094 This is a simplified interface to the C<guestfs_sfdisk>
3095 command, where partition sizes are specified in megabytes
3096 only (rounded to the nearest cylinder) and you don't need
3097 to specify the cyls, heads and sectors parameters which
3098 were rarely if ever used anyway.
3099
3100 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3101 and C<guestfs_part_disk>");
3102
3103   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3104    [],
3105    "determine file type inside a compressed file",
3106    "\
3107 This command runs C<file> after first decompressing C<path>
3108 using C<method>.
3109
3110 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3111
3112 Since 1.0.63, use C<guestfs_file> instead which can now
3113 process compressed files.");
3114
3115   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3116    [],
3117    "list extended attributes of a file or directory",
3118    "\
3119 This call lists the extended attributes of the file or directory
3120 C<path>.
3121
3122 At the system call level, this is a combination of the
3123 L<listxattr(2)> and L<getxattr(2)> calls.
3124
3125 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3126
3127   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3128    [],
3129    "list extended attributes of a file or directory",
3130    "\
3131 This is the same as C<guestfs_getxattrs>, but if C<path>
3132 is a symbolic link, then it returns the extended attributes
3133 of the link itself.");
3134
3135   ("setxattr", (RErr, [String "xattr";
3136                        String "val"; Int "vallen"; (* will be BufferIn *)
3137                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3138    [],
3139    "set extended attribute of a file or directory",
3140    "\
3141 This call sets the extended attribute named C<xattr>
3142 of the file C<path> to the value C<val> (of length C<vallen>).
3143 The value is arbitrary 8 bit data.
3144
3145 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3146
3147   ("lsetxattr", (RErr, [String "xattr";
3148                         String "val"; Int "vallen"; (* will be BufferIn *)
3149                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3150    [],
3151    "set extended attribute of a file or directory",
3152    "\
3153 This is the same as C<guestfs_setxattr>, but if C<path>
3154 is a symbolic link, then it sets an extended attribute
3155 of the link itself.");
3156
3157   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3158    [],
3159    "remove extended attribute of a file or directory",
3160    "\
3161 This call removes the extended attribute named C<xattr>
3162 of the file C<path>.
3163
3164 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3165
3166   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3167    [],
3168    "remove extended attribute of a file or directory",
3169    "\
3170 This is the same as C<guestfs_removexattr>, but if C<path>
3171 is a symbolic link, then it removes an extended attribute
3172 of the link itself.");
3173
3174   ("mountpoints", (RHashtable "mps", []), 147, [],
3175    [],
3176    "show mountpoints",
3177    "\
3178 This call is similar to C<guestfs_mounts>.  That call returns
3179 a list of devices.  This one returns a hash table (map) of
3180 device name to directory where the device is mounted.");
3181
3182   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3183    (* This is a special case: while you would expect a parameter
3184     * of type "Pathname", that doesn't work, because it implies
3185     * NEED_ROOT in the generated calling code in stubs.c, and
3186     * this function cannot use NEED_ROOT.
3187     *)
3188    [],
3189    "create a mountpoint",
3190    "\
3191 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3192 specialized calls that can be used to create extra mountpoints
3193 before mounting the first filesystem.
3194
3195 These calls are I<only> necessary in some very limited circumstances,
3196 mainly the case where you want to mount a mix of unrelated and/or
3197 read-only filesystems together.
3198
3199 For example, live CDs often contain a \"Russian doll\" nest of
3200 filesystems, an ISO outer layer, with a squashfs image inside, with
3201 an ext2/3 image inside that.  You can unpack this as follows
3202 in guestfish:
3203
3204  add-ro Fedora-11-i686-Live.iso
3205  run
3206  mkmountpoint /cd
3207  mkmountpoint /squash
3208  mkmountpoint /ext3
3209  mount /dev/sda /cd
3210  mount-loop /cd/LiveOS/squashfs.img /squash
3211  mount-loop /squash/LiveOS/ext3fs.img /ext3
3212
3213 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3214
3215   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3216    [],
3217    "remove a mountpoint",
3218    "\
3219 This calls removes a mountpoint that was previously created
3220 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3221 for full details.");
3222
3223   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3224    [InitISOFS, Always, TestOutputBuffer (
3225       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3226    "read a file",
3227    "\
3228 This calls returns the contents of the file C<path> as a
3229 buffer.
3230
3231 Unlike C<guestfs_cat>, this function can correctly
3232 handle files that contain embedded ASCII NUL characters.
3233 However unlike C<guestfs_download>, this function is limited
3234 in the total size of file that can be handled.");
3235
3236   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3237    [InitISOFS, Always, TestOutputList (
3238       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3239     InitISOFS, Always, TestOutputList (
3240       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3241    "return lines matching a pattern",
3242    "\
3243 This calls the external C<grep> program and returns the
3244 matching lines.");
3245
3246   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3247    [InitISOFS, Always, TestOutputList (
3248       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3249    "return lines matching a pattern",
3250    "\
3251 This calls the external C<egrep> program and returns the
3252 matching lines.");
3253
3254   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3255    [InitISOFS, Always, TestOutputList (
3256       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3257    "return lines matching a pattern",
3258    "\
3259 This calls the external C<fgrep> program and returns the
3260 matching lines.");
3261
3262   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3263    [InitISOFS, Always, TestOutputList (
3264       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3265    "return lines matching a pattern",
3266    "\
3267 This calls the external C<grep -i> program and returns the
3268 matching lines.");
3269
3270   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3271    [InitISOFS, Always, TestOutputList (
3272       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3273    "return lines matching a pattern",
3274    "\
3275 This calls the external C<egrep -i> program and returns the
3276 matching lines.");
3277
3278   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3279    [InitISOFS, Always, TestOutputList (
3280       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3281    "return lines matching a pattern",
3282    "\
3283 This calls the external C<fgrep -i> program and returns the
3284 matching lines.");
3285
3286   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputList (
3288       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3289    "return lines matching a pattern",
3290    "\
3291 This calls the external C<zgrep> program and returns the
3292 matching lines.");
3293
3294   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3295    [InitISOFS, Always, TestOutputList (
3296       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3297    "return lines matching a pattern",
3298    "\
3299 This calls the external C<zegrep> program and returns the
3300 matching lines.");
3301
3302   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3303    [InitISOFS, Always, TestOutputList (
3304       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3305    "return lines matching a pattern",
3306    "\
3307 This calls the external C<zfgrep> program and returns the
3308 matching lines.");
3309
3310   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3311    [InitISOFS, Always, TestOutputList (
3312       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3313    "return lines matching a pattern",
3314    "\
3315 This calls the external C<zgrep -i> program and returns the
3316 matching lines.");
3317
3318   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3319    [InitISOFS, Always, TestOutputList (
3320       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<zegrep -i> program and returns the
3324 matching lines.");
3325
3326   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<zfgrep -i> program and returns the
3332 matching lines.");
3333
3334   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3335    [InitISOFS, Always, TestOutput (
3336       [["realpath"; "/../directory"]], "/directory")],
3337    "canonicalized absolute pathname",
3338    "\
3339 Return the canonicalized absolute pathname of C<path>.  The
3340 returned path has no C<.>, C<..> or symbolic link path elements.");
3341
3342   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3343    [InitBasicFS, Always, TestOutputStruct (
3344       [["touch"; "/a"];
3345        ["ln"; "/a"; "/b"];
3346        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3347    "create a hard link",
3348    "\
3349 This command creates a hard link using the C<ln> command.");
3350
3351   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3352    [InitBasicFS, Always, TestOutputStruct (
3353       [["touch"; "/a"];
3354        ["touch"; "/b"];
3355        ["ln_f"; "/a"; "/b"];
3356        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357    "create a hard link",
3358    "\
3359 This command creates a hard link using the C<ln -f> command.
3360 The C<-f> option removes the link (C<linkname>) if it exists already.");
3361
3362   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3363    [InitBasicFS, Always, TestOutputStruct (
3364       [["touch"; "/a"];
3365        ["ln_s"; "a"; "/b"];
3366        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3367    "create a symbolic link",
3368    "\
3369 This command creates a symbolic link using the C<ln -s> command.");
3370
3371   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3372    [InitBasicFS, Always, TestOutput (
3373       [["mkdir_p"; "/a/b"];
3374        ["touch"; "/a/b/c"];
3375        ["ln_sf"; "../d"; "/a/b/c"];
3376        ["readlink"; "/a/b/c"]], "../d")],
3377    "create a symbolic link",
3378    "\
3379 This command creates a symbolic link using the C<ln -sf> command,
3380 The C<-f> option removes the link (C<linkname>) if it exists already.");
3381
3382   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3383    [] (* XXX tested above *),
3384    "read the target of a symbolic link",
3385    "\
3386 This command reads the target of a symbolic link.");
3387
3388   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3389    [InitBasicFS, Always, TestOutputStruct (
3390       [["fallocate"; "/a"; "1000000"];
3391        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3392    "preallocate a file in the guest filesystem",
3393    "\
3394 This command preallocates a file (containing zero bytes) named
3395 C<path> of size C<len> bytes.  If the file exists already, it
3396 is overwritten.
3397
3398 Do not confuse this with the guestfish-specific
3399 C<alloc> command which allocates a file in the host and
3400 attaches it as a device.");
3401
3402   ("swapon_device", (RErr, [Device "device"]), 170, [],
3403    [InitPartition, Always, TestRun (
3404       [["mkswap"; "/dev/sda1"];
3405        ["swapon_device"; "/dev/sda1"];
3406        ["swapoff_device"; "/dev/sda1"]])],
3407    "enable swap on device",
3408    "\
3409 This command enables the libguestfs appliance to use the
3410 swap device or partition named C<device>.  The increased
3411 memory is made available for all commands, for example
3412 those run using C<guestfs_command> or C<guestfs_sh>.
3413
3414 Note that you should not swap to existing guest swap
3415 partitions unless you know what you are doing.  They may
3416 contain hibernation information, or other information that
3417 the guest doesn't want you to trash.  You also risk leaking
3418 information about the host to the guest this way.  Instead,
3419 attach a new host device to the guest and swap on that.");
3420
3421   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3422    [], (* XXX tested by swapon_device *)
3423    "disable swap on device",
3424    "\
3425 This command disables the libguestfs appliance swap
3426 device or partition named C<device>.
3427 See C<guestfs_swapon_device>.");
3428
3429   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3430    [InitBasicFS, Always, TestRun (
3431       [["fallocate"; "/swap"; "8388608"];
3432        ["mkswap_file"; "/swap"];
3433        ["swapon_file"; "/swap"];
3434        ["swapoff_file"; "/swap"]])],
3435    "enable swap on file",
3436    "\
3437 This command enables swap to a file.
3438 See C<guestfs_swapon_device> for other notes.");
3439
3440   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3441    [], (* XXX tested by swapon_file *)
3442    "disable swap on file",
3443    "\
3444 This command disables the libguestfs appliance swap on file.");
3445
3446   ("swapon_label", (RErr, [String "label"]), 174, [],
3447    [InitEmpty, Always, TestRun (
3448       [["part_disk"; "/dev/sdb"; "mbr"];
3449        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3450        ["swapon_label"; "swapit"];
3451        ["swapoff_label"; "swapit"];
3452        ["zero"; "/dev/sdb"];
3453        ["blockdev_rereadpt"; "/dev/sdb"]])],
3454    "enable swap on labeled swap partition",
3455    "\
3456 This command enables swap to a labeled swap partition.
3457 See C<guestfs_swapon_device> for other notes.");
3458
3459   ("swapoff_label", (RErr, [String "label"]), 175, [],
3460    [], (* XXX tested by swapon_label *)
3461    "disable swap on labeled swap partition",
3462    "\
3463 This command disables the libguestfs appliance swap on
3464 labeled swap partition.");
3465
3466   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3467    (let uuid = uuidgen () in
3468     [InitEmpty, Always, TestRun (
3469        [["mkswap_U"; uuid; "/dev/sdb"];
3470         ["swapon_uuid"; uuid];
3471         ["swapoff_uuid"; uuid]])]),
3472    "enable swap on swap partition by UUID",
3473    "\
3474 This command enables swap to a swap partition with the given UUID.
3475 See C<guestfs_swapon_device> for other notes.");
3476
3477   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3478    [], (* XXX tested by swapon_uuid *)
3479    "disable swap on swap partition by UUID",
3480    "\
3481 This command disables the libguestfs appliance swap partition
3482 with the given UUID.");
3483
3484   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3485    [InitBasicFS, Always, TestRun (
3486       [["fallocate"; "/swap"; "8388608"];
3487        ["mkswap_file"; "/swap"]])],
3488    "create a swap file",
3489    "\
3490 Create a swap file.
3491
3492 This command just writes a swap file signature to an existing
3493 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3494
3495   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3496    [InitISOFS, Always, TestRun (
3497       [["inotify_init"; "0"]])],
3498    "create an inotify handle",
3499    "\
3500 This command creates a new inotify handle.
3501 The inotify subsystem can be used to notify events which happen to
3502 objects in the guest filesystem.
3503
3504 C<maxevents> is the maximum number of events which will be
3505 queued up between calls to C<guestfs_inotify_read> or
3506 C<guestfs_inotify_files>.
3507 If this is passed as C<0>, then the kernel (or previously set)
3508 default is used.  For Linux 2.6.29 the default was 16384 events.
3509 Beyond this limit, the kernel throws away events, but records
3510 the fact that it threw them away by setting a flag
3511 C<IN_Q_OVERFLOW> in the returned structure list (see
3512 C<guestfs_inotify_read>).
3513
3514 Before any events are generated, you have to add some
3515 watches to the internal watch list.  See:
3516 C<guestfs_inotify_add_watch>,
3517 C<guestfs_inotify_rm_watch> and
3518 C<guestfs_inotify_watch_all>.
3519
3520 Queued up events should be read periodically by calling
3521 C<guestfs_inotify_read>
3522 (or C<guestfs_inotify_files> which is just a helpful
3523 wrapper around C<guestfs_inotify_read>).  If you don't
3524 read the events out often enough then you risk the internal
3525 queue overflowing.
3526
3527 The handle should be closed after use by calling
3528 C<guestfs_inotify_close>.  This also removes any
3529 watches automatically.
3530
3531 See also L<inotify(7)> for an overview of the inotify interface
3532 as exposed by the Linux kernel, which is roughly what we expose
3533 via libguestfs.  Note that there is one global inotify handle
3534 per libguestfs instance.");
3535
3536   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3537    [InitBasicFS, Always, TestOutputList (
3538       [["inotify_init"; "0"];
3539        ["inotify_add_watch"; "/"; "1073741823"];
3540        ["touch"; "/a"];
3541        ["touch"; "/b"];
3542        ["inotify_files"]], ["a"; "b"])],
3543    "add an inotify watch",
3544    "\
3545 Watch C<path> for the events listed in C<mask>.
3546
3547 Note that if C<path> is a directory then events within that
3548 directory are watched, but this does I<not> happen recursively
3549 (in subdirectories).
3550
3551 Note for non-C or non-Linux callers: the inotify events are
3552 defined by the Linux kernel ABI and are listed in
3553 C</usr/include/sys/inotify.h>.");
3554
3555   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3556    [],
3557    "remove an inotify watch",
3558    "\
3559 Remove a previously defined inotify watch.
3560 See C<guestfs_inotify_add_watch>.");
3561
3562   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3563    [],
3564    "return list of inotify events",
3565    "\
3566 Return the complete queue of events that have happened
3567 since the previous read call.
3568
3569 If no events have happened, this returns an empty list.
3570
3571 I<Note>: In order to make sure that all events have been
3572 read, you must call this function repeatedly until it
3573 returns an empty list.  The reason is that the call will
3574 read events up to the maximum appliance-to-host message
3575 size and leave remaining events in the queue.");
3576
3577   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3578    [],
3579    "return list of watched files that had events",
3580    "\
3581 This function is a helpful wrapper around C<guestfs_inotify_read>
3582 which just returns a list of pathnames of objects that were
3583 touched.  The returned pathnames are sorted and deduplicated.");
3584
3585   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3586    [],
3587    "close the inotify handle",
3588    "\
3589 This closes the inotify handle which was previously
3590 opened by inotify_init.  It removes all watches, throws
3591 away any pending events, and deallocates all resources.");
3592
3593   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3594    [],
3595    "set SELinux security context",
3596    "\
3597 This sets the SELinux security context of the daemon
3598 to the string C<context>.
3599
3600 See the documentation about SELINUX in L<guestfs(3)>.");
3601
3602   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3603    [],
3604    "get SELinux security context",
3605    "\
3606 This gets the SELinux security context of the daemon.
3607
3608 See the documentation about SELINUX in L<guestfs(3)>,
3609 and C<guestfs_setcon>");
3610
3611   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3612    [InitEmpty, Always, TestOutput (
3613       [["part_disk"; "/dev/sda"; "mbr"];
3614        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3615        ["mount_options"; ""; "/dev/sda1"; "/"];
3616        ["write_file"; "/new"; "new file contents"; "0"];
3617        ["cat"; "/new"]], "new file contents")],
3618    "make a filesystem with block size",
3619    "\
3620 This call is similar to C<guestfs_mkfs>, but it allows you to
3621 control the block size of the resulting filesystem.  Supported
3622 block sizes depend on the filesystem type, but typically they
3623 are C<1024>, C<2048> or C<4096> only.");
3624
3625   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3626    [InitEmpty, Always, TestOutput (
3627       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3628        ["mke2journal"; "4096"; "/dev/sda1"];
3629        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3630        ["mount_options"; ""; "/dev/sda2"; "/"];
3631        ["write_file"; "/new"; "new file contents"; "0"];
3632        ["cat"; "/new"]], "new file contents")],
3633    "make ext2/3/4 external journal",
3634    "\
3635 This creates an ext2 external journal on C<device>.  It is equivalent
3636 to the command:
3637
3638  mke2fs -O journal_dev -b blocksize device");
3639
3640   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3641    [InitEmpty, Always, TestOutput (
3642       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3644        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3645        ["mount_options"; ""; "/dev/sda2"; "/"];
3646        ["write_file"; "/new"; "new file contents"; "0"];
3647        ["cat"; "/new"]], "new file contents")],
3648    "make ext2/3/4 external journal with label",
3649    "\
3650 This creates an ext2 external journal on C<device> with label C<label>.");
3651
3652   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3653    (let uuid = uuidgen () in
3654     [InitEmpty, Always, TestOutput (
3655        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3656         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3657         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3658         ["mount_options"; ""; "/dev/sda2"; "/"];
3659         ["write_file"; "/new"; "new file contents"; "0"];
3660         ["cat"; "/new"]], "new file contents")]),
3661    "make ext2/3/4 external journal with UUID",
3662    "\
3663 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3664
3665   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3666    [],
3667    "make ext2/3/4 filesystem with external journal",
3668    "\
3669 This creates an ext2/3/4 filesystem on C<device> with
3670 an external journal on C<journal>.  It is equivalent
3671 to the command:
3672
3673  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3674
3675 See also C<guestfs_mke2journal>.");
3676
3677   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3678    [],
3679    "make ext2/3/4 filesystem with external journal",
3680    "\
3681 This creates an ext2/3/4 filesystem on C<device> with
3682 an external journal on the journal labeled C<label>.
3683
3684 See also C<guestfs_mke2journal_L>.");
3685
3686   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3687    [],
3688    "make ext2/3/4 filesystem with external journal",
3689    "\
3690 This creates an ext2/3/4 filesystem on C<device> with
3691 an external journal on the journal with UUID C<uuid>.
3692
3693 See also C<guestfs_mke2journal_U>.");
3694
3695   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3696    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3697    "load a kernel module",
3698    "\
3699 This loads a kernel module in the appliance.
3700
3701 The kernel module must have been whitelisted when libguestfs
3702 was built (see C<appliance/kmod.whitelist.in> in the source).");
3703
3704   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3705    [InitNone, Always, TestOutput (
3706       [["echo_daemon"; "This is a test"]], "This is a test"
3707     )],
3708    "echo arguments back to the client",
3709    "\
3710 This command concatenate the list of C<words> passed with single spaces between
3711 them and returns the resulting string.
3712
3713 You can use this command to test the connection through to the daemon.
3714
3715 See also C<guestfs_ping_daemon>.");
3716
3717   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3718    [], (* There is a regression test for this. *)
3719    "find all files and directories, returning NUL-separated list",
3720    "\
3721 This command lists out all files and directories, recursively,
3722 starting at C<directory>, placing the resulting list in the
3723 external file called C<files>.
3724
3725 This command works the same way as C<guestfs_find> with the
3726 following exceptions:
3727
3728 =over 4
3729
3730 =item *
3731
3732 The resulting list is written to an external file.
3733
3734 =item *
3735
3736 Items (filenames) in the result are separated
3737 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3738
3739 =item *
3740
3741 This command is not limited in the number of names that it
3742 can return.
3743
3744 =item *
3745
3746 The result list is not sorted.
3747
3748 =back");
3749
3750   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3751    [InitISOFS, Always, TestOutput (
3752       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3753     InitISOFS, Always, TestOutput (
3754       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3755     InitISOFS, Always, TestOutput (
3756       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3757     InitISOFS, Always, TestLastFail (
3758       [["case_sensitive_path"; "/Known-1/"]]);
3759     InitBasicFS, Always, TestOutput (
3760       [["mkdir"; "/a"];
3761        ["mkdir"; "/a/bbb"];
3762        ["touch"; "/a/bbb/c"];
3763        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3764     InitBasicFS, Always, TestOutput (
3765       [["mkdir"; "/a"];
3766        ["mkdir"; "/a/bbb"];
3767        ["touch"; "/a/bbb/c"];
3768        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3769     InitBasicFS, Always, TestLastFail (
3770       [["mkdir"; "/a"];
3771        ["mkdir"; "/a/bbb"];
3772        ["touch"; "/a/bbb/c"];
3773        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3774    "return true path on case-insensitive filesystem",
3775    "\
3776 This can be used to resolve case insensitive paths on
3777 a filesystem which is case sensitive.  The use case is
3778 to resolve paths which you have read from Windows configuration
3779 files or the Windows Registry, to the true path.
3780
3781 The command handles a peculiarity of the Linux ntfs-3g
3782 filesystem driver (and probably others), which is that although
3783 the underlying filesystem is case-insensitive, the driver
3784 exports the filesystem to Linux as case-sensitive.
3785
3786 One consequence of this is that special directories such
3787 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3788 (or other things) depending on the precise details of how
3789 they were created.  In Windows itself this would not be
3790 a problem.
3791
3792 Bug or feature?  You decide:
3793 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3794
3795 This function resolves the true case of each element in the
3796 path and returns the case-sensitive path.
3797
3798 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3799 might return C<\"/WINDOWS/system32\"> (the exact return value
3800 would depend on details of how the directories were originally
3801 created under Windows).
3802
3803 I<Note>:
3804 This function does not handle drive names, backslashes etc.
3805
3806 See also C<guestfs_realpath>.");
3807
3808   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3809    [InitBasicFS, Always, TestOutput (
3810       [["vfs_type"; "/dev/sda1"]], "ext2")],
3811    "get the Linux VFS type corresponding to a mounted device",
3812    "\
3813 This command gets the block device type corresponding to
3814 a mounted device called C<device>.
3815
3816 Usually the result is the name of the Linux VFS module that
3817 is used to mount this device (probably determined automatically
3818 if you used the C<guestfs_mount> call).");
3819
3820   ("truncate", (RErr, [Pathname "path"]), 199, [],
3821    [InitBasicFS, Always, TestOutputStruct (
3822       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3823        ["truncate"; "/test"];
3824        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3825    "truncate a file to zero size",
3826    "\
3827 This command truncates C<path> to a zero-length file.  The
3828 file must exist already.");
3829
3830   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3831    [InitBasicFS, Always, TestOutputStruct (
3832       [["touch"; "/test"];
3833        ["truncate_size"; "/test"; "1000"];
3834        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3835    "truncate a file to a particular size",
3836    "\
3837 This command truncates C<path> to size C<size> bytes.  The file
3838 must exist already.  If the file is smaller than C<size> then
3839 the file is extended to the required size with null bytes.");
3840
3841   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3842    [InitBasicFS, Always, TestOutputStruct (
3843       [["touch"; "/test"];
3844        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3845        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3846    "set timestamp of a file with nanosecond precision",
3847    "\
3848 This command sets the timestamps of a file with nanosecond
3849 precision.
3850
3851 C<atsecs, atnsecs> are the last access time (atime) in secs and
3852 nanoseconds from the epoch.
3853
3854 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3855 secs and nanoseconds from the epoch.
3856
3857 If the C<*nsecs> field contains the special value C<-1> then
3858 the corresponding timestamp is set to the current time.  (The
3859 C<*secs> field is ignored in this case).
3860
3861 If the C<*nsecs> field contains the special value C<-2> then
3862 the corresponding timestamp is left unchanged.  (The
3863 C<*secs> field is ignored in this case).");
3864
3865   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3866    [InitBasicFS, Always, TestOutputStruct (
3867       [["mkdir_mode"; "/test"; "0o111"];
3868        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3869    "create a directory with a particular mode",
3870    "\
3871 This command creates a directory, setting the initial permissions
3872 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3873
3874   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3875    [], (* XXX *)
3876    "change file owner and group",
3877    "\
3878 Change the file owner to C<owner> and group to C<group>.
3879 This is like C<guestfs_chown> but if C<path> is a symlink then
3880 the link itself is changed, not the target.
3881
3882 Only numeric uid and gid are supported.  If you want to use
3883 names, you will need to locate and parse the password file
3884 yourself (Augeas support makes this relatively easy).");
3885
3886   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3887    [], (* XXX *)
3888    "lstat on multiple files",
3889    "\
3890 This call allows you to perform the C<guestfs_lstat> operation
3891 on multiple files, where all files are in the directory C<path>.
3892 C<names> is the list of files from this directory.
3893
3894 On return you get a list of stat structs, with a one-to-one
3895 correspondence to the C<names> list.  If any name did not exist
3896 or could not be lstat'd, then the C<ino> field of that structure
3897 is set to C<-1>.
3898
3899 This call is intended for programs that want to efficiently
3900 list a directory contents without making many round-trips.
3901 See also C<guestfs_lxattrlist> for a similarly efficient call
3902 for getting extended attributes.  Very long directory listings
3903 might cause the protocol message size to be exceeded, causing
3904 this call to fail.  The caller must split up such requests
3905 into smaller groups of names.");
3906
3907   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3908    [], (* XXX *)
3909    "lgetxattr on multiple files",
3910    "\
3911 This call allows you to get the extended attributes
3912 of multiple files, where all files are in the directory C<path>.
3913 C<names> is the list of files from this directory.
3914
3915 On return you get a flat list of xattr structs which must be
3916 interpreted sequentially.  The first xattr struct always has a zero-length
3917 C<attrname>.  C<attrval> in this struct is zero-length
3918 to indicate there was an error doing C<lgetxattr> for this
3919 file, I<or> is a C string which is a decimal number
3920 (the number of following attributes for this file, which could
3921 be C<\"0\">).  Then after the first xattr struct are the
3922 zero or more attributes for the first named file.
3923 This repeats for the second and subsequent files.
3924
3925 This call is intended for programs that want to efficiently
3926 list a directory contents without making many round-trips.
3927 See also C<guestfs_lstatlist> for a similarly efficient call
3928 for getting standard stats.  Very long directory listings
3929 might cause the protocol message size to be exceeded, causing
3930 this call to fail.  The caller must split up such requests
3931 into smaller groups of names.");
3932
3933   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3934    [], (* XXX *)
3935    "readlink on multiple files",
3936    "\
3937 This call allows you to do a C<readlink> operation
3938 on multiple files, where all files are in the directory C<path>.
3939 C<names> is the list of files from this directory.
3940
3941 On return you get a list of strings, with a one-to-one
3942 correspondence to the C<names> list.  Each string is the
3943 value of the symbol link.
3944
3945 If the C<readlink(2)> operation fails on any name, then
3946 the corresponding result string is the empty string C<\"\">.
3947 However the whole operation is completed even if there
3948 were C<readlink(2)> errors, and so you can call this
3949 function with names where you don't know if they are
3950 symbolic links already (albeit slightly less efficient).
3951
3952 This call is intended for programs that want to efficiently
3953 list a directory contents without making many round-trips.
3954 Very long directory listings might cause the protocol
3955 message size to be exceeded, causing
3956 this call to fail.  The caller must split up such requests
3957 into smaller groups of names.");
3958
3959   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3960    [InitISOFS, Always, TestOutputBuffer (
3961       [["pread"; "/known-4"; "1"; "3"]], "\n");
3962     InitISOFS, Always, TestOutputBuffer (
3963       [["pread"; "/empty"; "0"; "100"]], "")],
3964    "read part of a file",
3965    "\
3966 This command lets you read part of a file.  It reads C<count>
3967 bytes of the file, starting at C<offset>, from file C<path>.
3968
3969 This may read fewer bytes than requested.  For further details
3970 see the L<pread(2)> system call.");
3971
3972   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3973    [InitEmpty, Always, TestRun (
3974       [["part_init"; "/dev/sda"; "gpt"]])],
3975    "create an empty partition table",
3976    "\
3977 This creates an empty partition table on C<device> of one of the
3978 partition types listed below.  Usually C<parttype> should be
3979 either C<msdos> or C<gpt> (for large disks).
3980
3981 Initially there are no partitions.  Following this, you should
3982 call C<guestfs_part_add> for each partition required.
3983
3984 Possible values for C<parttype> are:
3985
3986 =over 4
3987
3988 =item B<efi> | B<gpt>
3989
3990 Intel EFI / GPT partition table.
3991
3992 This is recommended for >= 2 TB partitions that will be accessed
3993 from Linux and Intel-based Mac OS X.  It also has limited backwards
3994 compatibility with the C<mbr> format.
3995
3996 =item B<mbr> | B<msdos>
3997
3998 The standard PC \"Master Boot Record\" (MBR) format used
3999 by MS-DOS and Windows.  This partition type will B<only> work
4000 for device sizes up to 2 TB.  For large disks we recommend
4001 using C<gpt>.
4002
4003 =back
4004
4005 Other partition table types that may work but are not
4006 supported include:
4007
4008 =over 4
4009
4010 =item B<aix>
4011
4012 AIX disk labels.
4013
4014 =item B<amiga> | B<rdb>
4015
4016 Amiga \"Rigid Disk Block\" format.
4017
4018 =item B<bsd>
4019
4020 BSD disk labels.
4021
4022 =item B<dasd>
4023
4024 DASD, used on IBM mainframes.
4025
4026 =item B<dvh>
4027
4028 MIPS/SGI volumes.
4029
4030 =item B<mac>
4031
4032 Old Mac partition format.  Modern Macs use C<gpt>.
4033
4034 =item B<pc98>
4035
4036 NEC PC-98 format, common in Japan apparently.
4037
4038 =item B<sun>
4039
4040 Sun disk labels.
4041
4042 =back");
4043
4044   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4045    [InitEmpty, Always, TestRun (
4046       [["part_init"; "/dev/sda"; "mbr"];
4047        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4048     InitEmpty, Always, TestRun (
4049       [["part_init"; "/dev/sda"; "gpt"];
4050        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4051        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4052     InitEmpty, Always, TestRun (
4053       [["part_init"; "/dev/sda"; "mbr"];
4054        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4055        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4056        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4057        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4058    "add a partition to the device",
4059    "\
4060 This command adds a partition to C<device>.  If there is no partition
4061 table on the device, call C<guestfs_part_init> first.
4062
4063 The C<prlogex> parameter is the type of partition.  Normally you
4064 should pass C<p> or C<primary> here, but MBR partition tables also
4065 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4066 types.
4067
4068 C<startsect> and C<endsect> are the start and end of the partition
4069 in I<sectors>.  C<endsect> may be negative, which means it counts
4070 backwards from the end of the disk (C<-1> is the last sector).
4071
4072 Creating a partition which covers the whole disk is not so easy.
4073 Use C<guestfs_part_disk> to do that.");
4074
4075   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4076    [InitEmpty, Always, TestRun (
4077       [["part_disk"; "/dev/sda"; "mbr"]]);
4078     InitEmpty, Always, TestRun (
4079       [["part_disk"; "/dev/sda"; "gpt"]])],
4080    "partition whole disk with a single primary partition",
4081    "\
4082 This command is simply a combination of C<guestfs_part_init>
4083 followed by C<guestfs_part_add> to create a single primary partition
4084 covering the whole disk.
4085
4086 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4087 but other possible values are described in C<guestfs_part_init>.");
4088
4089   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4090    [InitEmpty, Always, TestRun (
4091       [["part_disk"; "/dev/sda"; "mbr"];
4092        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4093    "make a partition bootable",
4094    "\
4095 This sets the bootable flag on partition numbered C<partnum> on
4096 device C<device>.  Note that partitions are numbered from 1.
4097
4098 The bootable flag is used by some PC BIOSes to determine which
4099 partition to boot from.  It is by no means universally recognized,
4100 and in any case if your operating system installed a boot
4101 sector on the device itself, then that takes precedence.");
4102
4103   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4104    [InitEmpty, Always, TestRun (
4105       [["part_disk"; "/dev/sda"; "gpt"];
4106        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4107    "set partition name",
4108    "\
4109 This sets the partition name on partition numbered C<partnum> on
4110 device C<device>.  Note that partitions are numbered from 1.
4111
4112 The partition name can only be set on certain types of partition
4113 table.  This works on C<gpt> but not on C<mbr> partitions.");
4114
4115   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4116    [], (* XXX Add a regression test for this. *)
4117    "list partitions on a device",
4118    "\
4119 This command parses the partition table on C<device> and
4120 returns the list of partitions found.
4121
4122 The fields in the returned structure are:
4123
4124 =over 4
4125
4126 =item B<part_num>
4127
4128 Partition number, counting from 1.
4129
4130 =item B<part_start>
4131
4132 Start of the partition I<in bytes>.  To get sectors you have to
4133 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4134
4135 =item B<part_end>
4136
4137 End of the partition in bytes.
4138
4139 =item B<part_size>
4140
4141 Size of the partition in bytes.
4142
4143 =back");
4144
4145   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4146    [InitEmpty, Always, TestOutput (
4147       [["part_disk"; "/dev/sda"; "gpt"];
4148        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4149    "get the partition table type",
4150    "\
4151 This command examines the partition table on C<device> and
4152 returns the partition table type (format) being used.
4153
4154 Common return values include: C<msdos> (a DOS/Windows style MBR
4155 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4156 values are possible, although unusual.  See C<guestfs_part_init>
4157 for a full list.");
4158
4159   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4160    [InitBasicFS, Always, TestOutputBuffer (
4161       [["fill"; "0x63"; "10"; "/test"];
4162        ["read_file"; "/test"]], "cccccccccc")],
4163    "fill a file with octets",
4164    "\
4165 This command creates a new file called C<path>.  The initial
4166 content of the file is C<len> octets of C<c>, where C<c>
4167 must be a number in the range C<[0..255]>.
4168
4169 To fill a file with zero bytes (sparsely), it is
4170 much more efficient to use C<guestfs_truncate_size>.");
4171
4172   ("available", (RErr, [StringList "groups"]), 216, [],
4173    [InitNone, Always, TestRun [["available"; ""]]],
4174    "test availability of some parts of the API",
4175    "\
4176 This command is used to check the availability of some
4177 groups of functionality in the appliance, which not all builds of
4178 the libguestfs appliance will be able to provide.
4179
4180 The libguestfs groups, and the functions that those
4181 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4182
4183 The argument C<groups> is a list of group names, eg:
4184 C<[\"inotify\", \"augeas\"]> would check for the availability of
4185 the Linux inotify functions and Augeas (configuration file
4186 editing) functions.
4187
4188 The command returns no error if I<all> requested groups are available.
4189
4190 It fails with an error if one or more of the requested
4191 groups is unavailable in the appliance.
4192
4193 If an unknown group name is included in the
4194 list of groups then an error is always returned.
4195
4196 I<Notes:>
4197
4198 =over 4
4199
4200 =item *
4201
4202 You must call C<guestfs_launch> before calling this function.
4203
4204 The reason is because we don't know what groups are
4205 supported by the appliance/daemon until it is running and can
4206 be queried.
4207
4208 =item *
4209
4210 If a group of functions is available, this does not necessarily
4211 mean that they will work.  You still have to check for errors
4212 when calling individual API functions even if they are
4213 available.
4214
4215 =item *
4216
4217 It is usually the job of distro packagers to build
4218 complete functionality into the libguestfs appliance.
4219 Upstream libguestfs, if built from source with all
4220 requirements satisfied, will support everything.
4221
4222 =item *
4223
4224 This call was added in version C<1.0.80>.  In previous
4225 versions of libguestfs all you could do would be to speculatively
4226 execute a command to find out if the daemon implemented it.
4227 See also C<guestfs_version>.
4228
4229 =back");
4230
4231   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4232    [InitBasicFS, Always, TestOutputBuffer (
4233       [["write_file"; "/src"; "hello, world"; "0"];
4234        ["dd"; "/src"; "/dest"];
4235        ["read_file"; "/dest"]], "hello, world")],
4236    "copy from source to destination using dd",
4237    "\
4238 This command copies from one source device or file C<src>
4239 to another destination device or file C<dest>.  Normally you
4240 would use this to copy to or from a device or partition, for
4241 example to duplicate a filesystem.
4242
4243 If the destination is a device, it must be as large or larger
4244 than the source file or device, otherwise the copy will fail.
4245 This command cannot do partial copies (see C<guestfs_copy_size>).");
4246
4247   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4248    [InitBasicFS, Always, TestOutputInt (
4249       [["write_file"; "/file"; "hello, world"; "0"];
4250        ["filesize"; "/file"]], 12)],
4251    "return the size of the file in bytes",
4252    "\
4253 This command returns the size of C<file> in bytes.
4254
4255 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4256 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4257 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4258
4259   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4260    [InitBasicFSonLVM, Always, TestOutputList (
4261       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4262        ["lvs"]], ["/dev/VG/LV2"])],
4263    "rename an LVM logical volume",
4264    "\
4265 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4266
4267   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4268    [InitBasicFSonLVM, Always, TestOutputList (
4269       [["umount"; "/"];
4270        ["vg_activate"; "false"; "VG"];
4271        ["vgrename"; "VG"; "VG2"];
4272        ["vg_activate"; "true"; "VG2"];
4273        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4274        ["vgs"]], ["VG2"])],
4275    "rename an LVM volume group",
4276    "\
4277 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4278
4279   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4280    [InitISOFS, Always, TestOutputBuffer (
4281       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4282    "list the contents of a single file in an initrd",
4283    "\
4284 This command unpacks the file C<filename> from the initrd file
4285 called C<initrdpath>.  The filename must be given I<without> the
4286 initial C</> character.
4287
4288 For example, in guestfish you could use the following command
4289 to examine the boot script (usually called C</init>)
4290 contained in a Linux initrd or initramfs image:
4291
4292  initrd-cat /boot/initrd-<version>.img init
4293
4294 See also C<guestfs_initrd_list>.");
4295
4296   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4297    [],
4298    "get the UUID of a physical volume",
4299    "\
4300 This command returns the UUID of the LVM PV C<device>.");
4301
4302   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4303    [],
4304    "get the UUID of a volume group",
4305    "\
4306 This command returns the UUID of the LVM VG named C<vgname>.");
4307
4308   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4309    [],
4310    "get the UUID of a logical volume",
4311    "\
4312 This command returns the UUID of the LVM LV C<device>.");
4313
4314   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4315    [],
4316    "get the PV UUIDs containing the volume group",
4317    "\
4318 Given a VG called C<vgname>, this returns the UUIDs of all
4319 the physical volumes that this volume group resides on.
4320
4321 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4322 calls to associate physical volumes and volume groups.
4323
4324 See also C<guestfs_vglvuuids>.");
4325
4326   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4327    [],
4328    "get the LV UUIDs of all LVs in the volume group",
4329    "\
4330 Given a VG called C<vgname>, this returns the UUIDs of all
4331 the logical volumes created in this volume group.
4332
4333 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4334 calls to associate logical volumes and volume groups.
4335
4336 See also C<guestfs_vgpvuuids>.");
4337
4338   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4339    [InitBasicFS, Always, TestOutputBuffer (
4340       [["write_file"; "/src"; "hello, world"; "0"];
4341        ["copy_size"; "/src"; "/dest"; "5"];
4342        ["read_file"; "/dest"]], "hello")],
4343    "copy size bytes from source to destination using dd",
4344    "\
4345 This command copies exactly C<size> bytes from one source device
4346 or file C<src> to another destination device or file C<dest>.
4347
4348 Note this will fail if the source is too short or if the destination
4349 is not large enough.");
4350
4351   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4352    [InitBasicFSonLVM, Always, TestRun (
4353       [["zero_device"; "/dev/VG/LV"]])],
4354    "write zeroes to an entire device",
4355    "\
4356 This command writes zeroes over the entire C<device>.  Compare
4357 with C<guestfs_zero> which just zeroes the first few blocks of
4358 a device.");
4359
4360   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4361    [InitBasicFS, Always, TestOutput (
4362       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4363        ["cat"; "/hello"]], "hello\n")],
4364    "unpack compressed tarball to directory",
4365    "\
4366 This command uploads and unpacks local file C<tarball> (an
4367 I<xz compressed> tar file) into C<directory>.");
4368
4369   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4370    [],
4371    "pack directory into compressed tarball",
4372    "\
4373 This command packs the contents of C<directory> and downloads
4374 it to local file C<tarball> (as an xz compressed tar archive).");
4375
4376   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4377    [],
4378    "resize an NTFS filesystem",
4379    "\
4380 This command resizes an NTFS filesystem, expanding or
4381 shrinking it to the size of the underlying device.
4382 See also L<ntfsresize(8)>.");
4383
4384 ]
4385
4386 let all_functions = non_daemon_functions @ daemon_functions
4387
4388 (* In some places we want the functions to be displayed sorted
4389  * alphabetically, so this is useful:
4390  *)
4391 let all_functions_sorted =
4392   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4393                compare n1 n2) all_functions
4394
4395 (* Field types for structures. *)
4396 type field =
4397   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4398   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4399   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4400   | FUInt32
4401   | FInt32
4402   | FUInt64
4403   | FInt64
4404   | FBytes                      (* Any int measure that counts bytes. *)
4405   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4406   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4407
4408 (* Because we generate extra parsing code for LVM command line tools,
4409  * we have to pull out the LVM columns separately here.
4410  *)
4411 let lvm_pv_cols = [
4412   "pv_name", FString;
4413   "pv_uuid", FUUID;
4414   "pv_fmt", FString;
4415   "pv_size", FBytes;
4416   "dev_size", FBytes;
4417   "pv_free", FBytes;
4418   "pv_used", FBytes;
4419   "pv_attr", FString (* XXX *);
4420   "pv_pe_count", FInt64;
4421   "pv_pe_alloc_count", FInt64;
4422   "pv_tags", FString;
4423   "pe_start", FBytes;
4424   "pv_mda_count", FInt64;
4425   "pv_mda_free", FBytes;
4426   (* Not in Fedora 10:
4427      "pv_mda_size", FBytes;
4428   *)
4429 ]
4430 let lvm_vg_cols = [
4431   "vg_name", FString;
4432   "vg_uuid", FUUID;
4433   "vg_fmt", FString;
4434   "vg_attr", FString (* XXX *);
4435   "vg_size", FBytes;
4436   "vg_free", FBytes;
4437   "vg_sysid", FString;
4438   "vg_extent_size", FBytes;
4439   "vg_extent_count", FInt64;
4440   "vg_free_count", FInt64;
4441   "max_lv", FInt64;
4442   "max_pv", FInt64;
4443   "pv_count", FInt64;
4444   "lv_count", FInt64;
4445   "snap_count", FInt64;
4446   "vg_seqno", FInt64;
4447   "vg_tags", FString;
4448   "vg_mda_count", FInt64;
4449   "vg_mda_free", FBytes;
4450   (* Not in Fedora 10:
4451      "vg_mda_size", FBytes;
4452   *)
4453 ]
4454 let lvm_lv_cols = [
4455   "lv_name", FString;
4456   "lv_uuid", FUUID;
4457   "lv_attr", FString (* XXX *);
4458   "lv_major", FInt64;
4459   "lv_minor", FInt64;
4460   "lv_kernel_major", FInt64;
4461   "lv_kernel_minor", FInt64;
4462   "lv_size", FBytes;
4463   "seg_count", FInt64;
4464   "origin", FString;
4465   "snap_percent", FOptPercent;
4466   "copy_percent", FOptPercent;
4467   "move_pv", FString;
4468   "lv_tags", FString;
4469   "mirror_log", FString;
4470   "modules", FString;
4471 ]
4472
4473 (* Names and fields in all structures (in RStruct and RStructList)
4474  * that we support.
4475  *)
4476 let structs = [
4477   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4478    * not use this struct in any new code.
4479    *)
4480   "int_bool", [
4481     "i", FInt32;                (* for historical compatibility *)
4482     "b", FInt32;                (* for historical compatibility *)
4483   ];
4484
4485   (* LVM PVs, VGs, LVs. *)
4486   "lvm_pv", lvm_pv_cols;
4487   "lvm_vg", lvm_vg_cols;
4488   "lvm_lv", lvm_lv_cols;
4489
4490   (* Column names and types from stat structures.
4491    * NB. Can't use things like 'st_atime' because glibc header files
4492    * define some of these as macros.  Ugh.
4493    *)
4494   "stat", [
4495     "dev", FInt64;
4496     "ino", FInt64;
4497     "mode", FInt64;
4498     "nlink", FInt64;
4499     "uid", FInt64;
4500     "gid", FInt64;
4501     "rdev", FInt64;
4502     "size", FInt64;
4503     "blksize", FInt64;
4504     "blocks", FInt64;
4505     "atime", FInt64;
4506     "mtime", FInt64;
4507     "ctime", FInt64;
4508   ];
4509   "statvfs", [
4510     "bsize", FInt64;
4511     "frsize", FInt64;
4512     "blocks", FInt64;
4513     "bfree", FInt64;
4514     "bavail", FInt64;
4515     "files", FInt64;
4516     "ffree", FInt64;
4517     "favail", FInt64;
4518     "fsid", FInt64;
4519     "flag", FInt64;
4520     "namemax", FInt64;
4521   ];
4522
4523   (* Column names in dirent structure. *)
4524   "dirent", [
4525     "ino", FInt64;
4526     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4527     "ftyp", FChar;
4528     "name", FString;
4529   ];
4530
4531   (* Version numbers. *)
4532   "version", [
4533     "major", FInt64;
4534     "minor", FInt64;
4535     "release", FInt64;
4536     "extra", FString;
4537   ];
4538
4539   (* Extended attribute. *)
4540   "xattr", [
4541     "attrname", FString;
4542     "attrval", FBuffer;
4543   ];
4544
4545   (* Inotify events. *)
4546   "inotify_event", [
4547     "in_wd", FInt64;
4548     "in_mask", FUInt32;
4549     "in_cookie", FUInt32;
4550     "in_name", FString;
4551   ];
4552
4553   (* Partition table entry. *)
4554   "partition", [
4555     "part_num", FInt32;
4556     "part_start", FBytes;
4557     "part_end", FBytes;
4558     "part_size", FBytes;
4559   ];
4560 ] (* end of structs *)
4561
4562 (* Ugh, Java has to be different ..
4563  * These names are also used by the Haskell bindings.
4564  *)
4565 let java_structs = [
4566   "int_bool", "IntBool";
4567   "lvm_pv", "PV";
4568   "lvm_vg", "VG";
4569   "lvm_lv", "LV";
4570   "stat", "Stat";
4571   "statvfs", "StatVFS";
4572   "dirent", "Dirent";
4573   "version", "Version";
4574   "xattr", "XAttr";
4575   "inotify_event", "INotifyEvent";
4576   "partition", "Partition";
4577 ]
4578
4579 (* What structs are actually returned. *)
4580 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4581
4582 (* Returns a list of RStruct/RStructList structs that are returned
4583  * by any function.  Each element of returned list is a pair:
4584  *
4585  * (structname, RStructOnly)
4586  *    == there exists function which returns RStruct (_, structname)
4587  * (structname, RStructListOnly)
4588  *    == there exists function which returns RStructList (_, structname)
4589  * (structname, RStructAndList)
4590  *    == there are functions returning both RStruct (_, structname)
4591  *                                      and RStructList (_, structname)
4592  *)
4593 let rstructs_used_by functions =
4594   (* ||| is a "logical OR" for rstructs_used_t *)
4595   let (|||) a b =
4596     match a, b with
4597     | RStructAndList, _
4598     | _, RStructAndList -> RStructAndList
4599     | RStructOnly, RStructListOnly
4600     | RStructListOnly, RStructOnly -> RStructAndList
4601     | RStructOnly, RStructOnly -> RStructOnly
4602     | RStructListOnly, RStructListOnly -> RStructListOnly
4603   in
4604
4605   let h = Hashtbl.create 13 in
4606
4607   (* if elem->oldv exists, update entry using ||| operator,
4608    * else just add elem->newv to the hash
4609    *)
4610   let update elem newv =
4611     try  let oldv = Hashtbl.find h elem in
4612          Hashtbl.replace h elem (newv ||| oldv)
4613     with Not_found -> Hashtbl.add h elem newv
4614   in
4615
4616   List.iter (
4617     fun (_, style, _, _, _, _, _) ->
4618       match fst style with
4619       | RStruct (_, structname) -> update structname RStructOnly
4620       | RStructList (_, structname) -> update structname RStructListOnly
4621       | _ -> ()
4622   ) functions;
4623
4624   (* return key->values as a list of (key,value) *)
4625   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4626
4627 (* Used for testing language bindings. *)
4628 type callt =
4629   | CallString of string
4630   | CallOptString of string option
4631   | CallStringList of string list
4632   | CallInt of int
4633   | CallInt64 of int64
4634   | CallBool of bool
4635
4636 (* Used to memoize the result of pod2text. *)
4637 let pod2text_memo_filename = "src/.pod2text.data"
4638 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4639   try
4640     let chan = open_in pod2text_memo_filename in
4641     let v = input_value chan in
4642     close_in chan;
4643     v
4644   with
4645     _ -> Hashtbl.create 13
4646 let pod2text_memo_updated () =
4647   let chan = open_out pod2text_memo_filename in
4648   output_value chan pod2text_memo;
4649   close_out chan
4650
4651 (* Useful functions.
4652  * Note we don't want to use any external OCaml libraries which
4653  * makes this a bit harder than it should be.
4654  *)
4655 module StringMap = Map.Make (String)
4656
4657 let failwithf fs = ksprintf failwith fs
4658
4659 let unique = let i = ref 0 in fun () -> incr i; !i
4660
4661 let replace_char s c1 c2 =
4662   let s2 = String.copy s in
4663   let r = ref false in
4664   for i = 0 to String.length s2 - 1 do
4665     if String.unsafe_get s2 i = c1 then (
4666       String.unsafe_set s2 i c2;
4667       r := true
4668     )
4669   done;
4670   if not !r then s else s2
4671
4672 let isspace c =
4673   c = ' '
4674   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4675
4676 let triml ?(test = isspace) str =
4677   let i = ref 0 in
4678   let n = ref (String.length str) in
4679   while !n > 0 && test str.[!i]; do
4680     decr n;
4681     incr i
4682   done;
4683   if !i = 0 then str
4684   else String.sub str !i !n
4685
4686 let trimr ?(test = isspace) str =
4687   let n = ref (String.length str) in
4688   while !n > 0 && test str.[!n-1]; do
4689     decr n
4690   done;
4691   if !n = String.length str then str
4692   else String.sub str 0 !n
4693
4694 let trim ?(test = isspace) str =
4695   trimr ~test (triml ~test str)
4696
4697 let rec find s sub =
4698   let len = String.length s in
4699   let sublen = String.length sub in
4700   let rec loop i =
4701     if i <= len-sublen then (
4702       let rec loop2 j =
4703         if j < sublen then (
4704           if s.[i+j] = sub.[j] then loop2 (j+1)
4705           else -1
4706         ) else
4707           i (* found *)
4708       in
4709       let r = loop2 0 in
4710       if r = -1 then loop (i+1) else r
4711     ) else
4712       -1 (* not found *)
4713   in
4714   loop 0
4715
4716 let rec replace_str s s1 s2 =
4717   let len = String.length s in
4718   let sublen = String.length s1 in
4719   let i = find s s1 in
4720   if i = -1 then s
4721   else (
4722     let s' = String.sub s 0 i in
4723     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4724     s' ^ s2 ^ replace_str s'' s1 s2
4725   )
4726
4727 let rec string_split sep str =
4728   let len = String.length str in
4729   let seplen = String.length sep in
4730   let i = find str sep in
4731   if i = -1 then [str]
4732   else (
4733     let s' = String.sub str 0 i in
4734     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4735     s' :: string_split sep s''
4736   )
4737
4738 let files_equal n1 n2 =
4739   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4740   match Sys.command cmd with
4741   | 0 -> true
4742   | 1 -> false
4743   | i -> failwithf "%s: failed with error code %d" cmd i
4744
4745 let rec filter_map f = function
4746   | [] -> []
4747   | x :: xs ->
4748       match f x with
4749       | Some y -> y :: filter_map f xs
4750       | None -> filter_map f xs
4751
4752 let rec find_map f = function
4753   | [] -> raise Not_found
4754   | x :: xs ->
4755       match f x with
4756       | Some y -> y
4757       | None -> find_map f xs
4758
4759 let iteri f xs =
4760   let rec loop i = function
4761     | [] -> ()
4762     | x :: xs -> f i x; loop (i+1) xs
4763   in
4764   loop 0 xs
4765
4766 let mapi f xs =
4767   let rec loop i = function
4768     | [] -> []
4769     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4770   in
4771   loop 0 xs
4772
4773 let count_chars c str =
4774   let count = ref 0 in
4775   for i = 0 to String.length str - 1 do
4776     if c = String.unsafe_get str i then incr count
4777   done;
4778   !count
4779
4780 let name_of_argt = function
4781   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4782   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4783   | FileIn n | FileOut n -> n
4784
4785 let java_name_of_struct typ =
4786   try List.assoc typ java_structs
4787   with Not_found ->
4788     failwithf
4789       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4790
4791 let cols_of_struct typ =
4792   try List.assoc typ structs
4793   with Not_found ->
4794     failwithf "cols_of_struct: unknown struct %s" typ
4795
4796 let seq_of_test = function
4797   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4798   | TestOutputListOfDevices (s, _)
4799   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4800   | TestOutputTrue s | TestOutputFalse s
4801   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4802   | TestOutputStruct (s, _)
4803   | TestLastFail s -> s
4804
4805 (* Handling for function flags. *)
4806 let protocol_limit_warning =
4807   "Because of the message protocol, there is a transfer limit
4808 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4809
4810 let danger_will_robinson =
4811   "B<This command is dangerous.  Without careful use you
4812 can easily destroy all your data>."
4813
4814 let deprecation_notice flags =
4815   try
4816     let alt =
4817       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4818     let txt =
4819       sprintf "This function is deprecated.
4820 In new code, use the C<%s> call instead.
4821
4822 Deprecated functions will not be removed from the API, but the
4823 fact that they are deprecated indicates that there are problems
4824 with correct use of these functions." alt in
4825     Some txt
4826   with
4827     Not_found -> None
4828
4829 (* Create list of optional groups. *)
4830 let optgroups =
4831   let h = Hashtbl.create 13 in
4832   List.iter (
4833     fun (name, _, _, flags, _, _, _) ->
4834       List.iter (
4835         function
4836         | Optional group ->
4837             let names = try Hashtbl.find h group with Not_found -> [] in
4838             Hashtbl.replace h group (name :: names)
4839         | _ -> ()
4840       ) flags
4841   ) daemon_functions;
4842   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4843   let groups =
4844     List.map (
4845       fun group -> group, List.sort compare (Hashtbl.find h group)
4846     ) groups in
4847   List.sort (fun x y -> compare (fst x) (fst y)) groups
4848
4849 (* Check function names etc. for consistency. *)
4850 let check_functions () =
4851   let contains_uppercase str =
4852     let len = String.length str in
4853     let rec loop i =
4854       if i >= len then false
4855       else (
4856         let c = str.[i] in
4857         if c >= 'A' && c <= 'Z' then true
4858         else loop (i+1)
4859       )
4860     in
4861     loop 0
4862   in
4863
4864   (* Check function names. *)
4865   List.iter (
4866     fun (name, _, _, _, _, _, _) ->
4867       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4868         failwithf "function name %s does not need 'guestfs' prefix" name;
4869       if name = "" then
4870         failwithf "function name is empty";
4871       if name.[0] < 'a' || name.[0] > 'z' then
4872         failwithf "function name %s must start with lowercase a-z" name;
4873       if String.contains name '-' then
4874         failwithf "function name %s should not contain '-', use '_' instead."
4875           name
4876   ) all_functions;
4877
4878   (* Check function parameter/return names. *)
4879   List.iter (
4880     fun (name, style, _, _, _, _, _) ->
4881       let check_arg_ret_name n =
4882         if contains_uppercase n then
4883           failwithf "%s param/ret %s should not contain uppercase chars"
4884             name n;
4885         if String.contains n '-' || String.contains n '_' then
4886           failwithf "%s param/ret %s should not contain '-' or '_'"
4887             name n;
4888         if n = "value" then
4889           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;
4890         if n = "int" || n = "char" || n = "short" || n = "long" then
4891           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4892         if n = "i" || n = "n" then
4893           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4894         if n = "argv" || n = "args" then
4895           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4896
4897         (* List Haskell, OCaml and C keywords here.
4898          * http://www.haskell.org/haskellwiki/Keywords
4899          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4900          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4901          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4902          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4903          * Omitting _-containing words, since they're handled above.
4904          * Omitting the OCaml reserved word, "val", is ok,
4905          * and saves us from renaming several parameters.
4906          *)
4907         let reserved = [
4908           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4909           "char"; "class"; "const"; "constraint"; "continue"; "data";
4910           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4911           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4912           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4913           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4914           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4915           "interface";
4916           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4917           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4918           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4919           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4920           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4921           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4922           "volatile"; "when"; "where"; "while";
4923           ] in
4924         if List.mem n reserved then
4925           failwithf "%s has param/ret using reserved word %s" name n;
4926       in
4927
4928       (match fst style with
4929        | RErr -> ()
4930        | RInt n | RInt64 n | RBool n
4931        | RConstString n | RConstOptString n | RString n
4932        | RStringList n | RStruct (n, _) | RStructList (n, _)
4933        | RHashtable n | RBufferOut n ->
4934            check_arg_ret_name n
4935       );
4936       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4937   ) all_functions;
4938
4939   (* Check short descriptions. *)
4940   List.iter (
4941     fun (name, _, _, _, _, shortdesc, _) ->
4942       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4943         failwithf "short description of %s should begin with lowercase." name;
4944       let c = shortdesc.[String.length shortdesc-1] in
4945       if c = '\n' || c = '.' then
4946         failwithf "short description of %s should not end with . or \\n." name
4947   ) all_functions;
4948
4949   (* Check long dscriptions. *)
4950   List.iter (
4951     fun (name, _, _, _, _, _, longdesc) ->
4952       if longdesc.[String.length longdesc-1] = '\n' then
4953         failwithf "long description of %s should not end with \\n." name
4954   ) all_functions;
4955
4956   (* Check proc_nrs. *)
4957   List.iter (
4958     fun (name, _, proc_nr, _, _, _, _) ->
4959       if proc_nr <= 0 then
4960         failwithf "daemon function %s should have proc_nr > 0" name
4961   ) daemon_functions;
4962
4963   List.iter (
4964     fun (name, _, proc_nr, _, _, _, _) ->
4965       if proc_nr <> -1 then
4966         failwithf "non-daemon function %s should have proc_nr -1" name
4967   ) non_daemon_functions;
4968
4969   let proc_nrs =
4970     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4971       daemon_functions in
4972   let proc_nrs =
4973     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4974   let rec loop = function
4975     | [] -> ()
4976     | [_] -> ()
4977     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4978         loop rest
4979     | (name1,nr1) :: (name2,nr2) :: _ ->
4980         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4981           name1 name2 nr1 nr2
4982   in
4983   loop proc_nrs;
4984
4985   (* Check tests. *)
4986   List.iter (
4987     function
4988       (* Ignore functions that have no tests.  We generate a
4989        * warning when the user does 'make check' instead.
4990        *)
4991     | name, _, _, _, [], _, _ -> ()
4992     | name, _, _, _, tests, _, _ ->
4993         let funcs =
4994           List.map (
4995             fun (_, _, test) ->
4996               match seq_of_test test with
4997               | [] ->
4998                   failwithf "%s has a test containing an empty sequence" name
4999               | cmds -> List.map List.hd cmds
5000           ) tests in
5001         let funcs = List.flatten funcs in
5002
5003         let tested = List.mem name funcs in
5004
5005         if not tested then
5006           failwithf "function %s has tests but does not test itself" name
5007   ) all_functions
5008
5009 (* 'pr' prints to the current output file. *)
5010 let chan = ref Pervasives.stdout
5011 let lines = ref 0
5012 let pr fs =
5013   ksprintf
5014     (fun str ->
5015        let i = count_chars '\n' str in
5016        lines := !lines + i;
5017        output_string !chan str
5018     ) fs
5019
5020 let copyright_years =
5021   let this_year = 1900 + (localtime (time ())).tm_year in
5022   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5023
5024 (* Generate a header block in a number of standard styles. *)
5025 type comment_style =
5026     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5027 type license = GPLv2plus | LGPLv2plus
5028
5029 let generate_header ?(extra_inputs = []) comment license =
5030   let inputs = "src/generator.ml" :: extra_inputs in
5031   let c = match comment with
5032     | CStyle ->         pr "/* "; " *"
5033     | CPlusPlusStyle -> pr "// "; "//"
5034     | HashStyle ->      pr "# ";  "#"
5035     | OCamlStyle ->     pr "(* "; " *"
5036     | HaskellStyle ->   pr "{- "; "  " in
5037   pr "libguestfs generated file\n";
5038   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5039   List.iter (pr "%s   %s\n" c) inputs;
5040   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5041   pr "%s\n" c;
5042   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5043   pr "%s\n" c;
5044   (match license with
5045    | GPLv2plus ->
5046        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5047        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5048        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5049        pr "%s (at your option) any later version.\n" c;
5050        pr "%s\n" c;
5051        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5052        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5053        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5054        pr "%s GNU General Public License for more details.\n" c;
5055        pr "%s\n" c;
5056        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5057        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5058        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5059
5060    | LGPLv2plus ->
5061        pr "%s This library is free software; you can redistribute it and/or\n" c;
5062        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5063        pr "%s License as published by the Free Software Foundation; either\n" c;
5064        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5065        pr "%s\n" c;
5066        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5067        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5068        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5069        pr "%s Lesser General Public License for more details.\n" c;
5070        pr "%s\n" c;
5071        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5072        pr "%s License along with this library; if not, write to the Free Software\n" c;
5073        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5074   );
5075   (match comment with
5076    | CStyle -> pr " */\n"
5077    | CPlusPlusStyle
5078    | HashStyle -> ()
5079    | OCamlStyle -> pr " *)\n"
5080    | HaskellStyle -> pr "-}\n"
5081   );
5082   pr "\n"
5083
5084 (* Start of main code generation functions below this line. *)
5085
5086 (* Generate the pod documentation for the C API. *)
5087 let rec generate_actions_pod () =
5088   List.iter (
5089     fun (shortname, style, _, flags, _, _, longdesc) ->
5090       if not (List.mem NotInDocs flags) then (
5091         let name = "guestfs_" ^ shortname in
5092         pr "=head2 %s\n\n" name;
5093         pr " ";
5094         generate_prototype ~extern:false ~handle:"handle" name style;
5095         pr "\n\n";
5096         pr "%s\n\n" longdesc;
5097         (match fst style with
5098          | RErr ->
5099              pr "This function returns 0 on success or -1 on error.\n\n"
5100          | RInt _ ->
5101              pr "On error this function returns -1.\n\n"
5102          | RInt64 _ ->
5103              pr "On error this function returns -1.\n\n"
5104          | RBool _ ->
5105              pr "This function returns a C truth value on success or -1 on error.\n\n"
5106          | RConstString _ ->
5107              pr "This function returns a string, or NULL on error.
5108 The string is owned by the guest handle and must I<not> be freed.\n\n"
5109          | RConstOptString _ ->
5110              pr "This function returns a string which may be NULL.
5111 There is way to return an error from this function.
5112 The string is owned by the guest handle and must I<not> be freed.\n\n"
5113          | RString _ ->
5114              pr "This function returns a string, or NULL on error.
5115 I<The caller must free the returned string after use>.\n\n"
5116          | RStringList _ ->
5117              pr "This function returns a NULL-terminated array of strings
5118 (like L<environ(3)>), or NULL if there was an error.
5119 I<The caller must free the strings and the array after use>.\n\n"
5120          | RStruct (_, typ) ->
5121              pr "This function returns a C<struct guestfs_%s *>,
5122 or NULL if there was an error.
5123 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5124          | RStructList (_, typ) ->
5125              pr "This function returns a C<struct guestfs_%s_list *>
5126 (see E<lt>guestfs-structs.hE<gt>),
5127 or NULL if there was an error.
5128 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5129          | RHashtable _ ->
5130              pr "This function returns a NULL-terminated array of
5131 strings, or NULL if there was an error.
5132 The array of strings will always have length C<2n+1>, where
5133 C<n> keys and values alternate, followed by the trailing NULL entry.
5134 I<The caller must free the strings and the array after use>.\n\n"
5135          | RBufferOut _ ->
5136              pr "This function returns a buffer, or NULL on error.
5137 The size of the returned buffer is written to C<*size_r>.
5138 I<The caller must free the returned buffer after use>.\n\n"
5139         );
5140         if List.mem ProtocolLimitWarning flags then
5141           pr "%s\n\n" protocol_limit_warning;
5142         if List.mem DangerWillRobinson flags then
5143           pr "%s\n\n" danger_will_robinson;
5144         match deprecation_notice flags with
5145         | None -> ()
5146         | Some txt -> pr "%s\n\n" txt
5147       )
5148   ) all_functions_sorted
5149
5150 and generate_structs_pod () =
5151   (* Structs documentation. *)
5152   List.iter (
5153     fun (typ, cols) ->
5154       pr "=head2 guestfs_%s\n" typ;
5155       pr "\n";
5156       pr " struct guestfs_%s {\n" typ;
5157       List.iter (
5158         function
5159         | name, FChar -> pr "   char %s;\n" name
5160         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5161         | name, FInt32 -> pr "   int32_t %s;\n" name
5162         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5163         | name, FInt64 -> pr "   int64_t %s;\n" name
5164         | name, FString -> pr "   char *%s;\n" name
5165         | name, FBuffer ->
5166             pr "   /* The next two fields describe a byte array. */\n";
5167             pr "   uint32_t %s_len;\n" name;
5168             pr "   char *%s;\n" name
5169         | name, FUUID ->
5170             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5171             pr "   char %s[32];\n" name
5172         | name, FOptPercent ->
5173             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5174             pr "   float %s;\n" name
5175       ) cols;
5176       pr " };\n";
5177       pr " \n";
5178       pr " struct guestfs_%s_list {\n" typ;
5179       pr "   uint32_t len; /* Number of elements in list. */\n";
5180       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5181       pr " };\n";
5182       pr " \n";
5183       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5184       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5185         typ typ;
5186       pr "\n"
5187   ) structs
5188
5189 and generate_availability_pod () =
5190   (* Availability documentation. *)
5191   pr "=over 4\n";
5192   pr "\n";
5193   List.iter (
5194     fun (group, functions) ->
5195       pr "=item B<%s>\n" group;
5196       pr "\n";
5197       pr "The following functions:\n";
5198       List.iter (pr "L</guestfs_%s>\n") functions;
5199       pr "\n"
5200   ) optgroups;
5201   pr "=back\n";
5202   pr "\n"
5203
5204 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5205  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5206  *
5207  * We have to use an underscore instead of a dash because otherwise
5208  * rpcgen generates incorrect code.
5209  *
5210  * This header is NOT exported to clients, but see also generate_structs_h.
5211  *)
5212 and generate_xdr () =
5213   generate_header CStyle LGPLv2plus;
5214
5215   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5216   pr "typedef string str<>;\n";
5217   pr "\n";
5218
5219   (* Internal structures. *)
5220   List.iter (
5221     function
5222     | typ, cols ->
5223         pr "struct guestfs_int_%s {\n" typ;
5224         List.iter (function
5225                    | name, FChar -> pr "  char %s;\n" name
5226                    | name, FString -> pr "  string %s<>;\n" name
5227                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5228                    | name, FUUID -> pr "  opaque %s[32];\n" name
5229                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5230                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5231                    | name, FOptPercent -> pr "  float %s;\n" name
5232                   ) cols;
5233         pr "};\n";
5234         pr "\n";
5235         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5236         pr "\n";
5237   ) structs;
5238
5239   List.iter (
5240     fun (shortname, style, _, _, _, _, _) ->
5241       let name = "guestfs_" ^ shortname in
5242
5243       (match snd style with
5244        | [] -> ()
5245        | args ->
5246            pr "struct %s_args {\n" name;
5247            List.iter (
5248              function
5249              | Pathname n | Device n | Dev_or_Path n | String n ->
5250                  pr "  string %s<>;\n" n
5251              | OptString n -> pr "  str *%s;\n" n
5252              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5253              | Bool n -> pr "  bool %s;\n" n
5254              | Int n -> pr "  int %s;\n" n
5255              | Int64 n -> pr "  hyper %s;\n" n
5256              | FileIn _ | FileOut _ -> ()
5257            ) args;
5258            pr "};\n\n"
5259       );
5260       (match fst style with
5261        | RErr -> ()
5262        | RInt n ->
5263            pr "struct %s_ret {\n" name;
5264            pr "  int %s;\n" n;
5265            pr "};\n\n"
5266        | RInt64 n ->
5267            pr "struct %s_ret {\n" name;
5268            pr "  hyper %s;\n" n;
5269            pr "};\n\n"
5270        | RBool n ->
5271            pr "struct %s_ret {\n" name;
5272            pr "  bool %s;\n" n;
5273            pr "};\n\n"
5274        | RConstString _ | RConstOptString _ ->
5275            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5276        | RString n ->
5277            pr "struct %s_ret {\n" name;
5278            pr "  string %s<>;\n" n;
5279            pr "};\n\n"
5280        | RStringList n ->
5281            pr "struct %s_ret {\n" name;
5282            pr "  str %s<>;\n" n;
5283            pr "};\n\n"
5284        | RStruct (n, typ) ->
5285            pr "struct %s_ret {\n" name;
5286            pr "  guestfs_int_%s %s;\n" typ n;
5287            pr "};\n\n"
5288        | RStructList (n, typ) ->
5289            pr "struct %s_ret {\n" name;
5290            pr "  guestfs_int_%s_list %s;\n" typ n;
5291            pr "};\n\n"
5292        | RHashtable n ->
5293            pr "struct %s_ret {\n" name;
5294            pr "  str %s<>;\n" n;
5295            pr "};\n\n"
5296        | RBufferOut n ->
5297            pr "struct %s_ret {\n" name;
5298            pr "  opaque %s<>;\n" n;
5299            pr "};\n\n"
5300       );
5301   ) daemon_functions;
5302
5303   (* Table of procedure numbers. *)
5304   pr "enum guestfs_procedure {\n";
5305   List.iter (
5306     fun (shortname, _, proc_nr, _, _, _, _) ->
5307       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5308   ) daemon_functions;
5309   pr "  GUESTFS_PROC_NR_PROCS\n";
5310   pr "};\n";
5311   pr "\n";
5312
5313   (* Having to choose a maximum message size is annoying for several
5314    * reasons (it limits what we can do in the API), but it (a) makes
5315    * the protocol a lot simpler, and (b) provides a bound on the size
5316    * of the daemon which operates in limited memory space.
5317    *)
5318   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5319   pr "\n";
5320
5321   (* Message header, etc. *)
5322   pr "\
5323 /* The communication protocol is now documented in the guestfs(3)
5324  * manpage.
5325  */
5326
5327 const GUESTFS_PROGRAM = 0x2000F5F5;
5328 const GUESTFS_PROTOCOL_VERSION = 1;
5329
5330 /* These constants must be larger than any possible message length. */
5331 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5332 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5333
5334 enum guestfs_message_direction {
5335   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5336   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5337 };
5338
5339 enum guestfs_message_status {
5340   GUESTFS_STATUS_OK = 0,
5341   GUESTFS_STATUS_ERROR = 1
5342 };
5343
5344 const GUESTFS_ERROR_LEN = 256;
5345
5346 struct guestfs_message_error {
5347   string error_message<GUESTFS_ERROR_LEN>;
5348 };
5349
5350 struct guestfs_message_header {
5351   unsigned prog;                     /* GUESTFS_PROGRAM */
5352   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5353   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5354   guestfs_message_direction direction;
5355   unsigned serial;                   /* message serial number */
5356   guestfs_message_status status;
5357 };
5358
5359 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5360
5361 struct guestfs_chunk {
5362   int cancel;                        /* if non-zero, transfer is cancelled */
5363   /* data size is 0 bytes if the transfer has finished successfully */
5364   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5365 };
5366 "
5367
5368 (* Generate the guestfs-structs.h file. *)
5369 and generate_structs_h () =
5370   generate_header CStyle LGPLv2plus;
5371
5372   (* This is a public exported header file containing various
5373    * structures.  The structures are carefully written to have
5374    * exactly the same in-memory format as the XDR structures that
5375    * we use on the wire to the daemon.  The reason for creating
5376    * copies of these structures here is just so we don't have to
5377    * export the whole of guestfs_protocol.h (which includes much
5378    * unrelated and XDR-dependent stuff that we don't want to be
5379    * public, or required by clients).
5380    *
5381    * To reiterate, we will pass these structures to and from the
5382    * client with a simple assignment or memcpy, so the format
5383    * must be identical to what rpcgen / the RFC defines.
5384    *)
5385
5386   (* Public structures. *)
5387   List.iter (
5388     fun (typ, cols) ->
5389       pr "struct guestfs_%s {\n" typ;
5390       List.iter (
5391         function
5392         | name, FChar -> pr "  char %s;\n" name
5393         | name, FString -> pr "  char *%s;\n" name
5394         | name, FBuffer ->
5395             pr "  uint32_t %s_len;\n" name;
5396             pr "  char *%s;\n" name
5397         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5398         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5399         | name, FInt32 -> pr "  int32_t %s;\n" name
5400         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5401         | name, FInt64 -> pr "  int64_t %s;\n" name
5402         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5403       ) cols;
5404       pr "};\n";
5405       pr "\n";
5406       pr "struct guestfs_%s_list {\n" typ;
5407       pr "  uint32_t len;\n";
5408       pr "  struct guestfs_%s *val;\n" typ;
5409       pr "};\n";
5410       pr "\n";
5411       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5412       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5413       pr "\n"
5414   ) structs
5415
5416 (* Generate the guestfs-actions.h file. *)
5417 and generate_actions_h () =
5418   generate_header CStyle LGPLv2plus;
5419   List.iter (
5420     fun (shortname, style, _, _, _, _, _) ->
5421       let name = "guestfs_" ^ shortname in
5422       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5423         name style
5424   ) all_functions
5425
5426 (* Generate the guestfs-internal-actions.h file. *)
5427 and generate_internal_actions_h () =
5428   generate_header CStyle LGPLv2plus;
5429   List.iter (
5430     fun (shortname, style, _, _, _, _, _) ->
5431       let name = "guestfs__" ^ shortname in
5432       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5433         name style
5434   ) non_daemon_functions
5435
5436 (* Generate the client-side dispatch stubs. *)
5437 and generate_client_actions () =
5438   generate_header CStyle LGPLv2plus;
5439
5440   pr "\
5441 #include <stdio.h>
5442 #include <stdlib.h>
5443 #include <stdint.h>
5444 #include <string.h>
5445 #include <inttypes.h>
5446
5447 #include \"guestfs.h\"
5448 #include \"guestfs-internal.h\"
5449 #include \"guestfs-internal-actions.h\"
5450 #include \"guestfs_protocol.h\"
5451
5452 #define error guestfs_error
5453 //#define perrorf guestfs_perrorf
5454 #define safe_malloc guestfs_safe_malloc
5455 #define safe_realloc guestfs_safe_realloc
5456 //#define safe_strdup guestfs_safe_strdup
5457 #define safe_memdup guestfs_safe_memdup
5458
5459 /* Check the return message from a call for validity. */
5460 static int
5461 check_reply_header (guestfs_h *g,
5462                     const struct guestfs_message_header *hdr,
5463                     unsigned int proc_nr, unsigned int serial)
5464 {
5465   if (hdr->prog != GUESTFS_PROGRAM) {
5466     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5467     return -1;
5468   }
5469   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5470     error (g, \"wrong protocol version (%%d/%%d)\",
5471            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5472     return -1;
5473   }
5474   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5475     error (g, \"unexpected message direction (%%d/%%d)\",
5476            hdr->direction, GUESTFS_DIRECTION_REPLY);
5477     return -1;
5478   }
5479   if (hdr->proc != proc_nr) {
5480     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5481     return -1;
5482   }
5483   if (hdr->serial != serial) {
5484     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5485     return -1;
5486   }
5487
5488   return 0;
5489 }
5490
5491 /* Check we are in the right state to run a high-level action. */
5492 static int
5493 check_state (guestfs_h *g, const char *caller)
5494 {
5495   if (!guestfs__is_ready (g)) {
5496     if (guestfs__is_config (g) || guestfs__is_launching (g))
5497       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5498         caller);
5499     else
5500       error (g, \"%%s called from the wrong state, %%d != READY\",
5501         caller, guestfs__get_state (g));
5502     return -1;
5503   }
5504   return 0;
5505 }
5506
5507 ";
5508
5509   (* Generate code to generate guestfish call traces. *)
5510   let trace_call shortname style =
5511     pr "  if (guestfs__get_trace (g)) {\n";
5512
5513     let needs_i =
5514       List.exists (function
5515                    | StringList _ | DeviceList _ -> true
5516                    | _ -> false) (snd style) in
5517     if needs_i then (
5518       pr "    int i;\n";
5519       pr "\n"
5520     );
5521
5522     pr "    printf (\"%s\");\n" shortname;
5523     List.iter (
5524       function
5525       | String n                        (* strings *)
5526       | Device n
5527       | Pathname n
5528       | Dev_or_Path n
5529       | FileIn n
5530       | FileOut n ->
5531           (* guestfish doesn't support string escaping, so neither do we *)
5532           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5533       | OptString n ->                  (* string option *)
5534           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5535           pr "    else printf (\" null\");\n"
5536       | StringList n
5537       | DeviceList n ->                 (* string list *)
5538           pr "    putchar (' ');\n";
5539           pr "    putchar ('\"');\n";
5540           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5541           pr "      if (i > 0) putchar (' ');\n";
5542           pr "      fputs (%s[i], stdout);\n" n;
5543           pr "    }\n";
5544           pr "    putchar ('\"');\n";
5545       | Bool n ->                       (* boolean *)
5546           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5547       | Int n ->                        (* int *)
5548           pr "    printf (\" %%d\", %s);\n" n
5549       | Int64 n ->
5550           pr "    printf (\" %%\" PRIi64, %s);\n" n
5551     ) (snd style);
5552     pr "    putchar ('\\n');\n";
5553     pr "  }\n";
5554     pr "\n";
5555   in
5556
5557   (* For non-daemon functions, generate a wrapper around each function. *)
5558   List.iter (
5559     fun (shortname, style, _, _, _, _, _) ->
5560       let name = "guestfs_" ^ shortname in
5561
5562       generate_prototype ~extern:false ~semicolon:false ~newline:true
5563         ~handle:"g" name style;
5564       pr "{\n";
5565       trace_call shortname style;
5566       pr "  return guestfs__%s " shortname;
5567       generate_c_call_args ~handle:"g" style;
5568       pr ";\n";
5569       pr "}\n";
5570       pr "\n"
5571   ) non_daemon_functions;
5572
5573   (* Client-side stubs for each function. *)
5574   List.iter (
5575     fun (shortname, style, _, _, _, _, _) ->
5576       let name = "guestfs_" ^ shortname in
5577
5578       (* Generate the action stub. *)
5579       generate_prototype ~extern:false ~semicolon:false ~newline:true
5580         ~handle:"g" name style;
5581
5582       let error_code =
5583         match fst style with
5584         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5585         | RConstString _ | RConstOptString _ ->
5586             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5587         | RString _ | RStringList _
5588         | RStruct _ | RStructList _
5589         | RHashtable _ | RBufferOut _ ->
5590             "NULL" in
5591
5592       pr "{\n";
5593
5594       (match snd style with
5595        | [] -> ()
5596        | _ -> pr "  struct %s_args args;\n" name
5597       );
5598
5599       pr "  guestfs_message_header hdr;\n";
5600       pr "  guestfs_message_error err;\n";
5601       let has_ret =
5602         match fst style with
5603         | RErr -> false
5604         | RConstString _ | RConstOptString _ ->
5605             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5606         | RInt _ | RInt64 _
5607         | RBool _ | RString _ | RStringList _
5608         | RStruct _ | RStructList _
5609         | RHashtable _ | RBufferOut _ ->
5610             pr "  struct %s_ret ret;\n" name;
5611             true in
5612
5613       pr "  int serial;\n";
5614       pr "  int r;\n";
5615       pr "\n";
5616       trace_call shortname style;
5617       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5618       pr "  guestfs___set_busy (g);\n";
5619       pr "\n";
5620
5621       (* Send the main header and arguments. *)
5622       (match snd style with
5623        | [] ->
5624            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5625              (String.uppercase shortname)
5626        | args ->
5627            List.iter (
5628              function
5629              | Pathname n | Device n | Dev_or_Path n | String n ->
5630                  pr "  args.%s = (char *) %s;\n" n n
5631              | OptString n ->
5632                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5633              | StringList n | DeviceList n ->
5634                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5635                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5636              | Bool n ->
5637                  pr "  args.%s = %s;\n" n n
5638              | Int n ->
5639                  pr "  args.%s = %s;\n" n n
5640              | Int64 n ->
5641                  pr "  args.%s = %s;\n" n n
5642              | FileIn _ | FileOut _ -> ()
5643            ) args;
5644            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5645              (String.uppercase shortname);
5646            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5647              name;
5648       );
5649       pr "  if (serial == -1) {\n";
5650       pr "    guestfs___end_busy (g);\n";
5651       pr "    return %s;\n" error_code;
5652       pr "  }\n";
5653       pr "\n";
5654
5655       (* Send any additional files (FileIn) requested. *)
5656       let need_read_reply_label = ref false in
5657       List.iter (
5658         function
5659         | FileIn n ->
5660             pr "  r = guestfs___send_file (g, %s);\n" n;
5661             pr "  if (r == -1) {\n";
5662             pr "    guestfs___end_busy (g);\n";
5663             pr "    return %s;\n" error_code;
5664             pr "  }\n";
5665             pr "  if (r == -2) /* daemon cancelled */\n";
5666             pr "    goto read_reply;\n";
5667             need_read_reply_label := true;
5668             pr "\n";
5669         | _ -> ()
5670       ) (snd style);
5671
5672       (* Wait for the reply from the remote end. *)
5673       if !need_read_reply_label then pr " read_reply:\n";
5674       pr "  memset (&hdr, 0, sizeof hdr);\n";
5675       pr "  memset (&err, 0, sizeof err);\n";
5676       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5677       pr "\n";
5678       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5679       if not has_ret then
5680         pr "NULL, NULL"
5681       else
5682         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5683       pr ");\n";
5684
5685       pr "  if (r == -1) {\n";
5686       pr "    guestfs___end_busy (g);\n";
5687       pr "    return %s;\n" error_code;
5688       pr "  }\n";
5689       pr "\n";
5690
5691       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5692         (String.uppercase shortname);
5693       pr "    guestfs___end_busy (g);\n";
5694       pr "    return %s;\n" error_code;
5695       pr "  }\n";
5696       pr "\n";
5697
5698       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5699       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5700       pr "    free (err.error_message);\n";
5701       pr "    guestfs___end_busy (g);\n";
5702       pr "    return %s;\n" error_code;
5703       pr "  }\n";
5704       pr "\n";
5705
5706       (* Expecting to receive further files (FileOut)? *)
5707       List.iter (
5708         function
5709         | FileOut n ->
5710             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5711             pr "    guestfs___end_busy (g);\n";
5712             pr "    return %s;\n" error_code;
5713             pr "  }\n";
5714             pr "\n";
5715         | _ -> ()
5716       ) (snd style);
5717
5718       pr "  guestfs___end_busy (g);\n";
5719
5720       (match fst style with
5721        | RErr -> pr "  return 0;\n"
5722        | RInt n | RInt64 n | RBool n ->
5723            pr "  return ret.%s;\n" n
5724        | RConstString _ | RConstOptString _ ->
5725            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5726        | RString n ->
5727            pr "  return ret.%s; /* caller will free */\n" n
5728        | RStringList n | RHashtable n ->
5729            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5730            pr "  ret.%s.%s_val =\n" n n;
5731            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5732            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5733              n n;
5734            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5735            pr "  return ret.%s.%s_val;\n" n n
5736        | RStruct (n, _) ->
5737            pr "  /* caller will free this */\n";
5738            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5739        | RStructList (n, _) ->
5740            pr "  /* caller will free this */\n";
5741            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5742        | RBufferOut n ->
5743            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5744            pr "   * _val might be NULL here.  To make the API saner for\n";
5745            pr "   * callers, we turn this case into a unique pointer (using\n";
5746            pr "   * malloc(1)).\n";
5747            pr "   */\n";
5748            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5749            pr "    *size_r = ret.%s.%s_len;\n" n n;
5750            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5751            pr "  } else {\n";
5752            pr "    free (ret.%s.%s_val);\n" n n;
5753            pr "    char *p = safe_malloc (g, 1);\n";
5754            pr "    *size_r = ret.%s.%s_len;\n" n n;
5755            pr "    return p;\n";
5756            pr "  }\n";
5757       );
5758
5759       pr "}\n\n"
5760   ) daemon_functions;
5761
5762   (* Functions to free structures. *)
5763   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5764   pr " * structure format is identical to the XDR format.  See note in\n";
5765   pr " * generator.ml.\n";
5766   pr " */\n";
5767   pr "\n";
5768
5769   List.iter (
5770     fun (typ, _) ->
5771       pr "void\n";
5772       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5773       pr "{\n";
5774       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5775       pr "  free (x);\n";
5776       pr "}\n";
5777       pr "\n";
5778
5779       pr "void\n";
5780       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5781       pr "{\n";
5782       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5783       pr "  free (x);\n";
5784       pr "}\n";
5785       pr "\n";
5786
5787   ) structs;
5788
5789 (* Generate daemon/actions.h. *)
5790 and generate_daemon_actions_h () =
5791   generate_header CStyle GPLv2plus;
5792
5793   pr "#include \"../src/guestfs_protocol.h\"\n";
5794   pr "\n";
5795
5796   List.iter (
5797     fun (name, style, _, _, _, _, _) ->
5798       generate_prototype
5799         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5800         name style;
5801   ) daemon_functions
5802
5803 (* Generate the linker script which controls the visibility of
5804  * symbols in the public ABI and ensures no other symbols get
5805  * exported accidentally.
5806  *)
5807 and generate_linker_script () =
5808   generate_header HashStyle GPLv2plus;
5809
5810   let globals = [
5811     "guestfs_create";
5812     "guestfs_close";
5813     "guestfs_get_error_handler";
5814     "guestfs_get_out_of_memory_handler";
5815     "guestfs_last_error";
5816     "guestfs_set_error_handler";
5817     "guestfs_set_launch_done_callback";
5818     "guestfs_set_log_message_callback";
5819     "guestfs_set_out_of_memory_handler";
5820     "guestfs_set_subprocess_quit_callback";
5821
5822     (* Unofficial parts of the API: the bindings code use these
5823      * functions, so it is useful to export them.
5824      *)
5825     "guestfs_safe_calloc";
5826     "guestfs_safe_malloc";
5827   ] in
5828   let functions =
5829     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5830       all_functions in
5831   let structs =
5832     List.concat (
5833       List.map (fun (typ, _) ->
5834                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5835         structs
5836     ) in
5837   let globals = List.sort compare (globals @ functions @ structs) in
5838
5839   pr "{\n";
5840   pr "    global:\n";
5841   List.iter (pr "        %s;\n") globals;
5842   pr "\n";
5843
5844   pr "    local:\n";
5845   pr "        *;\n";
5846   pr "};\n"
5847
5848 (* Generate the server-side stubs. *)
5849 and generate_daemon_actions () =
5850   generate_header CStyle GPLv2plus;
5851
5852   pr "#include <config.h>\n";
5853   pr "\n";
5854   pr "#include <stdio.h>\n";
5855   pr "#include <stdlib.h>\n";
5856   pr "#include <string.h>\n";
5857   pr "#include <inttypes.h>\n";
5858   pr "#include <rpc/types.h>\n";
5859   pr "#include <rpc/xdr.h>\n";
5860   pr "\n";
5861   pr "#include \"daemon.h\"\n";
5862   pr "#include \"c-ctype.h\"\n";
5863   pr "#include \"../src/guestfs_protocol.h\"\n";
5864   pr "#include \"actions.h\"\n";
5865   pr "\n";
5866
5867   List.iter (
5868     fun (name, style, _, _, _, _, _) ->
5869       (* Generate server-side stubs. *)
5870       pr "static void %s_stub (XDR *xdr_in)\n" name;
5871       pr "{\n";
5872       let error_code =
5873         match fst style with
5874         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5875         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5876         | RBool _ -> pr "  int r;\n"; "-1"
5877         | RConstString _ | RConstOptString _ ->
5878             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5879         | RString _ -> pr "  char *r;\n"; "NULL"
5880         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5881         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5882         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5883         | RBufferOut _ ->
5884             pr "  size_t size = 1;\n";
5885             pr "  char *r;\n";
5886             "NULL" in
5887
5888       (match snd style with
5889        | [] -> ()
5890        | args ->
5891            pr "  struct guestfs_%s_args args;\n" name;
5892            List.iter (
5893              function
5894              | Device n | Dev_or_Path n
5895              | Pathname n
5896              | String n -> ()
5897              | OptString n -> pr "  char *%s;\n" n
5898              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5899              | Bool n -> pr "  int %s;\n" n
5900              | Int n -> pr "  int %s;\n" n
5901              | Int64 n -> pr "  int64_t %s;\n" n
5902              | FileIn _ | FileOut _ -> ()
5903            ) args
5904       );
5905       pr "\n";
5906
5907       (match snd style with
5908        | [] -> ()
5909        | args ->
5910            pr "  memset (&args, 0, sizeof args);\n";
5911            pr "\n";
5912            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5913            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5914            pr "    return;\n";
5915            pr "  }\n";
5916            let pr_args n =
5917              pr "  char *%s = args.%s;\n" n n
5918            in
5919            let pr_list_handling_code n =
5920              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5921              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5922              pr "  if (%s == NULL) {\n" n;
5923              pr "    reply_with_perror (\"realloc\");\n";
5924              pr "    goto done;\n";
5925              pr "  }\n";
5926              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5927              pr "  args.%s.%s_val = %s;\n" n n n;
5928            in
5929            List.iter (
5930              function
5931              | Pathname n ->
5932                  pr_args n;
5933                  pr "  ABS_PATH (%s, goto done);\n" n;
5934              | Device n ->
5935                  pr_args n;
5936                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5937              | Dev_or_Path n ->
5938                  pr_args n;
5939                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5940              | String n -> pr_args n
5941              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5942              | StringList n ->
5943                  pr_list_handling_code n;
5944              | DeviceList n ->
5945                  pr_list_handling_code n;
5946                  pr "  /* Ensure that each is a device,\n";
5947                  pr "   * and perform device name translation. */\n";
5948                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5949                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5950                  pr "  }\n";
5951              | Bool n -> pr "  %s = args.%s;\n" n n
5952              | Int n -> pr "  %s = args.%s;\n" n n
5953              | Int64 n -> pr "  %s = args.%s;\n" n n
5954              | FileIn _ | FileOut _ -> ()
5955            ) args;
5956            pr "\n"
5957       );
5958
5959
5960       (* this is used at least for do_equal *)
5961       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5962         (* Emit NEED_ROOT just once, even when there are two or
5963            more Pathname args *)
5964         pr "  NEED_ROOT (goto done);\n";
5965       );
5966
5967       (* Don't want to call the impl with any FileIn or FileOut
5968        * parameters, since these go "outside" the RPC protocol.
5969        *)
5970       let args' =
5971         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5972           (snd style) in
5973       pr "  r = do_%s " name;
5974       generate_c_call_args (fst style, args');
5975       pr ";\n";
5976
5977       (match fst style with
5978        | RErr | RInt _ | RInt64 _ | RBool _
5979        | RConstString _ | RConstOptString _
5980        | RString _ | RStringList _ | RHashtable _
5981        | RStruct (_, _) | RStructList (_, _) ->
5982            pr "  if (r == %s)\n" error_code;
5983            pr "    /* do_%s has already called reply_with_error */\n" name;
5984            pr "    goto done;\n";
5985            pr "\n"
5986        | RBufferOut _ ->
5987            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5988            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5989            pr "   */\n";
5990            pr "  if (size == 1 && r == %s)\n" error_code;
5991            pr "    /* do_%s has already called reply_with_error */\n" name;
5992            pr "    goto done;\n";
5993            pr "\n"
5994       );
5995
5996       (* If there are any FileOut parameters, then the impl must
5997        * send its own reply.
5998        *)
5999       let no_reply =
6000         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6001       if no_reply then
6002         pr "  /* do_%s has already sent a reply */\n" name
6003       else (
6004         match fst style with
6005         | RErr -> pr "  reply (NULL, NULL);\n"
6006         | RInt n | RInt64 n | RBool n ->
6007             pr "  struct guestfs_%s_ret ret;\n" name;
6008             pr "  ret.%s = r;\n" n;
6009             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6010               name
6011         | RConstString _ | RConstOptString _ ->
6012             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6013         | RString n ->
6014             pr "  struct guestfs_%s_ret ret;\n" name;
6015             pr "  ret.%s = r;\n" n;
6016             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6017               name;
6018             pr "  free (r);\n"
6019         | RStringList n | RHashtable n ->
6020             pr "  struct guestfs_%s_ret ret;\n" name;
6021             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6022             pr "  ret.%s.%s_val = r;\n" n n;
6023             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6024               name;
6025             pr "  free_strings (r);\n"
6026         | RStruct (n, _) ->
6027             pr "  struct guestfs_%s_ret ret;\n" name;
6028             pr "  ret.%s = *r;\n" n;
6029             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6030               name;
6031             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6032               name
6033         | RStructList (n, _) ->
6034             pr "  struct guestfs_%s_ret ret;\n" name;
6035             pr "  ret.%s = *r;\n" n;
6036             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6037               name;
6038             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6039               name
6040         | RBufferOut n ->
6041             pr "  struct guestfs_%s_ret ret;\n" name;
6042             pr "  ret.%s.%s_val = r;\n" n n;
6043             pr "  ret.%s.%s_len = size;\n" n n;
6044             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6045               name;
6046             pr "  free (r);\n"
6047       );
6048
6049       (* Free the args. *)
6050       (match snd style with
6051        | [] ->
6052            pr "done: ;\n";
6053        | _ ->
6054            pr "done:\n";
6055            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6056              name
6057       );
6058
6059       pr "}\n\n";
6060   ) daemon_functions;
6061
6062   (* Dispatch function. *)
6063   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6064   pr "{\n";
6065   pr "  switch (proc_nr) {\n";
6066
6067   List.iter (
6068     fun (name, style, _, _, _, _, _) ->
6069       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6070       pr "      %s_stub (xdr_in);\n" name;
6071       pr "      break;\n"
6072   ) daemon_functions;
6073
6074   pr "    default:\n";
6075   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";
6076   pr "  }\n";
6077   pr "}\n";
6078   pr "\n";
6079
6080   (* LVM columns and tokenization functions. *)
6081   (* XXX This generates crap code.  We should rethink how we
6082    * do this parsing.
6083    *)
6084   List.iter (
6085     function
6086     | typ, cols ->
6087         pr "static const char *lvm_%s_cols = \"%s\";\n"
6088           typ (String.concat "," (List.map fst cols));
6089         pr "\n";
6090
6091         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6092         pr "{\n";
6093         pr "  char *tok, *p, *next;\n";
6094         pr "  int i, j;\n";
6095         pr "\n";
6096         (*
6097           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6098           pr "\n";
6099         *)
6100         pr "  if (!str) {\n";
6101         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6102         pr "    return -1;\n";
6103         pr "  }\n";
6104         pr "  if (!*str || c_isspace (*str)) {\n";
6105         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6106         pr "    return -1;\n";
6107         pr "  }\n";
6108         pr "  tok = str;\n";
6109         List.iter (
6110           fun (name, coltype) ->
6111             pr "  if (!tok) {\n";
6112             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6113             pr "    return -1;\n";
6114             pr "  }\n";
6115             pr "  p = strchrnul (tok, ',');\n";
6116             pr "  if (*p) next = p+1; else next = NULL;\n";
6117             pr "  *p = '\\0';\n";
6118             (match coltype with
6119              | FString ->
6120                  pr "  r->%s = strdup (tok);\n" name;
6121                  pr "  if (r->%s == NULL) {\n" name;
6122                  pr "    perror (\"strdup\");\n";
6123                  pr "    return -1;\n";
6124                  pr "  }\n"
6125              | FUUID ->
6126                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6127                  pr "    if (tok[j] == '\\0') {\n";
6128                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6129                  pr "      return -1;\n";
6130                  pr "    } else if (tok[j] != '-')\n";
6131                  pr "      r->%s[i++] = tok[j];\n" name;
6132                  pr "  }\n";
6133              | FBytes ->
6134                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6135                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6136                  pr "    return -1;\n";
6137                  pr "  }\n";
6138              | FInt64 ->
6139                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6140                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6141                  pr "    return -1;\n";
6142                  pr "  }\n";
6143              | FOptPercent ->
6144                  pr "  if (tok[0] == '\\0')\n";
6145                  pr "    r->%s = -1;\n" name;
6146                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6147                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6148                  pr "    return -1;\n";
6149                  pr "  }\n";
6150              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6151                  assert false (* can never be an LVM column *)
6152             );
6153             pr "  tok = next;\n";
6154         ) cols;
6155
6156         pr "  if (tok != NULL) {\n";
6157         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6158         pr "    return -1;\n";
6159         pr "  }\n";
6160         pr "  return 0;\n";
6161         pr "}\n";
6162         pr "\n";
6163
6164         pr "guestfs_int_lvm_%s_list *\n" typ;
6165         pr "parse_command_line_%ss (void)\n" typ;
6166         pr "{\n";
6167         pr "  char *out, *err;\n";
6168         pr "  char *p, *pend;\n";
6169         pr "  int r, i;\n";
6170         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6171         pr "  void *newp;\n";
6172         pr "\n";
6173         pr "  ret = malloc (sizeof *ret);\n";
6174         pr "  if (!ret) {\n";
6175         pr "    reply_with_perror (\"malloc\");\n";
6176         pr "    return NULL;\n";
6177         pr "  }\n";
6178         pr "\n";
6179         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6180         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6181         pr "\n";
6182         pr "  r = command (&out, &err,\n";
6183         pr "           \"lvm\", \"%ss\",\n" typ;
6184         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6185         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6186         pr "  if (r == -1) {\n";
6187         pr "    reply_with_error (\"%%s\", err);\n";
6188         pr "    free (out);\n";
6189         pr "    free (err);\n";
6190         pr "    free (ret);\n";
6191         pr "    return NULL;\n";
6192         pr "  }\n";
6193         pr "\n";
6194         pr "  free (err);\n";
6195         pr "\n";
6196         pr "  /* Tokenize each line of the output. */\n";
6197         pr "  p = out;\n";
6198         pr "  i = 0;\n";
6199         pr "  while (p) {\n";
6200         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6201         pr "    if (pend) {\n";
6202         pr "      *pend = '\\0';\n";
6203         pr "      pend++;\n";
6204         pr "    }\n";
6205         pr "\n";
6206         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6207         pr "      p++;\n";
6208         pr "\n";
6209         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6210         pr "      p = pend;\n";
6211         pr "      continue;\n";
6212         pr "    }\n";
6213         pr "\n";
6214         pr "    /* Allocate some space to store this next entry. */\n";
6215         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6216         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6217         pr "    if (newp == NULL) {\n";
6218         pr "      reply_with_perror (\"realloc\");\n";
6219         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6220         pr "      free (ret);\n";
6221         pr "      free (out);\n";
6222         pr "      return NULL;\n";
6223         pr "    }\n";
6224         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6225         pr "\n";
6226         pr "    /* Tokenize the next entry. */\n";
6227         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6228         pr "    if (r == -1) {\n";
6229         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6230         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6231         pr "      free (ret);\n";
6232         pr "      free (out);\n";
6233         pr "      return NULL;\n";
6234         pr "    }\n";
6235         pr "\n";
6236         pr "    ++i;\n";
6237         pr "    p = pend;\n";
6238         pr "  }\n";
6239         pr "\n";
6240         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6241         pr "\n";
6242         pr "  free (out);\n";
6243         pr "  return ret;\n";
6244         pr "}\n"
6245
6246   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6247
6248 (* Generate a list of function names, for debugging in the daemon.. *)
6249 and generate_daemon_names () =
6250   generate_header CStyle GPLv2plus;
6251
6252   pr "#include <config.h>\n";
6253   pr "\n";
6254   pr "#include \"daemon.h\"\n";
6255   pr "\n";
6256
6257   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6258   pr "const char *function_names[] = {\n";
6259   List.iter (
6260     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6261   ) daemon_functions;
6262   pr "};\n";
6263
6264 (* Generate the optional groups for the daemon to implement
6265  * guestfs_available.
6266  *)
6267 and generate_daemon_optgroups_c () =
6268   generate_header CStyle GPLv2plus;
6269
6270   pr "#include <config.h>\n";
6271   pr "\n";
6272   pr "#include \"daemon.h\"\n";
6273   pr "#include \"optgroups.h\"\n";
6274   pr "\n";
6275
6276   pr "struct optgroup optgroups[] = {\n";
6277   List.iter (
6278     fun (group, _) ->
6279       pr "  { \"%s\", optgroup_%s_available },\n" group group
6280   ) optgroups;
6281   pr "  { NULL, NULL }\n";
6282   pr "};\n"
6283
6284 and generate_daemon_optgroups_h () =
6285   generate_header CStyle GPLv2plus;
6286
6287   List.iter (
6288     fun (group, _) ->
6289       pr "extern int optgroup_%s_available (void);\n" group
6290   ) optgroups
6291
6292 (* Generate the tests. *)
6293 and generate_tests () =
6294   generate_header CStyle GPLv2plus;
6295
6296   pr "\
6297 #include <stdio.h>
6298 #include <stdlib.h>
6299 #include <string.h>
6300 #include <unistd.h>
6301 #include <sys/types.h>
6302 #include <fcntl.h>
6303
6304 #include \"guestfs.h\"
6305 #include \"guestfs-internal.h\"
6306
6307 static guestfs_h *g;
6308 static int suppress_error = 0;
6309
6310 static void print_error (guestfs_h *g, void *data, const char *msg)
6311 {
6312   if (!suppress_error)
6313     fprintf (stderr, \"%%s\\n\", msg);
6314 }
6315
6316 /* FIXME: nearly identical code appears in fish.c */
6317 static void print_strings (char *const *argv)
6318 {
6319   int argc;
6320
6321   for (argc = 0; argv[argc] != NULL; ++argc)
6322     printf (\"\\t%%s\\n\", argv[argc]);
6323 }
6324
6325 /*
6326 static void print_table (char const *const *argv)
6327 {
6328   int i;
6329
6330   for (i = 0; argv[i] != NULL; i += 2)
6331     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6332 }
6333 */
6334
6335 ";
6336
6337   (* Generate a list of commands which are not tested anywhere. *)
6338   pr "static void no_test_warnings (void)\n";
6339   pr "{\n";
6340
6341   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6342   List.iter (
6343     fun (_, _, _, _, tests, _, _) ->
6344       let tests = filter_map (
6345         function
6346         | (_, (Always|If _|Unless _), test) -> Some test
6347         | (_, Disabled, _) -> None
6348       ) tests in
6349       let seq = List.concat (List.map seq_of_test tests) in
6350       let cmds_tested = List.map List.hd seq in
6351       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6352   ) all_functions;
6353
6354   List.iter (
6355     fun (name, _, _, _, _, _, _) ->
6356       if not (Hashtbl.mem hash name) then
6357         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6358   ) all_functions;
6359
6360   pr "}\n";
6361   pr "\n";
6362
6363   (* Generate the actual tests.  Note that we generate the tests
6364    * in reverse order, deliberately, so that (in general) the
6365    * newest tests run first.  This makes it quicker and easier to
6366    * debug them.
6367    *)
6368   let test_names =
6369     List.map (
6370       fun (name, _, _, flags, tests, _, _) ->
6371         mapi (generate_one_test name flags) tests
6372     ) (List.rev all_functions) in
6373   let test_names = List.concat test_names in
6374   let nr_tests = List.length test_names in
6375
6376   pr "\
6377 int main (int argc, char *argv[])
6378 {
6379   char c = 0;
6380   unsigned long int n_failed = 0;
6381   const char *filename;
6382   int fd;
6383   int nr_tests, test_num = 0;
6384
6385   setbuf (stdout, NULL);
6386
6387   no_test_warnings ();
6388
6389   g = guestfs_create ();
6390   if (g == NULL) {
6391     printf (\"guestfs_create FAILED\\n\");
6392     exit (EXIT_FAILURE);
6393   }
6394
6395   guestfs_set_error_handler (g, print_error, NULL);
6396
6397   guestfs_set_path (g, \"../appliance\");
6398
6399   filename = \"test1.img\";
6400   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6401   if (fd == -1) {
6402     perror (filename);
6403     exit (EXIT_FAILURE);
6404   }
6405   if (lseek (fd, %d, SEEK_SET) == -1) {
6406     perror (\"lseek\");
6407     close (fd);
6408     unlink (filename);
6409     exit (EXIT_FAILURE);
6410   }
6411   if (write (fd, &c, 1) == -1) {
6412     perror (\"write\");
6413     close (fd);
6414     unlink (filename);
6415     exit (EXIT_FAILURE);
6416   }
6417   if (close (fd) == -1) {
6418     perror (filename);
6419     unlink (filename);
6420     exit (EXIT_FAILURE);
6421   }
6422   if (guestfs_add_drive (g, filename) == -1) {
6423     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6424     exit (EXIT_FAILURE);
6425   }
6426
6427   filename = \"test2.img\";
6428   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6429   if (fd == -1) {
6430     perror (filename);
6431     exit (EXIT_FAILURE);
6432   }
6433   if (lseek (fd, %d, SEEK_SET) == -1) {
6434     perror (\"lseek\");
6435     close (fd);
6436     unlink (filename);
6437     exit (EXIT_FAILURE);
6438   }
6439   if (write (fd, &c, 1) == -1) {
6440     perror (\"write\");
6441     close (fd);
6442     unlink (filename);
6443     exit (EXIT_FAILURE);
6444   }
6445   if (close (fd) == -1) {
6446     perror (filename);
6447     unlink (filename);
6448     exit (EXIT_FAILURE);
6449   }
6450   if (guestfs_add_drive (g, filename) == -1) {
6451     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6452     exit (EXIT_FAILURE);
6453   }
6454
6455   filename = \"test3.img\";
6456   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6457   if (fd == -1) {
6458     perror (filename);
6459     exit (EXIT_FAILURE);
6460   }
6461   if (lseek (fd, %d, SEEK_SET) == -1) {
6462     perror (\"lseek\");
6463     close (fd);
6464     unlink (filename);
6465     exit (EXIT_FAILURE);
6466   }
6467   if (write (fd, &c, 1) == -1) {
6468     perror (\"write\");
6469     close (fd);
6470     unlink (filename);
6471     exit (EXIT_FAILURE);
6472   }
6473   if (close (fd) == -1) {
6474     perror (filename);
6475     unlink (filename);
6476     exit (EXIT_FAILURE);
6477   }
6478   if (guestfs_add_drive (g, filename) == -1) {
6479     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6480     exit (EXIT_FAILURE);
6481   }
6482
6483   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6484     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6485     exit (EXIT_FAILURE);
6486   }
6487
6488   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6489   alarm (600);
6490
6491   if (guestfs_launch (g) == -1) {
6492     printf (\"guestfs_launch FAILED\\n\");
6493     exit (EXIT_FAILURE);
6494   }
6495
6496   /* Cancel previous alarm. */
6497   alarm (0);
6498
6499   nr_tests = %d;
6500
6501 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6502
6503   iteri (
6504     fun i test_name ->
6505       pr "  test_num++;\n";
6506       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6507       pr "  if (%s () == -1) {\n" test_name;
6508       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6509       pr "    n_failed++;\n";
6510       pr "  }\n";
6511   ) test_names;
6512   pr "\n";
6513
6514   pr "  guestfs_close (g);\n";
6515   pr "  unlink (\"test1.img\");\n";
6516   pr "  unlink (\"test2.img\");\n";
6517   pr "  unlink (\"test3.img\");\n";
6518   pr "\n";
6519
6520   pr "  if (n_failed > 0) {\n";
6521   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6522   pr "    exit (EXIT_FAILURE);\n";
6523   pr "  }\n";
6524   pr "\n";
6525
6526   pr "  exit (EXIT_SUCCESS);\n";
6527   pr "}\n"
6528
6529 and generate_one_test name flags i (init, prereq, test) =
6530   let test_name = sprintf "test_%s_%d" name i in
6531
6532   pr "\
6533 static int %s_skip (void)
6534 {
6535   const char *str;
6536
6537   str = getenv (\"TEST_ONLY\");
6538   if (str)
6539     return strstr (str, \"%s\") == NULL;
6540   str = getenv (\"SKIP_%s\");
6541   if (str && STREQ (str, \"1\")) return 1;
6542   str = getenv (\"SKIP_TEST_%s\");
6543   if (str && STREQ (str, \"1\")) return 1;
6544   return 0;
6545 }
6546
6547 " test_name name (String.uppercase test_name) (String.uppercase name);
6548
6549   (match prereq with
6550    | Disabled | Always -> ()
6551    | If code | Unless code ->
6552        pr "static int %s_prereq (void)\n" test_name;
6553        pr "{\n";
6554        pr "  %s\n" code;
6555        pr "}\n";
6556        pr "\n";
6557   );
6558
6559   pr "\
6560 static int %s (void)
6561 {
6562   if (%s_skip ()) {
6563     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6564     return 0;
6565   }
6566
6567 " test_name test_name test_name;
6568
6569   (* Optional functions should only be tested if the relevant
6570    * support is available in the daemon.
6571    *)
6572   List.iter (
6573     function
6574     | Optional group ->
6575         pr "  {\n";
6576         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6577         pr "    int r;\n";
6578         pr "    suppress_error = 1;\n";
6579         pr "    r = guestfs_available (g, (char **) groups);\n";
6580         pr "    suppress_error = 0;\n";
6581         pr "    if (r == -1) {\n";
6582         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6583         pr "      return 0;\n";
6584         pr "    }\n";
6585         pr "  }\n";
6586     | _ -> ()
6587   ) flags;
6588
6589   (match prereq with
6590    | Disabled ->
6591        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6592    | If _ ->
6593        pr "  if (! %s_prereq ()) {\n" test_name;
6594        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6595        pr "    return 0;\n";
6596        pr "  }\n";
6597        pr "\n";
6598        generate_one_test_body name i test_name init test;
6599    | Unless _ ->
6600        pr "  if (%s_prereq ()) {\n" test_name;
6601        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6602        pr "    return 0;\n";
6603        pr "  }\n";
6604        pr "\n";
6605        generate_one_test_body name i test_name init test;
6606    | Always ->
6607        generate_one_test_body name i test_name init test
6608   );
6609
6610   pr "  return 0;\n";
6611   pr "}\n";
6612   pr "\n";
6613   test_name
6614
6615 and generate_one_test_body name i test_name init test =
6616   (match init with
6617    | InitNone (* XXX at some point, InitNone and InitEmpty became
6618                * folded together as the same thing.  Really we should
6619                * make InitNone do nothing at all, but the tests may
6620                * need to be checked to make sure this is OK.
6621                *)
6622    | InitEmpty ->
6623        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6624        List.iter (generate_test_command_call test_name)
6625          [["blockdev_setrw"; "/dev/sda"];
6626           ["umount_all"];
6627           ["lvm_remove_all"]]
6628    | InitPartition ->
6629        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6630        List.iter (generate_test_command_call test_name)
6631          [["blockdev_setrw"; "/dev/sda"];
6632           ["umount_all"];
6633           ["lvm_remove_all"];
6634           ["part_disk"; "/dev/sda"; "mbr"]]
6635    | InitBasicFS ->
6636        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6637        List.iter (generate_test_command_call test_name)
6638          [["blockdev_setrw"; "/dev/sda"];
6639           ["umount_all"];
6640           ["lvm_remove_all"];
6641           ["part_disk"; "/dev/sda"; "mbr"];
6642           ["mkfs"; "ext2"; "/dev/sda1"];
6643           ["mount_options"; ""; "/dev/sda1"; "/"]]
6644    | InitBasicFSonLVM ->
6645        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6646          test_name;
6647        List.iter (generate_test_command_call test_name)
6648          [["blockdev_setrw"; "/dev/sda"];
6649           ["umount_all"];
6650           ["lvm_remove_all"];
6651           ["part_disk"; "/dev/sda"; "mbr"];
6652           ["pvcreate"; "/dev/sda1"];
6653           ["vgcreate"; "VG"; "/dev/sda1"];
6654           ["lvcreate"; "LV"; "VG"; "8"];
6655           ["mkfs"; "ext2"; "/dev/VG/LV"];
6656           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6657    | InitISOFS ->
6658        pr "  /* InitISOFS for %s */\n" test_name;
6659        List.iter (generate_test_command_call test_name)
6660          [["blockdev_setrw"; "/dev/sda"];
6661           ["umount_all"];
6662           ["lvm_remove_all"];
6663           ["mount_ro"; "/dev/sdd"; "/"]]
6664   );
6665
6666   let get_seq_last = function
6667     | [] ->
6668         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6669           test_name
6670     | seq ->
6671         let seq = List.rev seq in
6672         List.rev (List.tl seq), List.hd seq
6673   in
6674
6675   match test with
6676   | TestRun seq ->
6677       pr "  /* TestRun for %s (%d) */\n" name i;
6678       List.iter (generate_test_command_call test_name) seq
6679   | TestOutput (seq, expected) ->
6680       pr "  /* TestOutput for %s (%d) */\n" name i;
6681       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6682       let seq, last = get_seq_last seq in
6683       let test () =
6684         pr "    if (STRNEQ (r, expected)) {\n";
6685         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6686         pr "      return -1;\n";
6687         pr "    }\n"
6688       in
6689       List.iter (generate_test_command_call test_name) seq;
6690       generate_test_command_call ~test test_name last
6691   | TestOutputList (seq, expected) ->
6692       pr "  /* TestOutputList for %s (%d) */\n" name i;
6693       let seq, last = get_seq_last seq in
6694       let test () =
6695         iteri (
6696           fun i str ->
6697             pr "    if (!r[%d]) {\n" i;
6698             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6699             pr "      print_strings (r);\n";
6700             pr "      return -1;\n";
6701             pr "    }\n";
6702             pr "    {\n";
6703             pr "      const char *expected = \"%s\";\n" (c_quote str);
6704             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6705             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6706             pr "        return -1;\n";
6707             pr "      }\n";
6708             pr "    }\n"
6709         ) expected;
6710         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6711         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6712           test_name;
6713         pr "      print_strings (r);\n";
6714         pr "      return -1;\n";
6715         pr "    }\n"
6716       in
6717       List.iter (generate_test_command_call test_name) seq;
6718       generate_test_command_call ~test test_name last
6719   | TestOutputListOfDevices (seq, expected) ->
6720       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6721       let seq, last = get_seq_last seq in
6722       let test () =
6723         iteri (
6724           fun i str ->
6725             pr "    if (!r[%d]) {\n" i;
6726             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6727             pr "      print_strings (r);\n";
6728             pr "      return -1;\n";
6729             pr "    }\n";
6730             pr "    {\n";
6731             pr "      const char *expected = \"%s\";\n" (c_quote str);
6732             pr "      r[%d][5] = 's';\n" i;
6733             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6734             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6735             pr "        return -1;\n";
6736             pr "      }\n";
6737             pr "    }\n"
6738         ) expected;
6739         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6740         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6741           test_name;
6742         pr "      print_strings (r);\n";
6743         pr "      return -1;\n";
6744         pr "    }\n"
6745       in
6746       List.iter (generate_test_command_call test_name) seq;
6747       generate_test_command_call ~test test_name last
6748   | TestOutputInt (seq, expected) ->
6749       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6750       let seq, last = get_seq_last seq in
6751       let test () =
6752         pr "    if (r != %d) {\n" expected;
6753         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6754           test_name expected;
6755         pr "               (int) r);\n";
6756         pr "      return -1;\n";
6757         pr "    }\n"
6758       in
6759       List.iter (generate_test_command_call test_name) seq;
6760       generate_test_command_call ~test test_name last
6761   | TestOutputIntOp (seq, op, expected) ->
6762       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6763       let seq, last = get_seq_last seq in
6764       let test () =
6765         pr "    if (! (r %s %d)) {\n" op expected;
6766         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6767           test_name op expected;
6768         pr "               (int) r);\n";
6769         pr "      return -1;\n";
6770         pr "    }\n"
6771       in
6772       List.iter (generate_test_command_call test_name) seq;
6773       generate_test_command_call ~test test_name last
6774   | TestOutputTrue seq ->
6775       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6776       let seq, last = get_seq_last seq in
6777       let test () =
6778         pr "    if (!r) {\n";
6779         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6780           test_name;
6781         pr "      return -1;\n";
6782         pr "    }\n"
6783       in
6784       List.iter (generate_test_command_call test_name) seq;
6785       generate_test_command_call ~test test_name last
6786   | TestOutputFalse seq ->
6787       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6788       let seq, last = get_seq_last seq in
6789       let test () =
6790         pr "    if (r) {\n";
6791         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6792           test_name;
6793         pr "      return -1;\n";
6794         pr "    }\n"
6795       in
6796       List.iter (generate_test_command_call test_name) seq;
6797       generate_test_command_call ~test test_name last
6798   | TestOutputLength (seq, expected) ->
6799       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6800       let seq, last = get_seq_last seq in
6801       let test () =
6802         pr "    int j;\n";
6803         pr "    for (j = 0; j < %d; ++j)\n" expected;
6804         pr "      if (r[j] == NULL) {\n";
6805         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6806           test_name;
6807         pr "        print_strings (r);\n";
6808         pr "        return -1;\n";
6809         pr "      }\n";
6810         pr "    if (r[j] != NULL) {\n";
6811         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6812           test_name;
6813         pr "      print_strings (r);\n";
6814         pr "      return -1;\n";
6815         pr "    }\n"
6816       in
6817       List.iter (generate_test_command_call test_name) seq;
6818       generate_test_command_call ~test test_name last
6819   | TestOutputBuffer (seq, expected) ->
6820       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6821       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6822       let seq, last = get_seq_last seq in
6823       let len = String.length expected in
6824       let test () =
6825         pr "    if (size != %d) {\n" len;
6826         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6827         pr "      return -1;\n";
6828         pr "    }\n";
6829         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6830         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6831         pr "      return -1;\n";
6832         pr "    }\n"
6833       in
6834       List.iter (generate_test_command_call test_name) seq;
6835       generate_test_command_call ~test test_name last
6836   | TestOutputStruct (seq, checks) ->
6837       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6838       let seq, last = get_seq_last seq in
6839       let test () =
6840         List.iter (
6841           function
6842           | CompareWithInt (field, expected) ->
6843               pr "    if (r->%s != %d) {\n" field expected;
6844               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6845                 test_name field expected;
6846               pr "               (int) r->%s);\n" field;
6847               pr "      return -1;\n";
6848               pr "    }\n"
6849           | CompareWithIntOp (field, op, expected) ->
6850               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6851               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6852                 test_name field op expected;
6853               pr "               (int) r->%s);\n" field;
6854               pr "      return -1;\n";
6855               pr "    }\n"
6856           | CompareWithString (field, expected) ->
6857               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6858               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6859                 test_name field expected;
6860               pr "               r->%s);\n" field;
6861               pr "      return -1;\n";
6862               pr "    }\n"
6863           | CompareFieldsIntEq (field1, field2) ->
6864               pr "    if (r->%s != r->%s) {\n" field1 field2;
6865               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6866                 test_name field1 field2;
6867               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6868               pr "      return -1;\n";
6869               pr "    }\n"
6870           | CompareFieldsStrEq (field1, field2) ->
6871               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6872               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6873                 test_name field1 field2;
6874               pr "               r->%s, r->%s);\n" field1 field2;
6875               pr "      return -1;\n";
6876               pr "    }\n"
6877         ) checks
6878       in
6879       List.iter (generate_test_command_call test_name) seq;
6880       generate_test_command_call ~test test_name last
6881   | TestLastFail seq ->
6882       pr "  /* TestLastFail for %s (%d) */\n" name i;
6883       let seq, last = get_seq_last seq in
6884       List.iter (generate_test_command_call test_name) seq;
6885       generate_test_command_call test_name ~expect_error:true last
6886
6887 (* Generate the code to run a command, leaving the result in 'r'.
6888  * If you expect to get an error then you should set expect_error:true.
6889  *)
6890 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6891   match cmd with
6892   | [] -> assert false
6893   | name :: args ->
6894       (* Look up the command to find out what args/ret it has. *)
6895       let style =
6896         try
6897           let _, style, _, _, _, _, _ =
6898             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6899           style
6900         with Not_found ->
6901           failwithf "%s: in test, command %s was not found" test_name name in
6902
6903       if List.length (snd style) <> List.length args then
6904         failwithf "%s: in test, wrong number of args given to %s"
6905           test_name name;
6906
6907       pr "  {\n";
6908
6909       List.iter (
6910         function
6911         | OptString n, "NULL" -> ()
6912         | Pathname n, arg
6913         | Device n, arg
6914         | Dev_or_Path n, arg
6915         | String n, arg
6916         | OptString n, arg ->
6917             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6918         | Int _, _
6919         | Int64 _, _
6920         | Bool _, _
6921         | FileIn _, _ | FileOut _, _ -> ()
6922         | StringList n, "" | DeviceList n, "" ->
6923             pr "    const char *const %s[1] = { NULL };\n" n
6924         | StringList n, arg | DeviceList n, arg ->
6925             let strs = string_split " " arg in
6926             iteri (
6927               fun i str ->
6928                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6929             ) strs;
6930             pr "    const char *const %s[] = {\n" n;
6931             iteri (
6932               fun i _ -> pr "      %s_%d,\n" n i
6933             ) strs;
6934             pr "      NULL\n";
6935             pr "    };\n";
6936       ) (List.combine (snd style) args);
6937
6938       let error_code =
6939         match fst style with
6940         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6941         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6942         | RConstString _ | RConstOptString _ ->
6943             pr "    const char *r;\n"; "NULL"
6944         | RString _ -> pr "    char *r;\n"; "NULL"
6945         | RStringList _ | RHashtable _ ->
6946             pr "    char **r;\n";
6947             pr "    int i;\n";
6948             "NULL"
6949         | RStruct (_, typ) ->
6950             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6951         | RStructList (_, typ) ->
6952             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6953         | RBufferOut _ ->
6954             pr "    char *r;\n";
6955             pr "    size_t size;\n";
6956             "NULL" in
6957
6958       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6959       pr "    r = guestfs_%s (g" name;
6960
6961       (* Generate the parameters. *)
6962       List.iter (
6963         function
6964         | OptString _, "NULL" -> pr ", NULL"
6965         | Pathname n, _
6966         | Device n, _ | Dev_or_Path n, _
6967         | String n, _
6968         | OptString n, _ ->
6969             pr ", %s" n
6970         | FileIn _, arg | FileOut _, arg ->
6971             pr ", \"%s\"" (c_quote arg)
6972         | StringList n, _ | DeviceList n, _ ->
6973             pr ", (char **) %s" n
6974         | Int _, arg ->
6975             let i =
6976               try int_of_string arg
6977               with Failure "int_of_string" ->
6978                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6979             pr ", %d" i
6980         | Int64 _, arg ->
6981             let i =
6982               try Int64.of_string arg
6983               with Failure "int_of_string" ->
6984                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6985             pr ", %Ld" i
6986         | Bool _, arg ->
6987             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6988       ) (List.combine (snd style) args);
6989
6990       (match fst style with
6991        | RBufferOut _ -> pr ", &size"
6992        | _ -> ()
6993       );
6994
6995       pr ");\n";
6996
6997       if not expect_error then
6998         pr "    if (r == %s)\n" error_code
6999       else
7000         pr "    if (r != %s)\n" error_code;
7001       pr "      return -1;\n";
7002
7003       (* Insert the test code. *)
7004       (match test with
7005        | None -> ()
7006        | Some f -> f ()
7007       );
7008
7009       (match fst style with
7010        | RErr | RInt _ | RInt64 _ | RBool _
7011        | RConstString _ | RConstOptString _ -> ()
7012        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7013        | RStringList _ | RHashtable _ ->
7014            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7015            pr "      free (r[i]);\n";
7016            pr "    free (r);\n"
7017        | RStruct (_, typ) ->
7018            pr "    guestfs_free_%s (r);\n" typ
7019        | RStructList (_, typ) ->
7020            pr "    guestfs_free_%s_list (r);\n" typ
7021       );
7022
7023       pr "  }\n"
7024
7025 and c_quote str =
7026   let str = replace_str str "\r" "\\r" in
7027   let str = replace_str str "\n" "\\n" in
7028   let str = replace_str str "\t" "\\t" in
7029   let str = replace_str str "\000" "\\0" in
7030   str
7031
7032 (* Generate a lot of different functions for guestfish. *)
7033 and generate_fish_cmds () =
7034   generate_header CStyle GPLv2plus;
7035
7036   let all_functions =
7037     List.filter (
7038       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7039     ) all_functions in
7040   let all_functions_sorted =
7041     List.filter (
7042       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7043     ) all_functions_sorted in
7044
7045   pr "#include <config.h>\n";
7046   pr "\n";
7047   pr "#include <stdio.h>\n";
7048   pr "#include <stdlib.h>\n";
7049   pr "#include <string.h>\n";
7050   pr "#include <inttypes.h>\n";
7051   pr "\n";
7052   pr "#include <guestfs.h>\n";
7053   pr "#include \"c-ctype.h\"\n";
7054   pr "#include \"full-write.h\"\n";
7055   pr "#include \"xstrtol.h\"\n";
7056   pr "#include \"fish.h\"\n";
7057   pr "\n";
7058
7059   (* list_commands function, which implements guestfish -h *)
7060   pr "void list_commands (void)\n";
7061   pr "{\n";
7062   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7063   pr "  list_builtin_commands ();\n";
7064   List.iter (
7065     fun (name, _, _, flags, _, shortdesc, _) ->
7066       let name = replace_char name '_' '-' in
7067       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7068         name shortdesc
7069   ) all_functions_sorted;
7070   pr "  printf (\"    %%s\\n\",";
7071   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7072   pr "}\n";
7073   pr "\n";
7074
7075   (* display_command function, which implements guestfish -h cmd *)
7076   pr "void display_command (const char *cmd)\n";
7077   pr "{\n";
7078   List.iter (
7079     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7080       let name2 = replace_char name '_' '-' in
7081       let alias =
7082         try find_map (function FishAlias n -> Some n | _ -> None) flags
7083         with Not_found -> name in
7084       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7085       let synopsis =
7086         match snd style with
7087         | [] -> name2
7088         | args ->
7089             sprintf "%s %s"
7090               name2 (String.concat " " (List.map name_of_argt args)) in
7091
7092       let warnings =
7093         if List.mem ProtocolLimitWarning flags then
7094           ("\n\n" ^ protocol_limit_warning)
7095         else "" in
7096
7097       (* For DangerWillRobinson commands, we should probably have
7098        * guestfish prompt before allowing you to use them (especially
7099        * in interactive mode). XXX
7100        *)
7101       let warnings =
7102         warnings ^
7103           if List.mem DangerWillRobinson flags then
7104             ("\n\n" ^ danger_will_robinson)
7105           else "" in
7106
7107       let warnings =
7108         warnings ^
7109           match deprecation_notice flags with
7110           | None -> ""
7111           | Some txt -> "\n\n" ^ txt in
7112
7113       let describe_alias =
7114         if name <> alias then
7115           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7116         else "" in
7117
7118       pr "  if (";
7119       pr "STRCASEEQ (cmd, \"%s\")" name;
7120       if name <> name2 then
7121         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7122       if name <> alias then
7123         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7124       pr ")\n";
7125       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7126         name2 shortdesc
7127         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7128          "=head1 DESCRIPTION\n\n" ^
7129          longdesc ^ warnings ^ describe_alias);
7130       pr "  else\n"
7131   ) all_functions;
7132   pr "    display_builtin_command (cmd);\n";
7133   pr "}\n";
7134   pr "\n";
7135
7136   let emit_print_list_function typ =
7137     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7138       typ typ typ;
7139     pr "{\n";
7140     pr "  unsigned int i;\n";
7141     pr "\n";
7142     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7143     pr "    printf (\"[%%d] = {\\n\", i);\n";
7144     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7145     pr "    printf (\"}\\n\");\n";
7146     pr "  }\n";
7147     pr "}\n";
7148     pr "\n";
7149   in
7150
7151   (* print_* functions *)
7152   List.iter (
7153     fun (typ, cols) ->
7154       let needs_i =
7155         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7156
7157       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7158       pr "{\n";
7159       if needs_i then (
7160         pr "  unsigned int i;\n";
7161         pr "\n"
7162       );
7163       List.iter (
7164         function
7165         | name, FString ->
7166             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7167         | name, FUUID ->
7168             pr "  printf (\"%%s%s: \", indent);\n" name;
7169             pr "  for (i = 0; i < 32; ++i)\n";
7170             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7171             pr "  printf (\"\\n\");\n"
7172         | name, FBuffer ->
7173             pr "  printf (\"%%s%s: \", indent);\n" name;
7174             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7175             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7176             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7177             pr "    else\n";
7178             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7179             pr "  printf (\"\\n\");\n"
7180         | name, (FUInt64|FBytes) ->
7181             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7182               name typ name
7183         | name, FInt64 ->
7184             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7185               name typ name
7186         | name, FUInt32 ->
7187             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7188               name typ name
7189         | name, FInt32 ->
7190             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7191               name typ name
7192         | name, FChar ->
7193             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7194               name typ name
7195         | name, FOptPercent ->
7196             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7197               typ name name typ name;
7198             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7199       ) cols;
7200       pr "}\n";
7201       pr "\n";
7202   ) structs;
7203
7204   (* Emit a print_TYPE_list function definition only if that function is used. *)
7205   List.iter (
7206     function
7207     | typ, (RStructListOnly | RStructAndList) ->
7208         (* generate the function for typ *)
7209         emit_print_list_function typ
7210     | typ, _ -> () (* empty *)
7211   ) (rstructs_used_by all_functions);
7212
7213   (* Emit a print_TYPE function definition only if that function is used. *)
7214   List.iter (
7215     function
7216     | typ, (RStructOnly | RStructAndList) ->
7217         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7218         pr "{\n";
7219         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7220         pr "}\n";
7221         pr "\n";
7222     | typ, _ -> () (* empty *)
7223   ) (rstructs_used_by all_functions);
7224
7225   (* run_<action> actions *)
7226   List.iter (
7227     fun (name, style, _, flags, _, _, _) ->
7228       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7229       pr "{\n";
7230       (match fst style with
7231        | RErr
7232        | RInt _
7233        | RBool _ -> pr "  int r;\n"
7234        | RInt64 _ -> pr "  int64_t r;\n"
7235        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7236        | RString _ -> pr "  char *r;\n"
7237        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7238        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7239        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7240        | RBufferOut _ ->
7241            pr "  char *r;\n";
7242            pr "  size_t size;\n";
7243       );
7244       List.iter (
7245         function
7246         | Device n
7247         | String n
7248         | OptString n
7249         | FileIn n
7250         | FileOut n -> pr "  const char *%s;\n" n
7251         | Pathname n
7252         | Dev_or_Path n -> pr "  char *%s;\n" n
7253         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7254         | Bool n -> pr "  int %s;\n" n
7255         | Int n -> pr "  int %s;\n" n
7256         | Int64 n -> pr "  int64_t %s;\n" n
7257       ) (snd style);
7258
7259       (* Check and convert parameters. *)
7260       let argc_expected = List.length (snd style) in
7261       pr "  if (argc != %d) {\n" argc_expected;
7262       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7263         argc_expected;
7264       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7265       pr "    return -1;\n";
7266       pr "  }\n";
7267
7268       let parse_integer fn fntyp rtyp range name i =
7269         pr "  {\n";
7270         pr "    strtol_error xerr;\n";
7271         pr "    %s r;\n" fntyp;
7272         pr "\n";
7273         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7274         pr "    if (xerr != LONGINT_OK) {\n";
7275         pr "      fprintf (stderr,\n";
7276         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7277         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7278         pr "      return -1;\n";
7279         pr "    }\n";
7280         (match range with
7281          | None -> ()
7282          | Some (min, max, comment) ->
7283              pr "    /* %s */\n" comment;
7284              pr "    if (r < %s || r > %s) {\n" min max;
7285              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7286                name;
7287              pr "      return -1;\n";
7288              pr "    }\n";
7289              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7290         );
7291         pr "    %s = r;\n" name;
7292         pr "  }\n";
7293       in
7294
7295       iteri (
7296         fun i ->
7297           function
7298           | Device name
7299           | String name ->
7300               pr "  %s = argv[%d];\n" name i
7301           | Pathname name
7302           | Dev_or_Path name ->
7303               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7304               pr "  if (%s == NULL) return -1;\n" name
7305           | OptString name ->
7306               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7307                 name i i
7308           | FileIn name ->
7309               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7310                 name i i
7311           | FileOut name ->
7312               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7313                 name i i
7314           | StringList name | DeviceList name ->
7315               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7316               pr "  if (%s == NULL) return -1;\n" name;
7317           | Bool name ->
7318               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7319           | Int name ->
7320               let range =
7321                 let min = "(-(2LL<<30))"
7322                 and max = "((2LL<<30)-1)"
7323                 and comment =
7324                   "The Int type in the generator is a signed 31 bit int." in
7325                 Some (min, max, comment) in
7326               parse_integer "xstrtoll" "long long" "int" range name i
7327           | Int64 name ->
7328               parse_integer "xstrtoll" "long long" "int64_t" None name i
7329       ) (snd style);
7330
7331       (* Call C API function. *)
7332       let fn =
7333         try find_map (function FishAction n -> Some n | _ -> None) flags
7334         with Not_found -> sprintf "guestfs_%s" name in
7335       pr "  r = %s " fn;
7336       generate_c_call_args ~handle:"g" style;
7337       pr ";\n";
7338
7339       List.iter (
7340         function
7341         | Device name | String name
7342         | OptString name | FileIn name | FileOut name | Bool name
7343         | Int name | Int64 name -> ()
7344         | Pathname name | Dev_or_Path name ->
7345             pr "  free (%s);\n" name
7346         | StringList name | DeviceList name ->
7347             pr "  free_strings (%s);\n" name
7348       ) (snd style);
7349
7350       (* Check return value for errors and display command results. *)
7351       (match fst style with
7352        | RErr -> pr "  return r;\n"
7353        | RInt _ ->
7354            pr "  if (r == -1) return -1;\n";
7355            pr "  printf (\"%%d\\n\", r);\n";
7356            pr "  return 0;\n"
7357        | RInt64 _ ->
7358            pr "  if (r == -1) return -1;\n";
7359            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7360            pr "  return 0;\n"
7361        | RBool _ ->
7362            pr "  if (r == -1) return -1;\n";
7363            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7364            pr "  return 0;\n"
7365        | RConstString _ ->
7366            pr "  if (r == NULL) return -1;\n";
7367            pr "  printf (\"%%s\\n\", r);\n";
7368            pr "  return 0;\n"
7369        | RConstOptString _ ->
7370            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7371            pr "  return 0;\n"
7372        | RString _ ->
7373            pr "  if (r == NULL) return -1;\n";
7374            pr "  printf (\"%%s\\n\", r);\n";
7375            pr "  free (r);\n";
7376            pr "  return 0;\n"
7377        | RStringList _ ->
7378            pr "  if (r == NULL) return -1;\n";
7379            pr "  print_strings (r);\n";
7380            pr "  free_strings (r);\n";
7381            pr "  return 0;\n"
7382        | RStruct (_, typ) ->
7383            pr "  if (r == NULL) return -1;\n";
7384            pr "  print_%s (r);\n" typ;
7385            pr "  guestfs_free_%s (r);\n" typ;
7386            pr "  return 0;\n"
7387        | RStructList (_, typ) ->
7388            pr "  if (r == NULL) return -1;\n";
7389            pr "  print_%s_list (r);\n" typ;
7390            pr "  guestfs_free_%s_list (r);\n" typ;
7391            pr "  return 0;\n"
7392        | RHashtable _ ->
7393            pr "  if (r == NULL) return -1;\n";
7394            pr "  print_table (r);\n";
7395            pr "  free_strings (r);\n";
7396            pr "  return 0;\n"
7397        | RBufferOut _ ->
7398            pr "  if (r == NULL) return -1;\n";
7399            pr "  if (full_write (1, r, size) != size) {\n";
7400            pr "    perror (\"write\");\n";
7401            pr "    free (r);\n";
7402            pr "    return -1;\n";
7403            pr "  }\n";
7404            pr "  free (r);\n";
7405            pr "  return 0;\n"
7406       );
7407       pr "}\n";
7408       pr "\n"
7409   ) all_functions;
7410
7411   (* run_action function *)
7412   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7413   pr "{\n";
7414   List.iter (
7415     fun (name, _, _, flags, _, _, _) ->
7416       let name2 = replace_char name '_' '-' in
7417       let alias =
7418         try find_map (function FishAlias n -> Some n | _ -> None) flags
7419         with Not_found -> name in
7420       pr "  if (";
7421       pr "STRCASEEQ (cmd, \"%s\")" name;
7422       if name <> name2 then
7423         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7424       if name <> alias then
7425         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7426       pr ")\n";
7427       pr "    return run_%s (cmd, argc, argv);\n" name;
7428       pr "  else\n";
7429   ) all_functions;
7430   pr "    {\n";
7431   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7432   pr "      if (command_num == 1)\n";
7433   pr "        extended_help_message ();\n";
7434   pr "      return -1;\n";
7435   pr "    }\n";
7436   pr "  return 0;\n";
7437   pr "}\n";
7438   pr "\n"
7439
7440 (* Readline completion for guestfish. *)
7441 and generate_fish_completion () =
7442   generate_header CStyle GPLv2plus;
7443
7444   let all_functions =
7445     List.filter (
7446       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7447     ) all_functions in
7448
7449   pr "\
7450 #include <config.h>
7451
7452 #include <stdio.h>
7453 #include <stdlib.h>
7454 #include <string.h>
7455
7456 #ifdef HAVE_LIBREADLINE
7457 #include <readline/readline.h>
7458 #endif
7459
7460 #include \"fish.h\"
7461
7462 #ifdef HAVE_LIBREADLINE
7463
7464 static const char *const commands[] = {
7465   BUILTIN_COMMANDS_FOR_COMPLETION,
7466 ";
7467
7468   (* Get the commands, including the aliases.  They don't need to be
7469    * sorted - the generator() function just does a dumb linear search.
7470    *)
7471   let commands =
7472     List.map (
7473       fun (name, _, _, flags, _, _, _) ->
7474         let name2 = replace_char name '_' '-' in
7475         let alias =
7476           try find_map (function FishAlias n -> Some n | _ -> None) flags
7477           with Not_found -> name in
7478
7479         if name <> alias then [name2; alias] else [name2]
7480     ) all_functions in
7481   let commands = List.flatten commands in
7482
7483   List.iter (pr "  \"%s\",\n") commands;
7484
7485   pr "  NULL
7486 };
7487
7488 static char *
7489 generator (const char *text, int state)
7490 {
7491   static int index, len;
7492   const char *name;
7493
7494   if (!state) {
7495     index = 0;
7496     len = strlen (text);
7497   }
7498
7499   rl_attempted_completion_over = 1;
7500
7501   while ((name = commands[index]) != NULL) {
7502     index++;
7503     if (STRCASEEQLEN (name, text, len))
7504       return strdup (name);
7505   }
7506
7507   return NULL;
7508 }
7509
7510 #endif /* HAVE_LIBREADLINE */
7511
7512 #ifdef HAVE_RL_COMPLETION_MATCHES
7513 #define RL_COMPLETION_MATCHES rl_completion_matches
7514 #else
7515 #ifdef HAVE_COMPLETION_MATCHES
7516 #define RL_COMPLETION_MATCHES completion_matches
7517 #endif
7518 #endif /* else just fail if we don't have either symbol */
7519
7520 char **
7521 do_completion (const char *text, int start, int end)
7522 {
7523   char **matches = NULL;
7524
7525 #ifdef HAVE_LIBREADLINE
7526   rl_completion_append_character = ' ';
7527
7528   if (start == 0)
7529     matches = RL_COMPLETION_MATCHES (text, generator);
7530   else if (complete_dest_paths)
7531     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7532 #endif
7533
7534   return matches;
7535 }
7536 ";
7537
7538 (* Generate the POD documentation for guestfish. *)
7539 and generate_fish_actions_pod () =
7540   let all_functions_sorted =
7541     List.filter (
7542       fun (_, _, _, flags, _, _, _) ->
7543         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7544     ) all_functions_sorted in
7545
7546   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7547
7548   List.iter (
7549     fun (name, style, _, flags, _, _, longdesc) ->
7550       let longdesc =
7551         Str.global_substitute rex (
7552           fun s ->
7553             let sub =
7554               try Str.matched_group 1 s
7555               with Not_found ->
7556                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7557             "C<" ^ replace_char sub '_' '-' ^ ">"
7558         ) longdesc in
7559       let name = replace_char name '_' '-' in
7560       let alias =
7561         try find_map (function FishAlias n -> Some n | _ -> None) flags
7562         with Not_found -> name in
7563
7564       pr "=head2 %s" name;
7565       if name <> alias then
7566         pr " | %s" alias;
7567       pr "\n";
7568       pr "\n";
7569       pr " %s" name;
7570       List.iter (
7571         function
7572         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7573         | OptString n -> pr " %s" n
7574         | StringList n | DeviceList n -> pr " '%s ...'" n
7575         | Bool _ -> pr " true|false"
7576         | Int n -> pr " %s" n
7577         | Int64 n -> pr " %s" n
7578         | FileIn n | FileOut n -> pr " (%s|-)" n
7579       ) (snd style);
7580       pr "\n";
7581       pr "\n";
7582       pr "%s\n\n" longdesc;
7583
7584       if List.exists (function FileIn _ | FileOut _ -> true
7585                       | _ -> false) (snd style) then
7586         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7587
7588       if List.mem ProtocolLimitWarning flags then
7589         pr "%s\n\n" protocol_limit_warning;
7590
7591       if List.mem DangerWillRobinson flags then
7592         pr "%s\n\n" danger_will_robinson;
7593
7594       match deprecation_notice flags with
7595       | None -> ()
7596       | Some txt -> pr "%s\n\n" txt
7597   ) all_functions_sorted
7598
7599 (* Generate a C function prototype. *)
7600 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7601     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7602     ?(prefix = "")
7603     ?handle name style =
7604   if extern then pr "extern ";
7605   if static then pr "static ";
7606   (match fst style with
7607    | RErr -> pr "int "
7608    | RInt _ -> pr "int "
7609    | RInt64 _ -> pr "int64_t "
7610    | RBool _ -> pr "int "
7611    | RConstString _ | RConstOptString _ -> pr "const char *"
7612    | RString _ | RBufferOut _ -> pr "char *"
7613    | RStringList _ | RHashtable _ -> pr "char **"
7614    | RStruct (_, typ) ->
7615        if not in_daemon then pr "struct guestfs_%s *" typ
7616        else pr "guestfs_int_%s *" typ
7617    | RStructList (_, typ) ->
7618        if not in_daemon then pr "struct guestfs_%s_list *" typ
7619        else pr "guestfs_int_%s_list *" typ
7620   );
7621   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7622   pr "%s%s (" prefix name;
7623   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7624     pr "void"
7625   else (
7626     let comma = ref false in
7627     (match handle with
7628      | None -> ()
7629      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7630     );
7631     let next () =
7632       if !comma then (
7633         if single_line then pr ", " else pr ",\n\t\t"
7634       );
7635       comma := true
7636     in
7637     List.iter (
7638       function
7639       | Pathname n
7640       | Device n | Dev_or_Path n
7641       | String n
7642       | OptString n ->
7643           next ();
7644           pr "const char *%s" n
7645       | StringList n | DeviceList n ->
7646           next ();
7647           pr "char *const *%s" n
7648       | Bool n -> next (); pr "int %s" n
7649       | Int n -> next (); pr "int %s" n
7650       | Int64 n -> next (); pr "int64_t %s" n
7651       | FileIn n
7652       | FileOut n ->
7653           if not in_daemon then (next (); pr "const char *%s" n)
7654     ) (snd style);
7655     if is_RBufferOut then (next (); pr "size_t *size_r");
7656   );
7657   pr ")";
7658   if semicolon then pr ";";
7659   if newline then pr "\n"
7660
7661 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7662 and generate_c_call_args ?handle ?(decl = false) style =
7663   pr "(";
7664   let comma = ref false in
7665   let next () =
7666     if !comma then pr ", ";
7667     comma := true
7668   in
7669   (match handle with
7670    | None -> ()
7671    | Some handle -> pr "%s" handle; comma := true
7672   );
7673   List.iter (
7674     fun arg ->
7675       next ();
7676       pr "%s" (name_of_argt arg)
7677   ) (snd style);
7678   (* For RBufferOut calls, add implicit &size parameter. *)
7679   if not decl then (
7680     match fst style with
7681     | RBufferOut _ ->
7682         next ();
7683         pr "&size"
7684     | _ -> ()
7685   );
7686   pr ")"
7687
7688 (* Generate the OCaml bindings interface. *)
7689 and generate_ocaml_mli () =
7690   generate_header OCamlStyle LGPLv2plus;
7691
7692   pr "\
7693 (** For API documentation you should refer to the C API
7694     in the guestfs(3) manual page.  The OCaml API uses almost
7695     exactly the same calls. *)
7696
7697 type t
7698 (** A [guestfs_h] handle. *)
7699
7700 exception Error of string
7701 (** This exception is raised when there is an error. *)
7702
7703 exception Handle_closed of string
7704 (** This exception is raised if you use a {!Guestfs.t} handle
7705     after calling {!close} on it.  The string is the name of
7706     the function. *)
7707
7708 val create : unit -> t
7709 (** Create a {!Guestfs.t} handle. *)
7710
7711 val close : t -> unit
7712 (** Close the {!Guestfs.t} handle and free up all resources used
7713     by it immediately.
7714
7715     Handles are closed by the garbage collector when they become
7716     unreferenced, but callers can call this in order to provide
7717     predictable cleanup. *)
7718
7719 ";
7720   generate_ocaml_structure_decls ();
7721
7722   (* The actions. *)
7723   List.iter (
7724     fun (name, style, _, _, _, shortdesc, _) ->
7725       generate_ocaml_prototype name style;
7726       pr "(** %s *)\n" shortdesc;
7727       pr "\n"
7728   ) all_functions_sorted
7729
7730 (* Generate the OCaml bindings implementation. *)
7731 and generate_ocaml_ml () =
7732   generate_header OCamlStyle LGPLv2plus;
7733
7734   pr "\
7735 type t
7736
7737 exception Error of string
7738 exception Handle_closed of string
7739
7740 external create : unit -> t = \"ocaml_guestfs_create\"
7741 external close : t -> unit = \"ocaml_guestfs_close\"
7742
7743 (* Give the exceptions names, so they can be raised from the C code. *)
7744 let () =
7745   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7746   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7747
7748 ";
7749
7750   generate_ocaml_structure_decls ();
7751
7752   (* The actions. *)
7753   List.iter (
7754     fun (name, style, _, _, _, shortdesc, _) ->
7755       generate_ocaml_prototype ~is_external:true name style;
7756   ) all_functions_sorted
7757
7758 (* Generate the OCaml bindings C implementation. *)
7759 and generate_ocaml_c () =
7760   generate_header CStyle LGPLv2plus;
7761
7762   pr "\
7763 #include <stdio.h>
7764 #include <stdlib.h>
7765 #include <string.h>
7766
7767 #include <caml/config.h>
7768 #include <caml/alloc.h>
7769 #include <caml/callback.h>
7770 #include <caml/fail.h>
7771 #include <caml/memory.h>
7772 #include <caml/mlvalues.h>
7773 #include <caml/signals.h>
7774
7775 #include <guestfs.h>
7776
7777 #include \"guestfs_c.h\"
7778
7779 /* Copy a hashtable of string pairs into an assoc-list.  We return
7780  * the list in reverse order, but hashtables aren't supposed to be
7781  * ordered anyway.
7782  */
7783 static CAMLprim value
7784 copy_table (char * const * argv)
7785 {
7786   CAMLparam0 ();
7787   CAMLlocal5 (rv, pairv, kv, vv, cons);
7788   int i;
7789
7790   rv = Val_int (0);
7791   for (i = 0; argv[i] != NULL; i += 2) {
7792     kv = caml_copy_string (argv[i]);
7793     vv = caml_copy_string (argv[i+1]);
7794     pairv = caml_alloc (2, 0);
7795     Store_field (pairv, 0, kv);
7796     Store_field (pairv, 1, vv);
7797     cons = caml_alloc (2, 0);
7798     Store_field (cons, 1, rv);
7799     rv = cons;
7800     Store_field (cons, 0, pairv);
7801   }
7802
7803   CAMLreturn (rv);
7804 }
7805
7806 ";
7807
7808   (* Struct copy functions. *)
7809
7810   let emit_ocaml_copy_list_function typ =
7811     pr "static CAMLprim value\n";
7812     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7813     pr "{\n";
7814     pr "  CAMLparam0 ();\n";
7815     pr "  CAMLlocal2 (rv, v);\n";
7816     pr "  unsigned int i;\n";
7817     pr "\n";
7818     pr "  if (%ss->len == 0)\n" typ;
7819     pr "    CAMLreturn (Atom (0));\n";
7820     pr "  else {\n";
7821     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7822     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7823     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7824     pr "      caml_modify (&Field (rv, i), v);\n";
7825     pr "    }\n";
7826     pr "    CAMLreturn (rv);\n";
7827     pr "  }\n";
7828     pr "}\n";
7829     pr "\n";
7830   in
7831
7832   List.iter (
7833     fun (typ, cols) ->
7834       let has_optpercent_col =
7835         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7836
7837       pr "static CAMLprim value\n";
7838       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7839       pr "{\n";
7840       pr "  CAMLparam0 ();\n";
7841       if has_optpercent_col then
7842         pr "  CAMLlocal3 (rv, v, v2);\n"
7843       else
7844         pr "  CAMLlocal2 (rv, v);\n";
7845       pr "\n";
7846       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7847       iteri (
7848         fun i col ->
7849           (match col with
7850            | name, FString ->
7851                pr "  v = caml_copy_string (%s->%s);\n" typ name
7852            | name, FBuffer ->
7853                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7854                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7855                  typ name typ name
7856            | name, FUUID ->
7857                pr "  v = caml_alloc_string (32);\n";
7858                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7859            | name, (FBytes|FInt64|FUInt64) ->
7860                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7861            | name, (FInt32|FUInt32) ->
7862                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7863            | name, FOptPercent ->
7864                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7865                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7866                pr "    v = caml_alloc (1, 0);\n";
7867                pr "    Store_field (v, 0, v2);\n";
7868                pr "  } else /* None */\n";
7869                pr "    v = Val_int (0);\n";
7870            | name, FChar ->
7871                pr "  v = Val_int (%s->%s);\n" typ name
7872           );
7873           pr "  Store_field (rv, %d, v);\n" i
7874       ) cols;
7875       pr "  CAMLreturn (rv);\n";
7876       pr "}\n";
7877       pr "\n";
7878   ) structs;
7879
7880   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7881   List.iter (
7882     function
7883     | typ, (RStructListOnly | RStructAndList) ->
7884         (* generate the function for typ *)
7885         emit_ocaml_copy_list_function typ
7886     | typ, _ -> () (* empty *)
7887   ) (rstructs_used_by all_functions);
7888
7889   (* The wrappers. *)
7890   List.iter (
7891     fun (name, style, _, _, _, _, _) ->
7892       pr "/* Automatically generated wrapper for function\n";
7893       pr " * ";
7894       generate_ocaml_prototype name style;
7895       pr " */\n";
7896       pr "\n";
7897
7898       let params =
7899         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7900
7901       let needs_extra_vs =
7902         match fst style with RConstOptString _ -> true | _ -> false in
7903
7904       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7905       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7906       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7907       pr "\n";
7908
7909       pr "CAMLprim value\n";
7910       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7911       List.iter (pr ", value %s") (List.tl params);
7912       pr ")\n";
7913       pr "{\n";
7914
7915       (match params with
7916        | [p1; p2; p3; p4; p5] ->
7917            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7918        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7919            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7920            pr "  CAMLxparam%d (%s);\n"
7921              (List.length rest) (String.concat ", " rest)
7922        | ps ->
7923            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7924       );
7925       if not needs_extra_vs then
7926         pr "  CAMLlocal1 (rv);\n"
7927       else
7928         pr "  CAMLlocal3 (rv, v, v2);\n";
7929       pr "\n";
7930
7931       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7932       pr "  if (g == NULL)\n";
7933       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7934       pr "\n";
7935
7936       List.iter (
7937         function
7938         | Pathname n
7939         | Device n | Dev_or_Path n
7940         | String n
7941         | FileIn n
7942         | FileOut n ->
7943             pr "  const char *%s = String_val (%sv);\n" n n
7944         | OptString n ->
7945             pr "  const char *%s =\n" n;
7946             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7947               n n
7948         | StringList n | DeviceList n ->
7949             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7950         | Bool n ->
7951             pr "  int %s = Bool_val (%sv);\n" n n
7952         | Int n ->
7953             pr "  int %s = Int_val (%sv);\n" n n
7954         | Int64 n ->
7955             pr "  int64_t %s = Int64_val (%sv);\n" n n
7956       ) (snd style);
7957       let error_code =
7958         match fst style with
7959         | RErr -> pr "  int r;\n"; "-1"
7960         | RInt _ -> pr "  int r;\n"; "-1"
7961         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7962         | RBool _ -> pr "  int r;\n"; "-1"
7963         | RConstString _ | RConstOptString _ ->
7964             pr "  const char *r;\n"; "NULL"
7965         | RString _ -> pr "  char *r;\n"; "NULL"
7966         | RStringList _ ->
7967             pr "  int i;\n";
7968             pr "  char **r;\n";
7969             "NULL"
7970         | RStruct (_, typ) ->
7971             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7972         | RStructList (_, typ) ->
7973             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7974         | RHashtable _ ->
7975             pr "  int i;\n";
7976             pr "  char **r;\n";
7977             "NULL"
7978         | RBufferOut _ ->
7979             pr "  char *r;\n";
7980             pr "  size_t size;\n";
7981             "NULL" in
7982       pr "\n";
7983
7984       pr "  caml_enter_blocking_section ();\n";
7985       pr "  r = guestfs_%s " name;
7986       generate_c_call_args ~handle:"g" style;
7987       pr ";\n";
7988       pr "  caml_leave_blocking_section ();\n";
7989
7990       List.iter (
7991         function
7992         | StringList n | DeviceList n ->
7993             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7994         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7995         | Bool _ | Int _ | Int64 _
7996         | FileIn _ | FileOut _ -> ()
7997       ) (snd style);
7998
7999       pr "  if (r == %s)\n" error_code;
8000       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8001       pr "\n";
8002
8003       (match fst style with
8004        | RErr -> pr "  rv = Val_unit;\n"
8005        | RInt _ -> pr "  rv = Val_int (r);\n"
8006        | RInt64 _ ->
8007            pr "  rv = caml_copy_int64 (r);\n"
8008        | RBool _ -> pr "  rv = Val_bool (r);\n"
8009        | RConstString _ ->
8010            pr "  rv = caml_copy_string (r);\n"
8011        | RConstOptString _ ->
8012            pr "  if (r) { /* Some string */\n";
8013            pr "    v = caml_alloc (1, 0);\n";
8014            pr "    v2 = caml_copy_string (r);\n";
8015            pr "    Store_field (v, 0, v2);\n";
8016            pr "  } else /* None */\n";
8017            pr "    v = Val_int (0);\n";
8018        | RString _ ->
8019            pr "  rv = caml_copy_string (r);\n";
8020            pr "  free (r);\n"
8021        | RStringList _ ->
8022            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8023            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8024            pr "  free (r);\n"
8025        | RStruct (_, typ) ->
8026            pr "  rv = copy_%s (r);\n" typ;
8027            pr "  guestfs_free_%s (r);\n" typ;
8028        | RStructList (_, typ) ->
8029            pr "  rv = copy_%s_list (r);\n" typ;
8030            pr "  guestfs_free_%s_list (r);\n" typ;
8031        | RHashtable _ ->
8032            pr "  rv = copy_table (r);\n";
8033            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8034            pr "  free (r);\n";
8035        | RBufferOut _ ->
8036            pr "  rv = caml_alloc_string (size);\n";
8037            pr "  memcpy (String_val (rv), r, size);\n";
8038       );
8039
8040       pr "  CAMLreturn (rv);\n";
8041       pr "}\n";
8042       pr "\n";
8043
8044       if List.length params > 5 then (
8045         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8046         pr "CAMLprim value ";
8047         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8048         pr "CAMLprim value\n";
8049         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8050         pr "{\n";
8051         pr "  return ocaml_guestfs_%s (argv[0]" name;
8052         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8053         pr ");\n";
8054         pr "}\n";
8055         pr "\n"
8056       )
8057   ) all_functions_sorted
8058
8059 and generate_ocaml_structure_decls () =
8060   List.iter (
8061     fun (typ, cols) ->
8062       pr "type %s = {\n" typ;
8063       List.iter (
8064         function
8065         | name, FString -> pr "  %s : string;\n" name
8066         | name, FBuffer -> pr "  %s : string;\n" name
8067         | name, FUUID -> pr "  %s : string;\n" name
8068         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8069         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8070         | name, FChar -> pr "  %s : char;\n" name
8071         | name, FOptPercent -> pr "  %s : float option;\n" name
8072       ) cols;
8073       pr "}\n";
8074       pr "\n"
8075   ) structs
8076
8077 and generate_ocaml_prototype ?(is_external = false) name style =
8078   if is_external then pr "external " else pr "val ";
8079   pr "%s : t -> " name;
8080   List.iter (
8081     function
8082     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8083     | OptString _ -> pr "string option -> "
8084     | StringList _ | DeviceList _ -> pr "string array -> "
8085     | Bool _ -> pr "bool -> "
8086     | Int _ -> pr "int -> "
8087     | Int64 _ -> pr "int64 -> "
8088   ) (snd style);
8089   (match fst style with
8090    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8091    | RInt _ -> pr "int"
8092    | RInt64 _ -> pr "int64"
8093    | RBool _ -> pr "bool"
8094    | RConstString _ -> pr "string"
8095    | RConstOptString _ -> pr "string option"
8096    | RString _ | RBufferOut _ -> pr "string"
8097    | RStringList _ -> pr "string array"
8098    | RStruct (_, typ) -> pr "%s" typ
8099    | RStructList (_, typ) -> pr "%s array" typ
8100    | RHashtable _ -> pr "(string * string) list"
8101   );
8102   if is_external then (
8103     pr " = ";
8104     if List.length (snd style) + 1 > 5 then
8105       pr "\"ocaml_guestfs_%s_byte\" " name;
8106     pr "\"ocaml_guestfs_%s\"" name
8107   );
8108   pr "\n"
8109
8110 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8111 and generate_perl_xs () =
8112   generate_header CStyle LGPLv2plus;
8113
8114   pr "\
8115 #include \"EXTERN.h\"
8116 #include \"perl.h\"
8117 #include \"XSUB.h\"
8118
8119 #include <guestfs.h>
8120
8121 #ifndef PRId64
8122 #define PRId64 \"lld\"
8123 #endif
8124
8125 static SV *
8126 my_newSVll(long long val) {
8127 #ifdef USE_64_BIT_ALL
8128   return newSViv(val);
8129 #else
8130   char buf[100];
8131   int len;
8132   len = snprintf(buf, 100, \"%%\" PRId64, val);
8133   return newSVpv(buf, len);
8134 #endif
8135 }
8136
8137 #ifndef PRIu64
8138 #define PRIu64 \"llu\"
8139 #endif
8140
8141 static SV *
8142 my_newSVull(unsigned long long val) {
8143 #ifdef USE_64_BIT_ALL
8144   return newSVuv(val);
8145 #else
8146   char buf[100];
8147   int len;
8148   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8149   return newSVpv(buf, len);
8150 #endif
8151 }
8152
8153 /* http://www.perlmonks.org/?node_id=680842 */
8154 static char **
8155 XS_unpack_charPtrPtr (SV *arg) {
8156   char **ret;
8157   AV *av;
8158   I32 i;
8159
8160   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8161     croak (\"array reference expected\");
8162
8163   av = (AV *)SvRV (arg);
8164   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8165   if (!ret)
8166     croak (\"malloc failed\");
8167
8168   for (i = 0; i <= av_len (av); i++) {
8169     SV **elem = av_fetch (av, i, 0);
8170
8171     if (!elem || !*elem)
8172       croak (\"missing element in list\");
8173
8174     ret[i] = SvPV_nolen (*elem);
8175   }
8176
8177   ret[i] = NULL;
8178
8179   return ret;
8180 }
8181
8182 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8183
8184 PROTOTYPES: ENABLE
8185
8186 guestfs_h *
8187 _create ()
8188    CODE:
8189       RETVAL = guestfs_create ();
8190       if (!RETVAL)
8191         croak (\"could not create guestfs handle\");
8192       guestfs_set_error_handler (RETVAL, NULL, NULL);
8193  OUTPUT:
8194       RETVAL
8195
8196 void
8197 DESTROY (g)
8198       guestfs_h *g;
8199  PPCODE:
8200       guestfs_close (g);
8201
8202 ";
8203
8204   List.iter (
8205     fun (name, style, _, _, _, _, _) ->
8206       (match fst style with
8207        | RErr -> pr "void\n"
8208        | RInt _ -> pr "SV *\n"
8209        | RInt64 _ -> pr "SV *\n"
8210        | RBool _ -> pr "SV *\n"
8211        | RConstString _ -> pr "SV *\n"
8212        | RConstOptString _ -> pr "SV *\n"
8213        | RString _ -> pr "SV *\n"
8214        | RBufferOut _ -> pr "SV *\n"
8215        | RStringList _
8216        | RStruct _ | RStructList _
8217        | RHashtable _ ->
8218            pr "void\n" (* all lists returned implictly on the stack *)
8219       );
8220       (* Call and arguments. *)
8221       pr "%s " name;
8222       generate_c_call_args ~handle:"g" ~decl:true style;
8223       pr "\n";
8224       pr "      guestfs_h *g;\n";
8225       iteri (
8226         fun i ->
8227           function
8228           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8229               pr "      char *%s;\n" n
8230           | OptString n ->
8231               (* http://www.perlmonks.org/?node_id=554277
8232                * Note that the implicit handle argument means we have
8233                * to add 1 to the ST(x) operator.
8234                *)
8235               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8236           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8237           | Bool n -> pr "      int %s;\n" n
8238           | Int n -> pr "      int %s;\n" n
8239           | Int64 n -> pr "      int64_t %s;\n" n
8240       ) (snd style);
8241
8242       let do_cleanups () =
8243         List.iter (
8244           function
8245           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8246           | Bool _ | Int _ | Int64 _
8247           | FileIn _ | FileOut _ -> ()
8248           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8249         ) (snd style)
8250       in
8251
8252       (* Code. *)
8253       (match fst style with
8254        | RErr ->
8255            pr "PREINIT:\n";
8256            pr "      int r;\n";
8257            pr " PPCODE:\n";
8258            pr "      r = guestfs_%s " name;
8259            generate_c_call_args ~handle:"g" style;
8260            pr ";\n";
8261            do_cleanups ();
8262            pr "      if (r == -1)\n";
8263            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8264        | RInt n
8265        | RBool n ->
8266            pr "PREINIT:\n";
8267            pr "      int %s;\n" n;
8268            pr "   CODE:\n";
8269            pr "      %s = guestfs_%s " n name;
8270            generate_c_call_args ~handle:"g" style;
8271            pr ";\n";
8272            do_cleanups ();
8273            pr "      if (%s == -1)\n" n;
8274            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8275            pr "      RETVAL = newSViv (%s);\n" n;
8276            pr " OUTPUT:\n";
8277            pr "      RETVAL\n"
8278        | RInt64 n ->
8279            pr "PREINIT:\n";
8280            pr "      int64_t %s;\n" n;
8281            pr "   CODE:\n";
8282            pr "      %s = guestfs_%s " n name;
8283            generate_c_call_args ~handle:"g" style;
8284            pr ";\n";
8285            do_cleanups ();
8286            pr "      if (%s == -1)\n" n;
8287            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8288            pr "      RETVAL = my_newSVll (%s);\n" n;
8289            pr " OUTPUT:\n";
8290            pr "      RETVAL\n"
8291        | RConstString n ->
8292            pr "PREINIT:\n";
8293            pr "      const char *%s;\n" n;
8294            pr "   CODE:\n";
8295            pr "      %s = guestfs_%s " n name;
8296            generate_c_call_args ~handle:"g" style;
8297            pr ";\n";
8298            do_cleanups ();
8299            pr "      if (%s == NULL)\n" n;
8300            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8301            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8302            pr " OUTPUT:\n";
8303            pr "      RETVAL\n"
8304        | RConstOptString n ->
8305            pr "PREINIT:\n";
8306            pr "      const char *%s;\n" n;
8307            pr "   CODE:\n";
8308            pr "      %s = guestfs_%s " n name;
8309            generate_c_call_args ~handle:"g" style;
8310            pr ";\n";
8311            do_cleanups ();
8312            pr "      if (%s == NULL)\n" n;
8313            pr "        RETVAL = &PL_sv_undef;\n";
8314            pr "      else\n";
8315            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8316            pr " OUTPUT:\n";
8317            pr "      RETVAL\n"
8318        | RString n ->
8319            pr "PREINIT:\n";
8320            pr "      char *%s;\n" n;
8321            pr "   CODE:\n";
8322            pr "      %s = guestfs_%s " n name;
8323            generate_c_call_args ~handle:"g" style;
8324            pr ";\n";
8325            do_cleanups ();
8326            pr "      if (%s == NULL)\n" n;
8327            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8328            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8329            pr "      free (%s);\n" n;
8330            pr " OUTPUT:\n";
8331            pr "      RETVAL\n"
8332        | RStringList n | RHashtable n ->
8333            pr "PREINIT:\n";
8334            pr "      char **%s;\n" n;
8335            pr "      int i, n;\n";
8336            pr " PPCODE:\n";
8337            pr "      %s = guestfs_%s " n name;
8338            generate_c_call_args ~handle:"g" style;
8339            pr ";\n";
8340            do_cleanups ();
8341            pr "      if (%s == NULL)\n" n;
8342            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8343            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8344            pr "      EXTEND (SP, n);\n";
8345            pr "      for (i = 0; i < n; ++i) {\n";
8346            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8347            pr "        free (%s[i]);\n" n;
8348            pr "      }\n";
8349            pr "      free (%s);\n" n;
8350        | RStruct (n, typ) ->
8351            let cols = cols_of_struct typ in
8352            generate_perl_struct_code typ cols name style n do_cleanups
8353        | RStructList (n, typ) ->
8354            let cols = cols_of_struct typ in
8355            generate_perl_struct_list_code typ cols name style n do_cleanups
8356        | RBufferOut n ->
8357            pr "PREINIT:\n";
8358            pr "      char *%s;\n" n;
8359            pr "      size_t size;\n";
8360            pr "   CODE:\n";
8361            pr "      %s = guestfs_%s " n name;
8362            generate_c_call_args ~handle:"g" style;
8363            pr ";\n";
8364            do_cleanups ();
8365            pr "      if (%s == NULL)\n" n;
8366            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8367            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8368            pr "      free (%s);\n" n;
8369            pr " OUTPUT:\n";
8370            pr "      RETVAL\n"
8371       );
8372
8373       pr "\n"
8374   ) all_functions
8375
8376 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8377   pr "PREINIT:\n";
8378   pr "      struct guestfs_%s_list *%s;\n" typ n;
8379   pr "      int i;\n";
8380   pr "      HV *hv;\n";
8381   pr " PPCODE:\n";
8382   pr "      %s = guestfs_%s " n name;
8383   generate_c_call_args ~handle:"g" style;
8384   pr ";\n";
8385   do_cleanups ();
8386   pr "      if (%s == NULL)\n" n;
8387   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8388   pr "      EXTEND (SP, %s->len);\n" n;
8389   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8390   pr "        hv = newHV ();\n";
8391   List.iter (
8392     function
8393     | name, FString ->
8394         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8395           name (String.length name) n name
8396     | name, FUUID ->
8397         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8398           name (String.length name) n name
8399     | name, FBuffer ->
8400         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8401           name (String.length name) n name n name
8402     | name, (FBytes|FUInt64) ->
8403         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8404           name (String.length name) n name
8405     | name, FInt64 ->
8406         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8407           name (String.length name) n name
8408     | name, (FInt32|FUInt32) ->
8409         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8410           name (String.length name) n name
8411     | name, FChar ->
8412         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8413           name (String.length name) n name
8414     | name, FOptPercent ->
8415         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8416           name (String.length name) n name
8417   ) cols;
8418   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8419   pr "      }\n";
8420   pr "      guestfs_free_%s_list (%s);\n" typ n
8421
8422 and generate_perl_struct_code typ cols name style n do_cleanups =
8423   pr "PREINIT:\n";
8424   pr "      struct guestfs_%s *%s;\n" typ n;
8425   pr " PPCODE:\n";
8426   pr "      %s = guestfs_%s " n name;
8427   generate_c_call_args ~handle:"g" style;
8428   pr ";\n";
8429   do_cleanups ();
8430   pr "      if (%s == NULL)\n" n;
8431   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8432   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8433   List.iter (
8434     fun ((name, _) as col) ->
8435       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8436
8437       match col with
8438       | name, FString ->
8439           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8440             n name
8441       | name, FBuffer ->
8442           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8443             n name n name
8444       | name, FUUID ->
8445           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8446             n name
8447       | name, (FBytes|FUInt64) ->
8448           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8449             n name
8450       | name, FInt64 ->
8451           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8452             n name
8453       | name, (FInt32|FUInt32) ->
8454           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8455             n name
8456       | name, FChar ->
8457           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8458             n name
8459       | name, FOptPercent ->
8460           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8461             n name
8462   ) cols;
8463   pr "      free (%s);\n" n
8464
8465 (* Generate Sys/Guestfs.pm. *)
8466 and generate_perl_pm () =
8467   generate_header HashStyle LGPLv2plus;
8468
8469   pr "\
8470 =pod
8471
8472 =head1 NAME
8473
8474 Sys::Guestfs - Perl bindings for libguestfs
8475
8476 =head1 SYNOPSIS
8477
8478  use Sys::Guestfs;
8479
8480  my $h = Sys::Guestfs->new ();
8481  $h->add_drive ('guest.img');
8482  $h->launch ();
8483  $h->mount ('/dev/sda1', '/');
8484  $h->touch ('/hello');
8485  $h->sync ();
8486
8487 =head1 DESCRIPTION
8488
8489 The C<Sys::Guestfs> module provides a Perl XS binding to the
8490 libguestfs API for examining and modifying virtual machine
8491 disk images.
8492
8493 Amongst the things this is good for: making batch configuration
8494 changes to guests, getting disk used/free statistics (see also:
8495 virt-df), migrating between virtualization systems (see also:
8496 virt-p2v), performing partial backups, performing partial guest
8497 clones, cloning guests and changing registry/UUID/hostname info, and
8498 much else besides.
8499
8500 Libguestfs uses Linux kernel and qemu code, and can access any type of
8501 guest filesystem that Linux and qemu can, including but not limited
8502 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8503 schemes, qcow, qcow2, vmdk.
8504
8505 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8506 LVs, what filesystem is in each LV, etc.).  It can also run commands
8507 in the context of the guest.  Also you can access filesystems over
8508 FUSE.
8509
8510 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8511 functions for using libguestfs from Perl, including integration
8512 with libvirt.
8513
8514 =head1 ERRORS
8515
8516 All errors turn into calls to C<croak> (see L<Carp(3)>).
8517
8518 =head1 METHODS
8519
8520 =over 4
8521
8522 =cut
8523
8524 package Sys::Guestfs;
8525
8526 use strict;
8527 use warnings;
8528
8529 require XSLoader;
8530 XSLoader::load ('Sys::Guestfs');
8531
8532 =item $h = Sys::Guestfs->new ();
8533
8534 Create a new guestfs handle.
8535
8536 =cut
8537
8538 sub new {
8539   my $proto = shift;
8540   my $class = ref ($proto) || $proto;
8541
8542   my $self = Sys::Guestfs::_create ();
8543   bless $self, $class;
8544   return $self;
8545 }
8546
8547 ";
8548
8549   (* Actions.  We only need to print documentation for these as
8550    * they are pulled in from the XS code automatically.
8551    *)
8552   List.iter (
8553     fun (name, style, _, flags, _, _, longdesc) ->
8554       if not (List.mem NotInDocs flags) then (
8555         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8556         pr "=item ";
8557         generate_perl_prototype name style;
8558         pr "\n\n";
8559         pr "%s\n\n" longdesc;
8560         if List.mem ProtocolLimitWarning flags then
8561           pr "%s\n\n" protocol_limit_warning;
8562         if List.mem DangerWillRobinson flags then
8563           pr "%s\n\n" danger_will_robinson;
8564         match deprecation_notice flags with
8565         | None -> ()
8566         | Some txt -> pr "%s\n\n" txt
8567       )
8568   ) all_functions_sorted;
8569
8570   (* End of file. *)
8571   pr "\
8572 =cut
8573
8574 1;
8575
8576 =back
8577
8578 =head1 COPYRIGHT
8579
8580 Copyright (C) %s Red Hat Inc.
8581
8582 =head1 LICENSE
8583
8584 Please see the file COPYING.LIB for the full license.
8585
8586 =head1 SEE ALSO
8587
8588 L<guestfs(3)>,
8589 L<guestfish(1)>,
8590 L<http://libguestfs.org>,
8591 L<Sys::Guestfs::Lib(3)>.
8592
8593 =cut
8594 " copyright_years
8595
8596 and generate_perl_prototype name style =
8597   (match fst style with
8598    | RErr -> ()
8599    | RBool n
8600    | RInt n
8601    | RInt64 n
8602    | RConstString n
8603    | RConstOptString n
8604    | RString n
8605    | RBufferOut n -> pr "$%s = " n
8606    | RStruct (n,_)
8607    | RHashtable n -> pr "%%%s = " n
8608    | RStringList n
8609    | RStructList (n,_) -> pr "@%s = " n
8610   );
8611   pr "$h->%s (" name;
8612   let comma = ref false in
8613   List.iter (
8614     fun arg ->
8615       if !comma then pr ", ";
8616       comma := true;
8617       match arg with
8618       | Pathname n | Device n | Dev_or_Path n | String n
8619       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8620           pr "$%s" n
8621       | StringList n | DeviceList n ->
8622           pr "\\@%s" n
8623   ) (snd style);
8624   pr ");"
8625
8626 (* Generate Python C module. *)
8627 and generate_python_c () =
8628   generate_header CStyle LGPLv2plus;
8629
8630   pr "\
8631 #include <Python.h>
8632
8633 #include <stdio.h>
8634 #include <stdlib.h>
8635 #include <assert.h>
8636
8637 #include \"guestfs.h\"
8638
8639 typedef struct {
8640   PyObject_HEAD
8641   guestfs_h *g;
8642 } Pyguestfs_Object;
8643
8644 static guestfs_h *
8645 get_handle (PyObject *obj)
8646 {
8647   assert (obj);
8648   assert (obj != Py_None);
8649   return ((Pyguestfs_Object *) obj)->g;
8650 }
8651
8652 static PyObject *
8653 put_handle (guestfs_h *g)
8654 {
8655   assert (g);
8656   return
8657     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8658 }
8659
8660 /* This list should be freed (but not the strings) after use. */
8661 static char **
8662 get_string_list (PyObject *obj)
8663 {
8664   int i, len;
8665   char **r;
8666
8667   assert (obj);
8668
8669   if (!PyList_Check (obj)) {
8670     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8671     return NULL;
8672   }
8673
8674   len = PyList_Size (obj);
8675   r = malloc (sizeof (char *) * (len+1));
8676   if (r == NULL) {
8677     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8678     return NULL;
8679   }
8680
8681   for (i = 0; i < len; ++i)
8682     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8683   r[len] = NULL;
8684
8685   return r;
8686 }
8687
8688 static PyObject *
8689 put_string_list (char * const * const argv)
8690 {
8691   PyObject *list;
8692   int argc, i;
8693
8694   for (argc = 0; argv[argc] != NULL; ++argc)
8695     ;
8696
8697   list = PyList_New (argc);
8698   for (i = 0; i < argc; ++i)
8699     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8700
8701   return list;
8702 }
8703
8704 static PyObject *
8705 put_table (char * const * const argv)
8706 {
8707   PyObject *list, *item;
8708   int argc, i;
8709
8710   for (argc = 0; argv[argc] != NULL; ++argc)
8711     ;
8712
8713   list = PyList_New (argc >> 1);
8714   for (i = 0; i < argc; i += 2) {
8715     item = PyTuple_New (2);
8716     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8717     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8718     PyList_SetItem (list, i >> 1, item);
8719   }
8720
8721   return list;
8722 }
8723
8724 static void
8725 free_strings (char **argv)
8726 {
8727   int argc;
8728
8729   for (argc = 0; argv[argc] != NULL; ++argc)
8730     free (argv[argc]);
8731   free (argv);
8732 }
8733
8734 static PyObject *
8735 py_guestfs_create (PyObject *self, PyObject *args)
8736 {
8737   guestfs_h *g;
8738
8739   g = guestfs_create ();
8740   if (g == NULL) {
8741     PyErr_SetString (PyExc_RuntimeError,
8742                      \"guestfs.create: failed to allocate handle\");
8743     return NULL;
8744   }
8745   guestfs_set_error_handler (g, NULL, NULL);
8746   return put_handle (g);
8747 }
8748
8749 static PyObject *
8750 py_guestfs_close (PyObject *self, PyObject *args)
8751 {
8752   PyObject *py_g;
8753   guestfs_h *g;
8754
8755   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8756     return NULL;
8757   g = get_handle (py_g);
8758
8759   guestfs_close (g);
8760
8761   Py_INCREF (Py_None);
8762   return Py_None;
8763 }
8764
8765 ";
8766
8767   let emit_put_list_function typ =
8768     pr "static PyObject *\n";
8769     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8770     pr "{\n";
8771     pr "  PyObject *list;\n";
8772     pr "  int i;\n";
8773     pr "\n";
8774     pr "  list = PyList_New (%ss->len);\n" typ;
8775     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8776     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8777     pr "  return list;\n";
8778     pr "};\n";
8779     pr "\n"
8780   in
8781
8782   (* Structures, turned into Python dictionaries. *)
8783   List.iter (
8784     fun (typ, cols) ->
8785       pr "static PyObject *\n";
8786       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8787       pr "{\n";
8788       pr "  PyObject *dict;\n";
8789       pr "\n";
8790       pr "  dict = PyDict_New ();\n";
8791       List.iter (
8792         function
8793         | name, FString ->
8794             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8795             pr "                        PyString_FromString (%s->%s));\n"
8796               typ name
8797         | name, FBuffer ->
8798             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8799             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8800               typ name typ name
8801         | name, FUUID ->
8802             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8803             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8804               typ name
8805         | name, (FBytes|FUInt64) ->
8806             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8807             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8808               typ name
8809         | name, FInt64 ->
8810             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8811             pr "                        PyLong_FromLongLong (%s->%s));\n"
8812               typ name
8813         | name, FUInt32 ->
8814             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8815             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8816               typ name
8817         | name, FInt32 ->
8818             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8819             pr "                        PyLong_FromLong (%s->%s));\n"
8820               typ name
8821         | name, FOptPercent ->
8822             pr "  if (%s->%s >= 0)\n" typ name;
8823             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8824             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8825               typ name;
8826             pr "  else {\n";
8827             pr "    Py_INCREF (Py_None);\n";
8828             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8829             pr "  }\n"
8830         | name, FChar ->
8831             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8832             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8833       ) cols;
8834       pr "  return dict;\n";
8835       pr "};\n";
8836       pr "\n";
8837
8838   ) structs;
8839
8840   (* Emit a put_TYPE_list function definition only if that function is used. *)
8841   List.iter (
8842     function
8843     | typ, (RStructListOnly | RStructAndList) ->
8844         (* generate the function for typ *)
8845         emit_put_list_function typ
8846     | typ, _ -> () (* empty *)
8847   ) (rstructs_used_by all_functions);
8848
8849   (* Python wrapper functions. *)
8850   List.iter (
8851     fun (name, style, _, _, _, _, _) ->
8852       pr "static PyObject *\n";
8853       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8854       pr "{\n";
8855
8856       pr "  PyObject *py_g;\n";
8857       pr "  guestfs_h *g;\n";
8858       pr "  PyObject *py_r;\n";
8859
8860       let error_code =
8861         match fst style with
8862         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8863         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8864         | RConstString _ | RConstOptString _ ->
8865             pr "  const char *r;\n"; "NULL"
8866         | RString _ -> pr "  char *r;\n"; "NULL"
8867         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8868         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8869         | RStructList (_, typ) ->
8870             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8871         | RBufferOut _ ->
8872             pr "  char *r;\n";
8873             pr "  size_t size;\n";
8874             "NULL" in
8875
8876       List.iter (
8877         function
8878         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8879             pr "  const char *%s;\n" n
8880         | OptString n -> pr "  const char *%s;\n" n
8881         | StringList n | DeviceList n ->
8882             pr "  PyObject *py_%s;\n" n;
8883             pr "  char **%s;\n" n
8884         | Bool n -> pr "  int %s;\n" n
8885         | Int n -> pr "  int %s;\n" n
8886         | Int64 n -> pr "  long long %s;\n" n
8887       ) (snd style);
8888
8889       pr "\n";
8890
8891       (* Convert the parameters. *)
8892       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8893       List.iter (
8894         function
8895         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8896         | OptString _ -> pr "z"
8897         | StringList _ | DeviceList _ -> pr "O"
8898         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8899         | Int _ -> pr "i"
8900         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8901                              * emulate C's int/long/long long in Python?
8902                              *)
8903       ) (snd style);
8904       pr ":guestfs_%s\",\n" name;
8905       pr "                         &py_g";
8906       List.iter (
8907         function
8908         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8909         | OptString n -> pr ", &%s" n
8910         | StringList n | DeviceList n -> pr ", &py_%s" n
8911         | Bool n -> pr ", &%s" n
8912         | Int n -> pr ", &%s" n
8913         | Int64 n -> pr ", &%s" n
8914       ) (snd style);
8915
8916       pr "))\n";
8917       pr "    return NULL;\n";
8918
8919       pr "  g = get_handle (py_g);\n";
8920       List.iter (
8921         function
8922         | Pathname _ | Device _ | Dev_or_Path _ | String _
8923         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8924         | StringList n | DeviceList n ->
8925             pr "  %s = get_string_list (py_%s);\n" n n;
8926             pr "  if (!%s) return NULL;\n" n
8927       ) (snd style);
8928
8929       pr "\n";
8930
8931       pr "  r = guestfs_%s " name;
8932       generate_c_call_args ~handle:"g" style;
8933       pr ";\n";
8934
8935       List.iter (
8936         function
8937         | Pathname _ | Device _ | Dev_or_Path _ | String _
8938         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8939         | StringList n | DeviceList n ->
8940             pr "  free (%s);\n" n
8941       ) (snd style);
8942
8943       pr "  if (r == %s) {\n" error_code;
8944       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8945       pr "    return NULL;\n";
8946       pr "  }\n";
8947       pr "\n";
8948
8949       (match fst style with
8950        | RErr ->
8951            pr "  Py_INCREF (Py_None);\n";
8952            pr "  py_r = Py_None;\n"
8953        | RInt _
8954        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8955        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8956        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8957        | RConstOptString _ ->
8958            pr "  if (r)\n";
8959            pr "    py_r = PyString_FromString (r);\n";
8960            pr "  else {\n";
8961            pr "    Py_INCREF (Py_None);\n";
8962            pr "    py_r = Py_None;\n";
8963            pr "  }\n"
8964        | RString _ ->
8965            pr "  py_r = PyString_FromString (r);\n";
8966            pr "  free (r);\n"
8967        | RStringList _ ->
8968            pr "  py_r = put_string_list (r);\n";
8969            pr "  free_strings (r);\n"
8970        | RStruct (_, typ) ->
8971            pr "  py_r = put_%s (r);\n" typ;
8972            pr "  guestfs_free_%s (r);\n" typ
8973        | RStructList (_, typ) ->
8974            pr "  py_r = put_%s_list (r);\n" typ;
8975            pr "  guestfs_free_%s_list (r);\n" typ
8976        | RHashtable n ->
8977            pr "  py_r = put_table (r);\n";
8978            pr "  free_strings (r);\n"
8979        | RBufferOut _ ->
8980            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8981            pr "  free (r);\n"
8982       );
8983
8984       pr "  return py_r;\n";
8985       pr "}\n";
8986       pr "\n"
8987   ) all_functions;
8988
8989   (* Table of functions. *)
8990   pr "static PyMethodDef methods[] = {\n";
8991   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8992   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8993   List.iter (
8994     fun (name, _, _, _, _, _, _) ->
8995       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8996         name name
8997   ) all_functions;
8998   pr "  { NULL, NULL, 0, NULL }\n";
8999   pr "};\n";
9000   pr "\n";
9001
9002   (* Init function. *)
9003   pr "\
9004 void
9005 initlibguestfsmod (void)
9006 {
9007   static int initialized = 0;
9008
9009   if (initialized) return;
9010   Py_InitModule ((char *) \"libguestfsmod\", methods);
9011   initialized = 1;
9012 }
9013 "
9014
9015 (* Generate Python module. *)
9016 and generate_python_py () =
9017   generate_header HashStyle LGPLv2plus;
9018
9019   pr "\
9020 u\"\"\"Python bindings for libguestfs
9021
9022 import guestfs
9023 g = guestfs.GuestFS ()
9024 g.add_drive (\"guest.img\")
9025 g.launch ()
9026 parts = g.list_partitions ()
9027
9028 The guestfs module provides a Python binding to the libguestfs API
9029 for examining and modifying virtual machine disk images.
9030
9031 Amongst the things this is good for: making batch configuration
9032 changes to guests, getting disk used/free statistics (see also:
9033 virt-df), migrating between virtualization systems (see also:
9034 virt-p2v), performing partial backups, performing partial guest
9035 clones, cloning guests and changing registry/UUID/hostname info, and
9036 much else besides.
9037
9038 Libguestfs uses Linux kernel and qemu code, and can access any type of
9039 guest filesystem that Linux and qemu can, including but not limited
9040 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9041 schemes, qcow, qcow2, vmdk.
9042
9043 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9044 LVs, what filesystem is in each LV, etc.).  It can also run commands
9045 in the context of the guest.  Also you can access filesystems over
9046 FUSE.
9047
9048 Errors which happen while using the API are turned into Python
9049 RuntimeError exceptions.
9050
9051 To create a guestfs handle you usually have to perform the following
9052 sequence of calls:
9053
9054 # Create the handle, call add_drive at least once, and possibly
9055 # several times if the guest has multiple block devices:
9056 g = guestfs.GuestFS ()
9057 g.add_drive (\"guest.img\")
9058
9059 # Launch the qemu subprocess and wait for it to become ready:
9060 g.launch ()
9061
9062 # Now you can issue commands, for example:
9063 logvols = g.lvs ()
9064
9065 \"\"\"
9066
9067 import libguestfsmod
9068
9069 class GuestFS:
9070     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9071
9072     def __init__ (self):
9073         \"\"\"Create a new libguestfs handle.\"\"\"
9074         self._o = libguestfsmod.create ()
9075
9076     def __del__ (self):
9077         libguestfsmod.close (self._o)
9078
9079 ";
9080
9081   List.iter (
9082     fun (name, style, _, flags, _, _, longdesc) ->
9083       pr "    def %s " name;
9084       generate_py_call_args ~handle:"self" (snd style);
9085       pr ":\n";
9086
9087       if not (List.mem NotInDocs flags) then (
9088         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9089         let doc =
9090           match fst style with
9091           | RErr | RInt _ | RInt64 _ | RBool _
9092           | RConstOptString _ | RConstString _
9093           | RString _ | RBufferOut _ -> doc
9094           | RStringList _ ->
9095               doc ^ "\n\nThis function returns a list of strings."
9096           | RStruct (_, typ) ->
9097               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9098           | RStructList (_, typ) ->
9099               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9100           | RHashtable _ ->
9101               doc ^ "\n\nThis function returns a dictionary." in
9102         let doc =
9103           if List.mem ProtocolLimitWarning flags then
9104             doc ^ "\n\n" ^ protocol_limit_warning
9105           else doc in
9106         let doc =
9107           if List.mem DangerWillRobinson flags then
9108             doc ^ "\n\n" ^ danger_will_robinson
9109           else doc in
9110         let doc =
9111           match deprecation_notice flags with
9112           | None -> doc
9113           | Some txt -> doc ^ "\n\n" ^ txt in
9114         let doc = pod2text ~width:60 name doc in
9115         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9116         let doc = String.concat "\n        " doc in
9117         pr "        u\"\"\"%s\"\"\"\n" doc;
9118       );
9119       pr "        return libguestfsmod.%s " name;
9120       generate_py_call_args ~handle:"self._o" (snd style);
9121       pr "\n";
9122       pr "\n";
9123   ) all_functions
9124
9125 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9126 and generate_py_call_args ~handle args =
9127   pr "(%s" handle;
9128   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9129   pr ")"
9130
9131 (* Useful if you need the longdesc POD text as plain text.  Returns a
9132  * list of lines.
9133  *
9134  * Because this is very slow (the slowest part of autogeneration),
9135  * we memoize the results.
9136  *)
9137 and pod2text ~width name longdesc =
9138   let key = width, name, longdesc in
9139   try Hashtbl.find pod2text_memo key
9140   with Not_found ->
9141     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9142     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9143     close_out chan;
9144     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9145     let chan = open_process_in cmd in
9146     let lines = ref [] in
9147     let rec loop i =
9148       let line = input_line chan in
9149       if i = 1 then             (* discard the first line of output *)
9150         loop (i+1)
9151       else (
9152         let line = triml line in
9153         lines := line :: !lines;
9154         loop (i+1)
9155       ) in
9156     let lines = try loop 1 with End_of_file -> List.rev !lines in
9157     unlink filename;
9158     (match close_process_in chan with
9159      | WEXITED 0 -> ()
9160      | WEXITED i ->
9161          failwithf "pod2text: process exited with non-zero status (%d)" i
9162      | WSIGNALED i | WSTOPPED i ->
9163          failwithf "pod2text: process signalled or stopped by signal %d" i
9164     );
9165     Hashtbl.add pod2text_memo key lines;
9166     pod2text_memo_updated ();
9167     lines
9168
9169 (* Generate ruby bindings. *)
9170 and generate_ruby_c () =
9171   generate_header CStyle LGPLv2plus;
9172
9173   pr "\
9174 #include <stdio.h>
9175 #include <stdlib.h>
9176
9177 #include <ruby.h>
9178
9179 #include \"guestfs.h\"
9180
9181 #include \"extconf.h\"
9182
9183 /* For Ruby < 1.9 */
9184 #ifndef RARRAY_LEN
9185 #define RARRAY_LEN(r) (RARRAY((r))->len)
9186 #endif
9187
9188 static VALUE m_guestfs;                 /* guestfs module */
9189 static VALUE c_guestfs;                 /* guestfs_h handle */
9190 static VALUE e_Error;                   /* used for all errors */
9191
9192 static void ruby_guestfs_free (void *p)
9193 {
9194   if (!p) return;
9195   guestfs_close ((guestfs_h *) p);
9196 }
9197
9198 static VALUE ruby_guestfs_create (VALUE m)
9199 {
9200   guestfs_h *g;
9201
9202   g = guestfs_create ();
9203   if (!g)
9204     rb_raise (e_Error, \"failed to create guestfs handle\");
9205
9206   /* Don't print error messages to stderr by default. */
9207   guestfs_set_error_handler (g, NULL, NULL);
9208
9209   /* Wrap it, and make sure the close function is called when the
9210    * handle goes away.
9211    */
9212   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9213 }
9214
9215 static VALUE ruby_guestfs_close (VALUE gv)
9216 {
9217   guestfs_h *g;
9218   Data_Get_Struct (gv, guestfs_h, g);
9219
9220   ruby_guestfs_free (g);
9221   DATA_PTR (gv) = NULL;
9222
9223   return Qnil;
9224 }
9225
9226 ";
9227
9228   List.iter (
9229     fun (name, style, _, _, _, _, _) ->
9230       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9231       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9232       pr ")\n";
9233       pr "{\n";
9234       pr "  guestfs_h *g;\n";
9235       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9236       pr "  if (!g)\n";
9237       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9238         name;
9239       pr "\n";
9240
9241       List.iter (
9242         function
9243         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9244             pr "  Check_Type (%sv, T_STRING);\n" n;
9245             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9246             pr "  if (!%s)\n" n;
9247             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9248             pr "              \"%s\", \"%s\");\n" n name
9249         | OptString n ->
9250             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9251         | StringList n | DeviceList n ->
9252             pr "  char **%s;\n" n;
9253             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9254             pr "  {\n";
9255             pr "    int i, len;\n";
9256             pr "    len = RARRAY_LEN (%sv);\n" n;
9257             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9258               n;
9259             pr "    for (i = 0; i < len; ++i) {\n";
9260             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9261             pr "      %s[i] = StringValueCStr (v);\n" n;
9262             pr "    }\n";
9263             pr "    %s[len] = NULL;\n" n;
9264             pr "  }\n";
9265         | Bool n ->
9266             pr "  int %s = RTEST (%sv);\n" n n
9267         | Int n ->
9268             pr "  int %s = NUM2INT (%sv);\n" n n
9269         | Int64 n ->
9270             pr "  long long %s = NUM2LL (%sv);\n" n n
9271       ) (snd style);
9272       pr "\n";
9273
9274       let error_code =
9275         match fst style with
9276         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9277         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9278         | RConstString _ | RConstOptString _ ->
9279             pr "  const char *r;\n"; "NULL"
9280         | RString _ -> pr "  char *r;\n"; "NULL"
9281         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9282         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9283         | RStructList (_, typ) ->
9284             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9285         | RBufferOut _ ->
9286             pr "  char *r;\n";
9287             pr "  size_t size;\n";
9288             "NULL" in
9289       pr "\n";
9290
9291       pr "  r = guestfs_%s " name;
9292       generate_c_call_args ~handle:"g" style;
9293       pr ";\n";
9294
9295       List.iter (
9296         function
9297         | Pathname _ | Device _ | Dev_or_Path _ | String _
9298         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9299         | StringList n | DeviceList n ->
9300             pr "  free (%s);\n" n
9301       ) (snd style);
9302
9303       pr "  if (r == %s)\n" error_code;
9304       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9305       pr "\n";
9306
9307       (match fst style with
9308        | RErr ->
9309            pr "  return Qnil;\n"
9310        | RInt _ | RBool _ ->
9311            pr "  return INT2NUM (r);\n"
9312        | RInt64 _ ->
9313            pr "  return ULL2NUM (r);\n"
9314        | RConstString _ ->
9315            pr "  return rb_str_new2 (r);\n";
9316        | RConstOptString _ ->
9317            pr "  if (r)\n";
9318            pr "    return rb_str_new2 (r);\n";
9319            pr "  else\n";
9320            pr "    return Qnil;\n";
9321        | RString _ ->
9322            pr "  VALUE rv = rb_str_new2 (r);\n";
9323            pr "  free (r);\n";
9324            pr "  return rv;\n";
9325        | RStringList _ ->
9326            pr "  int i, len = 0;\n";
9327            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9328            pr "  VALUE rv = rb_ary_new2 (len);\n";
9329            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9330            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9331            pr "    free (r[i]);\n";
9332            pr "  }\n";
9333            pr "  free (r);\n";
9334            pr "  return rv;\n"
9335        | RStruct (_, typ) ->
9336            let cols = cols_of_struct typ in
9337            generate_ruby_struct_code typ cols
9338        | RStructList (_, typ) ->
9339            let cols = cols_of_struct typ in
9340            generate_ruby_struct_list_code typ cols
9341        | RHashtable _ ->
9342            pr "  VALUE rv = rb_hash_new ();\n";
9343            pr "  int i;\n";
9344            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9345            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9346            pr "    free (r[i]);\n";
9347            pr "    free (r[i+1]);\n";
9348            pr "  }\n";
9349            pr "  free (r);\n";
9350            pr "  return rv;\n"
9351        | RBufferOut _ ->
9352            pr "  VALUE rv = rb_str_new (r, size);\n";
9353            pr "  free (r);\n";
9354            pr "  return rv;\n";
9355       );
9356
9357       pr "}\n";
9358       pr "\n"
9359   ) all_functions;
9360
9361   pr "\
9362 /* Initialize the module. */
9363 void Init__guestfs ()
9364 {
9365   m_guestfs = rb_define_module (\"Guestfs\");
9366   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9367   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9368
9369   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9370   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9371
9372 ";
9373   (* Define the rest of the methods. *)
9374   List.iter (
9375     fun (name, style, _, _, _, _, _) ->
9376       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9377       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9378   ) all_functions;
9379
9380   pr "}\n"
9381
9382 (* Ruby code to return a struct. *)
9383 and generate_ruby_struct_code typ cols =
9384   pr "  VALUE rv = rb_hash_new ();\n";
9385   List.iter (
9386     function
9387     | name, FString ->
9388         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9389     | name, FBuffer ->
9390         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9391     | name, FUUID ->
9392         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9393     | name, (FBytes|FUInt64) ->
9394         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9395     | name, FInt64 ->
9396         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9397     | name, FUInt32 ->
9398         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9399     | name, FInt32 ->
9400         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9401     | name, FOptPercent ->
9402         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9403     | name, FChar -> (* XXX wrong? *)
9404         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9405   ) cols;
9406   pr "  guestfs_free_%s (r);\n" typ;
9407   pr "  return rv;\n"
9408
9409 (* Ruby code to return a struct list. *)
9410 and generate_ruby_struct_list_code typ cols =
9411   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9412   pr "  int i;\n";
9413   pr "  for (i = 0; i < r->len; ++i) {\n";
9414   pr "    VALUE hv = rb_hash_new ();\n";
9415   List.iter (
9416     function
9417     | name, FString ->
9418         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9419     | name, FBuffer ->
9420         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
9421     | name, FUUID ->
9422         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9423     | name, (FBytes|FUInt64) ->
9424         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9425     | name, FInt64 ->
9426         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9427     | name, FUInt32 ->
9428         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9429     | name, FInt32 ->
9430         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9431     | name, FOptPercent ->
9432         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9433     | name, FChar -> (* XXX wrong? *)
9434         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9435   ) cols;
9436   pr "    rb_ary_push (rv, hv);\n";
9437   pr "  }\n";
9438   pr "  guestfs_free_%s_list (r);\n" typ;
9439   pr "  return rv;\n"
9440
9441 (* Generate Java bindings GuestFS.java file. *)
9442 and generate_java_java () =
9443   generate_header CStyle LGPLv2plus;
9444
9445   pr "\
9446 package com.redhat.et.libguestfs;
9447
9448 import java.util.HashMap;
9449 import com.redhat.et.libguestfs.LibGuestFSException;
9450 import com.redhat.et.libguestfs.PV;
9451 import com.redhat.et.libguestfs.VG;
9452 import com.redhat.et.libguestfs.LV;
9453 import com.redhat.et.libguestfs.Stat;
9454 import com.redhat.et.libguestfs.StatVFS;
9455 import com.redhat.et.libguestfs.IntBool;
9456 import com.redhat.et.libguestfs.Dirent;
9457
9458 /**
9459  * The GuestFS object is a libguestfs handle.
9460  *
9461  * @author rjones
9462  */
9463 public class GuestFS {
9464   // Load the native code.
9465   static {
9466     System.loadLibrary (\"guestfs_jni\");
9467   }
9468
9469   /**
9470    * The native guestfs_h pointer.
9471    */
9472   long g;
9473
9474   /**
9475    * Create a libguestfs handle.
9476    *
9477    * @throws LibGuestFSException
9478    */
9479   public GuestFS () throws LibGuestFSException
9480   {
9481     g = _create ();
9482   }
9483   private native long _create () throws LibGuestFSException;
9484
9485   /**
9486    * Close a libguestfs handle.
9487    *
9488    * You can also leave handles to be collected by the garbage
9489    * collector, but this method ensures that the resources used
9490    * by the handle are freed up immediately.  If you call any
9491    * other methods after closing the handle, you will get an
9492    * exception.
9493    *
9494    * @throws LibGuestFSException
9495    */
9496   public void close () throws LibGuestFSException
9497   {
9498     if (g != 0)
9499       _close (g);
9500     g = 0;
9501   }
9502   private native void _close (long g) throws LibGuestFSException;
9503
9504   public void finalize () throws LibGuestFSException
9505   {
9506     close ();
9507   }
9508
9509 ";
9510
9511   List.iter (
9512     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9513       if not (List.mem NotInDocs flags); then (
9514         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9515         let doc =
9516           if List.mem ProtocolLimitWarning flags then
9517             doc ^ "\n\n" ^ protocol_limit_warning
9518           else doc in
9519         let doc =
9520           if List.mem DangerWillRobinson flags then
9521             doc ^ "\n\n" ^ danger_will_robinson
9522           else doc in
9523         let doc =
9524           match deprecation_notice flags with
9525           | None -> doc
9526           | Some txt -> doc ^ "\n\n" ^ txt in
9527         let doc = pod2text ~width:60 name doc in
9528         let doc = List.map (            (* RHBZ#501883 *)
9529           function
9530           | "" -> "<p>"
9531           | nonempty -> nonempty
9532         ) doc in
9533         let doc = String.concat "\n   * " doc in
9534
9535         pr "  /**\n";
9536         pr "   * %s\n" shortdesc;
9537         pr "   * <p>\n";
9538         pr "   * %s\n" doc;
9539         pr "   * @throws LibGuestFSException\n";
9540         pr "   */\n";
9541         pr "  ";
9542       );
9543       generate_java_prototype ~public:true ~semicolon:false name style;
9544       pr "\n";
9545       pr "  {\n";
9546       pr "    if (g == 0)\n";
9547       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9548         name;
9549       pr "    ";
9550       if fst style <> RErr then pr "return ";
9551       pr "_%s " name;
9552       generate_java_call_args ~handle:"g" (snd style);
9553       pr ";\n";
9554       pr "  }\n";
9555       pr "  ";
9556       generate_java_prototype ~privat:true ~native:true name style;
9557       pr "\n";
9558       pr "\n";
9559   ) all_functions;
9560
9561   pr "}\n"
9562
9563 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9564 and generate_java_call_args ~handle args =
9565   pr "(%s" handle;
9566   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9567   pr ")"
9568
9569 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9570     ?(semicolon=true) name style =
9571   if privat then pr "private ";
9572   if public then pr "public ";
9573   if native then pr "native ";
9574
9575   (* return type *)
9576   (match fst style with
9577    | RErr -> pr "void ";
9578    | RInt _ -> pr "int ";
9579    | RInt64 _ -> pr "long ";
9580    | RBool _ -> pr "boolean ";
9581    | RConstString _ | RConstOptString _ | RString _
9582    | RBufferOut _ -> pr "String ";
9583    | RStringList _ -> pr "String[] ";
9584    | RStruct (_, typ) ->
9585        let name = java_name_of_struct typ in
9586        pr "%s " name;
9587    | RStructList (_, typ) ->
9588        let name = java_name_of_struct typ in
9589        pr "%s[] " name;
9590    | RHashtable _ -> pr "HashMap<String,String> ";
9591   );
9592
9593   if native then pr "_%s " name else pr "%s " name;
9594   pr "(";
9595   let needs_comma = ref false in
9596   if native then (
9597     pr "long g";
9598     needs_comma := true
9599   );
9600
9601   (* args *)
9602   List.iter (
9603     fun arg ->
9604       if !needs_comma then pr ", ";
9605       needs_comma := true;
9606
9607       match arg with
9608       | Pathname n
9609       | Device n | Dev_or_Path n
9610       | String n
9611       | OptString n
9612       | FileIn n
9613       | FileOut n ->
9614           pr "String %s" n
9615       | StringList n | DeviceList n ->
9616           pr "String[] %s" n
9617       | Bool n ->
9618           pr "boolean %s" n
9619       | Int n ->
9620           pr "int %s" n
9621       | Int64 n ->
9622           pr "long %s" n
9623   ) (snd style);
9624
9625   pr ")\n";
9626   pr "    throws LibGuestFSException";
9627   if semicolon then pr ";"
9628
9629 and generate_java_struct jtyp cols () =
9630   generate_header CStyle LGPLv2plus;
9631
9632   pr "\
9633 package com.redhat.et.libguestfs;
9634
9635 /**
9636  * Libguestfs %s structure.
9637  *
9638  * @author rjones
9639  * @see GuestFS
9640  */
9641 public class %s {
9642 " jtyp jtyp;
9643
9644   List.iter (
9645     function
9646     | name, FString
9647     | name, FUUID
9648     | name, FBuffer -> pr "  public String %s;\n" name
9649     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9650     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9651     | name, FChar -> pr "  public char %s;\n" name
9652     | name, FOptPercent ->
9653         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9654         pr "  public float %s;\n" name
9655   ) cols;
9656
9657   pr "}\n"
9658
9659 and generate_java_c () =
9660   generate_header CStyle LGPLv2plus;
9661
9662   pr "\
9663 #include <stdio.h>
9664 #include <stdlib.h>
9665 #include <string.h>
9666
9667 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9668 #include \"guestfs.h\"
9669
9670 /* Note that this function returns.  The exception is not thrown
9671  * until after the wrapper function returns.
9672  */
9673 static void
9674 throw_exception (JNIEnv *env, const char *msg)
9675 {
9676   jclass cl;
9677   cl = (*env)->FindClass (env,
9678                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9679   (*env)->ThrowNew (env, cl, msg);
9680 }
9681
9682 JNIEXPORT jlong JNICALL
9683 Java_com_redhat_et_libguestfs_GuestFS__1create
9684   (JNIEnv *env, jobject obj)
9685 {
9686   guestfs_h *g;
9687
9688   g = guestfs_create ();
9689   if (g == NULL) {
9690     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9691     return 0;
9692   }
9693   guestfs_set_error_handler (g, NULL, NULL);
9694   return (jlong) (long) g;
9695 }
9696
9697 JNIEXPORT void JNICALL
9698 Java_com_redhat_et_libguestfs_GuestFS__1close
9699   (JNIEnv *env, jobject obj, jlong jg)
9700 {
9701   guestfs_h *g = (guestfs_h *) (long) jg;
9702   guestfs_close (g);
9703 }
9704
9705 ";
9706
9707   List.iter (
9708     fun (name, style, _, _, _, _, _) ->
9709       pr "JNIEXPORT ";
9710       (match fst style with
9711        | RErr -> pr "void ";
9712        | RInt _ -> pr "jint ";
9713        | RInt64 _ -> pr "jlong ";
9714        | RBool _ -> pr "jboolean ";
9715        | RConstString _ | RConstOptString _ | RString _
9716        | RBufferOut _ -> pr "jstring ";
9717        | RStruct _ | RHashtable _ ->
9718            pr "jobject ";
9719        | RStringList _ | RStructList _ ->
9720            pr "jobjectArray ";
9721       );
9722       pr "JNICALL\n";
9723       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9724       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9725       pr "\n";
9726       pr "  (JNIEnv *env, jobject obj, jlong jg";
9727       List.iter (
9728         function
9729         | Pathname n
9730         | Device n | Dev_or_Path n
9731         | String n
9732         | OptString n
9733         | FileIn n
9734         | FileOut n ->
9735             pr ", jstring j%s" n
9736         | StringList n | DeviceList n ->
9737             pr ", jobjectArray j%s" n
9738         | Bool n ->
9739             pr ", jboolean j%s" n
9740         | Int n ->
9741             pr ", jint j%s" n
9742         | Int64 n ->
9743             pr ", jlong j%s" n
9744       ) (snd style);
9745       pr ")\n";
9746       pr "{\n";
9747       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9748       let error_code, no_ret =
9749         match fst style with
9750         | RErr -> pr "  int r;\n"; "-1", ""
9751         | RBool _
9752         | RInt _ -> pr "  int r;\n"; "-1", "0"
9753         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9754         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9755         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9756         | RString _ ->
9757             pr "  jstring jr;\n";
9758             pr "  char *r;\n"; "NULL", "NULL"
9759         | RStringList _ ->
9760             pr "  jobjectArray jr;\n";
9761             pr "  int r_len;\n";
9762             pr "  jclass cl;\n";
9763             pr "  jstring jstr;\n";
9764             pr "  char **r;\n"; "NULL", "NULL"
9765         | RStruct (_, typ) ->
9766             pr "  jobject jr;\n";
9767             pr "  jclass cl;\n";
9768             pr "  jfieldID fl;\n";
9769             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9770         | RStructList (_, typ) ->
9771             pr "  jobjectArray jr;\n";
9772             pr "  jclass cl;\n";
9773             pr "  jfieldID fl;\n";
9774             pr "  jobject jfl;\n";
9775             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9776         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9777         | RBufferOut _ ->
9778             pr "  jstring jr;\n";
9779             pr "  char *r;\n";
9780             pr "  size_t size;\n";
9781             "NULL", "NULL" in
9782       List.iter (
9783         function
9784         | Pathname n
9785         | Device n | Dev_or_Path n
9786         | String n
9787         | OptString n
9788         | FileIn n
9789         | FileOut n ->
9790             pr "  const char *%s;\n" n
9791         | StringList n | DeviceList n ->
9792             pr "  int %s_len;\n" n;
9793             pr "  const char **%s;\n" n
9794         | Bool n
9795         | Int n ->
9796             pr "  int %s;\n" n
9797         | Int64 n ->
9798             pr "  int64_t %s;\n" n
9799       ) (snd style);
9800
9801       let needs_i =
9802         (match fst style with
9803          | RStringList _ | RStructList _ -> true
9804          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9805          | RConstOptString _
9806          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9807           List.exists (function
9808                        | StringList _ -> true
9809                        | DeviceList _ -> true
9810                        | _ -> false) (snd style) in
9811       if needs_i then
9812         pr "  int i;\n";
9813
9814       pr "\n";
9815
9816       (* Get the parameters. *)
9817       List.iter (
9818         function
9819         | Pathname n
9820         | Device n | Dev_or_Path n
9821         | String n
9822         | FileIn n
9823         | FileOut n ->
9824             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9825         | OptString n ->
9826             (* This is completely undocumented, but Java null becomes
9827              * a NULL parameter.
9828              *)
9829             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9830         | StringList n | DeviceList n ->
9831             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9832             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9833             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9834             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9835               n;
9836             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9837             pr "  }\n";
9838             pr "  %s[%s_len] = NULL;\n" n n;
9839         | Bool n
9840         | Int n
9841         | Int64 n ->
9842             pr "  %s = j%s;\n" n n
9843       ) (snd style);
9844
9845       (* Make the call. *)
9846       pr "  r = guestfs_%s " name;
9847       generate_c_call_args ~handle:"g" style;
9848       pr ";\n";
9849
9850       (* Release the parameters. *)
9851       List.iter (
9852         function
9853         | Pathname n
9854         | Device n | Dev_or_Path n
9855         | String n
9856         | FileIn n
9857         | FileOut n ->
9858             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9859         | OptString n ->
9860             pr "  if (j%s)\n" n;
9861             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9862         | StringList n | DeviceList n ->
9863             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9864             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9865               n;
9866             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9867             pr "  }\n";
9868             pr "  free (%s);\n" n
9869         | Bool n
9870         | Int n
9871         | Int64 n -> ()
9872       ) (snd style);
9873
9874       (* Check for errors. *)
9875       pr "  if (r == %s) {\n" error_code;
9876       pr "    throw_exception (env, guestfs_last_error (g));\n";
9877       pr "    return %s;\n" no_ret;
9878       pr "  }\n";
9879
9880       (* Return value. *)
9881       (match fst style with
9882        | RErr -> ()
9883        | RInt _ -> pr "  return (jint) r;\n"
9884        | RBool _ -> pr "  return (jboolean) r;\n"
9885        | RInt64 _ -> pr "  return (jlong) r;\n"
9886        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9887        | RConstOptString _ ->
9888            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9889        | RString _ ->
9890            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9891            pr "  free (r);\n";
9892            pr "  return jr;\n"
9893        | RStringList _ ->
9894            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9895            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9896            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9897            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9898            pr "  for (i = 0; i < r_len; ++i) {\n";
9899            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9900            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9901            pr "    free (r[i]);\n";
9902            pr "  }\n";
9903            pr "  free (r);\n";
9904            pr "  return jr;\n"
9905        | RStruct (_, typ) ->
9906            let jtyp = java_name_of_struct typ in
9907            let cols = cols_of_struct typ in
9908            generate_java_struct_return typ jtyp cols
9909        | RStructList (_, typ) ->
9910            let jtyp = java_name_of_struct typ in
9911            let cols = cols_of_struct typ in
9912            generate_java_struct_list_return typ jtyp cols
9913        | RHashtable _ ->
9914            (* XXX *)
9915            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9916            pr "  return NULL;\n"
9917        | RBufferOut _ ->
9918            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9919            pr "  free (r);\n";
9920            pr "  return jr;\n"
9921       );
9922
9923       pr "}\n";
9924       pr "\n"
9925   ) all_functions
9926
9927 and generate_java_struct_return typ jtyp cols =
9928   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9929   pr "  jr = (*env)->AllocObject (env, cl);\n";
9930   List.iter (
9931     function
9932     | name, FString ->
9933         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9934         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9935     | name, FUUID ->
9936         pr "  {\n";
9937         pr "    char s[33];\n";
9938         pr "    memcpy (s, r->%s, 32);\n" name;
9939         pr "    s[32] = 0;\n";
9940         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9941         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9942         pr "  }\n";
9943     | name, FBuffer ->
9944         pr "  {\n";
9945         pr "    int len = r->%s_len;\n" name;
9946         pr "    char s[len+1];\n";
9947         pr "    memcpy (s, r->%s, len);\n" name;
9948         pr "    s[len] = 0;\n";
9949         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9950         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9951         pr "  }\n";
9952     | name, (FBytes|FUInt64|FInt64) ->
9953         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9954         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9955     | name, (FUInt32|FInt32) ->
9956         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9957         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9958     | name, FOptPercent ->
9959         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9960         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9961     | name, FChar ->
9962         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9963         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9964   ) cols;
9965   pr "  free (r);\n";
9966   pr "  return jr;\n"
9967
9968 and generate_java_struct_list_return typ jtyp cols =
9969   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9970   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9971   pr "  for (i = 0; i < r->len; ++i) {\n";
9972   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9973   List.iter (
9974     function
9975     | name, FString ->
9976         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9977         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9978     | name, FUUID ->
9979         pr "    {\n";
9980         pr "      char s[33];\n";
9981         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9982         pr "      s[32] = 0;\n";
9983         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9984         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9985         pr "    }\n";
9986     | name, FBuffer ->
9987         pr "    {\n";
9988         pr "      int len = r->val[i].%s_len;\n" name;
9989         pr "      char s[len+1];\n";
9990         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9991         pr "      s[len] = 0;\n";
9992         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9993         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9994         pr "    }\n";
9995     | name, (FBytes|FUInt64|FInt64) ->
9996         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9997         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9998     | name, (FUInt32|FInt32) ->
9999         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10000         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10001     | name, FOptPercent ->
10002         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10003         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10004     | name, FChar ->
10005         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10006         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10007   ) cols;
10008   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10009   pr "  }\n";
10010   pr "  guestfs_free_%s_list (r);\n" typ;
10011   pr "  return jr;\n"
10012
10013 and generate_java_makefile_inc () =
10014   generate_header HashStyle GPLv2plus;
10015
10016   pr "java_built_sources = \\\n";
10017   List.iter (
10018     fun (typ, jtyp) ->
10019         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10020   ) java_structs;
10021   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10022
10023 and generate_haskell_hs () =
10024   generate_header HaskellStyle LGPLv2plus;
10025
10026   (* XXX We only know how to generate partial FFI for Haskell
10027    * at the moment.  Please help out!
10028    *)
10029   let can_generate style =
10030     match style with
10031     | RErr, _
10032     | RInt _, _
10033     | RInt64 _, _ -> true
10034     | RBool _, _
10035     | RConstString _, _
10036     | RConstOptString _, _
10037     | RString _, _
10038     | RStringList _, _
10039     | RStruct _, _
10040     | RStructList _, _
10041     | RHashtable _, _
10042     | RBufferOut _, _ -> false in
10043
10044   pr "\
10045 {-# INCLUDE <guestfs.h> #-}
10046 {-# LANGUAGE ForeignFunctionInterface #-}
10047
10048 module Guestfs (
10049   create";
10050
10051   (* List out the names of the actions we want to export. *)
10052   List.iter (
10053     fun (name, style, _, _, _, _, _) ->
10054       if can_generate style then pr ",\n  %s" name
10055   ) all_functions;
10056
10057   pr "
10058   ) where
10059
10060 -- Unfortunately some symbols duplicate ones already present
10061 -- in Prelude.  We don't know which, so we hard-code a list
10062 -- here.
10063 import Prelude hiding (truncate)
10064
10065 import Foreign
10066 import Foreign.C
10067 import Foreign.C.Types
10068 import IO
10069 import Control.Exception
10070 import Data.Typeable
10071
10072 data GuestfsS = GuestfsS            -- represents the opaque C struct
10073 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10074 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10075
10076 -- XXX define properly later XXX
10077 data PV = PV
10078 data VG = VG
10079 data LV = LV
10080 data IntBool = IntBool
10081 data Stat = Stat
10082 data StatVFS = StatVFS
10083 data Hashtable = Hashtable
10084
10085 foreign import ccall unsafe \"guestfs_create\" c_create
10086   :: IO GuestfsP
10087 foreign import ccall unsafe \"&guestfs_close\" c_close
10088   :: FunPtr (GuestfsP -> IO ())
10089 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10090   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10091
10092 create :: IO GuestfsH
10093 create = do
10094   p <- c_create
10095   c_set_error_handler p nullPtr nullPtr
10096   h <- newForeignPtr c_close p
10097   return h
10098
10099 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10100   :: GuestfsP -> IO CString
10101
10102 -- last_error :: GuestfsH -> IO (Maybe String)
10103 -- last_error h = do
10104 --   str <- withForeignPtr h (\\p -> c_last_error p)
10105 --   maybePeek peekCString str
10106
10107 last_error :: GuestfsH -> IO (String)
10108 last_error h = do
10109   str <- withForeignPtr h (\\p -> c_last_error p)
10110   if (str == nullPtr)
10111     then return \"no error\"
10112     else peekCString str
10113
10114 ";
10115
10116   (* Generate wrappers for each foreign function. *)
10117   List.iter (
10118     fun (name, style, _, _, _, _, _) ->
10119       if can_generate style then (
10120         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10121         pr "  :: ";
10122         generate_haskell_prototype ~handle:"GuestfsP" style;
10123         pr "\n";
10124         pr "\n";
10125         pr "%s :: " name;
10126         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10127         pr "\n";
10128         pr "%s %s = do\n" name
10129           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10130         pr "  r <- ";
10131         (* Convert pointer arguments using with* functions. *)
10132         List.iter (
10133           function
10134           | FileIn n
10135           | FileOut n
10136           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10137           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10138           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10139           | Bool _ | Int _ | Int64 _ -> ()
10140         ) (snd style);
10141         (* Convert integer arguments. *)
10142         let args =
10143           List.map (
10144             function
10145             | Bool n -> sprintf "(fromBool %s)" n
10146             | Int n -> sprintf "(fromIntegral %s)" n
10147             | Int64 n -> sprintf "(fromIntegral %s)" n
10148             | FileIn n | FileOut n
10149             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10150           ) (snd style) in
10151         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10152           (String.concat " " ("p" :: args));
10153         (match fst style with
10154          | RErr | RInt _ | RInt64 _ | RBool _ ->
10155              pr "  if (r == -1)\n";
10156              pr "    then do\n";
10157              pr "      err <- last_error h\n";
10158              pr "      fail err\n";
10159          | RConstString _ | RConstOptString _ | RString _
10160          | RStringList _ | RStruct _
10161          | RStructList _ | RHashtable _ | RBufferOut _ ->
10162              pr "  if (r == nullPtr)\n";
10163              pr "    then do\n";
10164              pr "      err <- last_error h\n";
10165              pr "      fail err\n";
10166         );
10167         (match fst style with
10168          | RErr ->
10169              pr "    else return ()\n"
10170          | RInt _ ->
10171              pr "    else return (fromIntegral r)\n"
10172          | RInt64 _ ->
10173              pr "    else return (fromIntegral r)\n"
10174          | RBool _ ->
10175              pr "    else return (toBool r)\n"
10176          | RConstString _
10177          | RConstOptString _
10178          | RString _
10179          | RStringList _
10180          | RStruct _
10181          | RStructList _
10182          | RHashtable _
10183          | RBufferOut _ ->
10184              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10185         );
10186         pr "\n";
10187       )
10188   ) all_functions
10189
10190 and generate_haskell_prototype ~handle ?(hs = false) style =
10191   pr "%s -> " handle;
10192   let string = if hs then "String" else "CString" in
10193   let int = if hs then "Int" else "CInt" in
10194   let bool = if hs then "Bool" else "CInt" in
10195   let int64 = if hs then "Integer" else "Int64" in
10196   List.iter (
10197     fun arg ->
10198       (match arg with
10199        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10200        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10201        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10202        | Bool _ -> pr "%s" bool
10203        | Int _ -> pr "%s" int
10204        | Int64 _ -> pr "%s" int
10205        | FileIn _ -> pr "%s" string
10206        | FileOut _ -> pr "%s" string
10207       );
10208       pr " -> ";
10209   ) (snd style);
10210   pr "IO (";
10211   (match fst style with
10212    | RErr -> if not hs then pr "CInt"
10213    | RInt _ -> pr "%s" int
10214    | RInt64 _ -> pr "%s" int64
10215    | RBool _ -> pr "%s" bool
10216    | RConstString _ -> pr "%s" string
10217    | RConstOptString _ -> pr "Maybe %s" string
10218    | RString _ -> pr "%s" string
10219    | RStringList _ -> pr "[%s]" string
10220    | RStruct (_, typ) ->
10221        let name = java_name_of_struct typ in
10222        pr "%s" name
10223    | RStructList (_, typ) ->
10224        let name = java_name_of_struct typ in
10225        pr "[%s]" name
10226    | RHashtable _ -> pr "Hashtable"
10227    | RBufferOut _ -> pr "%s" string
10228   );
10229   pr ")"
10230
10231 and generate_csharp () =
10232   generate_header CPlusPlusStyle LGPLv2plus;
10233
10234   (* XXX Make this configurable by the C# assembly users. *)
10235   let library = "libguestfs.so.0" in
10236
10237   pr "\
10238 // These C# bindings are highly experimental at present.
10239 //
10240 // Firstly they only work on Linux (ie. Mono).  In order to get them
10241 // to work on Windows (ie. .Net) you would need to port the library
10242 // itself to Windows first.
10243 //
10244 // The second issue is that some calls are known to be incorrect and
10245 // can cause Mono to segfault.  Particularly: calls which pass or
10246 // return string[], or return any structure value.  This is because
10247 // we haven't worked out the correct way to do this from C#.
10248 //
10249 // The third issue is that when compiling you get a lot of warnings.
10250 // We are not sure whether the warnings are important or not.
10251 //
10252 // Fourthly we do not routinely build or test these bindings as part
10253 // of the make && make check cycle, which means that regressions might
10254 // go unnoticed.
10255 //
10256 // Suggestions and patches are welcome.
10257
10258 // To compile:
10259 //
10260 // gmcs Libguestfs.cs
10261 // mono Libguestfs.exe
10262 //
10263 // (You'll probably want to add a Test class / static main function
10264 // otherwise this won't do anything useful).
10265
10266 using System;
10267 using System.IO;
10268 using System.Runtime.InteropServices;
10269 using System.Runtime.Serialization;
10270 using System.Collections;
10271
10272 namespace Guestfs
10273 {
10274   class Error : System.ApplicationException
10275   {
10276     public Error (string message) : base (message) {}
10277     protected Error (SerializationInfo info, StreamingContext context) {}
10278   }
10279
10280   class Guestfs
10281   {
10282     IntPtr _handle;
10283
10284     [DllImport (\"%s\")]
10285     static extern IntPtr guestfs_create ();
10286
10287     public Guestfs ()
10288     {
10289       _handle = guestfs_create ();
10290       if (_handle == IntPtr.Zero)
10291         throw new Error (\"could not create guestfs handle\");
10292     }
10293
10294     [DllImport (\"%s\")]
10295     static extern void guestfs_close (IntPtr h);
10296
10297     ~Guestfs ()
10298     {
10299       guestfs_close (_handle);
10300     }
10301
10302     [DllImport (\"%s\")]
10303     static extern string guestfs_last_error (IntPtr h);
10304
10305 " library library library;
10306
10307   (* Generate C# structure bindings.  We prefix struct names with
10308    * underscore because C# cannot have conflicting struct names and
10309    * method names (eg. "class stat" and "stat").
10310    *)
10311   List.iter (
10312     fun (typ, cols) ->
10313       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10314       pr "    public class _%s {\n" typ;
10315       List.iter (
10316         function
10317         | name, FChar -> pr "      char %s;\n" name
10318         | name, FString -> pr "      string %s;\n" name
10319         | name, FBuffer ->
10320             pr "      uint %s_len;\n" name;
10321             pr "      string %s;\n" name
10322         | name, FUUID ->
10323             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10324             pr "      string %s;\n" name
10325         | name, FUInt32 -> pr "      uint %s;\n" name
10326         | name, FInt32 -> pr "      int %s;\n" name
10327         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10328         | name, FInt64 -> pr "      long %s;\n" name
10329         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10330       ) cols;
10331       pr "    }\n";
10332       pr "\n"
10333   ) structs;
10334
10335   (* Generate C# function bindings. *)
10336   List.iter (
10337     fun (name, style, _, _, _, shortdesc, _) ->
10338       let rec csharp_return_type () =
10339         match fst style with
10340         | RErr -> "void"
10341         | RBool n -> "bool"
10342         | RInt n -> "int"
10343         | RInt64 n -> "long"
10344         | RConstString n
10345         | RConstOptString n
10346         | RString n
10347         | RBufferOut n -> "string"
10348         | RStruct (_,n) -> "_" ^ n
10349         | RHashtable n -> "Hashtable"
10350         | RStringList n -> "string[]"
10351         | RStructList (_,n) -> sprintf "_%s[]" n
10352
10353       and c_return_type () =
10354         match fst style with
10355         | RErr
10356         | RBool _
10357         | RInt _ -> "int"
10358         | RInt64 _ -> "long"
10359         | RConstString _
10360         | RConstOptString _
10361         | RString _
10362         | RBufferOut _ -> "string"
10363         | RStruct (_,n) -> "_" ^ n
10364         | RHashtable _
10365         | RStringList _ -> "string[]"
10366         | RStructList (_,n) -> sprintf "_%s[]" n
10367
10368       and c_error_comparison () =
10369         match fst style with
10370         | RErr
10371         | RBool _
10372         | RInt _
10373         | RInt64 _ -> "== -1"
10374         | RConstString _
10375         | RConstOptString _
10376         | RString _
10377         | RBufferOut _
10378         | RStruct (_,_)
10379         | RHashtable _
10380         | RStringList _
10381         | RStructList (_,_) -> "== null"
10382
10383       and generate_extern_prototype () =
10384         pr "    static extern %s guestfs_%s (IntPtr h"
10385           (c_return_type ()) name;
10386         List.iter (
10387           function
10388           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10389           | FileIn n | FileOut n ->
10390               pr ", [In] string %s" n
10391           | StringList n | DeviceList n ->
10392               pr ", [In] string[] %s" n
10393           | Bool n ->
10394               pr ", bool %s" n
10395           | Int n ->
10396               pr ", int %s" n
10397           | Int64 n ->
10398               pr ", long %s" n
10399         ) (snd style);
10400         pr ");\n"
10401
10402       and generate_public_prototype () =
10403         pr "    public %s %s (" (csharp_return_type ()) name;
10404         let comma = ref false in
10405         let next () =
10406           if !comma then pr ", ";
10407           comma := true
10408         in
10409         List.iter (
10410           function
10411           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10412           | FileIn n | FileOut n ->
10413               next (); pr "string %s" n
10414           | StringList n | DeviceList n ->
10415               next (); pr "string[] %s" n
10416           | Bool n ->
10417               next (); pr "bool %s" n
10418           | Int n ->
10419               next (); pr "int %s" n
10420           | Int64 n ->
10421               next (); pr "long %s" n
10422         ) (snd style);
10423         pr ")\n"
10424
10425       and generate_call () =
10426         pr "guestfs_%s (_handle" name;
10427         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10428         pr ");\n";
10429       in
10430
10431       pr "    [DllImport (\"%s\")]\n" library;
10432       generate_extern_prototype ();
10433       pr "\n";
10434       pr "    /// <summary>\n";
10435       pr "    /// %s\n" shortdesc;
10436       pr "    /// </summary>\n";
10437       generate_public_prototype ();
10438       pr "    {\n";
10439       pr "      %s r;\n" (c_return_type ());
10440       pr "      r = ";
10441       generate_call ();
10442       pr "      if (r %s)\n" (c_error_comparison ());
10443       pr "        throw new Error (guestfs_last_error (_handle));\n";
10444       (match fst style with
10445        | RErr -> ()
10446        | RBool _ ->
10447            pr "      return r != 0 ? true : false;\n"
10448        | RHashtable _ ->
10449            pr "      Hashtable rr = new Hashtable ();\n";
10450            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10451            pr "        rr.Add (r[i], r[i+1]);\n";
10452            pr "      return rr;\n"
10453        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10454        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10455        | RStructList _ ->
10456            pr "      return r;\n"
10457       );
10458       pr "    }\n";
10459       pr "\n";
10460   ) all_functions_sorted;
10461
10462   pr "  }
10463 }
10464 "
10465
10466 and generate_bindtests () =
10467   generate_header CStyle LGPLv2plus;
10468
10469   pr "\
10470 #include <stdio.h>
10471 #include <stdlib.h>
10472 #include <inttypes.h>
10473 #include <string.h>
10474
10475 #include \"guestfs.h\"
10476 #include \"guestfs-internal.h\"
10477 #include \"guestfs-internal-actions.h\"
10478 #include \"guestfs_protocol.h\"
10479
10480 #define error guestfs_error
10481 #define safe_calloc guestfs_safe_calloc
10482 #define safe_malloc guestfs_safe_malloc
10483
10484 static void
10485 print_strings (char *const *argv)
10486 {
10487   int argc;
10488
10489   printf (\"[\");
10490   for (argc = 0; argv[argc] != NULL; ++argc) {
10491     if (argc > 0) printf (\", \");
10492     printf (\"\\\"%%s\\\"\", argv[argc]);
10493   }
10494   printf (\"]\\n\");
10495 }
10496
10497 /* The test0 function prints its parameters to stdout. */
10498 ";
10499
10500   let test0, tests =
10501     match test_functions with
10502     | [] -> assert false
10503     | test0 :: tests -> test0, tests in
10504
10505   let () =
10506     let (name, style, _, _, _, _, _) = test0 in
10507     generate_prototype ~extern:false ~semicolon:false ~newline:true
10508       ~handle:"g" ~prefix:"guestfs__" name style;
10509     pr "{\n";
10510     List.iter (
10511       function
10512       | Pathname n
10513       | Device n | Dev_or_Path n
10514       | String n
10515       | FileIn n
10516       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10517       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10518       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10519       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10520       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10521       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10522     ) (snd style);
10523     pr "  /* Java changes stdout line buffering so we need this: */\n";
10524     pr "  fflush (stdout);\n";
10525     pr "  return 0;\n";
10526     pr "}\n";
10527     pr "\n" in
10528
10529   List.iter (
10530     fun (name, style, _, _, _, _, _) ->
10531       if String.sub name (String.length name - 3) 3 <> "err" then (
10532         pr "/* Test normal return. */\n";
10533         generate_prototype ~extern:false ~semicolon:false ~newline:true
10534           ~handle:"g" ~prefix:"guestfs__" name style;
10535         pr "{\n";
10536         (match fst style with
10537          | RErr ->
10538              pr "  return 0;\n"
10539          | RInt _ ->
10540              pr "  int r;\n";
10541              pr "  sscanf (val, \"%%d\", &r);\n";
10542              pr "  return r;\n"
10543          | RInt64 _ ->
10544              pr "  int64_t r;\n";
10545              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10546              pr "  return r;\n"
10547          | RBool _ ->
10548              pr "  return STREQ (val, \"true\");\n"
10549          | RConstString _
10550          | RConstOptString _ ->
10551              (* Can't return the input string here.  Return a static
10552               * string so we ensure we get a segfault if the caller
10553               * tries to free it.
10554               *)
10555              pr "  return \"static string\";\n"
10556          | RString _ ->
10557              pr "  return strdup (val);\n"
10558          | RStringList _ ->
10559              pr "  char **strs;\n";
10560              pr "  int n, i;\n";
10561              pr "  sscanf (val, \"%%d\", &n);\n";
10562              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10563              pr "  for (i = 0; i < n; ++i) {\n";
10564              pr "    strs[i] = safe_malloc (g, 16);\n";
10565              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10566              pr "  }\n";
10567              pr "  strs[n] = NULL;\n";
10568              pr "  return strs;\n"
10569          | RStruct (_, typ) ->
10570              pr "  struct guestfs_%s *r;\n" typ;
10571              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10572              pr "  return r;\n"
10573          | RStructList (_, typ) ->
10574              pr "  struct guestfs_%s_list *r;\n" typ;
10575              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10576              pr "  sscanf (val, \"%%d\", &r->len);\n";
10577              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10578              pr "  return r;\n"
10579          | RHashtable _ ->
10580              pr "  char **strs;\n";
10581              pr "  int n, i;\n";
10582              pr "  sscanf (val, \"%%d\", &n);\n";
10583              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10584              pr "  for (i = 0; i < n; ++i) {\n";
10585              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10586              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10587              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10588              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10589              pr "  }\n";
10590              pr "  strs[n*2] = NULL;\n";
10591              pr "  return strs;\n"
10592          | RBufferOut _ ->
10593              pr "  return strdup (val);\n"
10594         );
10595         pr "}\n";
10596         pr "\n"
10597       ) else (
10598         pr "/* Test error return. */\n";
10599         generate_prototype ~extern:false ~semicolon:false ~newline:true
10600           ~handle:"g" ~prefix:"guestfs__" name style;
10601         pr "{\n";
10602         pr "  error (g, \"error\");\n";
10603         (match fst style with
10604          | RErr | RInt _ | RInt64 _ | RBool _ ->
10605              pr "  return -1;\n"
10606          | RConstString _ | RConstOptString _
10607          | RString _ | RStringList _ | RStruct _
10608          | RStructList _
10609          | RHashtable _
10610          | RBufferOut _ ->
10611              pr "  return NULL;\n"
10612         );
10613         pr "}\n";
10614         pr "\n"
10615       )
10616   ) tests
10617
10618 and generate_ocaml_bindtests () =
10619   generate_header OCamlStyle GPLv2plus;
10620
10621   pr "\
10622 let () =
10623   let g = Guestfs.create () in
10624 ";
10625
10626   let mkargs args =
10627     String.concat " " (
10628       List.map (
10629         function
10630         | CallString s -> "\"" ^ s ^ "\""
10631         | CallOptString None -> "None"
10632         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10633         | CallStringList xs ->
10634             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10635         | CallInt i when i >= 0 -> string_of_int i
10636         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10637         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10638         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10639         | CallBool b -> string_of_bool b
10640       ) args
10641     )
10642   in
10643
10644   generate_lang_bindtests (
10645     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10646   );
10647
10648   pr "print_endline \"EOF\"\n"
10649
10650 and generate_perl_bindtests () =
10651   pr "#!/usr/bin/perl -w\n";
10652   generate_header HashStyle GPLv2plus;
10653
10654   pr "\
10655 use strict;
10656
10657 use Sys::Guestfs;
10658
10659 my $g = Sys::Guestfs->new ();
10660 ";
10661
10662   let mkargs args =
10663     String.concat ", " (
10664       List.map (
10665         function
10666         | CallString s -> "\"" ^ s ^ "\""
10667         | CallOptString None -> "undef"
10668         | CallOptString (Some s) -> sprintf "\"%s\"" s
10669         | CallStringList xs ->
10670             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10671         | CallInt i -> string_of_int i
10672         | CallInt64 i -> Int64.to_string i
10673         | CallBool b -> if b then "1" else "0"
10674       ) args
10675     )
10676   in
10677
10678   generate_lang_bindtests (
10679     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10680   );
10681
10682   pr "print \"EOF\\n\"\n"
10683
10684 and generate_python_bindtests () =
10685   generate_header HashStyle GPLv2plus;
10686
10687   pr "\
10688 import guestfs
10689
10690 g = guestfs.GuestFS ()
10691 ";
10692
10693   let mkargs args =
10694     String.concat ", " (
10695       List.map (
10696         function
10697         | CallString s -> "\"" ^ s ^ "\""
10698         | CallOptString None -> "None"
10699         | CallOptString (Some s) -> sprintf "\"%s\"" s
10700         | CallStringList xs ->
10701             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10702         | CallInt i -> string_of_int i
10703         | CallInt64 i -> Int64.to_string i
10704         | CallBool b -> if b then "1" else "0"
10705       ) args
10706     )
10707   in
10708
10709   generate_lang_bindtests (
10710     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10711   );
10712
10713   pr "print \"EOF\"\n"
10714
10715 and generate_ruby_bindtests () =
10716   generate_header HashStyle GPLv2plus;
10717
10718   pr "\
10719 require 'guestfs'
10720
10721 g = Guestfs::create()
10722 ";
10723
10724   let mkargs args =
10725     String.concat ", " (
10726       List.map (
10727         function
10728         | CallString s -> "\"" ^ s ^ "\""
10729         | CallOptString None -> "nil"
10730         | CallOptString (Some s) -> sprintf "\"%s\"" s
10731         | CallStringList xs ->
10732             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10733         | CallInt i -> string_of_int i
10734         | CallInt64 i -> Int64.to_string i
10735         | CallBool b -> string_of_bool b
10736       ) args
10737     )
10738   in
10739
10740   generate_lang_bindtests (
10741     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10742   );
10743
10744   pr "print \"EOF\\n\"\n"
10745
10746 and generate_java_bindtests () =
10747   generate_header CStyle GPLv2plus;
10748
10749   pr "\
10750 import com.redhat.et.libguestfs.*;
10751
10752 public class Bindtests {
10753     public static void main (String[] argv)
10754     {
10755         try {
10756             GuestFS g = new GuestFS ();
10757 ";
10758
10759   let mkargs args =
10760     String.concat ", " (
10761       List.map (
10762         function
10763         | CallString s -> "\"" ^ s ^ "\""
10764         | CallOptString None -> "null"
10765         | CallOptString (Some s) -> sprintf "\"%s\"" s
10766         | CallStringList xs ->
10767             "new String[]{" ^
10768               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10769         | CallInt i -> string_of_int i
10770         | CallInt64 i -> Int64.to_string i
10771         | CallBool b -> string_of_bool b
10772       ) args
10773     )
10774   in
10775
10776   generate_lang_bindtests (
10777     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10778   );
10779
10780   pr "
10781             System.out.println (\"EOF\");
10782         }
10783         catch (Exception exn) {
10784             System.err.println (exn);
10785             System.exit (1);
10786         }
10787     }
10788 }
10789 "
10790
10791 and generate_haskell_bindtests () =
10792   generate_header HaskellStyle GPLv2plus;
10793
10794   pr "\
10795 module Bindtests where
10796 import qualified Guestfs
10797
10798 main = do
10799   g <- Guestfs.create
10800 ";
10801
10802   let mkargs args =
10803     String.concat " " (
10804       List.map (
10805         function
10806         | CallString s -> "\"" ^ s ^ "\""
10807         | CallOptString None -> "Nothing"
10808         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10809         | CallStringList xs ->
10810             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10811         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10812         | CallInt i -> string_of_int i
10813         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10814         | CallInt64 i -> Int64.to_string i
10815         | CallBool true -> "True"
10816         | CallBool false -> "False"
10817       ) args
10818     )
10819   in
10820
10821   generate_lang_bindtests (
10822     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10823   );
10824
10825   pr "  putStrLn \"EOF\"\n"
10826
10827 (* Language-independent bindings tests - we do it this way to
10828  * ensure there is parity in testing bindings across all languages.
10829  *)
10830 and generate_lang_bindtests call =
10831   call "test0" [CallString "abc"; CallOptString (Some "def");
10832                 CallStringList []; CallBool false;
10833                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10834   call "test0" [CallString "abc"; CallOptString None;
10835                 CallStringList []; CallBool false;
10836                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10837   call "test0" [CallString ""; CallOptString (Some "def");
10838                 CallStringList []; CallBool false;
10839                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10840   call "test0" [CallString ""; CallOptString (Some "");
10841                 CallStringList []; CallBool false;
10842                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10843   call "test0" [CallString "abc"; CallOptString (Some "def");
10844                 CallStringList ["1"]; CallBool false;
10845                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10846   call "test0" [CallString "abc"; CallOptString (Some "def");
10847                 CallStringList ["1"; "2"]; CallBool false;
10848                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10849   call "test0" [CallString "abc"; CallOptString (Some "def");
10850                 CallStringList ["1"]; CallBool true;
10851                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10852   call "test0" [CallString "abc"; CallOptString (Some "def");
10853                 CallStringList ["1"]; CallBool false;
10854                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10855   call "test0" [CallString "abc"; CallOptString (Some "def");
10856                 CallStringList ["1"]; CallBool false;
10857                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10858   call "test0" [CallString "abc"; CallOptString (Some "def");
10859                 CallStringList ["1"]; CallBool false;
10860                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10861   call "test0" [CallString "abc"; CallOptString (Some "def");
10862                 CallStringList ["1"]; CallBool false;
10863                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10864   call "test0" [CallString "abc"; CallOptString (Some "def");
10865                 CallStringList ["1"]; CallBool false;
10866                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10867   call "test0" [CallString "abc"; CallOptString (Some "def");
10868                 CallStringList ["1"]; CallBool false;
10869                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10870
10871 (* XXX Add here tests of the return and error functions. *)
10872
10873 (* Code to generator bindings for virt-inspector.  Currently only
10874  * implemented for OCaml code (for virt-p2v 2.0).
10875  *)
10876 let rng_input = "inspector/virt-inspector.rng"
10877
10878 (* Read the input file and parse it into internal structures.  This is
10879  * by no means a complete RELAX NG parser, but is just enough to be
10880  * able to parse the specific input file.
10881  *)
10882 type rng =
10883   | Element of string * rng list        (* <element name=name/> *)
10884   | Attribute of string * rng list        (* <attribute name=name/> *)
10885   | Interleave of rng list                (* <interleave/> *)
10886   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10887   | OneOrMore of rng                        (* <oneOrMore/> *)
10888   | Optional of rng                        (* <optional/> *)
10889   | Choice of string list                (* <choice><value/>*</choice> *)
10890   | Value of string                        (* <value>str</value> *)
10891   | Text                                (* <text/> *)
10892
10893 let rec string_of_rng = function
10894   | Element (name, xs) ->
10895       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10896   | Attribute (name, xs) ->
10897       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10898   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10899   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10900   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10901   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10902   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10903   | Value value -> "Value \"" ^ value ^ "\""
10904   | Text -> "Text"
10905
10906 and string_of_rng_list xs =
10907   String.concat ", " (List.map string_of_rng xs)
10908
10909 let rec parse_rng ?defines context = function
10910   | [] -> []
10911   | Xml.Element ("element", ["name", name], children) :: rest ->
10912       Element (name, parse_rng ?defines context children)
10913       :: parse_rng ?defines context rest
10914   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10915       Attribute (name, parse_rng ?defines context children)
10916       :: parse_rng ?defines context rest
10917   | Xml.Element ("interleave", [], children) :: rest ->
10918       Interleave (parse_rng ?defines context children)
10919       :: parse_rng ?defines context rest
10920   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10921       let rng = parse_rng ?defines context [child] in
10922       (match rng with
10923        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10924        | _ ->
10925            failwithf "%s: <zeroOrMore> contains more than one child element"
10926              context
10927       )
10928   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10929       let rng = parse_rng ?defines context [child] in
10930       (match rng with
10931        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10932        | _ ->
10933            failwithf "%s: <oneOrMore> contains more than one child element"
10934              context
10935       )
10936   | Xml.Element ("optional", [], [child]) :: rest ->
10937       let rng = parse_rng ?defines context [child] in
10938       (match rng with
10939        | [child] -> Optional child :: parse_rng ?defines context rest
10940        | _ ->
10941            failwithf "%s: <optional> contains more than one child element"
10942              context
10943       )
10944   | Xml.Element ("choice", [], children) :: rest ->
10945       let values = List.map (
10946         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10947         | _ ->
10948             failwithf "%s: can't handle anything except <value> in <choice>"
10949               context
10950       ) children in
10951       Choice values
10952       :: parse_rng ?defines context rest
10953   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10954       Value value :: parse_rng ?defines context rest
10955   | Xml.Element ("text", [], []) :: rest ->
10956       Text :: parse_rng ?defines context rest
10957   | Xml.Element ("ref", ["name", name], []) :: rest ->
10958       (* Look up the reference.  Because of limitations in this parser,
10959        * we can't handle arbitrarily nested <ref> yet.  You can only
10960        * use <ref> from inside <start>.
10961        *)
10962       (match defines with
10963        | None ->
10964            failwithf "%s: contains <ref>, but no refs are defined yet" context
10965        | Some map ->
10966            let rng = StringMap.find name map in
10967            rng @ parse_rng ?defines context rest
10968       )
10969   | x :: _ ->
10970       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10971
10972 let grammar =
10973   let xml = Xml.parse_file rng_input in
10974   match xml with
10975   | Xml.Element ("grammar", _,
10976                  Xml.Element ("start", _, gram) :: defines) ->
10977       (* The <define/> elements are referenced in the <start> section,
10978        * so build a map of those first.
10979        *)
10980       let defines = List.fold_left (
10981         fun map ->
10982           function Xml.Element ("define", ["name", name], defn) ->
10983             StringMap.add name defn map
10984           | _ ->
10985               failwithf "%s: expected <define name=name/>" rng_input
10986       ) StringMap.empty defines in
10987       let defines = StringMap.mapi parse_rng defines in
10988
10989       (* Parse the <start> clause, passing the defines. *)
10990       parse_rng ~defines "<start>" gram
10991   | _ ->
10992       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10993         rng_input
10994
10995 let name_of_field = function
10996   | Element (name, _) | Attribute (name, _)
10997   | ZeroOrMore (Element (name, _))
10998   | OneOrMore (Element (name, _))
10999   | Optional (Element (name, _)) -> name
11000   | Optional (Attribute (name, _)) -> name
11001   | Text -> (* an unnamed field in an element *)
11002       "data"
11003   | rng ->
11004       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11005
11006 (* At the moment this function only generates OCaml types.  However we
11007  * should parameterize it later so it can generate types/structs in a
11008  * variety of languages.
11009  *)
11010 let generate_types xs =
11011   (* A simple type is one that can be printed out directly, eg.
11012    * "string option".  A complex type is one which has a name and has
11013    * to be defined via another toplevel definition, eg. a struct.
11014    *
11015    * generate_type generates code for either simple or complex types.
11016    * In the simple case, it returns the string ("string option").  In
11017    * the complex case, it returns the name ("mountpoint").  In the
11018    * complex case it has to print out the definition before returning,
11019    * so it should only be called when we are at the beginning of a
11020    * new line (BOL context).
11021    *)
11022   let rec generate_type = function
11023     | Text ->                                (* string *)
11024         "string", true
11025     | Choice values ->                        (* [`val1|`val2|...] *)
11026         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11027     | ZeroOrMore rng ->                        (* <rng> list *)
11028         let t, is_simple = generate_type rng in
11029         t ^ " list (* 0 or more *)", is_simple
11030     | OneOrMore rng ->                        (* <rng> list *)
11031         let t, is_simple = generate_type rng in
11032         t ^ " list (* 1 or more *)", is_simple
11033                                         (* virt-inspector hack: bool *)
11034     | Optional (Attribute (name, [Value "1"])) ->
11035         "bool", true
11036     | Optional rng ->                        (* <rng> list *)
11037         let t, is_simple = generate_type rng in
11038         t ^ " option", is_simple
11039                                         (* type name = { fields ... } *)
11040     | Element (name, fields) when is_attrs_interleave fields ->
11041         generate_type_struct name (get_attrs_interleave fields)
11042     | Element (name, [field])                (* type name = field *)
11043     | Attribute (name, [field]) ->
11044         let t, is_simple = generate_type field in
11045         if is_simple then (t, true)
11046         else (
11047           pr "type %s = %s\n" name t;
11048           name, false
11049         )
11050     | Element (name, fields) ->              (* type name = { fields ... } *)
11051         generate_type_struct name fields
11052     | rng ->
11053         failwithf "generate_type failed at: %s" (string_of_rng rng)
11054
11055   and is_attrs_interleave = function
11056     | [Interleave _] -> true
11057     | Attribute _ :: fields -> is_attrs_interleave fields
11058     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11059     | _ -> false
11060
11061   and get_attrs_interleave = function
11062     | [Interleave fields] -> fields
11063     | ((Attribute _) as field) :: fields
11064     | ((Optional (Attribute _)) as field) :: fields ->
11065         field :: get_attrs_interleave fields
11066     | _ -> assert false
11067
11068   and generate_types xs =
11069     List.iter (fun x -> ignore (generate_type x)) xs
11070
11071   and generate_type_struct name fields =
11072     (* Calculate the types of the fields first.  We have to do this
11073      * before printing anything so we are still in BOL context.
11074      *)
11075     let types = List.map fst (List.map generate_type fields) in
11076
11077     (* Special case of a struct containing just a string and another
11078      * field.  Turn it into an assoc list.
11079      *)
11080     match types with
11081     | ["string"; other] ->
11082         let fname1, fname2 =
11083           match fields with
11084           | [f1; f2] -> name_of_field f1, name_of_field f2
11085           | _ -> assert false in
11086         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11087         name, false
11088
11089     | types ->
11090         pr "type %s = {\n" name;
11091         List.iter (
11092           fun (field, ftype) ->
11093             let fname = name_of_field field in
11094             pr "  %s_%s : %s;\n" name fname ftype
11095         ) (List.combine fields types);
11096         pr "}\n";
11097         (* Return the name of this type, and
11098          * false because it's not a simple type.
11099          *)
11100         name, false
11101   in
11102
11103   generate_types xs
11104
11105 let generate_parsers xs =
11106   (* As for generate_type above, generate_parser makes a parser for
11107    * some type, and returns the name of the parser it has generated.
11108    * Because it (may) need to print something, it should always be
11109    * called in BOL context.
11110    *)
11111   let rec generate_parser = function
11112     | Text ->                                (* string *)
11113         "string_child_or_empty"
11114     | Choice values ->                        (* [`val1|`val2|...] *)
11115         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11116           (String.concat "|"
11117              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11118     | ZeroOrMore rng ->                        (* <rng> list *)
11119         let pa = generate_parser rng in
11120         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11121     | OneOrMore rng ->                        (* <rng> list *)
11122         let pa = generate_parser rng in
11123         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11124                                         (* virt-inspector hack: bool *)
11125     | Optional (Attribute (name, [Value "1"])) ->
11126         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11127     | Optional rng ->                        (* <rng> list *)
11128         let pa = generate_parser rng in
11129         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11130                                         (* type name = { fields ... } *)
11131     | Element (name, fields) when is_attrs_interleave fields ->
11132         generate_parser_struct name (get_attrs_interleave fields)
11133     | Element (name, [field]) ->        (* type name = field *)
11134         let pa = generate_parser field in
11135         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11136         pr "let %s =\n" parser_name;
11137         pr "  %s\n" pa;
11138         pr "let parse_%s = %s\n" name parser_name;
11139         parser_name
11140     | Attribute (name, [field]) ->
11141         let pa = generate_parser field in
11142         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11143         pr "let %s =\n" parser_name;
11144         pr "  %s\n" pa;
11145         pr "let parse_%s = %s\n" name parser_name;
11146         parser_name
11147     | Element (name, fields) ->              (* type name = { fields ... } *)
11148         generate_parser_struct name ([], fields)
11149     | rng ->
11150         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11151
11152   and is_attrs_interleave = function
11153     | [Interleave _] -> true
11154     | Attribute _ :: fields -> is_attrs_interleave fields
11155     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11156     | _ -> false
11157
11158   and get_attrs_interleave = function
11159     | [Interleave fields] -> [], fields
11160     | ((Attribute _) as field) :: fields
11161     | ((Optional (Attribute _)) as field) :: fields ->
11162         let attrs, interleaves = get_attrs_interleave fields in
11163         (field :: attrs), interleaves
11164     | _ -> assert false
11165
11166   and generate_parsers xs =
11167     List.iter (fun x -> ignore (generate_parser x)) xs
11168
11169   and generate_parser_struct name (attrs, interleaves) =
11170     (* Generate parsers for the fields first.  We have to do this
11171      * before printing anything so we are still in BOL context.
11172      *)
11173     let fields = attrs @ interleaves in
11174     let pas = List.map generate_parser fields in
11175
11176     (* Generate an intermediate tuple from all the fields first.
11177      * If the type is just a string + another field, then we will
11178      * return this directly, otherwise it is turned into a record.
11179      *
11180      * RELAX NG note: This code treats <interleave> and plain lists of
11181      * fields the same.  In other words, it doesn't bother enforcing
11182      * any ordering of fields in the XML.
11183      *)
11184     pr "let parse_%s x =\n" name;
11185     pr "  let t = (\n    ";
11186     let comma = ref false in
11187     List.iter (
11188       fun x ->
11189         if !comma then pr ",\n    ";
11190         comma := true;
11191         match x with
11192         | Optional (Attribute (fname, [field])), pa ->
11193             pr "%s x" pa
11194         | Optional (Element (fname, [field])), pa ->
11195             pr "%s (optional_child %S x)" pa fname
11196         | Attribute (fname, [Text]), _ ->
11197             pr "attribute %S x" fname
11198         | (ZeroOrMore _ | OneOrMore _), pa ->
11199             pr "%s x" pa
11200         | Text, pa ->
11201             pr "%s x" pa
11202         | (field, pa) ->
11203             let fname = name_of_field field in
11204             pr "%s (child %S x)" pa fname
11205     ) (List.combine fields pas);
11206     pr "\n  ) in\n";
11207
11208     (match fields with
11209      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11210          pr "  t\n"
11211
11212      | _ ->
11213          pr "  (Obj.magic t : %s)\n" name
11214 (*
11215          List.iter (
11216            function
11217            | (Optional (Attribute (fname, [field])), pa) ->
11218                pr "  %s_%s =\n" name fname;
11219                pr "    %s x;\n" pa
11220            | (Optional (Element (fname, [field])), pa) ->
11221                pr "  %s_%s =\n" name fname;
11222                pr "    (let x = optional_child %S x in\n" fname;
11223                pr "     %s x);\n" pa
11224            | (field, pa) ->
11225                let fname = name_of_field field in
11226                pr "  %s_%s =\n" name fname;
11227                pr "    (let x = child %S x in\n" fname;
11228                pr "     %s x);\n" pa
11229          ) (List.combine fields pas);
11230          pr "}\n"
11231 *)
11232     );
11233     sprintf "parse_%s" name
11234   in
11235
11236   generate_parsers xs
11237
11238 (* Generate ocaml/guestfs_inspector.mli. *)
11239 let generate_ocaml_inspector_mli () =
11240   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11241
11242   pr "\
11243 (** This is an OCaml language binding to the external [virt-inspector]
11244     program.
11245
11246     For more information, please read the man page [virt-inspector(1)].
11247 *)
11248
11249 ";
11250
11251   generate_types grammar;
11252   pr "(** The nested information returned from the {!inspect} function. *)\n";
11253   pr "\n";
11254
11255   pr "\
11256 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11257 (** To inspect a libvirt domain called [name], pass a singleton
11258     list: [inspect [name]].  When using libvirt only, you may
11259     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11260
11261     To inspect a disk image or images, pass a list of the filenames
11262     of the disk images: [inspect filenames]
11263
11264     This function inspects the given guest or disk images and
11265     returns a list of operating system(s) found and a large amount
11266     of information about them.  In the vast majority of cases,
11267     a virtual machine only contains a single operating system.
11268
11269     If the optional [~xml] parameter is given, then this function
11270     skips running the external virt-inspector program and just
11271     parses the given XML directly (which is expected to be XML
11272     produced from a previous run of virt-inspector).  The list of
11273     names and connect URI are ignored in this case.
11274
11275     This function can throw a wide variety of exceptions, for example
11276     if the external virt-inspector program cannot be found, or if
11277     it doesn't generate valid XML.
11278 *)
11279 "
11280
11281 (* Generate ocaml/guestfs_inspector.ml. *)
11282 let generate_ocaml_inspector_ml () =
11283   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11284
11285   pr "open Unix\n";
11286   pr "\n";
11287
11288   generate_types grammar;
11289   pr "\n";
11290
11291   pr "\
11292 (* Misc functions which are used by the parser code below. *)
11293 let first_child = function
11294   | Xml.Element (_, _, c::_) -> c
11295   | Xml.Element (name, _, []) ->
11296       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11297   | Xml.PCData str ->
11298       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11299
11300 let string_child_or_empty = function
11301   | Xml.Element (_, _, [Xml.PCData s]) -> s
11302   | Xml.Element (_, _, []) -> \"\"
11303   | Xml.Element (x, _, _) ->
11304       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11305                 x ^ \" instead\")
11306   | Xml.PCData str ->
11307       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11308
11309 let optional_child name xml =
11310   let children = Xml.children xml in
11311   try
11312     Some (List.find (function
11313                      | Xml.Element (n, _, _) when n = name -> true
11314                      | _ -> false) children)
11315   with
11316     Not_found -> None
11317
11318 let child name xml =
11319   match optional_child name xml with
11320   | Some c -> c
11321   | None ->
11322       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11323
11324 let attribute name xml =
11325   try Xml.attrib xml name
11326   with Xml.No_attribute _ ->
11327     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11328
11329 ";
11330
11331   generate_parsers grammar;
11332   pr "\n";
11333
11334   pr "\
11335 (* Run external virt-inspector, then use parser to parse the XML. *)
11336 let inspect ?connect ?xml names =
11337   let xml =
11338     match xml with
11339     | None ->
11340         if names = [] then invalid_arg \"inspect: no names given\";
11341         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11342           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11343           names in
11344         let cmd = List.map Filename.quote cmd in
11345         let cmd = String.concat \" \" cmd in
11346         let chan = open_process_in cmd in
11347         let xml = Xml.parse_in chan in
11348         (match close_process_in chan with
11349          | WEXITED 0 -> ()
11350          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11351          | WSIGNALED i | WSTOPPED i ->
11352              failwith (\"external virt-inspector command died or stopped on sig \" ^
11353                        string_of_int i)
11354         );
11355         xml
11356     | Some doc ->
11357         Xml.parse_string doc in
11358   parse_operatingsystems xml
11359 "
11360
11361 (* This is used to generate the src/MAX_PROC_NR file which
11362  * contains the maximum procedure number, a surrogate for the
11363  * ABI version number.  See src/Makefile.am for the details.
11364  *)
11365 and generate_max_proc_nr () =
11366   let proc_nrs = List.map (
11367     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11368   ) daemon_functions in
11369
11370   let max_proc_nr = List.fold_left max 0 proc_nrs in
11371
11372   pr "%d\n" max_proc_nr
11373
11374 let output_to filename k =
11375   let filename_new = filename ^ ".new" in
11376   chan := open_out filename_new;
11377   k ();
11378   close_out !chan;
11379   chan := Pervasives.stdout;
11380
11381   (* Is the new file different from the current file? *)
11382   if Sys.file_exists filename && files_equal filename filename_new then
11383     unlink filename_new                 (* same, so skip it *)
11384   else (
11385     (* different, overwrite old one *)
11386     (try chmod filename 0o644 with Unix_error _ -> ());
11387     rename filename_new filename;
11388     chmod filename 0o444;
11389     printf "written %s\n%!" filename;
11390   )
11391
11392 let perror msg = function
11393   | Unix_error (err, _, _) ->
11394       eprintf "%s: %s\n" msg (error_message err)
11395   | exn ->
11396       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11397
11398 (* Main program. *)
11399 let () =
11400   let lock_fd =
11401     try openfile "HACKING" [O_RDWR] 0
11402     with
11403     | Unix_error (ENOENT, _, _) ->
11404         eprintf "\
11405 You are probably running this from the wrong directory.
11406 Run it from the top source directory using the command
11407   src/generator.ml
11408 ";
11409         exit 1
11410     | exn ->
11411         perror "open: HACKING" exn;
11412         exit 1 in
11413
11414   (* Acquire a lock so parallel builds won't try to run the generator
11415    * twice at the same time.  Subsequent builds will wait for the first
11416    * one to finish.  Note the lock is released implicitly when the
11417    * program exits.
11418    *)
11419   (try lockf lock_fd F_LOCK 1
11420    with exn ->
11421      perror "lock: HACKING" exn;
11422      exit 1);
11423
11424   check_functions ();
11425
11426   output_to "src/guestfs_protocol.x" generate_xdr;
11427   output_to "src/guestfs-structs.h" generate_structs_h;
11428   output_to "src/guestfs-actions.h" generate_actions_h;
11429   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11430   output_to "src/guestfs-actions.c" generate_client_actions;
11431   output_to "src/guestfs-bindtests.c" generate_bindtests;
11432   output_to "src/guestfs-structs.pod" generate_structs_pod;
11433   output_to "src/guestfs-actions.pod" generate_actions_pod;
11434   output_to "src/guestfs-availability.pod" generate_availability_pod;
11435   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11436   output_to "src/libguestfs.syms" generate_linker_script;
11437   output_to "daemon/actions.h" generate_daemon_actions_h;
11438   output_to "daemon/stubs.c" generate_daemon_actions;
11439   output_to "daemon/names.c" generate_daemon_names;
11440   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11441   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11442   output_to "capitests/tests.c" generate_tests;
11443   output_to "fish/cmds.c" generate_fish_cmds;
11444   output_to "fish/completion.c" generate_fish_completion;
11445   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11446   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11447   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11448   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11449   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11450   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11451   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11452   output_to "perl/Guestfs.xs" generate_perl_xs;
11453   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11454   output_to "perl/bindtests.pl" generate_perl_bindtests;
11455   output_to "python/guestfs-py.c" generate_python_c;
11456   output_to "python/guestfs.py" generate_python_py;
11457   output_to "python/bindtests.py" generate_python_bindtests;
11458   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11459   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11460   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11461
11462   List.iter (
11463     fun (typ, jtyp) ->
11464       let cols = cols_of_struct typ in
11465       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11466       output_to filename (generate_java_struct jtyp cols);
11467   ) java_structs;
11468
11469   output_to "java/Makefile.inc" generate_java_makefile_inc;
11470   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11471   output_to "java/Bindtests.java" generate_java_bindtests;
11472   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11473   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11474   output_to "csharp/Libguestfs.cs" generate_csharp;
11475
11476   (* Always generate this file last, and unconditionally.  It's used
11477    * by the Makefile to know when we must re-run the generator.
11478    *)
11479   let chan = open_out "src/stamp-generator" in
11480   fprintf chan "1\n";
11481   close_out chan;
11482
11483   printf "generated %d lines of code\n" !lines