Mac OS X: include <string.h> in guestfs-actions.c
[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
2030   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2031    [],
2032    "pack directory into tarfile",
2033    "\
2034 This command packs the contents of C<directory> and downloads
2035 it to local file C<tarfile>.
2036
2037 To download a compressed tarball, use C<guestfs_tgz_out>.");
2038
2039   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2040    [InitBasicFS, Always, TestOutput (
2041       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2042        ["cat"; "/hello"]], "hello\n")],
2043    "unpack compressed tarball to directory",
2044    "\
2045 This command uploads and unpacks local file C<tarball> (a
2046 I<gzip compressed> tar file) into C<directory>.
2047
2048 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2049
2050   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2051    [],
2052    "pack directory into compressed tarball",
2053    "\
2054 This command packs the contents of C<directory> and downloads
2055 it to local file C<tarball>.
2056
2057 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2058
2059   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2060    [InitBasicFS, Always, TestLastFail (
2061       [["umount"; "/"];
2062        ["mount_ro"; "/dev/sda1"; "/"];
2063        ["touch"; "/new"]]);
2064     InitBasicFS, Always, TestOutput (
2065       [["write_file"; "/new"; "data"; "0"];
2066        ["umount"; "/"];
2067        ["mount_ro"; "/dev/sda1"; "/"];
2068        ["cat"; "/new"]], "data")],
2069    "mount a guest disk, read-only",
2070    "\
2071 This is the same as the C<guestfs_mount> command, but it
2072 mounts the filesystem with the read-only (I<-o ro>) flag.");
2073
2074   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2075    [],
2076    "mount a guest disk with mount options",
2077    "\
2078 This is the same as the C<guestfs_mount> command, but it
2079 allows you to set the mount options as for the
2080 L<mount(8)> I<-o> flag.");
2081
2082   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2083    [],
2084    "mount a guest disk with mount options and vfstype",
2085    "\
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set both the mount options and the vfstype
2088 as for the L<mount(8)> I<-o> and I<-t> flags.");
2089
2090   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2091    [],
2092    "debugging and internals",
2093    "\
2094 The C<guestfs_debug> command exposes some internals of
2095 C<guestfsd> (the guestfs daemon) that runs inside the
2096 qemu subprocess.
2097
2098 There is no comprehensive help for this command.  You have
2099 to look at the file C<daemon/debug.c> in the libguestfs source
2100 to find out what you can do.");
2101
2102   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2103    [InitEmpty, Always, TestOutputList (
2104       [["part_disk"; "/dev/sda"; "mbr"];
2105        ["pvcreate"; "/dev/sda1"];
2106        ["vgcreate"; "VG"; "/dev/sda1"];
2107        ["lvcreate"; "LV1"; "VG"; "50"];
2108        ["lvcreate"; "LV2"; "VG"; "50"];
2109        ["lvremove"; "/dev/VG/LV1"];
2110        ["lvs"]], ["/dev/VG/LV2"]);
2111     InitEmpty, Always, TestOutputList (
2112       [["part_disk"; "/dev/sda"; "mbr"];
2113        ["pvcreate"; "/dev/sda1"];
2114        ["vgcreate"; "VG"; "/dev/sda1"];
2115        ["lvcreate"; "LV1"; "VG"; "50"];
2116        ["lvcreate"; "LV2"; "VG"; "50"];
2117        ["lvremove"; "/dev/VG"];
2118        ["lvs"]], []);
2119     InitEmpty, Always, TestOutputList (
2120       [["part_disk"; "/dev/sda"; "mbr"];
2121        ["pvcreate"; "/dev/sda1"];
2122        ["vgcreate"; "VG"; "/dev/sda1"];
2123        ["lvcreate"; "LV1"; "VG"; "50"];
2124        ["lvcreate"; "LV2"; "VG"; "50"];
2125        ["lvremove"; "/dev/VG"];
2126        ["vgs"]], ["VG"])],
2127    "remove an LVM logical volume",
2128    "\
2129 Remove an LVM logical volume C<device>, where C<device> is
2130 the path to the LV, such as C</dev/VG/LV>.
2131
2132 You can also remove all LVs in a volume group by specifying
2133 the VG name, C</dev/VG>.");
2134
2135   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2136    [InitEmpty, Always, TestOutputList (
2137       [["part_disk"; "/dev/sda"; "mbr"];
2138        ["pvcreate"; "/dev/sda1"];
2139        ["vgcreate"; "VG"; "/dev/sda1"];
2140        ["lvcreate"; "LV1"; "VG"; "50"];
2141        ["lvcreate"; "LV2"; "VG"; "50"];
2142        ["vgremove"; "VG"];
2143        ["lvs"]], []);
2144     InitEmpty, Always, TestOutputList (
2145       [["part_disk"; "/dev/sda"; "mbr"];
2146        ["pvcreate"; "/dev/sda1"];
2147        ["vgcreate"; "VG"; "/dev/sda1"];
2148        ["lvcreate"; "LV1"; "VG"; "50"];
2149        ["lvcreate"; "LV2"; "VG"; "50"];
2150        ["vgremove"; "VG"];
2151        ["vgs"]], [])],
2152    "remove an LVM volume group",
2153    "\
2154 Remove an LVM volume group C<vgname>, (for example C<VG>).
2155
2156 This also forcibly removes all logical volumes in the volume
2157 group (if any).");
2158
2159   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2160    [InitEmpty, Always, TestOutputListOfDevices (
2161       [["part_disk"; "/dev/sda"; "mbr"];
2162        ["pvcreate"; "/dev/sda1"];
2163        ["vgcreate"; "VG"; "/dev/sda1"];
2164        ["lvcreate"; "LV1"; "VG"; "50"];
2165        ["lvcreate"; "LV2"; "VG"; "50"];
2166        ["vgremove"; "VG"];
2167        ["pvremove"; "/dev/sda1"];
2168        ["lvs"]], []);
2169     InitEmpty, Always, TestOutputListOfDevices (
2170       [["part_disk"; "/dev/sda"; "mbr"];
2171        ["pvcreate"; "/dev/sda1"];
2172        ["vgcreate"; "VG"; "/dev/sda1"];
2173        ["lvcreate"; "LV1"; "VG"; "50"];
2174        ["lvcreate"; "LV2"; "VG"; "50"];
2175        ["vgremove"; "VG"];
2176        ["pvremove"; "/dev/sda1"];
2177        ["vgs"]], []);
2178     InitEmpty, Always, TestOutputListOfDevices (
2179       [["part_disk"; "/dev/sda"; "mbr"];
2180        ["pvcreate"; "/dev/sda1"];
2181        ["vgcreate"; "VG"; "/dev/sda1"];
2182        ["lvcreate"; "LV1"; "VG"; "50"];
2183        ["lvcreate"; "LV2"; "VG"; "50"];
2184        ["vgremove"; "VG"];
2185        ["pvremove"; "/dev/sda1"];
2186        ["pvs"]], [])],
2187    "remove an LVM physical volume",
2188    "\
2189 This wipes a physical volume C<device> so that LVM will no longer
2190 recognise it.
2191
2192 The implementation uses the C<pvremove> command which refuses to
2193 wipe physical volumes that contain any volume groups, so you have
2194 to remove those first.");
2195
2196   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2197    [InitBasicFS, Always, TestOutput (
2198       [["set_e2label"; "/dev/sda1"; "testlabel"];
2199        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2200    "set the ext2/3/4 filesystem label",
2201    "\
2202 This sets the ext2/3/4 filesystem label of the filesystem on
2203 C<device> to C<label>.  Filesystem labels are limited to
2204 16 characters.
2205
2206 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2207 to return the existing label on a filesystem.");
2208
2209   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2210    [],
2211    "get the ext2/3/4 filesystem label",
2212    "\
2213 This returns the ext2/3/4 filesystem label of the filesystem on
2214 C<device>.");
2215
2216   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2217    (let uuid = uuidgen () in
2218     [InitBasicFS, Always, TestOutput (
2219        [["set_e2uuid"; "/dev/sda1"; uuid];
2220         ["get_e2uuid"; "/dev/sda1"]], uuid);
2221      InitBasicFS, Always, TestOutput (
2222        [["set_e2uuid"; "/dev/sda1"; "clear"];
2223         ["get_e2uuid"; "/dev/sda1"]], "");
2224      (* We can't predict what UUIDs will be, so just check the commands run. *)
2225      InitBasicFS, Always, TestRun (
2226        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2229    "set the ext2/3/4 filesystem UUID",
2230    "\
2231 This sets the ext2/3/4 filesystem UUID of the filesystem on
2232 C<device> to C<uuid>.  The format of the UUID and alternatives
2233 such as C<clear>, C<random> and C<time> are described in the
2234 L<tune2fs(8)> manpage.
2235
2236 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2237 to return the existing UUID of a filesystem.");
2238
2239   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2240    [],
2241    "get the ext2/3/4 filesystem UUID",
2242    "\
2243 This returns the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device>.");
2245
2246   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2247    [InitBasicFS, Always, TestOutputInt (
2248       [["umount"; "/dev/sda1"];
2249        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2250     InitBasicFS, Always, TestOutputInt (
2251       [["umount"; "/dev/sda1"];
2252        ["zero"; "/dev/sda1"];
2253        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2254    "run the filesystem checker",
2255    "\
2256 This runs the filesystem checker (fsck) on C<device> which
2257 should have filesystem type C<fstype>.
2258
2259 The returned integer is the status.  See L<fsck(8)> for the
2260 list of status codes from C<fsck>.
2261
2262 Notes:
2263
2264 =over 4
2265
2266 =item *
2267
2268 Multiple status codes can be summed together.
2269
2270 =item *
2271
2272 A non-zero return code can mean \"success\", for example if
2273 errors have been corrected on the filesystem.
2274
2275 =item *
2276
2277 Checking or repairing NTFS volumes is not supported
2278 (by linux-ntfs).
2279
2280 =back
2281
2282 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2283
2284   ("zero", (RErr, [Device "device"]), 85, [],
2285    [InitBasicFS, Always, TestOutput (
2286       [["umount"; "/dev/sda1"];
2287        ["zero"; "/dev/sda1"];
2288        ["file"; "/dev/sda1"]], "data")],
2289    "write zeroes to the device",
2290    "\
2291 This command writes zeroes over the first few blocks of C<device>.
2292
2293 How many blocks are zeroed isn't specified (but it's I<not> enough
2294 to securely wipe the device).  It should be sufficient to remove
2295 any partition tables, filesystem superblocks and so on.
2296
2297 See also: C<guestfs_scrub_device>.");
2298
2299   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2300    (* Test disabled because grub-install incompatible with virtio-blk driver.
2301     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2302     *)
2303    [InitBasicFS, Disabled, TestOutputTrue (
2304       [["grub_install"; "/"; "/dev/sda1"];
2305        ["is_dir"; "/boot"]])],
2306    "install GRUB",
2307    "\
2308 This command installs GRUB (the Grand Unified Bootloader) on
2309 C<device>, with the root directory being C<root>.");
2310
2311   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2312    [InitBasicFS, Always, TestOutput (
2313       [["write_file"; "/old"; "file content"; "0"];
2314        ["cp"; "/old"; "/new"];
2315        ["cat"; "/new"]], "file content");
2316     InitBasicFS, Always, TestOutputTrue (
2317       [["write_file"; "/old"; "file content"; "0"];
2318        ["cp"; "/old"; "/new"];
2319        ["is_file"; "/old"]]);
2320     InitBasicFS, Always, TestOutput (
2321       [["write_file"; "/old"; "file content"; "0"];
2322        ["mkdir"; "/dir"];
2323        ["cp"; "/old"; "/dir/new"];
2324        ["cat"; "/dir/new"]], "file content")],
2325    "copy a file",
2326    "\
2327 This copies a file from C<src> to C<dest> where C<dest> is
2328 either a destination filename or destination directory.");
2329
2330   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2331    [InitBasicFS, Always, TestOutput (
2332       [["mkdir"; "/olddir"];
2333        ["mkdir"; "/newdir"];
2334        ["write_file"; "/olddir/file"; "file content"; "0"];
2335        ["cp_a"; "/olddir"; "/newdir"];
2336        ["cat"; "/newdir/olddir/file"]], "file content")],
2337    "copy a file or directory recursively",
2338    "\
2339 This copies a file or directory from C<src> to C<dest>
2340 recursively using the C<cp -a> command.");
2341
2342   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["write_file"; "/old"; "file content"; "0"];
2345        ["mv"; "/old"; "/new"];
2346        ["cat"; "/new"]], "file content");
2347     InitBasicFS, Always, TestOutputFalse (
2348       [["write_file"; "/old"; "file content"; "0"];
2349        ["mv"; "/old"; "/new"];
2350        ["is_file"; "/old"]])],
2351    "move a file",
2352    "\
2353 This moves a file from C<src> to C<dest> where C<dest> is
2354 either a destination filename or destination directory.");
2355
2356   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2357    [InitEmpty, Always, TestRun (
2358       [["drop_caches"; "3"]])],
2359    "drop kernel page cache, dentries and inodes",
2360    "\
2361 This instructs the guest kernel to drop its page cache,
2362 and/or dentries and inode caches.  The parameter C<whattodrop>
2363 tells the kernel what precisely to drop, see
2364 L<http://linux-mm.org/Drop_Caches>
2365
2366 Setting C<whattodrop> to 3 should drop everything.
2367
2368 This automatically calls L<sync(2)> before the operation,
2369 so that the maximum guest memory is freed.");
2370
2371   ("dmesg", (RString "kmsgs", []), 91, [],
2372    [InitEmpty, Always, TestRun (
2373       [["dmesg"]])],
2374    "return kernel messages",
2375    "\
2376 This returns the kernel messages (C<dmesg> output) from
2377 the guest kernel.  This is sometimes useful for extended
2378 debugging of problems.
2379
2380 Another way to get the same information is to enable
2381 verbose messages with C<guestfs_set_verbose> or by setting
2382 the environment variable C<LIBGUESTFS_DEBUG=1> before
2383 running the program.");
2384
2385   ("ping_daemon", (RErr, []), 92, [],
2386    [InitEmpty, Always, TestRun (
2387       [["ping_daemon"]])],
2388    "ping the guest daemon",
2389    "\
2390 This is a test probe into the guestfs daemon running inside
2391 the qemu subprocess.  Calling this function checks that the
2392 daemon responds to the ping message, without affecting the daemon
2393 or attached block device(s) in any other way.");
2394
2395   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2396    [InitBasicFS, Always, TestOutputTrue (
2397       [["write_file"; "/file1"; "contents of a file"; "0"];
2398        ["cp"; "/file1"; "/file2"];
2399        ["equal"; "/file1"; "/file2"]]);
2400     InitBasicFS, Always, TestOutputFalse (
2401       [["write_file"; "/file1"; "contents of a file"; "0"];
2402        ["write_file"; "/file2"; "contents of another file"; "0"];
2403        ["equal"; "/file1"; "/file2"]]);
2404     InitBasicFS, Always, TestLastFail (
2405       [["equal"; "/file1"; "/file2"]])],
2406    "test if two files have equal contents",
2407    "\
2408 This compares the two files C<file1> and C<file2> and returns
2409 true if their content is exactly equal, or false otherwise.
2410
2411 The external L<cmp(1)> program is used for the comparison.");
2412
2413   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2414    [InitISOFS, Always, TestOutputList (
2415       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2416     InitISOFS, Always, TestOutputList (
2417       [["strings"; "/empty"]], [])],
2418    "print the printable strings in a file",
2419    "\
2420 This runs the L<strings(1)> command on a file and returns
2421 the list of printable strings found.");
2422
2423   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2424    [InitISOFS, Always, TestOutputList (
2425       [["strings_e"; "b"; "/known-5"]], []);
2426     InitBasicFS, Disabled, TestOutputList (
2427       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2428        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2429    "print the printable strings in a file",
2430    "\
2431 This is like the C<guestfs_strings> command, but allows you to
2432 specify the encoding.
2433
2434 See the L<strings(1)> manpage for the full list of encodings.
2435
2436 Commonly useful encodings are C<l> (lower case L) which will
2437 show strings inside Windows/x86 files.
2438
2439 The returned strings are transcoded to UTF-8.");
2440
2441   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2442    [InitISOFS, Always, TestOutput (
2443       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2444     (* Test for RHBZ#501888c2 regression which caused large hexdump
2445      * commands to segfault.
2446      *)
2447     InitISOFS, Always, TestRun (
2448       [["hexdump"; "/100krandom"]])],
2449    "dump a file in hexadecimal",
2450    "\
2451 This runs C<hexdump -C> on the given C<path>.  The result is
2452 the human-readable, canonical hex dump of the file.");
2453
2454   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2455    [InitNone, Always, TestOutput (
2456       [["part_disk"; "/dev/sda"; "mbr"];
2457        ["mkfs"; "ext3"; "/dev/sda1"];
2458        ["mount_options"; ""; "/dev/sda1"; "/"];
2459        ["write_file"; "/new"; "test file"; "0"];
2460        ["umount"; "/dev/sda1"];
2461        ["zerofree"; "/dev/sda1"];
2462        ["mount_options"; ""; "/dev/sda1"; "/"];
2463        ["cat"; "/new"]], "test file")],
2464    "zero unused inodes and disk blocks on ext2/3 filesystem",
2465    "\
2466 This runs the I<zerofree> program on C<device>.  This program
2467 claims to zero unused inodes and disk blocks on an ext2/3
2468 filesystem, thus making it possible to compress the filesystem
2469 more effectively.
2470
2471 You should B<not> run this program if the filesystem is
2472 mounted.
2473
2474 It is possible that using this program can damage the filesystem
2475 or data on the filesystem.");
2476
2477   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2478    [],
2479    "resize an LVM physical volume",
2480    "\
2481 This resizes (expands or shrinks) an existing LVM physical
2482 volume to match the new size of the underlying device.");
2483
2484   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2485                        Int "cyls"; Int "heads"; Int "sectors";
2486                        String "line"]), 99, [DangerWillRobinson],
2487    [],
2488    "modify a single partition on a block device",
2489    "\
2490 This runs L<sfdisk(8)> option to modify just the single
2491 partition C<n> (note: C<n> counts from 1).
2492
2493 For other parameters, see C<guestfs_sfdisk>.  You should usually
2494 pass C<0> for the cyls/heads/sectors parameters.
2495
2496 See also: C<guestfs_part_add>");
2497
2498   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2499    [],
2500    "display the partition table",
2501    "\
2502 This displays the partition table on C<device>, in the
2503 human-readable output of the L<sfdisk(8)> command.  It is
2504 not intended to be parsed.
2505
2506 See also: C<guestfs_part_list>");
2507
2508   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2509    [],
2510    "display the kernel geometry",
2511    "\
2512 This displays the kernel's idea of the geometry of C<device>.
2513
2514 The result is in human-readable format, and not designed to
2515 be parsed.");
2516
2517   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2518    [],
2519    "display the disk geometry from the partition table",
2520    "\
2521 This displays the disk geometry of C<device> read from the
2522 partition table.  Especially in the case where the underlying
2523 block device has been resized, this can be different from the
2524 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2525
2526 The result is in human-readable format, and not designed to
2527 be parsed.");
2528
2529   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2530    [],
2531    "activate or deactivate all volume groups",
2532    "\
2533 This command activates or (if C<activate> is false) deactivates
2534 all logical volumes in all volume groups.
2535 If activated, then they are made known to the
2536 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2537 then those devices disappear.
2538
2539 This command is the same as running C<vgchange -a y|n>");
2540
2541   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2542    [],
2543    "activate or deactivate some volume groups",
2544    "\
2545 This command activates or (if C<activate> is false) deactivates
2546 all logical volumes in the listed volume groups C<volgroups>.
2547 If activated, then they are made known to the
2548 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2549 then those devices disappear.
2550
2551 This command is the same as running C<vgchange -a y|n volgroups...>
2552
2553 Note that if C<volgroups> is an empty list then B<all> volume groups
2554 are activated or deactivated.");
2555
2556   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2557    [InitNone, Always, TestOutput (
2558       [["part_disk"; "/dev/sda"; "mbr"];
2559        ["pvcreate"; "/dev/sda1"];
2560        ["vgcreate"; "VG"; "/dev/sda1"];
2561        ["lvcreate"; "LV"; "VG"; "10"];
2562        ["mkfs"; "ext2"; "/dev/VG/LV"];
2563        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2564        ["write_file"; "/new"; "test content"; "0"];
2565        ["umount"; "/"];
2566        ["lvresize"; "/dev/VG/LV"; "20"];
2567        ["e2fsck_f"; "/dev/VG/LV"];
2568        ["resize2fs"; "/dev/VG/LV"];
2569        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2570        ["cat"; "/new"]], "test content")],
2571    "resize an LVM logical volume",
2572    "\
2573 This resizes (expands or shrinks) an existing LVM logical
2574 volume to C<mbytes>.  When reducing, data in the reduced part
2575 is lost.");
2576
2577   ("resize2fs", (RErr, [Device "device"]), 106, [],
2578    [], (* lvresize tests this *)
2579    "resize an ext2/ext3 filesystem",
2580    "\
2581 This resizes an ext2 or ext3 filesystem to match the size of
2582 the underlying device.
2583
2584 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2585 on the C<device> before calling this command.  For unknown reasons
2586 C<resize2fs> sometimes gives an error about this and sometimes not.
2587 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2588 calling this function.");
2589
2590   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2591    [InitBasicFS, Always, TestOutputList (
2592       [["find"; "/"]], ["lost+found"]);
2593     InitBasicFS, Always, TestOutputList (
2594       [["touch"; "/a"];
2595        ["mkdir"; "/b"];
2596        ["touch"; "/b/c"];
2597        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2598     InitBasicFS, Always, TestOutputList (
2599       [["mkdir_p"; "/a/b/c"];
2600        ["touch"; "/a/b/c/d"];
2601        ["find"; "/a/b/"]], ["c"; "c/d"])],
2602    "find all files and directories",
2603    "\
2604 This command lists out all files and directories, recursively,
2605 starting at C<directory>.  It is essentially equivalent to
2606 running the shell command C<find directory -print> but some
2607 post-processing happens on the output, described below.
2608
2609 This returns a list of strings I<without any prefix>.  Thus
2610 if the directory structure was:
2611
2612  /tmp/a
2613  /tmp/b
2614  /tmp/c/d
2615
2616 then the returned list from C<guestfs_find> C</tmp> would be
2617 4 elements:
2618
2619  a
2620  b
2621  c
2622  c/d
2623
2624 If C<directory> is not a directory, then this command returns
2625 an error.
2626
2627 The returned list is sorted.
2628
2629 See also C<guestfs_find0>.");
2630
2631   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2632    [], (* lvresize tests this *)
2633    "check an ext2/ext3 filesystem",
2634    "\
2635 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2636 filesystem checker on C<device>, noninteractively (C<-p>),
2637 even if the filesystem appears to be clean (C<-f>).
2638
2639 This command is only needed because of C<guestfs_resize2fs>
2640 (q.v.).  Normally you should use C<guestfs_fsck>.");
2641
2642   ("sleep", (RErr, [Int "secs"]), 109, [],
2643    [InitNone, Always, TestRun (
2644       [["sleep"; "1"]])],
2645    "sleep for some seconds",
2646    "\
2647 Sleep for C<secs> seconds.");
2648
2649   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2650    [InitNone, Always, TestOutputInt (
2651       [["part_disk"; "/dev/sda"; "mbr"];
2652        ["mkfs"; "ntfs"; "/dev/sda1"];
2653        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2654     InitNone, Always, TestOutputInt (
2655       [["part_disk"; "/dev/sda"; "mbr"];
2656        ["mkfs"; "ext2"; "/dev/sda1"];
2657        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2658    "probe NTFS volume",
2659    "\
2660 This command runs the L<ntfs-3g.probe(8)> command which probes
2661 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2662 be mounted read-write, and some cannot be mounted at all).
2663
2664 C<rw> is a boolean flag.  Set it to true if you want to test
2665 if the volume can be mounted read-write.  Set it to false if
2666 you want to test if the volume can be mounted read-only.
2667
2668 The return value is an integer which C<0> if the operation
2669 would succeed, or some non-zero value documented in the
2670 L<ntfs-3g.probe(8)> manual page.");
2671
2672   ("sh", (RString "output", [String "command"]), 111, [],
2673    [], (* XXX needs tests *)
2674    "run a command via the shell",
2675    "\
2676 This call runs a command from the guest filesystem via the
2677 guest's C</bin/sh>.
2678
2679 This is like C<guestfs_command>, but passes the command to:
2680
2681  /bin/sh -c \"command\"
2682
2683 Depending on the guest's shell, this usually results in
2684 wildcards being expanded, shell expressions being interpolated
2685 and so on.
2686
2687 All the provisos about C<guestfs_command> apply to this call.");
2688
2689   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2690    [], (* XXX needs tests *)
2691    "run a command via the shell returning lines",
2692    "\
2693 This is the same as C<guestfs_sh>, but splits the result
2694 into a list of lines.
2695
2696 See also: C<guestfs_command_lines>");
2697
2698   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2699    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2700     * code in stubs.c, since all valid glob patterns must start with "/".
2701     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2702     *)
2703    [InitBasicFS, Always, TestOutputList (
2704       [["mkdir_p"; "/a/b/c"];
2705        ["touch"; "/a/b/c/d"];
2706        ["touch"; "/a/b/c/e"];
2707        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2708     InitBasicFS, Always, TestOutputList (
2709       [["mkdir_p"; "/a/b/c"];
2710        ["touch"; "/a/b/c/d"];
2711        ["touch"; "/a/b/c/e"];
2712        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2713     InitBasicFS, Always, TestOutputList (
2714       [["mkdir_p"; "/a/b/c"];
2715        ["touch"; "/a/b/c/d"];
2716        ["touch"; "/a/b/c/e"];
2717        ["glob_expand"; "/a/*/x/*"]], [])],
2718    "expand a wildcard path",
2719    "\
2720 This command searches for all the pathnames matching
2721 C<pattern> according to the wildcard expansion rules
2722 used by the shell.
2723
2724 If no paths match, then this returns an empty list
2725 (note: not an error).
2726
2727 It is just a wrapper around the C L<glob(3)> function
2728 with flags C<GLOB_MARK|GLOB_BRACE>.
2729 See that manual page for more details.");
2730
2731   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2732    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2733       [["scrub_device"; "/dev/sdc"]])],
2734    "scrub (securely wipe) a device",
2735    "\
2736 This command writes patterns over C<device> to make data retrieval
2737 more difficult.
2738
2739 It is an interface to the L<scrub(1)> program.  See that
2740 manual page for more details.");
2741
2742   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2743    [InitBasicFS, Always, TestRun (
2744       [["write_file"; "/file"; "content"; "0"];
2745        ["scrub_file"; "/file"]])],
2746    "scrub (securely wipe) a file",
2747    "\
2748 This command writes patterns over a file to make data retrieval
2749 more difficult.
2750
2751 The file is I<removed> after scrubbing.
2752
2753 It is an interface to the L<scrub(1)> program.  See that
2754 manual page for more details.");
2755
2756   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2757    [], (* XXX needs testing *)
2758    "scrub (securely wipe) free space",
2759    "\
2760 This command creates the directory C<dir> and then fills it
2761 with files until the filesystem is full, and scrubs the files
2762 as for C<guestfs_scrub_file>, and deletes them.
2763 The intention is to scrub any free space on the partition
2764 containing C<dir>.
2765
2766 It is an interface to the L<scrub(1)> program.  See that
2767 manual page for more details.");
2768
2769   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2770    [InitBasicFS, Always, TestRun (
2771       [["mkdir"; "/tmp"];
2772        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2773    "create a temporary directory",
2774    "\
2775 This command creates a temporary directory.  The
2776 C<template> parameter should be a full pathname for the
2777 temporary directory name with the final six characters being
2778 \"XXXXXX\".
2779
2780 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2781 the second one being suitable for Windows filesystems.
2782
2783 The name of the temporary directory that was created
2784 is returned.
2785
2786 The temporary directory is created with mode 0700
2787 and is owned by root.
2788
2789 The caller is responsible for deleting the temporary
2790 directory and its contents after use.
2791
2792 See also: L<mkdtemp(3)>");
2793
2794   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2795    [InitISOFS, Always, TestOutputInt (
2796       [["wc_l"; "/10klines"]], 10000)],
2797    "count lines in a file",
2798    "\
2799 This command counts the lines in a file, using the
2800 C<wc -l> external command.");
2801
2802   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2803    [InitISOFS, Always, TestOutputInt (
2804       [["wc_w"; "/10klines"]], 10000)],
2805    "count words in a file",
2806    "\
2807 This command counts the words in a file, using the
2808 C<wc -w> external command.");
2809
2810   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2811    [InitISOFS, Always, TestOutputInt (
2812       [["wc_c"; "/100kallspaces"]], 102400)],
2813    "count characters in a file",
2814    "\
2815 This command counts the characters in a file, using the
2816 C<wc -c> external command.");
2817
2818   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2819    [InitISOFS, Always, TestOutputList (
2820       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2821    "return first 10 lines of a file",
2822    "\
2823 This command returns up to the first 10 lines of a file as
2824 a list of strings.");
2825
2826   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2827    [InitISOFS, Always, TestOutputList (
2828       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2829     InitISOFS, Always, TestOutputList (
2830       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "0"; "/10klines"]], [])],
2833    "return first N lines of a file",
2834    "\
2835 If the parameter C<nrlines> is a positive number, this returns the first
2836 C<nrlines> lines of the file C<path>.
2837
2838 If the parameter C<nrlines> is a negative number, this returns lines
2839 from the file C<path>, excluding the last C<nrlines> lines.
2840
2841 If the parameter C<nrlines> is zero, this returns an empty list.");
2842
2843   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2844    [InitISOFS, Always, TestOutputList (
2845       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2846    "return last 10 lines of a file",
2847    "\
2848 This command returns up to the last 10 lines of a file as
2849 a list of strings.");
2850
2851   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2852    [InitISOFS, Always, TestOutputList (
2853       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2854     InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "0"; "/10klines"]], [])],
2858    "return last N lines of a file",
2859    "\
2860 If the parameter C<nrlines> is a positive number, this returns the last
2861 C<nrlines> lines of the file C<path>.
2862
2863 If the parameter C<nrlines> is a negative number, this returns lines
2864 from the file C<path>, starting with the C<-nrlines>th line.
2865
2866 If the parameter C<nrlines> is zero, this returns an empty list.");
2867
2868   ("df", (RString "output", []), 125, [],
2869    [], (* XXX Tricky to test because it depends on the exact format
2870         * of the 'df' command and other imponderables.
2871         *)
2872    "report file system disk space usage",
2873    "\
2874 This command runs the C<df> command to report disk space used.
2875
2876 This command is mostly useful for interactive sessions.  It
2877 is I<not> intended that you try to parse the output string.
2878 Use C<statvfs> from programs.");
2879
2880   ("df_h", (RString "output", []), 126, [],
2881    [], (* XXX Tricky to test because it depends on the exact format
2882         * of the 'df' command and other imponderables.
2883         *)
2884    "report file system disk space usage (human readable)",
2885    "\
2886 This command runs the C<df -h> command to report disk space used
2887 in human-readable format.
2888
2889 This command is mostly useful for interactive sessions.  It
2890 is I<not> intended that you try to parse the output string.
2891 Use C<statvfs> from programs.");
2892
2893   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2894    [InitISOFS, Always, TestOutputInt (
2895       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2896    "estimate file space usage",
2897    "\
2898 This command runs the C<du -s> command to estimate file space
2899 usage for C<path>.
2900
2901 C<path> can be a file or a directory.  If C<path> is a directory
2902 then the estimate includes the contents of the directory and all
2903 subdirectories (recursively).
2904
2905 The result is the estimated size in I<kilobytes>
2906 (ie. units of 1024 bytes).");
2907
2908   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2909    [InitISOFS, Always, TestOutputList (
2910       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2911    "list files in an initrd",
2912    "\
2913 This command lists out files contained in an initrd.
2914
2915 The files are listed without any initial C</> character.  The
2916 files are listed in the order they appear (not necessarily
2917 alphabetical).  Directory names are listed as separate items.
2918
2919 Old Linux kernels (2.4 and earlier) used a compressed ext2
2920 filesystem as initrd.  We I<only> support the newer initramfs
2921 format (compressed cpio files).");
2922
2923   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2924    [],
2925    "mount a file using the loop device",
2926    "\
2927 This command lets you mount C<file> (a filesystem image
2928 in a file) on a mount point.  It is entirely equivalent to
2929 the command C<mount -o loop file mountpoint>.");
2930
2931   ("mkswap", (RErr, [Device "device"]), 130, [],
2932    [InitEmpty, Always, TestRun (
2933       [["part_disk"; "/dev/sda"; "mbr"];
2934        ["mkswap"; "/dev/sda1"]])],
2935    "create a swap partition",
2936    "\
2937 Create a swap partition on C<device>.");
2938
2939   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2940    [InitEmpty, Always, TestRun (
2941       [["part_disk"; "/dev/sda"; "mbr"];
2942        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2943    "create a swap partition with a label",
2944    "\
2945 Create a swap partition on C<device> with label C<label>.
2946
2947 Note that you cannot attach a swap label to a block device
2948 (eg. C</dev/sda>), just to a partition.  This appears to be
2949 a limitation of the kernel or swap tools.");
2950
2951   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2952    (let uuid = uuidgen () in
2953     [InitEmpty, Always, TestRun (
2954        [["part_disk"; "/dev/sda"; "mbr"];
2955         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2956    "create a swap partition with an explicit UUID",
2957    "\
2958 Create a swap partition on C<device> with UUID C<uuid>.");
2959
2960   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2961    [InitBasicFS, Always, TestOutputStruct (
2962       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2963        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2964        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2965     InitBasicFS, Always, TestOutputStruct (
2966       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2967        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2968    "make block, character or FIFO devices",
2969    "\
2970 This call creates block or character special devices, or
2971 named pipes (FIFOs).
2972
2973 The C<mode> parameter should be the mode, using the standard
2974 constants.  C<devmajor> and C<devminor> are the
2975 device major and minor numbers, only used when creating block
2976 and character special devices.");
2977
2978   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2979    [InitBasicFS, Always, TestOutputStruct (
2980       [["mkfifo"; "0o777"; "/node"];
2981        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2982    "make FIFO (named pipe)",
2983    "\
2984 This call creates a FIFO (named pipe) called C<path> with
2985 mode C<mode>.  It is just a convenient wrapper around
2986 C<guestfs_mknod>.");
2987
2988   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2989    [InitBasicFS, Always, TestOutputStruct (
2990       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2991        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2992    "make block device node",
2993    "\
2994 This call creates a block device node called C<path> with
2995 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2996 It is just a convenient wrapper around C<guestfs_mknod>.");
2997
2998   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2999    [InitBasicFS, Always, TestOutputStruct (
3000       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3001        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3002    "make char device node",
3003    "\
3004 This call creates a char device node called C<path> with
3005 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3006 It is just a convenient wrapper around C<guestfs_mknod>.");
3007
3008   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3009    [], (* XXX umask is one of those stateful things that we should
3010         * reset between each test.
3011         *)
3012    "set file mode creation mask (umask)",
3013    "\
3014 This function sets the mask used for creating new files and
3015 device nodes to C<mask & 0777>.
3016
3017 Typical umask values would be C<022> which creates new files
3018 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3019 C<002> which creates new files with permissions like
3020 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3021
3022 The default umask is C<022>.  This is important because it
3023 means that directories and device nodes will be created with
3024 C<0644> or C<0755> mode even if you specify C<0777>.
3025
3026 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3027
3028 This call returns the previous umask.");
3029
3030   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3031    [],
3032    "read directories entries",
3033    "\
3034 This returns the list of directory entries in directory C<dir>.
3035
3036 All entries in the directory are returned, including C<.> and
3037 C<..>.  The entries are I<not> sorted, but returned in the same
3038 order as the underlying filesystem.
3039
3040 Also this call returns basic file type information about each
3041 file.  The C<ftyp> field will contain one of the following characters:
3042
3043 =over 4
3044
3045 =item 'b'
3046
3047 Block special
3048
3049 =item 'c'
3050
3051 Char special
3052
3053 =item 'd'
3054
3055 Directory
3056
3057 =item 'f'
3058
3059 FIFO (named pipe)
3060
3061 =item 'l'
3062
3063 Symbolic link
3064
3065 =item 'r'
3066
3067 Regular file
3068
3069 =item 's'
3070
3071 Socket
3072
3073 =item 'u'
3074
3075 Unknown file type
3076
3077 =item '?'
3078
3079 The L<readdir(3)> returned a C<d_type> field with an
3080 unexpected value
3081
3082 =back
3083
3084 This function is primarily intended for use by programs.  To
3085 get a simple list of names, use C<guestfs_ls>.  To get a printable
3086 directory for human consumption, use C<guestfs_ll>.");
3087
3088   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3089    [],
3090    "create partitions on a block device",
3091    "\
3092 This is a simplified interface to the C<guestfs_sfdisk>
3093 command, where partition sizes are specified in megabytes
3094 only (rounded to the nearest cylinder) and you don't need
3095 to specify the cyls, heads and sectors parameters which
3096 were rarely if ever used anyway.
3097
3098 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3099 and C<guestfs_part_disk>");
3100
3101   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3102    [],
3103    "determine file type inside a compressed file",
3104    "\
3105 This command runs C<file> after first decompressing C<path>
3106 using C<method>.
3107
3108 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3109
3110 Since 1.0.63, use C<guestfs_file> instead which can now
3111 process compressed files.");
3112
3113   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3114    [],
3115    "list extended attributes of a file or directory",
3116    "\
3117 This call lists the extended attributes of the file or directory
3118 C<path>.
3119
3120 At the system call level, this is a combination of the
3121 L<listxattr(2)> and L<getxattr(2)> calls.
3122
3123 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3124
3125   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3126    [],
3127    "list extended attributes of a file or directory",
3128    "\
3129 This is the same as C<guestfs_getxattrs>, but if C<path>
3130 is a symbolic link, then it returns the extended attributes
3131 of the link itself.");
3132
3133   ("setxattr", (RErr, [String "xattr";
3134                        String "val"; Int "vallen"; (* will be BufferIn *)
3135                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3136    [],
3137    "set extended attribute of a file or directory",
3138    "\
3139 This call sets the extended attribute named C<xattr>
3140 of the file C<path> to the value C<val> (of length C<vallen>).
3141 The value is arbitrary 8 bit data.
3142
3143 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3144
3145   ("lsetxattr", (RErr, [String "xattr";
3146                         String "val"; Int "vallen"; (* will be BufferIn *)
3147                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3148    [],
3149    "set extended attribute of a file or directory",
3150    "\
3151 This is the same as C<guestfs_setxattr>, but if C<path>
3152 is a symbolic link, then it sets an extended attribute
3153 of the link itself.");
3154
3155   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3156    [],
3157    "remove extended attribute of a file or directory",
3158    "\
3159 This call removes the extended attribute named C<xattr>
3160 of the file C<path>.
3161
3162 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3163
3164   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3165    [],
3166    "remove extended attribute of a file or directory",
3167    "\
3168 This is the same as C<guestfs_removexattr>, but if C<path>
3169 is a symbolic link, then it removes an extended attribute
3170 of the link itself.");
3171
3172   ("mountpoints", (RHashtable "mps", []), 147, [],
3173    [],
3174    "show mountpoints",
3175    "\
3176 This call is similar to C<guestfs_mounts>.  That call returns
3177 a list of devices.  This one returns a hash table (map) of
3178 device name to directory where the device is mounted.");
3179
3180   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3181    (* This is a special case: while you would expect a parameter
3182     * of type "Pathname", that doesn't work, because it implies
3183     * NEED_ROOT in the generated calling code in stubs.c, and
3184     * this function cannot use NEED_ROOT.
3185     *)
3186    [],
3187    "create a mountpoint",
3188    "\
3189 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3190 specialized calls that can be used to create extra mountpoints
3191 before mounting the first filesystem.
3192
3193 These calls are I<only> necessary in some very limited circumstances,
3194 mainly the case where you want to mount a mix of unrelated and/or
3195 read-only filesystems together.
3196
3197 For example, live CDs often contain a \"Russian doll\" nest of
3198 filesystems, an ISO outer layer, with a squashfs image inside, with
3199 an ext2/3 image inside that.  You can unpack this as follows
3200 in guestfish:
3201
3202  add-ro Fedora-11-i686-Live.iso
3203  run
3204  mkmountpoint /cd
3205  mkmountpoint /squash
3206  mkmountpoint /ext3
3207  mount /dev/sda /cd
3208  mount-loop /cd/LiveOS/squashfs.img /squash
3209  mount-loop /squash/LiveOS/ext3fs.img /ext3
3210
3211 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3212
3213   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3214    [],
3215    "remove a mountpoint",
3216    "\
3217 This calls removes a mountpoint that was previously created
3218 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3219 for full details.");
3220
3221   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3222    [InitISOFS, Always, TestOutputBuffer (
3223       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3224    "read a file",
3225    "\
3226 This calls returns the contents of the file C<path> as a
3227 buffer.
3228
3229 Unlike C<guestfs_cat>, this function can correctly
3230 handle files that contain embedded ASCII NUL characters.
3231 However unlike C<guestfs_download>, this function is limited
3232 in the total size of file that can be handled.");
3233
3234   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3235    [InitISOFS, Always, TestOutputList (
3236       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3237     InitISOFS, Always, TestOutputList (
3238       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3239    "return lines matching a pattern",
3240    "\
3241 This calls the external C<grep> program and returns the
3242 matching lines.");
3243
3244   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3245    [InitISOFS, Always, TestOutputList (
3246       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3247    "return lines matching a pattern",
3248    "\
3249 This calls the external C<egrep> program and returns the
3250 matching lines.");
3251
3252   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3253    [InitISOFS, Always, TestOutputList (
3254       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3255    "return lines matching a pattern",
3256    "\
3257 This calls the external C<fgrep> program and returns the
3258 matching lines.");
3259
3260   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3261    [InitISOFS, Always, TestOutputList (
3262       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3263    "return lines matching a pattern",
3264    "\
3265 This calls the external C<grep -i> program and returns the
3266 matching lines.");
3267
3268   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3269    [InitISOFS, Always, TestOutputList (
3270       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3271    "return lines matching a pattern",
3272    "\
3273 This calls the external C<egrep -i> program and returns the
3274 matching lines.");
3275
3276   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3277    [InitISOFS, Always, TestOutputList (
3278       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3279    "return lines matching a pattern",
3280    "\
3281 This calls the external C<fgrep -i> program and returns the
3282 matching lines.");
3283
3284   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3285    [InitISOFS, Always, TestOutputList (
3286       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3287    "return lines matching a pattern",
3288    "\
3289 This calls the external C<zgrep> program and returns the
3290 matching lines.");
3291
3292   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3293    [InitISOFS, Always, TestOutputList (
3294       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3295    "return lines matching a pattern",
3296    "\
3297 This calls the external C<zegrep> program and returns the
3298 matching lines.");
3299
3300   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3301    [InitISOFS, Always, TestOutputList (
3302       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3303    "return lines matching a pattern",
3304    "\
3305 This calls the external C<zfgrep> program and returns the
3306 matching lines.");
3307
3308   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3309    [InitISOFS, Always, TestOutputList (
3310       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3311    "return lines matching a pattern",
3312    "\
3313 This calls the external C<zgrep -i> program and returns the
3314 matching lines.");
3315
3316   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3317    [InitISOFS, Always, TestOutputList (
3318       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3319    "return lines matching a pattern",
3320    "\
3321 This calls the external C<zegrep -i> program and returns the
3322 matching lines.");
3323
3324   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3325    [InitISOFS, Always, TestOutputList (
3326       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3327    "return lines matching a pattern",
3328    "\
3329 This calls the external C<zfgrep -i> program and returns the
3330 matching lines.");
3331
3332   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3333    [InitISOFS, Always, TestOutput (
3334       [["realpath"; "/../directory"]], "/directory")],
3335    "canonicalized absolute pathname",
3336    "\
3337 Return the canonicalized absolute pathname of C<path>.  The
3338 returned path has no C<.>, C<..> or symbolic link path elements.");
3339
3340   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3341    [InitBasicFS, Always, TestOutputStruct (
3342       [["touch"; "/a"];
3343        ["ln"; "/a"; "/b"];
3344        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3345    "create a hard link",
3346    "\
3347 This command creates a hard link using the C<ln> command.");
3348
3349   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3350    [InitBasicFS, Always, TestOutputStruct (
3351       [["touch"; "/a"];
3352        ["touch"; "/b"];
3353        ["ln_f"; "/a"; "/b"];
3354        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3355    "create a hard link",
3356    "\
3357 This command creates a hard link using the C<ln -f> command.
3358 The C<-f> option removes the link (C<linkname>) if it exists already.");
3359
3360   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3361    [InitBasicFS, Always, TestOutputStruct (
3362       [["touch"; "/a"];
3363        ["ln_s"; "a"; "/b"];
3364        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3365    "create a symbolic link",
3366    "\
3367 This command creates a symbolic link using the C<ln -s> command.");
3368
3369   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3370    [InitBasicFS, Always, TestOutput (
3371       [["mkdir_p"; "/a/b"];
3372        ["touch"; "/a/b/c"];
3373        ["ln_sf"; "../d"; "/a/b/c"];
3374        ["readlink"; "/a/b/c"]], "../d")],
3375    "create a symbolic link",
3376    "\
3377 This command creates a symbolic link using the C<ln -sf> command,
3378 The C<-f> option removes the link (C<linkname>) if it exists already.");
3379
3380   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3381    [] (* XXX tested above *),
3382    "read the target of a symbolic link",
3383    "\
3384 This command reads the target of a symbolic link.");
3385
3386   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3387    [InitBasicFS, Always, TestOutputStruct (
3388       [["fallocate"; "/a"; "1000000"];
3389        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3390    "preallocate a file in the guest filesystem",
3391    "\
3392 This command preallocates a file (containing zero bytes) named
3393 C<path> of size C<len> bytes.  If the file exists already, it
3394 is overwritten.
3395
3396 Do not confuse this with the guestfish-specific
3397 C<alloc> command which allocates a file in the host and
3398 attaches it as a device.");
3399
3400   ("swapon_device", (RErr, [Device "device"]), 170, [],
3401    [InitPartition, Always, TestRun (
3402       [["mkswap"; "/dev/sda1"];
3403        ["swapon_device"; "/dev/sda1"];
3404        ["swapoff_device"; "/dev/sda1"]])],
3405    "enable swap on device",
3406    "\
3407 This command enables the libguestfs appliance to use the
3408 swap device or partition named C<device>.  The increased
3409 memory is made available for all commands, for example
3410 those run using C<guestfs_command> or C<guestfs_sh>.
3411
3412 Note that you should not swap to existing guest swap
3413 partitions unless you know what you are doing.  They may
3414 contain hibernation information, or other information that
3415 the guest doesn't want you to trash.  You also risk leaking
3416 information about the host to the guest this way.  Instead,
3417 attach a new host device to the guest and swap on that.");
3418
3419   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3420    [], (* XXX tested by swapon_device *)
3421    "disable swap on device",
3422    "\
3423 This command disables the libguestfs appliance swap
3424 device or partition named C<device>.
3425 See C<guestfs_swapon_device>.");
3426
3427   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3428    [InitBasicFS, Always, TestRun (
3429       [["fallocate"; "/swap"; "8388608"];
3430        ["mkswap_file"; "/swap"];
3431        ["swapon_file"; "/swap"];
3432        ["swapoff_file"; "/swap"]])],
3433    "enable swap on file",
3434    "\
3435 This command enables swap to a file.
3436 See C<guestfs_swapon_device> for other notes.");
3437
3438   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3439    [], (* XXX tested by swapon_file *)
3440    "disable swap on file",
3441    "\
3442 This command disables the libguestfs appliance swap on file.");
3443
3444   ("swapon_label", (RErr, [String "label"]), 174, [],
3445    [InitEmpty, Always, TestRun (
3446       [["part_disk"; "/dev/sdb"; "mbr"];
3447        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3448        ["swapon_label"; "swapit"];
3449        ["swapoff_label"; "swapit"];
3450        ["zero"; "/dev/sdb"];
3451        ["blockdev_rereadpt"; "/dev/sdb"]])],
3452    "enable swap on labeled swap partition",
3453    "\
3454 This command enables swap to a labeled swap partition.
3455 See C<guestfs_swapon_device> for other notes.");
3456
3457   ("swapoff_label", (RErr, [String "label"]), 175, [],
3458    [], (* XXX tested by swapon_label *)
3459    "disable swap on labeled swap partition",
3460    "\
3461 This command disables the libguestfs appliance swap on
3462 labeled swap partition.");
3463
3464   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3465    (let uuid = uuidgen () in
3466     [InitEmpty, Always, TestRun (
3467        [["mkswap_U"; uuid; "/dev/sdb"];
3468         ["swapon_uuid"; uuid];
3469         ["swapoff_uuid"; uuid]])]),
3470    "enable swap on swap partition by UUID",
3471    "\
3472 This command enables swap to a swap partition with the given UUID.
3473 See C<guestfs_swapon_device> for other notes.");
3474
3475   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3476    [], (* XXX tested by swapon_uuid *)
3477    "disable swap on swap partition by UUID",
3478    "\
3479 This command disables the libguestfs appliance swap partition
3480 with the given UUID.");
3481
3482   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3483    [InitBasicFS, Always, TestRun (
3484       [["fallocate"; "/swap"; "8388608"];
3485        ["mkswap_file"; "/swap"]])],
3486    "create a swap file",
3487    "\
3488 Create a swap file.
3489
3490 This command just writes a swap file signature to an existing
3491 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3492
3493   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3494    [InitISOFS, Always, TestRun (
3495       [["inotify_init"; "0"]])],
3496    "create an inotify handle",
3497    "\
3498 This command creates a new inotify handle.
3499 The inotify subsystem can be used to notify events which happen to
3500 objects in the guest filesystem.
3501
3502 C<maxevents> is the maximum number of events which will be
3503 queued up between calls to C<guestfs_inotify_read> or
3504 C<guestfs_inotify_files>.
3505 If this is passed as C<0>, then the kernel (or previously set)
3506 default is used.  For Linux 2.6.29 the default was 16384 events.
3507 Beyond this limit, the kernel throws away events, but records
3508 the fact that it threw them away by setting a flag
3509 C<IN_Q_OVERFLOW> in the returned structure list (see
3510 C<guestfs_inotify_read>).
3511
3512 Before any events are generated, you have to add some
3513 watches to the internal watch list.  See:
3514 C<guestfs_inotify_add_watch>,
3515 C<guestfs_inotify_rm_watch> and
3516 C<guestfs_inotify_watch_all>.
3517
3518 Queued up events should be read periodically by calling
3519 C<guestfs_inotify_read>
3520 (or C<guestfs_inotify_files> which is just a helpful
3521 wrapper around C<guestfs_inotify_read>).  If you don't
3522 read the events out often enough then you risk the internal
3523 queue overflowing.
3524
3525 The handle should be closed after use by calling
3526 C<guestfs_inotify_close>.  This also removes any
3527 watches automatically.
3528
3529 See also L<inotify(7)> for an overview of the inotify interface
3530 as exposed by the Linux kernel, which is roughly what we expose
3531 via libguestfs.  Note that there is one global inotify handle
3532 per libguestfs instance.");
3533
3534   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3535    [InitBasicFS, Always, TestOutputList (
3536       [["inotify_init"; "0"];
3537        ["inotify_add_watch"; "/"; "1073741823"];
3538        ["touch"; "/a"];
3539        ["touch"; "/b"];
3540        ["inotify_files"]], ["a"; "b"])],
3541    "add an inotify watch",
3542    "\
3543 Watch C<path> for the events listed in C<mask>.
3544
3545 Note that if C<path> is a directory then events within that
3546 directory are watched, but this does I<not> happen recursively
3547 (in subdirectories).
3548
3549 Note for non-C or non-Linux callers: the inotify events are
3550 defined by the Linux kernel ABI and are listed in
3551 C</usr/include/sys/inotify.h>.");
3552
3553   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3554    [],
3555    "remove an inotify watch",
3556    "\
3557 Remove a previously defined inotify watch.
3558 See C<guestfs_inotify_add_watch>.");
3559
3560   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3561    [],
3562    "return list of inotify events",
3563    "\
3564 Return the complete queue of events that have happened
3565 since the previous read call.
3566
3567 If no events have happened, this returns an empty list.
3568
3569 I<Note>: In order to make sure that all events have been
3570 read, you must call this function repeatedly until it
3571 returns an empty list.  The reason is that the call will
3572 read events up to the maximum appliance-to-host message
3573 size and leave remaining events in the queue.");
3574
3575   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3576    [],
3577    "return list of watched files that had events",
3578    "\
3579 This function is a helpful wrapper around C<guestfs_inotify_read>
3580 which just returns a list of pathnames of objects that were
3581 touched.  The returned pathnames are sorted and deduplicated.");
3582
3583   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3584    [],
3585    "close the inotify handle",
3586    "\
3587 This closes the inotify handle which was previously
3588 opened by inotify_init.  It removes all watches, throws
3589 away any pending events, and deallocates all resources.");
3590
3591   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3592    [],
3593    "set SELinux security context",
3594    "\
3595 This sets the SELinux security context of the daemon
3596 to the string C<context>.
3597
3598 See the documentation about SELINUX in L<guestfs(3)>.");
3599
3600   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3601    [],
3602    "get SELinux security context",
3603    "\
3604 This gets the SELinux security context of the daemon.
3605
3606 See the documentation about SELINUX in L<guestfs(3)>,
3607 and C<guestfs_setcon>");
3608
3609   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3610    [InitEmpty, Always, TestOutput (
3611       [["part_disk"; "/dev/sda"; "mbr"];
3612        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3613        ["mount_options"; ""; "/dev/sda1"; "/"];
3614        ["write_file"; "/new"; "new file contents"; "0"];
3615        ["cat"; "/new"]], "new file contents")],
3616    "make a filesystem with block size",
3617    "\
3618 This call is similar to C<guestfs_mkfs>, but it allows you to
3619 control the block size of the resulting filesystem.  Supported
3620 block sizes depend on the filesystem type, but typically they
3621 are C<1024>, C<2048> or C<4096> only.");
3622
3623   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3624    [InitEmpty, Always, TestOutput (
3625       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3626        ["mke2journal"; "4096"; "/dev/sda1"];
3627        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3628        ["mount_options"; ""; "/dev/sda2"; "/"];
3629        ["write_file"; "/new"; "new file contents"; "0"];
3630        ["cat"; "/new"]], "new file contents")],
3631    "make ext2/3/4 external journal",
3632    "\
3633 This creates an ext2 external journal on C<device>.  It is equivalent
3634 to the command:
3635
3636  mke2fs -O journal_dev -b blocksize device");
3637
3638   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3639    [InitEmpty, Always, TestOutput (
3640       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3641        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3642        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3643        ["mount_options"; ""; "/dev/sda2"; "/"];
3644        ["write_file"; "/new"; "new file contents"; "0"];
3645        ["cat"; "/new"]], "new file contents")],
3646    "make ext2/3/4 external journal with label",
3647    "\
3648 This creates an ext2 external journal on C<device> with label C<label>.");
3649
3650   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3651    (let uuid = uuidgen () in
3652     [InitEmpty, Always, TestOutput (
3653        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3654         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3655         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3656         ["mount_options"; ""; "/dev/sda2"; "/"];
3657         ["write_file"; "/new"; "new file contents"; "0"];
3658         ["cat"; "/new"]], "new file contents")]),
3659    "make ext2/3/4 external journal with UUID",
3660    "\
3661 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3662
3663   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3664    [],
3665    "make ext2/3/4 filesystem with external journal",
3666    "\
3667 This creates an ext2/3/4 filesystem on C<device> with
3668 an external journal on C<journal>.  It is equivalent
3669 to the command:
3670
3671  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3672
3673 See also C<guestfs_mke2journal>.");
3674
3675   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3676    [],
3677    "make ext2/3/4 filesystem with external journal",
3678    "\
3679 This creates an ext2/3/4 filesystem on C<device> with
3680 an external journal on the journal labeled C<label>.
3681
3682 See also C<guestfs_mke2journal_L>.");
3683
3684   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3685    [],
3686    "make ext2/3/4 filesystem with external journal",
3687    "\
3688 This creates an ext2/3/4 filesystem on C<device> with
3689 an external journal on the journal with UUID C<uuid>.
3690
3691 See also C<guestfs_mke2journal_U>.");
3692
3693   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3694    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3695    "load a kernel module",
3696    "\
3697 This loads a kernel module in the appliance.
3698
3699 The kernel module must have been whitelisted when libguestfs
3700 was built (see C<appliance/kmod.whitelist.in> in the source).");
3701
3702   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3703    [InitNone, Always, TestOutput (
3704       [["echo_daemon"; "This is a test"]], "This is a test"
3705     )],
3706    "echo arguments back to the client",
3707    "\
3708 This command concatenate the list of C<words> passed with single spaces between
3709 them and returns the resulting string.
3710
3711 You can use this command to test the connection through to the daemon.
3712
3713 See also C<guestfs_ping_daemon>.");
3714
3715   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3716    [], (* There is a regression test for this. *)
3717    "find all files and directories, returning NUL-separated list",
3718    "\
3719 This command lists out all files and directories, recursively,
3720 starting at C<directory>, placing the resulting list in the
3721 external file called C<files>.
3722
3723 This command works the same way as C<guestfs_find> with the
3724 following exceptions:
3725
3726 =over 4
3727
3728 =item *
3729
3730 The resulting list is written to an external file.
3731
3732 =item *
3733
3734 Items (filenames) in the result are separated
3735 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3736
3737 =item *
3738
3739 This command is not limited in the number of names that it
3740 can return.
3741
3742 =item *
3743
3744 The result list is not sorted.
3745
3746 =back");
3747
3748   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3749    [InitISOFS, Always, TestOutput (
3750       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3751     InitISOFS, Always, TestOutput (
3752       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3753     InitISOFS, Always, TestOutput (
3754       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3755     InitISOFS, Always, TestLastFail (
3756       [["case_sensitive_path"; "/Known-1/"]]);
3757     InitBasicFS, Always, TestOutput (
3758       [["mkdir"; "/a"];
3759        ["mkdir"; "/a/bbb"];
3760        ["touch"; "/a/bbb/c"];
3761        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3762     InitBasicFS, Always, TestOutput (
3763       [["mkdir"; "/a"];
3764        ["mkdir"; "/a/bbb"];
3765        ["touch"; "/a/bbb/c"];
3766        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3767     InitBasicFS, Always, TestLastFail (
3768       [["mkdir"; "/a"];
3769        ["mkdir"; "/a/bbb"];
3770        ["touch"; "/a/bbb/c"];
3771        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3772    "return true path on case-insensitive filesystem",
3773    "\
3774 This can be used to resolve case insensitive paths on
3775 a filesystem which is case sensitive.  The use case is
3776 to resolve paths which you have read from Windows configuration
3777 files or the Windows Registry, to the true path.
3778
3779 The command handles a peculiarity of the Linux ntfs-3g
3780 filesystem driver (and probably others), which is that although
3781 the underlying filesystem is case-insensitive, the driver
3782 exports the filesystem to Linux as case-sensitive.
3783
3784 One consequence of this is that special directories such
3785 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3786 (or other things) depending on the precise details of how
3787 they were created.  In Windows itself this would not be
3788 a problem.
3789
3790 Bug or feature?  You decide:
3791 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3792
3793 This function resolves the true case of each element in the
3794 path and returns the case-sensitive path.
3795
3796 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3797 might return C<\"/WINDOWS/system32\"> (the exact return value
3798 would depend on details of how the directories were originally
3799 created under Windows).
3800
3801 I<Note>:
3802 This function does not handle drive names, backslashes etc.
3803
3804 See also C<guestfs_realpath>.");
3805
3806   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3807    [InitBasicFS, Always, TestOutput (
3808       [["vfs_type"; "/dev/sda1"]], "ext2")],
3809    "get the Linux VFS type corresponding to a mounted device",
3810    "\
3811 This command gets the block device type corresponding to
3812 a mounted device called C<device>.
3813
3814 Usually the result is the name of the Linux VFS module that
3815 is used to mount this device (probably determined automatically
3816 if you used the C<guestfs_mount> call).");
3817
3818   ("truncate", (RErr, [Pathname "path"]), 199, [],
3819    [InitBasicFS, Always, TestOutputStruct (
3820       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3821        ["truncate"; "/test"];
3822        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3823    "truncate a file to zero size",
3824    "\
3825 This command truncates C<path> to a zero-length file.  The
3826 file must exist already.");
3827
3828   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3829    [InitBasicFS, Always, TestOutputStruct (
3830       [["touch"; "/test"];
3831        ["truncate_size"; "/test"; "1000"];
3832        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3833    "truncate a file to a particular size",
3834    "\
3835 This command truncates C<path> to size C<size> bytes.  The file
3836 must exist already.  If the file is smaller than C<size> then
3837 the file is extended to the required size with null bytes.");
3838
3839   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3840    [InitBasicFS, Always, TestOutputStruct (
3841       [["touch"; "/test"];
3842        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3843        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3844    "set timestamp of a file with nanosecond precision",
3845    "\
3846 This command sets the timestamps of a file with nanosecond
3847 precision.
3848
3849 C<atsecs, atnsecs> are the last access time (atime) in secs and
3850 nanoseconds from the epoch.
3851
3852 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3853 secs and nanoseconds from the epoch.
3854
3855 If the C<*nsecs> field contains the special value C<-1> then
3856 the corresponding timestamp is set to the current time.  (The
3857 C<*secs> field is ignored in this case).
3858
3859 If the C<*nsecs> field contains the special value C<-2> then
3860 the corresponding timestamp is left unchanged.  (The
3861 C<*secs> field is ignored in this case).");
3862
3863   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3864    [InitBasicFS, Always, TestOutputStruct (
3865       [["mkdir_mode"; "/test"; "0o111"];
3866        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3867    "create a directory with a particular mode",
3868    "\
3869 This command creates a directory, setting the initial permissions
3870 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3871
3872   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3873    [], (* XXX *)
3874    "change file owner and group",
3875    "\
3876 Change the file owner to C<owner> and group to C<group>.
3877 This is like C<guestfs_chown> but if C<path> is a symlink then
3878 the link itself is changed, not the target.
3879
3880 Only numeric uid and gid are supported.  If you want to use
3881 names, you will need to locate and parse the password file
3882 yourself (Augeas support makes this relatively easy).");
3883
3884   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3885    [], (* XXX *)
3886    "lstat on multiple files",
3887    "\
3888 This call allows you to perform the C<guestfs_lstat> operation
3889 on multiple files, where all files are in the directory C<path>.
3890 C<names> is the list of files from this directory.
3891
3892 On return you get a list of stat structs, with a one-to-one
3893 correspondence to the C<names> list.  If any name did not exist
3894 or could not be lstat'd, then the C<ino> field of that structure
3895 is set to C<-1>.
3896
3897 This call is intended for programs that want to efficiently
3898 list a directory contents without making many round-trips.
3899 See also C<guestfs_lxattrlist> for a similarly efficient call
3900 for getting extended attributes.  Very long directory listings
3901 might cause the protocol message size to be exceeded, causing
3902 this call to fail.  The caller must split up such requests
3903 into smaller groups of names.");
3904
3905   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3906    [], (* XXX *)
3907    "lgetxattr on multiple files",
3908    "\
3909 This call allows you to get the extended attributes
3910 of multiple files, where all files are in the directory C<path>.
3911 C<names> is the list of files from this directory.
3912
3913 On return you get a flat list of xattr structs which must be
3914 interpreted sequentially.  The first xattr struct always has a zero-length
3915 C<attrname>.  C<attrval> in this struct is zero-length
3916 to indicate there was an error doing C<lgetxattr> for this
3917 file, I<or> is a C string which is a decimal number
3918 (the number of following attributes for this file, which could
3919 be C<\"0\">).  Then after the first xattr struct are the
3920 zero or more attributes for the first named file.
3921 This repeats for the second and subsequent files.
3922
3923 This call is intended for programs that want to efficiently
3924 list a directory contents without making many round-trips.
3925 See also C<guestfs_lstatlist> for a similarly efficient call
3926 for getting standard stats.  Very long directory listings
3927 might cause the protocol message size to be exceeded, causing
3928 this call to fail.  The caller must split up such requests
3929 into smaller groups of names.");
3930
3931   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3932    [], (* XXX *)
3933    "readlink on multiple files",
3934    "\
3935 This call allows you to do a C<readlink> operation
3936 on multiple files, where all files are in the directory C<path>.
3937 C<names> is the list of files from this directory.
3938
3939 On return you get a list of strings, with a one-to-one
3940 correspondence to the C<names> list.  Each string is the
3941 value of the symbol link.
3942
3943 If the C<readlink(2)> operation fails on any name, then
3944 the corresponding result string is the empty string C<\"\">.
3945 However the whole operation is completed even if there
3946 were C<readlink(2)> errors, and so you can call this
3947 function with names where you don't know if they are
3948 symbolic links already (albeit slightly less efficient).
3949
3950 This call is intended for programs that want to efficiently
3951 list a directory contents without making many round-trips.
3952 Very long directory listings might cause the protocol
3953 message size to be exceeded, causing
3954 this call to fail.  The caller must split up such requests
3955 into smaller groups of names.");
3956
3957   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3958    [InitISOFS, Always, TestOutputBuffer (
3959       [["pread"; "/known-4"; "1"; "3"]], "\n");
3960     InitISOFS, Always, TestOutputBuffer (
3961       [["pread"; "/empty"; "0"; "100"]], "")],
3962    "read part of a file",
3963    "\
3964 This command lets you read part of a file.  It reads C<count>
3965 bytes of the file, starting at C<offset>, from file C<path>.
3966
3967 This may read fewer bytes than requested.  For further details
3968 see the L<pread(2)> system call.");
3969
3970   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3971    [InitEmpty, Always, TestRun (
3972       [["part_init"; "/dev/sda"; "gpt"]])],
3973    "create an empty partition table",
3974    "\
3975 This creates an empty partition table on C<device> of one of the
3976 partition types listed below.  Usually C<parttype> should be
3977 either C<msdos> or C<gpt> (for large disks).
3978
3979 Initially there are no partitions.  Following this, you should
3980 call C<guestfs_part_add> for each partition required.
3981
3982 Possible values for C<parttype> are:
3983
3984 =over 4
3985
3986 =item B<efi> | B<gpt>
3987
3988 Intel EFI / GPT partition table.
3989
3990 This is recommended for >= 2 TB partitions that will be accessed
3991 from Linux and Intel-based Mac OS X.  It also has limited backwards
3992 compatibility with the C<mbr> format.
3993
3994 =item B<mbr> | B<msdos>
3995
3996 The standard PC \"Master Boot Record\" (MBR) format used
3997 by MS-DOS and Windows.  This partition type will B<only> work
3998 for device sizes up to 2 TB.  For large disks we recommend
3999 using C<gpt>.
4000
4001 =back
4002
4003 Other partition table types that may work but are not
4004 supported include:
4005
4006 =over 4
4007
4008 =item B<aix>
4009
4010 AIX disk labels.
4011
4012 =item B<amiga> | B<rdb>
4013
4014 Amiga \"Rigid Disk Block\" format.
4015
4016 =item B<bsd>
4017
4018 BSD disk labels.
4019
4020 =item B<dasd>
4021
4022 DASD, used on IBM mainframes.
4023
4024 =item B<dvh>
4025
4026 MIPS/SGI volumes.
4027
4028 =item B<mac>
4029
4030 Old Mac partition format.  Modern Macs use C<gpt>.
4031
4032 =item B<pc98>
4033
4034 NEC PC-98 format, common in Japan apparently.
4035
4036 =item B<sun>
4037
4038 Sun disk labels.
4039
4040 =back");
4041
4042   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4043    [InitEmpty, Always, TestRun (
4044       [["part_init"; "/dev/sda"; "mbr"];
4045        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4046     InitEmpty, Always, TestRun (
4047       [["part_init"; "/dev/sda"; "gpt"];
4048        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4049        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4050     InitEmpty, Always, TestRun (
4051       [["part_init"; "/dev/sda"; "mbr"];
4052        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4053        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4054        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4055        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4056    "add a partition to the device",
4057    "\
4058 This command adds a partition to C<device>.  If there is no partition
4059 table on the device, call C<guestfs_part_init> first.
4060
4061 The C<prlogex> parameter is the type of partition.  Normally you
4062 should pass C<p> or C<primary> here, but MBR partition tables also
4063 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4064 types.
4065
4066 C<startsect> and C<endsect> are the start and end of the partition
4067 in I<sectors>.  C<endsect> may be negative, which means it counts
4068 backwards from the end of the disk (C<-1> is the last sector).
4069
4070 Creating a partition which covers the whole disk is not so easy.
4071 Use C<guestfs_part_disk> to do that.");
4072
4073   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4074    [InitEmpty, Always, TestRun (
4075       [["part_disk"; "/dev/sda"; "mbr"]]);
4076     InitEmpty, Always, TestRun (
4077       [["part_disk"; "/dev/sda"; "gpt"]])],
4078    "partition whole disk with a single primary partition",
4079    "\
4080 This command is simply a combination of C<guestfs_part_init>
4081 followed by C<guestfs_part_add> to create a single primary partition
4082 covering the whole disk.
4083
4084 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4085 but other possible values are described in C<guestfs_part_init>.");
4086
4087   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4088    [InitEmpty, Always, TestRun (
4089       [["part_disk"; "/dev/sda"; "mbr"];
4090        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4091    "make a partition bootable",
4092    "\
4093 This sets the bootable flag on partition numbered C<partnum> on
4094 device C<device>.  Note that partitions are numbered from 1.
4095
4096 The bootable flag is used by some PC BIOSes to determine which
4097 partition to boot from.  It is by no means universally recognized,
4098 and in any case if your operating system installed a boot
4099 sector on the device itself, then that takes precedence.");
4100
4101   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4102    [InitEmpty, Always, TestRun (
4103       [["part_disk"; "/dev/sda"; "gpt"];
4104        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4105    "set partition name",
4106    "\
4107 This sets the partition name on partition numbered C<partnum> on
4108 device C<device>.  Note that partitions are numbered from 1.
4109
4110 The partition name can only be set on certain types of partition
4111 table.  This works on C<gpt> but not on C<mbr> partitions.");
4112
4113   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4114    [], (* XXX Add a regression test for this. *)
4115    "list partitions on a device",
4116    "\
4117 This command parses the partition table on C<device> and
4118 returns the list of partitions found.
4119
4120 The fields in the returned structure are:
4121
4122 =over 4
4123
4124 =item B<part_num>
4125
4126 Partition number, counting from 1.
4127
4128 =item B<part_start>
4129
4130 Start of the partition I<in bytes>.  To get sectors you have to
4131 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4132
4133 =item B<part_end>
4134
4135 End of the partition in bytes.
4136
4137 =item B<part_size>
4138
4139 Size of the partition in bytes.
4140
4141 =back");
4142
4143   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4144    [InitEmpty, Always, TestOutput (
4145       [["part_disk"; "/dev/sda"; "gpt"];
4146        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4147    "get the partition table type",
4148    "\
4149 This command examines the partition table on C<device> and
4150 returns the partition table type (format) being used.
4151
4152 Common return values include: C<msdos> (a DOS/Windows style MBR
4153 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4154 values are possible, although unusual.  See C<guestfs_part_init>
4155 for a full list.");
4156
4157   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4158    [InitBasicFS, Always, TestOutputBuffer (
4159       [["fill"; "0x63"; "10"; "/test"];
4160        ["read_file"; "/test"]], "cccccccccc")],
4161    "fill a file with octets",
4162    "\
4163 This command creates a new file called C<path>.  The initial
4164 content of the file is C<len> octets of C<c>, where C<c>
4165 must be a number in the range C<[0..255]>.
4166
4167 To fill a file with zero bytes (sparsely), it is
4168 much more efficient to use C<guestfs_truncate_size>.");
4169
4170   ("available", (RErr, [StringList "groups"]), 216, [],
4171    [InitNone, Always, TestRun [["available"; ""]]],
4172    "test availability of some parts of the API",
4173    "\
4174 This command is used to check the availability of some
4175 groups of functionality in the appliance, which not all builds of
4176 the libguestfs appliance will be able to provide.
4177
4178 The libguestfs groups, and the functions that those
4179 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4180
4181 The argument C<groups> is a list of group names, eg:
4182 C<[\"inotify\", \"augeas\"]> would check for the availability of
4183 the Linux inotify functions and Augeas (configuration file
4184 editing) functions.
4185
4186 The command returns no error if I<all> requested groups are available.
4187
4188 It fails with an error if one or more of the requested
4189 groups is unavailable in the appliance.
4190
4191 If an unknown group name is included in the
4192 list of groups then an error is always returned.
4193
4194 I<Notes:>
4195
4196 =over 4
4197
4198 =item *
4199
4200 You must call C<guestfs_launch> before calling this function.
4201
4202 The reason is because we don't know what groups are
4203 supported by the appliance/daemon until it is running and can
4204 be queried.
4205
4206 =item *
4207
4208 If a group of functions is available, this does not necessarily
4209 mean that they will work.  You still have to check for errors
4210 when calling individual API functions even if they are
4211 available.
4212
4213 =item *
4214
4215 It is usually the job of distro packagers to build
4216 complete functionality into the libguestfs appliance.
4217 Upstream libguestfs, if built from source with all
4218 requirements satisfied, will support everything.
4219
4220 =item *
4221
4222 This call was added in version C<1.0.80>.  In previous
4223 versions of libguestfs all you could do would be to speculatively
4224 execute a command to find out if the daemon implemented it.
4225 See also C<guestfs_version>.
4226
4227 =back");
4228
4229   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4230    [InitBasicFS, Always, TestOutputBuffer (
4231       [["write_file"; "/src"; "hello, world"; "0"];
4232        ["dd"; "/src"; "/dest"];
4233        ["read_file"; "/dest"]], "hello, world")],
4234    "copy from source to destination using dd",
4235    "\
4236 This command copies from one source device or file C<src>
4237 to another destination device or file C<dest>.  Normally you
4238 would use this to copy to or from a device or partition, for
4239 example to duplicate a filesystem.
4240
4241 If the destination is a device, it must be as large or larger
4242 than the source file or device, otherwise the copy will fail.
4243 This command cannot do partial copies.");
4244
4245   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4246    [InitBasicFS, Always, TestOutputInt (
4247       [["write_file"; "/file"; "hello, world"; "0"];
4248        ["filesize"; "/file"]], 12)],
4249    "return the size of the file in bytes",
4250    "\
4251 This command returns the size of C<file> in bytes.
4252
4253 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4254 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4255 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4256
4257   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4258    [InitBasicFSonLVM, Always, TestOutputList (
4259       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4260        ["lvs"]], ["/dev/VG/LV2"])],
4261    "rename an LVM logical volume",
4262    "\
4263 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4264
4265   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4266    [InitBasicFSonLVM, Always, TestOutputList (
4267       [["umount"; "/"];
4268        ["vg_activate"; "false"; "VG"];
4269        ["vgrename"; "VG"; "VG2"];
4270        ["vg_activate"; "true"; "VG2"];
4271        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4272        ["vgs"]], ["VG2"])],
4273    "rename an LVM volume group",
4274    "\
4275 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4276
4277   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4278    [InitISOFS, Always, TestOutputBuffer (
4279       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4280    "list the contents of a single file in an initrd",
4281    "\
4282 This command unpacks the file C<filename> from the initrd file
4283 called C<initrdpath>.  The filename must be given I<without> the
4284 initial C</> character.
4285
4286 For example, in guestfish you could use the following command
4287 to examine the boot script (usually called C</init>)
4288 contained in a Linux initrd or initramfs image:
4289
4290  initrd-cat /boot/initrd-<version>.img init
4291
4292 See also C<guestfs_initrd_list>.");
4293
4294   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4295    [],
4296    "get the UUID of a physical volume",
4297    "\
4298 This command returns the UUID of the LVM PV C<device>.");
4299
4300   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4301    [],
4302    "get the UUID of a volume group",
4303    "\
4304 This command returns the UUID of the LVM VG named C<vgname>.");
4305
4306   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4307    [],
4308    "get the UUID of a logical volume",
4309    "\
4310 This command returns the UUID of the LVM LV C<device>.");
4311
4312   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4313    [],
4314    "get the PV UUIDs containing the volume group",
4315    "\
4316 Given a VG called C<vgname>, this returns the UUIDs of all
4317 the physical volumes that this volume group resides on.
4318
4319 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4320 calls to associate physical volumes and volume groups.
4321
4322 See also C<guestfs_vglvuuids>.");
4323
4324   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4325    [],
4326    "get the LV UUIDs of all LVs in the volume group",
4327    "\
4328 Given a VG called C<vgname>, this returns the UUIDs of all
4329 the logical volumes created in this volume group.
4330
4331 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4332 calls to associate logical volumes and volume groups.
4333
4334 See also C<guestfs_vgpvuuids>.");
4335
4336 ]
4337
4338 let all_functions = non_daemon_functions @ daemon_functions
4339
4340 (* In some places we want the functions to be displayed sorted
4341  * alphabetically, so this is useful:
4342  *)
4343 let all_functions_sorted =
4344   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4345                compare n1 n2) all_functions
4346
4347 (* Field types for structures. *)
4348 type field =
4349   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4350   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4351   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4352   | FUInt32
4353   | FInt32
4354   | FUInt64
4355   | FInt64
4356   | FBytes                      (* Any int measure that counts bytes. *)
4357   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4358   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4359
4360 (* Because we generate extra parsing code for LVM command line tools,
4361  * we have to pull out the LVM columns separately here.
4362  *)
4363 let lvm_pv_cols = [
4364   "pv_name", FString;
4365   "pv_uuid", FUUID;
4366   "pv_fmt", FString;
4367   "pv_size", FBytes;
4368   "dev_size", FBytes;
4369   "pv_free", FBytes;
4370   "pv_used", FBytes;
4371   "pv_attr", FString (* XXX *);
4372   "pv_pe_count", FInt64;
4373   "pv_pe_alloc_count", FInt64;
4374   "pv_tags", FString;
4375   "pe_start", FBytes;
4376   "pv_mda_count", FInt64;
4377   "pv_mda_free", FBytes;
4378   (* Not in Fedora 10:
4379      "pv_mda_size", FBytes;
4380   *)
4381 ]
4382 let lvm_vg_cols = [
4383   "vg_name", FString;
4384   "vg_uuid", FUUID;
4385   "vg_fmt", FString;
4386   "vg_attr", FString (* XXX *);
4387   "vg_size", FBytes;
4388   "vg_free", FBytes;
4389   "vg_sysid", FString;
4390   "vg_extent_size", FBytes;
4391   "vg_extent_count", FInt64;
4392   "vg_free_count", FInt64;
4393   "max_lv", FInt64;
4394   "max_pv", FInt64;
4395   "pv_count", FInt64;
4396   "lv_count", FInt64;
4397   "snap_count", FInt64;
4398   "vg_seqno", FInt64;
4399   "vg_tags", FString;
4400   "vg_mda_count", FInt64;
4401   "vg_mda_free", FBytes;
4402   (* Not in Fedora 10:
4403      "vg_mda_size", FBytes;
4404   *)
4405 ]
4406 let lvm_lv_cols = [
4407   "lv_name", FString;
4408   "lv_uuid", FUUID;
4409   "lv_attr", FString (* XXX *);
4410   "lv_major", FInt64;
4411   "lv_minor", FInt64;
4412   "lv_kernel_major", FInt64;
4413   "lv_kernel_minor", FInt64;
4414   "lv_size", FBytes;
4415   "seg_count", FInt64;
4416   "origin", FString;
4417   "snap_percent", FOptPercent;
4418   "copy_percent", FOptPercent;
4419   "move_pv", FString;
4420   "lv_tags", FString;
4421   "mirror_log", FString;
4422   "modules", FString;
4423 ]
4424
4425 (* Names and fields in all structures (in RStruct and RStructList)
4426  * that we support.
4427  *)
4428 let structs = [
4429   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4430    * not use this struct in any new code.
4431    *)
4432   "int_bool", [
4433     "i", FInt32;                (* for historical compatibility *)
4434     "b", FInt32;                (* for historical compatibility *)
4435   ];
4436
4437   (* LVM PVs, VGs, LVs. *)
4438   "lvm_pv", lvm_pv_cols;
4439   "lvm_vg", lvm_vg_cols;
4440   "lvm_lv", lvm_lv_cols;
4441
4442   (* Column names and types from stat structures.
4443    * NB. Can't use things like 'st_atime' because glibc header files
4444    * define some of these as macros.  Ugh.
4445    *)
4446   "stat", [
4447     "dev", FInt64;
4448     "ino", FInt64;
4449     "mode", FInt64;
4450     "nlink", FInt64;
4451     "uid", FInt64;
4452     "gid", FInt64;
4453     "rdev", FInt64;
4454     "size", FInt64;
4455     "blksize", FInt64;
4456     "blocks", FInt64;
4457     "atime", FInt64;
4458     "mtime", FInt64;
4459     "ctime", FInt64;
4460   ];
4461   "statvfs", [
4462     "bsize", FInt64;
4463     "frsize", FInt64;
4464     "blocks", FInt64;
4465     "bfree", FInt64;
4466     "bavail", FInt64;
4467     "files", FInt64;
4468     "ffree", FInt64;
4469     "favail", FInt64;
4470     "fsid", FInt64;
4471     "flag", FInt64;
4472     "namemax", FInt64;
4473   ];
4474
4475   (* Column names in dirent structure. *)
4476   "dirent", [
4477     "ino", FInt64;
4478     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4479     "ftyp", FChar;
4480     "name", FString;
4481   ];
4482
4483   (* Version numbers. *)
4484   "version", [
4485     "major", FInt64;
4486     "minor", FInt64;
4487     "release", FInt64;
4488     "extra", FString;
4489   ];
4490
4491   (* Extended attribute. *)
4492   "xattr", [
4493     "attrname", FString;
4494     "attrval", FBuffer;
4495   ];
4496
4497   (* Inotify events. *)
4498   "inotify_event", [
4499     "in_wd", FInt64;
4500     "in_mask", FUInt32;
4501     "in_cookie", FUInt32;
4502     "in_name", FString;
4503   ];
4504
4505   (* Partition table entry. *)
4506   "partition", [
4507     "part_num", FInt32;
4508     "part_start", FBytes;
4509     "part_end", FBytes;
4510     "part_size", FBytes;
4511   ];
4512 ] (* end of structs *)
4513
4514 (* Ugh, Java has to be different ..
4515  * These names are also used by the Haskell bindings.
4516  *)
4517 let java_structs = [
4518   "int_bool", "IntBool";
4519   "lvm_pv", "PV";
4520   "lvm_vg", "VG";
4521   "lvm_lv", "LV";
4522   "stat", "Stat";
4523   "statvfs", "StatVFS";
4524   "dirent", "Dirent";
4525   "version", "Version";
4526   "xattr", "XAttr";
4527   "inotify_event", "INotifyEvent";
4528   "partition", "Partition";
4529 ]
4530
4531 (* What structs are actually returned. *)
4532 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4533
4534 (* Returns a list of RStruct/RStructList structs that are returned
4535  * by any function.  Each element of returned list is a pair:
4536  *
4537  * (structname, RStructOnly)
4538  *    == there exists function which returns RStruct (_, structname)
4539  * (structname, RStructListOnly)
4540  *    == there exists function which returns RStructList (_, structname)
4541  * (structname, RStructAndList)
4542  *    == there are functions returning both RStruct (_, structname)
4543  *                                      and RStructList (_, structname)
4544  *)
4545 let rstructs_used_by functions =
4546   (* ||| is a "logical OR" for rstructs_used_t *)
4547   let (|||) a b =
4548     match a, b with
4549     | RStructAndList, _
4550     | _, RStructAndList -> RStructAndList
4551     | RStructOnly, RStructListOnly
4552     | RStructListOnly, RStructOnly -> RStructAndList
4553     | RStructOnly, RStructOnly -> RStructOnly
4554     | RStructListOnly, RStructListOnly -> RStructListOnly
4555   in
4556
4557   let h = Hashtbl.create 13 in
4558
4559   (* if elem->oldv exists, update entry using ||| operator,
4560    * else just add elem->newv to the hash
4561    *)
4562   let update elem newv =
4563     try  let oldv = Hashtbl.find h elem in
4564          Hashtbl.replace h elem (newv ||| oldv)
4565     with Not_found -> Hashtbl.add h elem newv
4566   in
4567
4568   List.iter (
4569     fun (_, style, _, _, _, _, _) ->
4570       match fst style with
4571       | RStruct (_, structname) -> update structname RStructOnly
4572       | RStructList (_, structname) -> update structname RStructListOnly
4573       | _ -> ()
4574   ) functions;
4575
4576   (* return key->values as a list of (key,value) *)
4577   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4578
4579 (* Used for testing language bindings. *)
4580 type callt =
4581   | CallString of string
4582   | CallOptString of string option
4583   | CallStringList of string list
4584   | CallInt of int
4585   | CallInt64 of int64
4586   | CallBool of bool
4587
4588 (* Used to memoize the result of pod2text. *)
4589 let pod2text_memo_filename = "src/.pod2text.data"
4590 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4591   try
4592     let chan = open_in pod2text_memo_filename in
4593     let v = input_value chan in
4594     close_in chan;
4595     v
4596   with
4597     _ -> Hashtbl.create 13
4598 let pod2text_memo_updated () =
4599   let chan = open_out pod2text_memo_filename in
4600   output_value chan pod2text_memo;
4601   close_out chan
4602
4603 (* Useful functions.
4604  * Note we don't want to use any external OCaml libraries which
4605  * makes this a bit harder than it should be.
4606  *)
4607 module StringMap = Map.Make (String)
4608
4609 let failwithf fs = ksprintf failwith fs
4610
4611 let unique = let i = ref 0 in fun () -> incr i; !i
4612
4613 let replace_char s c1 c2 =
4614   let s2 = String.copy s in
4615   let r = ref false in
4616   for i = 0 to String.length s2 - 1 do
4617     if String.unsafe_get s2 i = c1 then (
4618       String.unsafe_set s2 i c2;
4619       r := true
4620     )
4621   done;
4622   if not !r then s else s2
4623
4624 let isspace c =
4625   c = ' '
4626   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4627
4628 let triml ?(test = isspace) str =
4629   let i = ref 0 in
4630   let n = ref (String.length str) in
4631   while !n > 0 && test str.[!i]; do
4632     decr n;
4633     incr i
4634   done;
4635   if !i = 0 then str
4636   else String.sub str !i !n
4637
4638 let trimr ?(test = isspace) str =
4639   let n = ref (String.length str) in
4640   while !n > 0 && test str.[!n-1]; do
4641     decr n
4642   done;
4643   if !n = String.length str then str
4644   else String.sub str 0 !n
4645
4646 let trim ?(test = isspace) str =
4647   trimr ~test (triml ~test str)
4648
4649 let rec find s sub =
4650   let len = String.length s in
4651   let sublen = String.length sub in
4652   let rec loop i =
4653     if i <= len-sublen then (
4654       let rec loop2 j =
4655         if j < sublen then (
4656           if s.[i+j] = sub.[j] then loop2 (j+1)
4657           else -1
4658         ) else
4659           i (* found *)
4660       in
4661       let r = loop2 0 in
4662       if r = -1 then loop (i+1) else r
4663     ) else
4664       -1 (* not found *)
4665   in
4666   loop 0
4667
4668 let rec replace_str s s1 s2 =
4669   let len = String.length s in
4670   let sublen = String.length s1 in
4671   let i = find s s1 in
4672   if i = -1 then s
4673   else (
4674     let s' = String.sub s 0 i in
4675     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4676     s' ^ s2 ^ replace_str s'' s1 s2
4677   )
4678
4679 let rec string_split sep str =
4680   let len = String.length str in
4681   let seplen = String.length sep in
4682   let i = find str sep in
4683   if i = -1 then [str]
4684   else (
4685     let s' = String.sub str 0 i in
4686     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4687     s' :: string_split sep s''
4688   )
4689
4690 let files_equal n1 n2 =
4691   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4692   match Sys.command cmd with
4693   | 0 -> true
4694   | 1 -> false
4695   | i -> failwithf "%s: failed with error code %d" cmd i
4696
4697 let rec filter_map f = function
4698   | [] -> []
4699   | x :: xs ->
4700       match f x with
4701       | Some y -> y :: filter_map f xs
4702       | None -> filter_map f xs
4703
4704 let rec find_map f = function
4705   | [] -> raise Not_found
4706   | x :: xs ->
4707       match f x with
4708       | Some y -> y
4709       | None -> find_map f xs
4710
4711 let iteri f xs =
4712   let rec loop i = function
4713     | [] -> ()
4714     | x :: xs -> f i x; loop (i+1) xs
4715   in
4716   loop 0 xs
4717
4718 let mapi f xs =
4719   let rec loop i = function
4720     | [] -> []
4721     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4722   in
4723   loop 0 xs
4724
4725 let count_chars c str =
4726   let count = ref 0 in
4727   for i = 0 to String.length str - 1 do
4728     if c = String.unsafe_get str i then incr count
4729   done;
4730   !count
4731
4732 let name_of_argt = function
4733   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4734   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4735   | FileIn n | FileOut n -> n
4736
4737 let java_name_of_struct typ =
4738   try List.assoc typ java_structs
4739   with Not_found ->
4740     failwithf
4741       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4742
4743 let cols_of_struct typ =
4744   try List.assoc typ structs
4745   with Not_found ->
4746     failwithf "cols_of_struct: unknown struct %s" typ
4747
4748 let seq_of_test = function
4749   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4750   | TestOutputListOfDevices (s, _)
4751   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4752   | TestOutputTrue s | TestOutputFalse s
4753   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4754   | TestOutputStruct (s, _)
4755   | TestLastFail s -> s
4756
4757 (* Handling for function flags. *)
4758 let protocol_limit_warning =
4759   "Because of the message protocol, there is a transfer limit
4760 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4761
4762 let danger_will_robinson =
4763   "B<This command is dangerous.  Without careful use you
4764 can easily destroy all your data>."
4765
4766 let deprecation_notice flags =
4767   try
4768     let alt =
4769       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4770     let txt =
4771       sprintf "This function is deprecated.
4772 In new code, use the C<%s> call instead.
4773
4774 Deprecated functions will not be removed from the API, but the
4775 fact that they are deprecated indicates that there are problems
4776 with correct use of these functions." alt in
4777     Some txt
4778   with
4779     Not_found -> None
4780
4781 (* Create list of optional groups. *)
4782 let optgroups =
4783   let h = Hashtbl.create 13 in
4784   List.iter (
4785     fun (name, _, _, flags, _, _, _) ->
4786       List.iter (
4787         function
4788         | Optional group ->
4789             let names = try Hashtbl.find h group with Not_found -> [] in
4790             Hashtbl.replace h group (name :: names)
4791         | _ -> ()
4792       ) flags
4793   ) daemon_functions;
4794   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4795   let groups =
4796     List.map (
4797       fun group -> group, List.sort compare (Hashtbl.find h group)
4798     ) groups in
4799   List.sort (fun x y -> compare (fst x) (fst y)) groups
4800
4801 (* Check function names etc. for consistency. *)
4802 let check_functions () =
4803   let contains_uppercase str =
4804     let len = String.length str in
4805     let rec loop i =
4806       if i >= len then false
4807       else (
4808         let c = str.[i] in
4809         if c >= 'A' && c <= 'Z' then true
4810         else loop (i+1)
4811       )
4812     in
4813     loop 0
4814   in
4815
4816   (* Check function names. *)
4817   List.iter (
4818     fun (name, _, _, _, _, _, _) ->
4819       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4820         failwithf "function name %s does not need 'guestfs' prefix" name;
4821       if name = "" then
4822         failwithf "function name is empty";
4823       if name.[0] < 'a' || name.[0] > 'z' then
4824         failwithf "function name %s must start with lowercase a-z" name;
4825       if String.contains name '-' then
4826         failwithf "function name %s should not contain '-', use '_' instead."
4827           name
4828   ) all_functions;
4829
4830   (* Check function parameter/return names. *)
4831   List.iter (
4832     fun (name, style, _, _, _, _, _) ->
4833       let check_arg_ret_name n =
4834         if contains_uppercase n then
4835           failwithf "%s param/ret %s should not contain uppercase chars"
4836             name n;
4837         if String.contains n '-' || String.contains n '_' then
4838           failwithf "%s param/ret %s should not contain '-' or '_'"
4839             name n;
4840         if n = "value" then
4841           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;
4842         if n = "int" || n = "char" || n = "short" || n = "long" then
4843           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4844         if n = "i" || n = "n" then
4845           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4846         if n = "argv" || n = "args" then
4847           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4848
4849         (* List Haskell, OCaml and C keywords here.
4850          * http://www.haskell.org/haskellwiki/Keywords
4851          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4852          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4853          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4854          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4855          * Omitting _-containing words, since they're handled above.
4856          * Omitting the OCaml reserved word, "val", is ok,
4857          * and saves us from renaming several parameters.
4858          *)
4859         let reserved = [
4860           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4861           "char"; "class"; "const"; "constraint"; "continue"; "data";
4862           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4863           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4864           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4865           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4866           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4867           "interface";
4868           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4869           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4870           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4871           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4872           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4873           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4874           "volatile"; "when"; "where"; "while";
4875           ] in
4876         if List.mem n reserved then
4877           failwithf "%s has param/ret using reserved word %s" name n;
4878       in
4879
4880       (match fst style with
4881        | RErr -> ()
4882        | RInt n | RInt64 n | RBool n
4883        | RConstString n | RConstOptString n | RString n
4884        | RStringList n | RStruct (n, _) | RStructList (n, _)
4885        | RHashtable n | RBufferOut n ->
4886            check_arg_ret_name n
4887       );
4888       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4889   ) all_functions;
4890
4891   (* Check short descriptions. *)
4892   List.iter (
4893     fun (name, _, _, _, _, shortdesc, _) ->
4894       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4895         failwithf "short description of %s should begin with lowercase." name;
4896       let c = shortdesc.[String.length shortdesc-1] in
4897       if c = '\n' || c = '.' then
4898         failwithf "short description of %s should not end with . or \\n." name
4899   ) all_functions;
4900
4901   (* Check long dscriptions. *)
4902   List.iter (
4903     fun (name, _, _, _, _, _, longdesc) ->
4904       if longdesc.[String.length longdesc-1] = '\n' then
4905         failwithf "long description of %s should not end with \\n." name
4906   ) all_functions;
4907
4908   (* Check proc_nrs. *)
4909   List.iter (
4910     fun (name, _, proc_nr, _, _, _, _) ->
4911       if proc_nr <= 0 then
4912         failwithf "daemon function %s should have proc_nr > 0" name
4913   ) daemon_functions;
4914
4915   List.iter (
4916     fun (name, _, proc_nr, _, _, _, _) ->
4917       if proc_nr <> -1 then
4918         failwithf "non-daemon function %s should have proc_nr -1" name
4919   ) non_daemon_functions;
4920
4921   let proc_nrs =
4922     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4923       daemon_functions in
4924   let proc_nrs =
4925     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4926   let rec loop = function
4927     | [] -> ()
4928     | [_] -> ()
4929     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4930         loop rest
4931     | (name1,nr1) :: (name2,nr2) :: _ ->
4932         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4933           name1 name2 nr1 nr2
4934   in
4935   loop proc_nrs;
4936
4937   (* Check tests. *)
4938   List.iter (
4939     function
4940       (* Ignore functions that have no tests.  We generate a
4941        * warning when the user does 'make check' instead.
4942        *)
4943     | name, _, _, _, [], _, _ -> ()
4944     | name, _, _, _, tests, _, _ ->
4945         let funcs =
4946           List.map (
4947             fun (_, _, test) ->
4948               match seq_of_test test with
4949               | [] ->
4950                   failwithf "%s has a test containing an empty sequence" name
4951               | cmds -> List.map List.hd cmds
4952           ) tests in
4953         let funcs = List.flatten funcs in
4954
4955         let tested = List.mem name funcs in
4956
4957         if not tested then
4958           failwithf "function %s has tests but does not test itself" name
4959   ) all_functions
4960
4961 (* 'pr' prints to the current output file. *)
4962 let chan = ref Pervasives.stdout
4963 let lines = ref 0
4964 let pr fs =
4965   ksprintf
4966     (fun str ->
4967        let i = count_chars '\n' str in
4968        lines := !lines + i;
4969        output_string !chan str
4970     ) fs
4971
4972 let copyright_years =
4973   let this_year = 1900 + (localtime (time ())).tm_year in
4974   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4975
4976 (* Generate a header block in a number of standard styles. *)
4977 type comment_style =
4978     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4979 type license = GPLv2plus | LGPLv2plus
4980
4981 let generate_header ?(extra_inputs = []) comment license =
4982   let inputs = "src/generator.ml" :: extra_inputs in
4983   let c = match comment with
4984     | CStyle ->         pr "/* "; " *"
4985     | CPlusPlusStyle -> pr "// "; "//"
4986     | HashStyle ->      pr "# ";  "#"
4987     | OCamlStyle ->     pr "(* "; " *"
4988     | HaskellStyle ->   pr "{- "; "  " in
4989   pr "libguestfs generated file\n";
4990   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4991   List.iter (pr "%s   %s\n" c) inputs;
4992   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4993   pr "%s\n" c;
4994   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4995   pr "%s\n" c;
4996   (match license with
4997    | GPLv2plus ->
4998        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4999        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5000        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5001        pr "%s (at your option) any later version.\n" c;
5002        pr "%s\n" c;
5003        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5004        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5005        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5006        pr "%s GNU General Public License for more details.\n" c;
5007        pr "%s\n" c;
5008        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5009        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5010        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5011
5012    | LGPLv2plus ->
5013        pr "%s This library is free software; you can redistribute it and/or\n" c;
5014        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5015        pr "%s License as published by the Free Software Foundation; either\n" c;
5016        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5017        pr "%s\n" c;
5018        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5019        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5020        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5021        pr "%s Lesser General Public License for more details.\n" c;
5022        pr "%s\n" c;
5023        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5024        pr "%s License along with this library; if not, write to the Free Software\n" c;
5025        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5026   );
5027   (match comment with
5028    | CStyle -> pr " */\n"
5029    | CPlusPlusStyle
5030    | HashStyle -> ()
5031    | OCamlStyle -> pr " *)\n"
5032    | HaskellStyle -> pr "-}\n"
5033   );
5034   pr "\n"
5035
5036 (* Start of main code generation functions below this line. *)
5037
5038 (* Generate the pod documentation for the C API. *)
5039 let rec generate_actions_pod () =
5040   List.iter (
5041     fun (shortname, style, _, flags, _, _, longdesc) ->
5042       if not (List.mem NotInDocs flags) then (
5043         let name = "guestfs_" ^ shortname in
5044         pr "=head2 %s\n\n" name;
5045         pr " ";
5046         generate_prototype ~extern:false ~handle:"handle" name style;
5047         pr "\n\n";
5048         pr "%s\n\n" longdesc;
5049         (match fst style with
5050          | RErr ->
5051              pr "This function returns 0 on success or -1 on error.\n\n"
5052          | RInt _ ->
5053              pr "On error this function returns -1.\n\n"
5054          | RInt64 _ ->
5055              pr "On error this function returns -1.\n\n"
5056          | RBool _ ->
5057              pr "This function returns a C truth value on success or -1 on error.\n\n"
5058          | RConstString _ ->
5059              pr "This function returns a string, or NULL on error.
5060 The string is owned by the guest handle and must I<not> be freed.\n\n"
5061          | RConstOptString _ ->
5062              pr "This function returns a string which may be NULL.
5063 There is way to return an error from this function.
5064 The string is owned by the guest handle and must I<not> be freed.\n\n"
5065          | RString _ ->
5066              pr "This function returns a string, or NULL on error.
5067 I<The caller must free the returned string after use>.\n\n"
5068          | RStringList _ ->
5069              pr "This function returns a NULL-terminated array of strings
5070 (like L<environ(3)>), or NULL if there was an error.
5071 I<The caller must free the strings and the array after use>.\n\n"
5072          | RStruct (_, typ) ->
5073              pr "This function returns a C<struct guestfs_%s *>,
5074 or NULL if there was an error.
5075 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5076          | RStructList (_, typ) ->
5077              pr "This function returns a C<struct guestfs_%s_list *>
5078 (see E<lt>guestfs-structs.hE<gt>),
5079 or NULL if there was an error.
5080 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5081          | RHashtable _ ->
5082              pr "This function returns a NULL-terminated array of
5083 strings, or NULL if there was an error.
5084 The array of strings will always have length C<2n+1>, where
5085 C<n> keys and values alternate, followed by the trailing NULL entry.
5086 I<The caller must free the strings and the array after use>.\n\n"
5087          | RBufferOut _ ->
5088              pr "This function returns a buffer, or NULL on error.
5089 The size of the returned buffer is written to C<*size_r>.
5090 I<The caller must free the returned buffer after use>.\n\n"
5091         );
5092         if List.mem ProtocolLimitWarning flags then
5093           pr "%s\n\n" protocol_limit_warning;
5094         if List.mem DangerWillRobinson flags then
5095           pr "%s\n\n" danger_will_robinson;
5096         match deprecation_notice flags with
5097         | None -> ()
5098         | Some txt -> pr "%s\n\n" txt
5099       )
5100   ) all_functions_sorted
5101
5102 and generate_structs_pod () =
5103   (* Structs documentation. *)
5104   List.iter (
5105     fun (typ, cols) ->
5106       pr "=head2 guestfs_%s\n" typ;
5107       pr "\n";
5108       pr " struct guestfs_%s {\n" typ;
5109       List.iter (
5110         function
5111         | name, FChar -> pr "   char %s;\n" name
5112         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5113         | name, FInt32 -> pr "   int32_t %s;\n" name
5114         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5115         | name, FInt64 -> pr "   int64_t %s;\n" name
5116         | name, FString -> pr "   char *%s;\n" name
5117         | name, FBuffer ->
5118             pr "   /* The next two fields describe a byte array. */\n";
5119             pr "   uint32_t %s_len;\n" name;
5120             pr "   char *%s;\n" name
5121         | name, FUUID ->
5122             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5123             pr "   char %s[32];\n" name
5124         | name, FOptPercent ->
5125             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5126             pr "   float %s;\n" name
5127       ) cols;
5128       pr " };\n";
5129       pr " \n";
5130       pr " struct guestfs_%s_list {\n" typ;
5131       pr "   uint32_t len; /* Number of elements in list. */\n";
5132       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5133       pr " };\n";
5134       pr " \n";
5135       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5136       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5137         typ typ;
5138       pr "\n"
5139   ) structs
5140
5141 and generate_availability_pod () =
5142   (* Availability documentation. *)
5143   pr "=over 4\n";
5144   pr "\n";
5145   List.iter (
5146     fun (group, functions) ->
5147       pr "=item B<%s>\n" group;
5148       pr "\n";
5149       pr "The following functions:\n";
5150       List.iter (pr "L</guestfs_%s>\n") functions;
5151       pr "\n"
5152   ) optgroups;
5153   pr "=back\n";
5154   pr "\n"
5155
5156 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5157  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5158  *
5159  * We have to use an underscore instead of a dash because otherwise
5160  * rpcgen generates incorrect code.
5161  *
5162  * This header is NOT exported to clients, but see also generate_structs_h.
5163  *)
5164 and generate_xdr () =
5165   generate_header CStyle LGPLv2plus;
5166
5167   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5168   pr "typedef string str<>;\n";
5169   pr "\n";
5170
5171   (* Internal structures. *)
5172   List.iter (
5173     function
5174     | typ, cols ->
5175         pr "struct guestfs_int_%s {\n" typ;
5176         List.iter (function
5177                    | name, FChar -> pr "  char %s;\n" name
5178                    | name, FString -> pr "  string %s<>;\n" name
5179                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5180                    | name, FUUID -> pr "  opaque %s[32];\n" name
5181                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5182                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5183                    | name, FOptPercent -> pr "  float %s;\n" name
5184                   ) cols;
5185         pr "};\n";
5186         pr "\n";
5187         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5188         pr "\n";
5189   ) structs;
5190
5191   List.iter (
5192     fun (shortname, style, _, _, _, _, _) ->
5193       let name = "guestfs_" ^ shortname in
5194
5195       (match snd style with
5196        | [] -> ()
5197        | args ->
5198            pr "struct %s_args {\n" name;
5199            List.iter (
5200              function
5201              | Pathname n | Device n | Dev_or_Path n | String n ->
5202                  pr "  string %s<>;\n" n
5203              | OptString n -> pr "  str *%s;\n" n
5204              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5205              | Bool n -> pr "  bool %s;\n" n
5206              | Int n -> pr "  int %s;\n" n
5207              | Int64 n -> pr "  hyper %s;\n" n
5208              | FileIn _ | FileOut _ -> ()
5209            ) args;
5210            pr "};\n\n"
5211       );
5212       (match fst style with
5213        | RErr -> ()
5214        | RInt n ->
5215            pr "struct %s_ret {\n" name;
5216            pr "  int %s;\n" n;
5217            pr "};\n\n"
5218        | RInt64 n ->
5219            pr "struct %s_ret {\n" name;
5220            pr "  hyper %s;\n" n;
5221            pr "};\n\n"
5222        | RBool n ->
5223            pr "struct %s_ret {\n" name;
5224            pr "  bool %s;\n" n;
5225            pr "};\n\n"
5226        | RConstString _ | RConstOptString _ ->
5227            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5228        | RString n ->
5229            pr "struct %s_ret {\n" name;
5230            pr "  string %s<>;\n" n;
5231            pr "};\n\n"
5232        | RStringList n ->
5233            pr "struct %s_ret {\n" name;
5234            pr "  str %s<>;\n" n;
5235            pr "};\n\n"
5236        | RStruct (n, typ) ->
5237            pr "struct %s_ret {\n" name;
5238            pr "  guestfs_int_%s %s;\n" typ n;
5239            pr "};\n\n"
5240        | RStructList (n, typ) ->
5241            pr "struct %s_ret {\n" name;
5242            pr "  guestfs_int_%s_list %s;\n" typ n;
5243            pr "};\n\n"
5244        | RHashtable n ->
5245            pr "struct %s_ret {\n" name;
5246            pr "  str %s<>;\n" n;
5247            pr "};\n\n"
5248        | RBufferOut n ->
5249            pr "struct %s_ret {\n" name;
5250            pr "  opaque %s<>;\n" n;
5251            pr "};\n\n"
5252       );
5253   ) daemon_functions;
5254
5255   (* Table of procedure numbers. *)
5256   pr "enum guestfs_procedure {\n";
5257   List.iter (
5258     fun (shortname, _, proc_nr, _, _, _, _) ->
5259       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5260   ) daemon_functions;
5261   pr "  GUESTFS_PROC_NR_PROCS\n";
5262   pr "};\n";
5263   pr "\n";
5264
5265   (* Having to choose a maximum message size is annoying for several
5266    * reasons (it limits what we can do in the API), but it (a) makes
5267    * the protocol a lot simpler, and (b) provides a bound on the size
5268    * of the daemon which operates in limited memory space.
5269    *)
5270   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5271   pr "\n";
5272
5273   (* Message header, etc. *)
5274   pr "\
5275 /* The communication protocol is now documented in the guestfs(3)
5276  * manpage.
5277  */
5278
5279 const GUESTFS_PROGRAM = 0x2000F5F5;
5280 const GUESTFS_PROTOCOL_VERSION = 1;
5281
5282 /* These constants must be larger than any possible message length. */
5283 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5284 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5285
5286 enum guestfs_message_direction {
5287   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5288   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5289 };
5290
5291 enum guestfs_message_status {
5292   GUESTFS_STATUS_OK = 0,
5293   GUESTFS_STATUS_ERROR = 1
5294 };
5295
5296 const GUESTFS_ERROR_LEN = 256;
5297
5298 struct guestfs_message_error {
5299   string error_message<GUESTFS_ERROR_LEN>;
5300 };
5301
5302 struct guestfs_message_header {
5303   unsigned prog;                     /* GUESTFS_PROGRAM */
5304   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5305   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5306   guestfs_message_direction direction;
5307   unsigned serial;                   /* message serial number */
5308   guestfs_message_status status;
5309 };
5310
5311 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5312
5313 struct guestfs_chunk {
5314   int cancel;                        /* if non-zero, transfer is cancelled */
5315   /* data size is 0 bytes if the transfer has finished successfully */
5316   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5317 };
5318 "
5319
5320 (* Generate the guestfs-structs.h file. *)
5321 and generate_structs_h () =
5322   generate_header CStyle LGPLv2plus;
5323
5324   (* This is a public exported header file containing various
5325    * structures.  The structures are carefully written to have
5326    * exactly the same in-memory format as the XDR structures that
5327    * we use on the wire to the daemon.  The reason for creating
5328    * copies of these structures here is just so we don't have to
5329    * export the whole of guestfs_protocol.h (which includes much
5330    * unrelated and XDR-dependent stuff that we don't want to be
5331    * public, or required by clients).
5332    *
5333    * To reiterate, we will pass these structures to and from the
5334    * client with a simple assignment or memcpy, so the format
5335    * must be identical to what rpcgen / the RFC defines.
5336    *)
5337
5338   (* Public structures. *)
5339   List.iter (
5340     fun (typ, cols) ->
5341       pr "struct guestfs_%s {\n" typ;
5342       List.iter (
5343         function
5344         | name, FChar -> pr "  char %s;\n" name
5345         | name, FString -> pr "  char *%s;\n" name
5346         | name, FBuffer ->
5347             pr "  uint32_t %s_len;\n" name;
5348             pr "  char *%s;\n" name
5349         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5350         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5351         | name, FInt32 -> pr "  int32_t %s;\n" name
5352         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5353         | name, FInt64 -> pr "  int64_t %s;\n" name
5354         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5355       ) cols;
5356       pr "};\n";
5357       pr "\n";
5358       pr "struct guestfs_%s_list {\n" typ;
5359       pr "  uint32_t len;\n";
5360       pr "  struct guestfs_%s *val;\n" typ;
5361       pr "};\n";
5362       pr "\n";
5363       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5364       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5365       pr "\n"
5366   ) structs
5367
5368 (* Generate the guestfs-actions.h file. *)
5369 and generate_actions_h () =
5370   generate_header CStyle LGPLv2plus;
5371   List.iter (
5372     fun (shortname, style, _, _, _, _, _) ->
5373       let name = "guestfs_" ^ shortname in
5374       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5375         name style
5376   ) all_functions
5377
5378 (* Generate the guestfs-internal-actions.h file. *)
5379 and generate_internal_actions_h () =
5380   generate_header CStyle LGPLv2plus;
5381   List.iter (
5382     fun (shortname, style, _, _, _, _, _) ->
5383       let name = "guestfs__" ^ shortname in
5384       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5385         name style
5386   ) non_daemon_functions
5387
5388 (* Generate the client-side dispatch stubs. *)
5389 and generate_client_actions () =
5390   generate_header CStyle LGPLv2plus;
5391
5392   pr "\
5393 #include <stdio.h>
5394 #include <stdlib.h>
5395 #include <stdint.h>
5396 #include <string.h>
5397 #include <inttypes.h>
5398
5399 #include \"guestfs.h\"
5400 #include \"guestfs-internal.h\"
5401 #include \"guestfs-internal-actions.h\"
5402 #include \"guestfs_protocol.h\"
5403
5404 #define error guestfs_error
5405 //#define perrorf guestfs_perrorf
5406 #define safe_malloc guestfs_safe_malloc
5407 #define safe_realloc guestfs_safe_realloc
5408 //#define safe_strdup guestfs_safe_strdup
5409 #define safe_memdup guestfs_safe_memdup
5410
5411 /* Check the return message from a call for validity. */
5412 static int
5413 check_reply_header (guestfs_h *g,
5414                     const struct guestfs_message_header *hdr,
5415                     unsigned int proc_nr, unsigned int serial)
5416 {
5417   if (hdr->prog != GUESTFS_PROGRAM) {
5418     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5419     return -1;
5420   }
5421   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5422     error (g, \"wrong protocol version (%%d/%%d)\",
5423            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5424     return -1;
5425   }
5426   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5427     error (g, \"unexpected message direction (%%d/%%d)\",
5428            hdr->direction, GUESTFS_DIRECTION_REPLY);
5429     return -1;
5430   }
5431   if (hdr->proc != proc_nr) {
5432     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5433     return -1;
5434   }
5435   if (hdr->serial != serial) {
5436     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5437     return -1;
5438   }
5439
5440   return 0;
5441 }
5442
5443 /* Check we are in the right state to run a high-level action. */
5444 static int
5445 check_state (guestfs_h *g, const char *caller)
5446 {
5447   if (!guestfs__is_ready (g)) {
5448     if (guestfs__is_config (g) || guestfs__is_launching (g))
5449       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5450         caller);
5451     else
5452       error (g, \"%%s called from the wrong state, %%d != READY\",
5453         caller, guestfs__get_state (g));
5454     return -1;
5455   }
5456   return 0;
5457 }
5458
5459 ";
5460
5461   (* Generate code to generate guestfish call traces. *)
5462   let trace_call shortname style =
5463     pr "  if (guestfs__get_trace (g)) {\n";
5464
5465     let needs_i =
5466       List.exists (function
5467                    | StringList _ | DeviceList _ -> true
5468                    | _ -> false) (snd style) in
5469     if needs_i then (
5470       pr "    int i;\n";
5471       pr "\n"
5472     );
5473
5474     pr "    printf (\"%s\");\n" shortname;
5475     List.iter (
5476       function
5477       | String n                        (* strings *)
5478       | Device n
5479       | Pathname n
5480       | Dev_or_Path n
5481       | FileIn n
5482       | FileOut n ->
5483           (* guestfish doesn't support string escaping, so neither do we *)
5484           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5485       | OptString n ->                  (* string option *)
5486           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5487           pr "    else printf (\" null\");\n"
5488       | StringList n
5489       | DeviceList n ->                 (* string list *)
5490           pr "    putchar (' ');\n";
5491           pr "    putchar ('\"');\n";
5492           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5493           pr "      if (i > 0) putchar (' ');\n";
5494           pr "      fputs (%s[i], stdout);\n" n;
5495           pr "    }\n";
5496           pr "    putchar ('\"');\n";
5497       | Bool n ->                       (* boolean *)
5498           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5499       | Int n ->                        (* int *)
5500           pr "    printf (\" %%d\", %s);\n" n
5501       | Int64 n ->
5502           pr "    printf (\" %%\" PRIi64, %s);\n" n
5503     ) (snd style);
5504     pr "    putchar ('\\n');\n";
5505     pr "  }\n";
5506     pr "\n";
5507   in
5508
5509   (* For non-daemon functions, generate a wrapper around each function. *)
5510   List.iter (
5511     fun (shortname, style, _, _, _, _, _) ->
5512       let name = "guestfs_" ^ shortname in
5513
5514       generate_prototype ~extern:false ~semicolon:false ~newline:true
5515         ~handle:"g" name style;
5516       pr "{\n";
5517       trace_call shortname style;
5518       pr "  return guestfs__%s " shortname;
5519       generate_c_call_args ~handle:"g" style;
5520       pr ";\n";
5521       pr "}\n";
5522       pr "\n"
5523   ) non_daemon_functions;
5524
5525   (* Client-side stubs for each function. *)
5526   List.iter (
5527     fun (shortname, style, _, _, _, _, _) ->
5528       let name = "guestfs_" ^ shortname in
5529
5530       (* Generate the action stub. *)
5531       generate_prototype ~extern:false ~semicolon:false ~newline:true
5532         ~handle:"g" name style;
5533
5534       let error_code =
5535         match fst style with
5536         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5537         | RConstString _ | RConstOptString _ ->
5538             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5539         | RString _ | RStringList _
5540         | RStruct _ | RStructList _
5541         | RHashtable _ | RBufferOut _ ->
5542             "NULL" in
5543
5544       pr "{\n";
5545
5546       (match snd style with
5547        | [] -> ()
5548        | _ -> pr "  struct %s_args args;\n" name
5549       );
5550
5551       pr "  guestfs_message_header hdr;\n";
5552       pr "  guestfs_message_error err;\n";
5553       let has_ret =
5554         match fst style with
5555         | RErr -> false
5556         | RConstString _ | RConstOptString _ ->
5557             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5558         | RInt _ | RInt64 _
5559         | RBool _ | RString _ | RStringList _
5560         | RStruct _ | RStructList _
5561         | RHashtable _ | RBufferOut _ ->
5562             pr "  struct %s_ret ret;\n" name;
5563             true in
5564
5565       pr "  int serial;\n";
5566       pr "  int r;\n";
5567       pr "\n";
5568       trace_call shortname style;
5569       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5570       pr "  guestfs___set_busy (g);\n";
5571       pr "\n";
5572
5573       (* Send the main header and arguments. *)
5574       (match snd style with
5575        | [] ->
5576            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5577              (String.uppercase shortname)
5578        | args ->
5579            List.iter (
5580              function
5581              | Pathname n | Device n | Dev_or_Path n | String n ->
5582                  pr "  args.%s = (char *) %s;\n" n n
5583              | OptString n ->
5584                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5585              | StringList n | DeviceList n ->
5586                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5587                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5588              | Bool n ->
5589                  pr "  args.%s = %s;\n" n n
5590              | Int n ->
5591                  pr "  args.%s = %s;\n" n n
5592              | Int64 n ->
5593                  pr "  args.%s = %s;\n" n n
5594              | FileIn _ | FileOut _ -> ()
5595            ) args;
5596            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5597              (String.uppercase shortname);
5598            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5599              name;
5600       );
5601       pr "  if (serial == -1) {\n";
5602       pr "    guestfs___end_busy (g);\n";
5603       pr "    return %s;\n" error_code;
5604       pr "  }\n";
5605       pr "\n";
5606
5607       (* Send any additional files (FileIn) requested. *)
5608       let need_read_reply_label = ref false in
5609       List.iter (
5610         function
5611         | FileIn n ->
5612             pr "  r = guestfs___send_file (g, %s);\n" n;
5613             pr "  if (r == -1) {\n";
5614             pr "    guestfs___end_busy (g);\n";
5615             pr "    return %s;\n" error_code;
5616             pr "  }\n";
5617             pr "  if (r == -2) /* daemon cancelled */\n";
5618             pr "    goto read_reply;\n";
5619             need_read_reply_label := true;
5620             pr "\n";
5621         | _ -> ()
5622       ) (snd style);
5623
5624       (* Wait for the reply from the remote end. *)
5625       if !need_read_reply_label then pr " read_reply:\n";
5626       pr "  memset (&hdr, 0, sizeof hdr);\n";
5627       pr "  memset (&err, 0, sizeof err);\n";
5628       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5629       pr "\n";
5630       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5631       if not has_ret then
5632         pr "NULL, NULL"
5633       else
5634         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5635       pr ");\n";
5636
5637       pr "  if (r == -1) {\n";
5638       pr "    guestfs___end_busy (g);\n";
5639       pr "    return %s;\n" error_code;
5640       pr "  }\n";
5641       pr "\n";
5642
5643       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5644         (String.uppercase shortname);
5645       pr "    guestfs___end_busy (g);\n";
5646       pr "    return %s;\n" error_code;
5647       pr "  }\n";
5648       pr "\n";
5649
5650       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5651       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5652       pr "    free (err.error_message);\n";
5653       pr "    guestfs___end_busy (g);\n";
5654       pr "    return %s;\n" error_code;
5655       pr "  }\n";
5656       pr "\n";
5657
5658       (* Expecting to receive further files (FileOut)? *)
5659       List.iter (
5660         function
5661         | FileOut n ->
5662             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5663             pr "    guestfs___end_busy (g);\n";
5664             pr "    return %s;\n" error_code;
5665             pr "  }\n";
5666             pr "\n";
5667         | _ -> ()
5668       ) (snd style);
5669
5670       pr "  guestfs___end_busy (g);\n";
5671
5672       (match fst style with
5673        | RErr -> pr "  return 0;\n"
5674        | RInt n | RInt64 n | RBool n ->
5675            pr "  return ret.%s;\n" n
5676        | RConstString _ | RConstOptString _ ->
5677            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5678        | RString n ->
5679            pr "  return ret.%s; /* caller will free */\n" n
5680        | RStringList n | RHashtable n ->
5681            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5682            pr "  ret.%s.%s_val =\n" n n;
5683            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5684            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5685              n n;
5686            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5687            pr "  return ret.%s.%s_val;\n" n n
5688        | RStruct (n, _) ->
5689            pr "  /* caller will free this */\n";
5690            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5691        | RStructList (n, _) ->
5692            pr "  /* caller will free this */\n";
5693            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5694        | RBufferOut n ->
5695            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5696            pr "   * _val might be NULL here.  To make the API saner for\n";
5697            pr "   * callers, we turn this case into a unique pointer (using\n";
5698            pr "   * malloc(1)).\n";
5699            pr "   */\n";
5700            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5701            pr "    *size_r = ret.%s.%s_len;\n" n n;
5702            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5703            pr "  } else {\n";
5704            pr "    free (ret.%s.%s_val);\n" n n;
5705            pr "    char *p = safe_malloc (g, 1);\n";
5706            pr "    *size_r = ret.%s.%s_len;\n" n n;
5707            pr "    return p;\n";
5708            pr "  }\n";
5709       );
5710
5711       pr "}\n\n"
5712   ) daemon_functions;
5713
5714   (* Functions to free structures. *)
5715   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5716   pr " * structure format is identical to the XDR format.  See note in\n";
5717   pr " * generator.ml.\n";
5718   pr " */\n";
5719   pr "\n";
5720
5721   List.iter (
5722     fun (typ, _) ->
5723       pr "void\n";
5724       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5725       pr "{\n";
5726       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5727       pr "  free (x);\n";
5728       pr "}\n";
5729       pr "\n";
5730
5731       pr "void\n";
5732       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5733       pr "{\n";
5734       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5735       pr "  free (x);\n";
5736       pr "}\n";
5737       pr "\n";
5738
5739   ) structs;
5740
5741 (* Generate daemon/actions.h. *)
5742 and generate_daemon_actions_h () =
5743   generate_header CStyle GPLv2plus;
5744
5745   pr "#include \"../src/guestfs_protocol.h\"\n";
5746   pr "\n";
5747
5748   List.iter (
5749     fun (name, style, _, _, _, _, _) ->
5750       generate_prototype
5751         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5752         name style;
5753   ) daemon_functions
5754
5755 (* Generate the linker script which controls the visibility of
5756  * symbols in the public ABI and ensures no other symbols get
5757  * exported accidentally.
5758  *)
5759 and generate_linker_script () =
5760   generate_header HashStyle GPLv2plus;
5761
5762   let globals = [
5763     "guestfs_create";
5764     "guestfs_close";
5765     "guestfs_get_error_handler";
5766     "guestfs_get_out_of_memory_handler";
5767     "guestfs_last_error";
5768     "guestfs_set_error_handler";
5769     "guestfs_set_launch_done_callback";
5770     "guestfs_set_log_message_callback";
5771     "guestfs_set_out_of_memory_handler";
5772     "guestfs_set_subprocess_quit_callback";
5773
5774     (* Unofficial parts of the API: the bindings code use these
5775      * functions, so it is useful to export them.
5776      *)
5777     "guestfs_safe_calloc";
5778     "guestfs_safe_malloc";
5779   ] in
5780   let functions =
5781     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5782       all_functions in
5783   let structs =
5784     List.concat (
5785       List.map (fun (typ, _) ->
5786                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5787         structs
5788     ) in
5789   let globals = List.sort compare (globals @ functions @ structs) in
5790
5791   pr "{\n";
5792   pr "    global:\n";
5793   List.iter (pr "        %s;\n") globals;
5794   pr "\n";
5795
5796   pr "    local:\n";
5797   pr "        *;\n";
5798   pr "};\n"
5799
5800 (* Generate the server-side stubs. *)
5801 and generate_daemon_actions () =
5802   generate_header CStyle GPLv2plus;
5803
5804   pr "#include <config.h>\n";
5805   pr "\n";
5806   pr "#include <stdio.h>\n";
5807   pr "#include <stdlib.h>\n";
5808   pr "#include <string.h>\n";
5809   pr "#include <inttypes.h>\n";
5810   pr "#include <rpc/types.h>\n";
5811   pr "#include <rpc/xdr.h>\n";
5812   pr "\n";
5813   pr "#include \"daemon.h\"\n";
5814   pr "#include \"c-ctype.h\"\n";
5815   pr "#include \"../src/guestfs_protocol.h\"\n";
5816   pr "#include \"actions.h\"\n";
5817   pr "\n";
5818
5819   List.iter (
5820     fun (name, style, _, _, _, _, _) ->
5821       (* Generate server-side stubs. *)
5822       pr "static void %s_stub (XDR *xdr_in)\n" name;
5823       pr "{\n";
5824       let error_code =
5825         match fst style with
5826         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5827         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5828         | RBool _ -> pr "  int r;\n"; "-1"
5829         | RConstString _ | RConstOptString _ ->
5830             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5831         | RString _ -> pr "  char *r;\n"; "NULL"
5832         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5833         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5834         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5835         | RBufferOut _ ->
5836             pr "  size_t size = 1;\n";
5837             pr "  char *r;\n";
5838             "NULL" in
5839
5840       (match snd style with
5841        | [] -> ()
5842        | args ->
5843            pr "  struct guestfs_%s_args args;\n" name;
5844            List.iter (
5845              function
5846              | Device n | Dev_or_Path n
5847              | Pathname n
5848              | String n -> ()
5849              | OptString n -> pr "  char *%s;\n" n
5850              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5851              | Bool n -> pr "  int %s;\n" n
5852              | Int n -> pr "  int %s;\n" n
5853              | Int64 n -> pr "  int64_t %s;\n" n
5854              | FileIn _ | FileOut _ -> ()
5855            ) args
5856       );
5857       pr "\n";
5858
5859       (match snd style with
5860        | [] -> ()
5861        | args ->
5862            pr "  memset (&args, 0, sizeof args);\n";
5863            pr "\n";
5864            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5865            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5866            pr "    return;\n";
5867            pr "  }\n";
5868            let pr_args n =
5869              pr "  char *%s = args.%s;\n" n n
5870            in
5871            let pr_list_handling_code n =
5872              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5873              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5874              pr "  if (%s == NULL) {\n" n;
5875              pr "    reply_with_perror (\"realloc\");\n";
5876              pr "    goto done;\n";
5877              pr "  }\n";
5878              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5879              pr "  args.%s.%s_val = %s;\n" n n n;
5880            in
5881            List.iter (
5882              function
5883              | Pathname n ->
5884                  pr_args n;
5885                  pr "  ABS_PATH (%s, goto done);\n" n;
5886              | Device n ->
5887                  pr_args n;
5888                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5889              | Dev_or_Path n ->
5890                  pr_args n;
5891                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5892              | String n -> pr_args n
5893              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5894              | StringList n ->
5895                  pr_list_handling_code n;
5896              | DeviceList n ->
5897                  pr_list_handling_code n;
5898                  pr "  /* Ensure that each is a device,\n";
5899                  pr "   * and perform device name translation. */\n";
5900                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5901                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5902                  pr "  }\n";
5903              | Bool n -> pr "  %s = args.%s;\n" n n
5904              | Int n -> pr "  %s = args.%s;\n" n n
5905              | Int64 n -> pr "  %s = args.%s;\n" n n
5906              | FileIn _ | FileOut _ -> ()
5907            ) args;
5908            pr "\n"
5909       );
5910
5911
5912       (* this is used at least for do_equal *)
5913       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5914         (* Emit NEED_ROOT just once, even when there are two or
5915            more Pathname args *)
5916         pr "  NEED_ROOT (goto done);\n";
5917       );
5918
5919       (* Don't want to call the impl with any FileIn or FileOut
5920        * parameters, since these go "outside" the RPC protocol.
5921        *)
5922       let args' =
5923         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5924           (snd style) in
5925       pr "  r = do_%s " name;
5926       generate_c_call_args (fst style, args');
5927       pr ";\n";
5928
5929       (match fst style with
5930        | RErr | RInt _ | RInt64 _ | RBool _
5931        | RConstString _ | RConstOptString _
5932        | RString _ | RStringList _ | RHashtable _
5933        | RStruct (_, _) | RStructList (_, _) ->
5934            pr "  if (r == %s)\n" error_code;
5935            pr "    /* do_%s has already called reply_with_error */\n" name;
5936            pr "    goto done;\n";
5937            pr "\n"
5938        | RBufferOut _ ->
5939            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5940            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5941            pr "   */\n";
5942            pr "  if (size == 1 && r == %s)\n" error_code;
5943            pr "    /* do_%s has already called reply_with_error */\n" name;
5944            pr "    goto done;\n";
5945            pr "\n"
5946       );
5947
5948       (* If there are any FileOut parameters, then the impl must
5949        * send its own reply.
5950        *)
5951       let no_reply =
5952         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5953       if no_reply then
5954         pr "  /* do_%s has already sent a reply */\n" name
5955       else (
5956         match fst style with
5957         | RErr -> pr "  reply (NULL, NULL);\n"
5958         | RInt n | RInt64 n | RBool n ->
5959             pr "  struct guestfs_%s_ret ret;\n" name;
5960             pr "  ret.%s = r;\n" n;
5961             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5962               name
5963         | RConstString _ | RConstOptString _ ->
5964             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5965         | RString n ->
5966             pr "  struct guestfs_%s_ret ret;\n" name;
5967             pr "  ret.%s = r;\n" n;
5968             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5969               name;
5970             pr "  free (r);\n"
5971         | RStringList n | RHashtable n ->
5972             pr "  struct guestfs_%s_ret ret;\n" name;
5973             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5974             pr "  ret.%s.%s_val = r;\n" n n;
5975             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5976               name;
5977             pr "  free_strings (r);\n"
5978         | RStruct (n, _) ->
5979             pr "  struct guestfs_%s_ret ret;\n" name;
5980             pr "  ret.%s = *r;\n" n;
5981             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5982               name;
5983             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5984               name
5985         | RStructList (n, _) ->
5986             pr "  struct guestfs_%s_ret ret;\n" name;
5987             pr "  ret.%s = *r;\n" n;
5988             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5989               name;
5990             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5991               name
5992         | RBufferOut n ->
5993             pr "  struct guestfs_%s_ret ret;\n" name;
5994             pr "  ret.%s.%s_val = r;\n" n n;
5995             pr "  ret.%s.%s_len = size;\n" n n;
5996             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5997               name;
5998             pr "  free (r);\n"
5999       );
6000
6001       (* Free the args. *)
6002       (match snd style with
6003        | [] ->
6004            pr "done: ;\n";
6005        | _ ->
6006            pr "done:\n";
6007            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6008              name
6009       );
6010
6011       pr "}\n\n";
6012   ) daemon_functions;
6013
6014   (* Dispatch function. *)
6015   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6016   pr "{\n";
6017   pr "  switch (proc_nr) {\n";
6018
6019   List.iter (
6020     fun (name, style, _, _, _, _, _) ->
6021       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6022       pr "      %s_stub (xdr_in);\n" name;
6023       pr "      break;\n"
6024   ) daemon_functions;
6025
6026   pr "    default:\n";
6027   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";
6028   pr "  }\n";
6029   pr "}\n";
6030   pr "\n";
6031
6032   (* LVM columns and tokenization functions. *)
6033   (* XXX This generates crap code.  We should rethink how we
6034    * do this parsing.
6035    *)
6036   List.iter (
6037     function
6038     | typ, cols ->
6039         pr "static const char *lvm_%s_cols = \"%s\";\n"
6040           typ (String.concat "," (List.map fst cols));
6041         pr "\n";
6042
6043         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6044         pr "{\n";
6045         pr "  char *tok, *p, *next;\n";
6046         pr "  int i, j;\n";
6047         pr "\n";
6048         (*
6049           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6050           pr "\n";
6051         *)
6052         pr "  if (!str) {\n";
6053         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6054         pr "    return -1;\n";
6055         pr "  }\n";
6056         pr "  if (!*str || c_isspace (*str)) {\n";
6057         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6058         pr "    return -1;\n";
6059         pr "  }\n";
6060         pr "  tok = str;\n";
6061         List.iter (
6062           fun (name, coltype) ->
6063             pr "  if (!tok) {\n";
6064             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6065             pr "    return -1;\n";
6066             pr "  }\n";
6067             pr "  p = strchrnul (tok, ',');\n";
6068             pr "  if (*p) next = p+1; else next = NULL;\n";
6069             pr "  *p = '\\0';\n";
6070             (match coltype with
6071              | FString ->
6072                  pr "  r->%s = strdup (tok);\n" name;
6073                  pr "  if (r->%s == NULL) {\n" name;
6074                  pr "    perror (\"strdup\");\n";
6075                  pr "    return -1;\n";
6076                  pr "  }\n"
6077              | FUUID ->
6078                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6079                  pr "    if (tok[j] == '\\0') {\n";
6080                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6081                  pr "      return -1;\n";
6082                  pr "    } else if (tok[j] != '-')\n";
6083                  pr "      r->%s[i++] = tok[j];\n" name;
6084                  pr "  }\n";
6085              | FBytes ->
6086                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6087                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6088                  pr "    return -1;\n";
6089                  pr "  }\n";
6090              | FInt64 ->
6091                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6092                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6093                  pr "    return -1;\n";
6094                  pr "  }\n";
6095              | FOptPercent ->
6096                  pr "  if (tok[0] == '\\0')\n";
6097                  pr "    r->%s = -1;\n" name;
6098                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6099                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6100                  pr "    return -1;\n";
6101                  pr "  }\n";
6102              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6103                  assert false (* can never be an LVM column *)
6104             );
6105             pr "  tok = next;\n";
6106         ) cols;
6107
6108         pr "  if (tok != NULL) {\n";
6109         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6110         pr "    return -1;\n";
6111         pr "  }\n";
6112         pr "  return 0;\n";
6113         pr "}\n";
6114         pr "\n";
6115
6116         pr "guestfs_int_lvm_%s_list *\n" typ;
6117         pr "parse_command_line_%ss (void)\n" typ;
6118         pr "{\n";
6119         pr "  char *out, *err;\n";
6120         pr "  char *p, *pend;\n";
6121         pr "  int r, i;\n";
6122         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6123         pr "  void *newp;\n";
6124         pr "\n";
6125         pr "  ret = malloc (sizeof *ret);\n";
6126         pr "  if (!ret) {\n";
6127         pr "    reply_with_perror (\"malloc\");\n";
6128         pr "    return NULL;\n";
6129         pr "  }\n";
6130         pr "\n";
6131         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6132         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6133         pr "\n";
6134         pr "  r = command (&out, &err,\n";
6135         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
6136         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6137         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6138         pr "  if (r == -1) {\n";
6139         pr "    reply_with_error (\"%%s\", err);\n";
6140         pr "    free (out);\n";
6141         pr "    free (err);\n";
6142         pr "    free (ret);\n";
6143         pr "    return NULL;\n";
6144         pr "  }\n";
6145         pr "\n";
6146         pr "  free (err);\n";
6147         pr "\n";
6148         pr "  /* Tokenize each line of the output. */\n";
6149         pr "  p = out;\n";
6150         pr "  i = 0;\n";
6151         pr "  while (p) {\n";
6152         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6153         pr "    if (pend) {\n";
6154         pr "      *pend = '\\0';\n";
6155         pr "      pend++;\n";
6156         pr "    }\n";
6157         pr "\n";
6158         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6159         pr "      p++;\n";
6160         pr "\n";
6161         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6162         pr "      p = pend;\n";
6163         pr "      continue;\n";
6164         pr "    }\n";
6165         pr "\n";
6166         pr "    /* Allocate some space to store this next entry. */\n";
6167         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6168         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6169         pr "    if (newp == NULL) {\n";
6170         pr "      reply_with_perror (\"realloc\");\n";
6171         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6172         pr "      free (ret);\n";
6173         pr "      free (out);\n";
6174         pr "      return NULL;\n";
6175         pr "    }\n";
6176         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6177         pr "\n";
6178         pr "    /* Tokenize the next entry. */\n";
6179         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6180         pr "    if (r == -1) {\n";
6181         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6182         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6183         pr "      free (ret);\n";
6184         pr "      free (out);\n";
6185         pr "      return NULL;\n";
6186         pr "    }\n";
6187         pr "\n";
6188         pr "    ++i;\n";
6189         pr "    p = pend;\n";
6190         pr "  }\n";
6191         pr "\n";
6192         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6193         pr "\n";
6194         pr "  free (out);\n";
6195         pr "  return ret;\n";
6196         pr "}\n"
6197
6198   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6199
6200 (* Generate a list of function names, for debugging in the daemon.. *)
6201 and generate_daemon_names () =
6202   generate_header CStyle GPLv2plus;
6203
6204   pr "#include <config.h>\n";
6205   pr "\n";
6206   pr "#include \"daemon.h\"\n";
6207   pr "\n";
6208
6209   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6210   pr "const char *function_names[] = {\n";
6211   List.iter (
6212     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6213   ) daemon_functions;
6214   pr "};\n";
6215
6216 (* Generate the optional groups for the daemon to implement
6217  * guestfs_available.
6218  *)
6219 and generate_daemon_optgroups_c () =
6220   generate_header CStyle GPLv2plus;
6221
6222   pr "#include <config.h>\n";
6223   pr "\n";
6224   pr "#include \"daemon.h\"\n";
6225   pr "#include \"optgroups.h\"\n";
6226   pr "\n";
6227
6228   pr "struct optgroup optgroups[] = {\n";
6229   List.iter (
6230     fun (group, _) ->
6231       pr "  { \"%s\", optgroup_%s_available },\n" group group
6232   ) optgroups;
6233   pr "  { NULL, NULL }\n";
6234   pr "};\n"
6235
6236 and generate_daemon_optgroups_h () =
6237   generate_header CStyle GPLv2plus;
6238
6239   List.iter (
6240     fun (group, _) ->
6241       pr "extern int optgroup_%s_available (void);\n" group
6242   ) optgroups
6243
6244 (* Generate the tests. *)
6245 and generate_tests () =
6246   generate_header CStyle GPLv2plus;
6247
6248   pr "\
6249 #include <stdio.h>
6250 #include <stdlib.h>
6251 #include <string.h>
6252 #include <unistd.h>
6253 #include <sys/types.h>
6254 #include <fcntl.h>
6255
6256 #include \"guestfs.h\"
6257 #include \"guestfs-internal.h\"
6258
6259 static guestfs_h *g;
6260 static int suppress_error = 0;
6261
6262 static void print_error (guestfs_h *g, void *data, const char *msg)
6263 {
6264   if (!suppress_error)
6265     fprintf (stderr, \"%%s\\n\", msg);
6266 }
6267
6268 /* FIXME: nearly identical code appears in fish.c */
6269 static void print_strings (char *const *argv)
6270 {
6271   int argc;
6272
6273   for (argc = 0; argv[argc] != NULL; ++argc)
6274     printf (\"\\t%%s\\n\", argv[argc]);
6275 }
6276
6277 /*
6278 static void print_table (char const *const *argv)
6279 {
6280   int i;
6281
6282   for (i = 0; argv[i] != NULL; i += 2)
6283     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6284 }
6285 */
6286
6287 ";
6288
6289   (* Generate a list of commands which are not tested anywhere. *)
6290   pr "static void no_test_warnings (void)\n";
6291   pr "{\n";
6292
6293   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6294   List.iter (
6295     fun (_, _, _, _, tests, _, _) ->
6296       let tests = filter_map (
6297         function
6298         | (_, (Always|If _|Unless _), test) -> Some test
6299         | (_, Disabled, _) -> None
6300       ) tests in
6301       let seq = List.concat (List.map seq_of_test tests) in
6302       let cmds_tested = List.map List.hd seq in
6303       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6304   ) all_functions;
6305
6306   List.iter (
6307     fun (name, _, _, _, _, _, _) ->
6308       if not (Hashtbl.mem hash name) then
6309         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6310   ) all_functions;
6311
6312   pr "}\n";
6313   pr "\n";
6314
6315   (* Generate the actual tests.  Note that we generate the tests
6316    * in reverse order, deliberately, so that (in general) the
6317    * newest tests run first.  This makes it quicker and easier to
6318    * debug them.
6319    *)
6320   let test_names =
6321     List.map (
6322       fun (name, _, _, flags, tests, _, _) ->
6323         mapi (generate_one_test name flags) tests
6324     ) (List.rev all_functions) in
6325   let test_names = List.concat test_names in
6326   let nr_tests = List.length test_names in
6327
6328   pr "\
6329 int main (int argc, char *argv[])
6330 {
6331   char c = 0;
6332   unsigned long int n_failed = 0;
6333   const char *filename;
6334   int fd;
6335   int nr_tests, test_num = 0;
6336
6337   setbuf (stdout, NULL);
6338
6339   no_test_warnings ();
6340
6341   g = guestfs_create ();
6342   if (g == NULL) {
6343     printf (\"guestfs_create FAILED\\n\");
6344     exit (EXIT_FAILURE);
6345   }
6346
6347   guestfs_set_error_handler (g, print_error, NULL);
6348
6349   guestfs_set_path (g, \"../appliance\");
6350
6351   filename = \"test1.img\";
6352   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6353   if (fd == -1) {
6354     perror (filename);
6355     exit (EXIT_FAILURE);
6356   }
6357   if (lseek (fd, %d, SEEK_SET) == -1) {
6358     perror (\"lseek\");
6359     close (fd);
6360     unlink (filename);
6361     exit (EXIT_FAILURE);
6362   }
6363   if (write (fd, &c, 1) == -1) {
6364     perror (\"write\");
6365     close (fd);
6366     unlink (filename);
6367     exit (EXIT_FAILURE);
6368   }
6369   if (close (fd) == -1) {
6370     perror (filename);
6371     unlink (filename);
6372     exit (EXIT_FAILURE);
6373   }
6374   if (guestfs_add_drive (g, filename) == -1) {
6375     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6376     exit (EXIT_FAILURE);
6377   }
6378
6379   filename = \"test2.img\";
6380   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6381   if (fd == -1) {
6382     perror (filename);
6383     exit (EXIT_FAILURE);
6384   }
6385   if (lseek (fd, %d, SEEK_SET) == -1) {
6386     perror (\"lseek\");
6387     close (fd);
6388     unlink (filename);
6389     exit (EXIT_FAILURE);
6390   }
6391   if (write (fd, &c, 1) == -1) {
6392     perror (\"write\");
6393     close (fd);
6394     unlink (filename);
6395     exit (EXIT_FAILURE);
6396   }
6397   if (close (fd) == -1) {
6398     perror (filename);
6399     unlink (filename);
6400     exit (EXIT_FAILURE);
6401   }
6402   if (guestfs_add_drive (g, filename) == -1) {
6403     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6404     exit (EXIT_FAILURE);
6405   }
6406
6407   filename = \"test3.img\";
6408   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6409   if (fd == -1) {
6410     perror (filename);
6411     exit (EXIT_FAILURE);
6412   }
6413   if (lseek (fd, %d, SEEK_SET) == -1) {
6414     perror (\"lseek\");
6415     close (fd);
6416     unlink (filename);
6417     exit (EXIT_FAILURE);
6418   }
6419   if (write (fd, &c, 1) == -1) {
6420     perror (\"write\");
6421     close (fd);
6422     unlink (filename);
6423     exit (EXIT_FAILURE);
6424   }
6425   if (close (fd) == -1) {
6426     perror (filename);
6427     unlink (filename);
6428     exit (EXIT_FAILURE);
6429   }
6430   if (guestfs_add_drive (g, filename) == -1) {
6431     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6432     exit (EXIT_FAILURE);
6433   }
6434
6435   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6436     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6437     exit (EXIT_FAILURE);
6438   }
6439
6440   if (guestfs_launch (g) == -1) {
6441     printf (\"guestfs_launch FAILED\\n\");
6442     exit (EXIT_FAILURE);
6443   }
6444
6445   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6446   alarm (600);
6447
6448   /* Cancel previous alarm. */
6449   alarm (0);
6450
6451   nr_tests = %d;
6452
6453 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6454
6455   iteri (
6456     fun i test_name ->
6457       pr "  test_num++;\n";
6458       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6459       pr "  if (%s () == -1) {\n" test_name;
6460       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6461       pr "    n_failed++;\n";
6462       pr "  }\n";
6463   ) test_names;
6464   pr "\n";
6465
6466   pr "  guestfs_close (g);\n";
6467   pr "  unlink (\"test1.img\");\n";
6468   pr "  unlink (\"test2.img\");\n";
6469   pr "  unlink (\"test3.img\");\n";
6470   pr "\n";
6471
6472   pr "  if (n_failed > 0) {\n";
6473   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6474   pr "    exit (EXIT_FAILURE);\n";
6475   pr "  }\n";
6476   pr "\n";
6477
6478   pr "  exit (EXIT_SUCCESS);\n";
6479   pr "}\n"
6480
6481 and generate_one_test name flags i (init, prereq, test) =
6482   let test_name = sprintf "test_%s_%d" name i in
6483
6484   pr "\
6485 static int %s_skip (void)
6486 {
6487   const char *str;
6488
6489   str = getenv (\"TEST_ONLY\");
6490   if (str)
6491     return strstr (str, \"%s\") == NULL;
6492   str = getenv (\"SKIP_%s\");
6493   if (str && STREQ (str, \"1\")) return 1;
6494   str = getenv (\"SKIP_TEST_%s\");
6495   if (str && STREQ (str, \"1\")) return 1;
6496   return 0;
6497 }
6498
6499 " test_name name (String.uppercase test_name) (String.uppercase name);
6500
6501   (match prereq with
6502    | Disabled | Always -> ()
6503    | If code | Unless code ->
6504        pr "static int %s_prereq (void)\n" test_name;
6505        pr "{\n";
6506        pr "  %s\n" code;
6507        pr "}\n";
6508        pr "\n";
6509   );
6510
6511   pr "\
6512 static int %s (void)
6513 {
6514   if (%s_skip ()) {
6515     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6516     return 0;
6517   }
6518
6519 " test_name test_name test_name;
6520
6521   (* Optional functions should only be tested if the relevant
6522    * support is available in the daemon.
6523    *)
6524   List.iter (
6525     function
6526     | Optional group ->
6527         pr "  {\n";
6528         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6529         pr "    int r;\n";
6530         pr "    suppress_error = 1;\n";
6531         pr "    r = guestfs_available (g, (char **) groups);\n";
6532         pr "    suppress_error = 0;\n";
6533         pr "    if (r == -1) {\n";
6534         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6535         pr "      return 0;\n";
6536         pr "    }\n";
6537         pr "  }\n";
6538     | _ -> ()
6539   ) flags;
6540
6541   (match prereq with
6542    | Disabled ->
6543        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6544    | If _ ->
6545        pr "  if (! %s_prereq ()) {\n" test_name;
6546        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6547        pr "    return 0;\n";
6548        pr "  }\n";
6549        pr "\n";
6550        generate_one_test_body name i test_name init test;
6551    | Unless _ ->
6552        pr "  if (%s_prereq ()) {\n" test_name;
6553        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6554        pr "    return 0;\n";
6555        pr "  }\n";
6556        pr "\n";
6557        generate_one_test_body name i test_name init test;
6558    | Always ->
6559        generate_one_test_body name i test_name init test
6560   );
6561
6562   pr "  return 0;\n";
6563   pr "}\n";
6564   pr "\n";
6565   test_name
6566
6567 and generate_one_test_body name i test_name init test =
6568   (match init with
6569    | InitNone (* XXX at some point, InitNone and InitEmpty became
6570                * folded together as the same thing.  Really we should
6571                * make InitNone do nothing at all, but the tests may
6572                * need to be checked to make sure this is OK.
6573                *)
6574    | InitEmpty ->
6575        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6576        List.iter (generate_test_command_call test_name)
6577          [["blockdev_setrw"; "/dev/sda"];
6578           ["umount_all"];
6579           ["lvm_remove_all"]]
6580    | InitPartition ->
6581        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6582        List.iter (generate_test_command_call test_name)
6583          [["blockdev_setrw"; "/dev/sda"];
6584           ["umount_all"];
6585           ["lvm_remove_all"];
6586           ["part_disk"; "/dev/sda"; "mbr"]]
6587    | InitBasicFS ->
6588        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6589        List.iter (generate_test_command_call test_name)
6590          [["blockdev_setrw"; "/dev/sda"];
6591           ["umount_all"];
6592           ["lvm_remove_all"];
6593           ["part_disk"; "/dev/sda"; "mbr"];
6594           ["mkfs"; "ext2"; "/dev/sda1"];
6595           ["mount_options"; ""; "/dev/sda1"; "/"]]
6596    | InitBasicFSonLVM ->
6597        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6598          test_name;
6599        List.iter (generate_test_command_call test_name)
6600          [["blockdev_setrw"; "/dev/sda"];
6601           ["umount_all"];
6602           ["lvm_remove_all"];
6603           ["part_disk"; "/dev/sda"; "mbr"];
6604           ["pvcreate"; "/dev/sda1"];
6605           ["vgcreate"; "VG"; "/dev/sda1"];
6606           ["lvcreate"; "LV"; "VG"; "8"];
6607           ["mkfs"; "ext2"; "/dev/VG/LV"];
6608           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6609    | InitISOFS ->
6610        pr "  /* InitISOFS for %s */\n" test_name;
6611        List.iter (generate_test_command_call test_name)
6612          [["blockdev_setrw"; "/dev/sda"];
6613           ["umount_all"];
6614           ["lvm_remove_all"];
6615           ["mount_ro"; "/dev/sdd"; "/"]]
6616   );
6617
6618   let get_seq_last = function
6619     | [] ->
6620         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6621           test_name
6622     | seq ->
6623         let seq = List.rev seq in
6624         List.rev (List.tl seq), List.hd seq
6625   in
6626
6627   match test with
6628   | TestRun seq ->
6629       pr "  /* TestRun for %s (%d) */\n" name i;
6630       List.iter (generate_test_command_call test_name) seq
6631   | TestOutput (seq, expected) ->
6632       pr "  /* TestOutput for %s (%d) */\n" name i;
6633       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6634       let seq, last = get_seq_last seq in
6635       let test () =
6636         pr "    if (STRNEQ (r, expected)) {\n";
6637         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6638         pr "      return -1;\n";
6639         pr "    }\n"
6640       in
6641       List.iter (generate_test_command_call test_name) seq;
6642       generate_test_command_call ~test test_name last
6643   | TestOutputList (seq, expected) ->
6644       pr "  /* TestOutputList for %s (%d) */\n" name i;
6645       let seq, last = get_seq_last seq in
6646       let test () =
6647         iteri (
6648           fun i str ->
6649             pr "    if (!r[%d]) {\n" i;
6650             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6651             pr "      print_strings (r);\n";
6652             pr "      return -1;\n";
6653             pr "    }\n";
6654             pr "    {\n";
6655             pr "      const char *expected = \"%s\";\n" (c_quote str);
6656             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6657             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6658             pr "        return -1;\n";
6659             pr "      }\n";
6660             pr "    }\n"
6661         ) expected;
6662         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6663         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6664           test_name;
6665         pr "      print_strings (r);\n";
6666         pr "      return -1;\n";
6667         pr "    }\n"
6668       in
6669       List.iter (generate_test_command_call test_name) seq;
6670       generate_test_command_call ~test test_name last
6671   | TestOutputListOfDevices (seq, expected) ->
6672       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6673       let seq, last = get_seq_last seq in
6674       let test () =
6675         iteri (
6676           fun i str ->
6677             pr "    if (!r[%d]) {\n" i;
6678             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6679             pr "      print_strings (r);\n";
6680             pr "      return -1;\n";
6681             pr "    }\n";
6682             pr "    {\n";
6683             pr "      const char *expected = \"%s\";\n" (c_quote str);
6684             pr "      r[%d][5] = 's';\n" i;
6685             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6686             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6687             pr "        return -1;\n";
6688             pr "      }\n";
6689             pr "    }\n"
6690         ) expected;
6691         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6692         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6693           test_name;
6694         pr "      print_strings (r);\n";
6695         pr "      return -1;\n";
6696         pr "    }\n"
6697       in
6698       List.iter (generate_test_command_call test_name) seq;
6699       generate_test_command_call ~test test_name last
6700   | TestOutputInt (seq, expected) ->
6701       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6702       let seq, last = get_seq_last seq in
6703       let test () =
6704         pr "    if (r != %d) {\n" expected;
6705         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6706           test_name expected;
6707         pr "               (int) r);\n";
6708         pr "      return -1;\n";
6709         pr "    }\n"
6710       in
6711       List.iter (generate_test_command_call test_name) seq;
6712       generate_test_command_call ~test test_name last
6713   | TestOutputIntOp (seq, op, expected) ->
6714       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6715       let seq, last = get_seq_last seq in
6716       let test () =
6717         pr "    if (! (r %s %d)) {\n" op expected;
6718         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6719           test_name op expected;
6720         pr "               (int) r);\n";
6721         pr "      return -1;\n";
6722         pr "    }\n"
6723       in
6724       List.iter (generate_test_command_call test_name) seq;
6725       generate_test_command_call ~test test_name last
6726   | TestOutputTrue seq ->
6727       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6728       let seq, last = get_seq_last seq in
6729       let test () =
6730         pr "    if (!r) {\n";
6731         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6732           test_name;
6733         pr "      return -1;\n";
6734         pr "    }\n"
6735       in
6736       List.iter (generate_test_command_call test_name) seq;
6737       generate_test_command_call ~test test_name last
6738   | TestOutputFalse seq ->
6739       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6740       let seq, last = get_seq_last seq in
6741       let test () =
6742         pr "    if (r) {\n";
6743         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6744           test_name;
6745         pr "      return -1;\n";
6746         pr "    }\n"
6747       in
6748       List.iter (generate_test_command_call test_name) seq;
6749       generate_test_command_call ~test test_name last
6750   | TestOutputLength (seq, expected) ->
6751       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6752       let seq, last = get_seq_last seq in
6753       let test () =
6754         pr "    int j;\n";
6755         pr "    for (j = 0; j < %d; ++j)\n" expected;
6756         pr "      if (r[j] == NULL) {\n";
6757         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6758           test_name;
6759         pr "        print_strings (r);\n";
6760         pr "        return -1;\n";
6761         pr "      }\n";
6762         pr "    if (r[j] != NULL) {\n";
6763         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6764           test_name;
6765         pr "      print_strings (r);\n";
6766         pr "      return -1;\n";
6767         pr "    }\n"
6768       in
6769       List.iter (generate_test_command_call test_name) seq;
6770       generate_test_command_call ~test test_name last
6771   | TestOutputBuffer (seq, expected) ->
6772       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6773       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6774       let seq, last = get_seq_last seq in
6775       let len = String.length expected in
6776       let test () =
6777         pr "    if (size != %d) {\n" len;
6778         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6779         pr "      return -1;\n";
6780         pr "    }\n";
6781         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6782         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6783         pr "      return -1;\n";
6784         pr "    }\n"
6785       in
6786       List.iter (generate_test_command_call test_name) seq;
6787       generate_test_command_call ~test test_name last
6788   | TestOutputStruct (seq, checks) ->
6789       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6790       let seq, last = get_seq_last seq in
6791       let test () =
6792         List.iter (
6793           function
6794           | CompareWithInt (field, expected) ->
6795               pr "    if (r->%s != %d) {\n" field expected;
6796               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6797                 test_name field expected;
6798               pr "               (int) r->%s);\n" field;
6799               pr "      return -1;\n";
6800               pr "    }\n"
6801           | CompareWithIntOp (field, op, expected) ->
6802               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6803               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6804                 test_name field op expected;
6805               pr "               (int) r->%s);\n" field;
6806               pr "      return -1;\n";
6807               pr "    }\n"
6808           | CompareWithString (field, expected) ->
6809               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6810               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6811                 test_name field expected;
6812               pr "               r->%s);\n" field;
6813               pr "      return -1;\n";
6814               pr "    }\n"
6815           | CompareFieldsIntEq (field1, field2) ->
6816               pr "    if (r->%s != r->%s) {\n" field1 field2;
6817               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6818                 test_name field1 field2;
6819               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6820               pr "      return -1;\n";
6821               pr "    }\n"
6822           | CompareFieldsStrEq (field1, field2) ->
6823               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6824               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6825                 test_name field1 field2;
6826               pr "               r->%s, r->%s);\n" field1 field2;
6827               pr "      return -1;\n";
6828               pr "    }\n"
6829         ) checks
6830       in
6831       List.iter (generate_test_command_call test_name) seq;
6832       generate_test_command_call ~test test_name last
6833   | TestLastFail seq ->
6834       pr "  /* TestLastFail for %s (%d) */\n" name i;
6835       let seq, last = get_seq_last seq in
6836       List.iter (generate_test_command_call test_name) seq;
6837       generate_test_command_call test_name ~expect_error:true last
6838
6839 (* Generate the code to run a command, leaving the result in 'r'.
6840  * If you expect to get an error then you should set expect_error:true.
6841  *)
6842 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6843   match cmd with
6844   | [] -> assert false
6845   | name :: args ->
6846       (* Look up the command to find out what args/ret it has. *)
6847       let style =
6848         try
6849           let _, style, _, _, _, _, _ =
6850             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6851           style
6852         with Not_found ->
6853           failwithf "%s: in test, command %s was not found" test_name name in
6854
6855       if List.length (snd style) <> List.length args then
6856         failwithf "%s: in test, wrong number of args given to %s"
6857           test_name name;
6858
6859       pr "  {\n";
6860
6861       List.iter (
6862         function
6863         | OptString n, "NULL" -> ()
6864         | Pathname n, arg
6865         | Device n, arg
6866         | Dev_or_Path n, arg
6867         | String n, arg
6868         | OptString n, arg ->
6869             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6870         | Int _, _
6871         | Int64 _, _
6872         | Bool _, _
6873         | FileIn _, _ | FileOut _, _ -> ()
6874         | StringList n, "" | DeviceList n, "" ->
6875             pr "    const char *const %s[1] = { NULL };\n" n
6876         | StringList n, arg | DeviceList n, arg ->
6877             let strs = string_split " " arg in
6878             iteri (
6879               fun i str ->
6880                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6881             ) strs;
6882             pr "    const char *const %s[] = {\n" n;
6883             iteri (
6884               fun i _ -> pr "      %s_%d,\n" n i
6885             ) strs;
6886             pr "      NULL\n";
6887             pr "    };\n";
6888       ) (List.combine (snd style) args);
6889
6890       let error_code =
6891         match fst style with
6892         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6893         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6894         | RConstString _ | RConstOptString _ ->
6895             pr "    const char *r;\n"; "NULL"
6896         | RString _ -> pr "    char *r;\n"; "NULL"
6897         | RStringList _ | RHashtable _ ->
6898             pr "    char **r;\n";
6899             pr "    int i;\n";
6900             "NULL"
6901         | RStruct (_, typ) ->
6902             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6903         | RStructList (_, typ) ->
6904             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6905         | RBufferOut _ ->
6906             pr "    char *r;\n";
6907             pr "    size_t size;\n";
6908             "NULL" in
6909
6910       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6911       pr "    r = guestfs_%s (g" name;
6912
6913       (* Generate the parameters. *)
6914       List.iter (
6915         function
6916         | OptString _, "NULL" -> pr ", NULL"
6917         | Pathname n, _
6918         | Device n, _ | Dev_or_Path n, _
6919         | String n, _
6920         | OptString n, _ ->
6921             pr ", %s" n
6922         | FileIn _, arg | FileOut _, arg ->
6923             pr ", \"%s\"" (c_quote arg)
6924         | StringList n, _ | DeviceList n, _ ->
6925             pr ", (char **) %s" n
6926         | Int _, arg ->
6927             let i =
6928               try int_of_string arg
6929               with Failure "int_of_string" ->
6930                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6931             pr ", %d" i
6932         | Int64 _, arg ->
6933             let i =
6934               try Int64.of_string arg
6935               with Failure "int_of_string" ->
6936                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6937             pr ", %Ld" i
6938         | Bool _, arg ->
6939             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6940       ) (List.combine (snd style) args);
6941
6942       (match fst style with
6943        | RBufferOut _ -> pr ", &size"
6944        | _ -> ()
6945       );
6946
6947       pr ");\n";
6948
6949       if not expect_error then
6950         pr "    if (r == %s)\n" error_code
6951       else
6952         pr "    if (r != %s)\n" error_code;
6953       pr "      return -1;\n";
6954
6955       (* Insert the test code. *)
6956       (match test with
6957        | None -> ()
6958        | Some f -> f ()
6959       );
6960
6961       (match fst style with
6962        | RErr | RInt _ | RInt64 _ | RBool _
6963        | RConstString _ | RConstOptString _ -> ()
6964        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6965        | RStringList _ | RHashtable _ ->
6966            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6967            pr "      free (r[i]);\n";
6968            pr "    free (r);\n"
6969        | RStruct (_, typ) ->
6970            pr "    guestfs_free_%s (r);\n" typ
6971        | RStructList (_, typ) ->
6972            pr "    guestfs_free_%s_list (r);\n" typ
6973       );
6974
6975       pr "  }\n"
6976
6977 and c_quote str =
6978   let str = replace_str str "\r" "\\r" in
6979   let str = replace_str str "\n" "\\n" in
6980   let str = replace_str str "\t" "\\t" in
6981   let str = replace_str str "\000" "\\0" in
6982   str
6983
6984 (* Generate a lot of different functions for guestfish. *)
6985 and generate_fish_cmds () =
6986   generate_header CStyle GPLv2plus;
6987
6988   let all_functions =
6989     List.filter (
6990       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6991     ) all_functions in
6992   let all_functions_sorted =
6993     List.filter (
6994       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6995     ) all_functions_sorted in
6996
6997   pr "#include <config.h>\n";
6998   pr "\n";
6999   pr "#include <stdio.h>\n";
7000   pr "#include <stdlib.h>\n";
7001   pr "#include <string.h>\n";
7002   pr "#include <inttypes.h>\n";
7003   pr "\n";
7004   pr "#include <guestfs.h>\n";
7005   pr "#include \"c-ctype.h\"\n";
7006   pr "#include \"full-write.h\"\n";
7007   pr "#include \"xstrtol.h\"\n";
7008   pr "#include \"fish.h\"\n";
7009   pr "\n";
7010
7011   (* list_commands function, which implements guestfish -h *)
7012   pr "void list_commands (void)\n";
7013   pr "{\n";
7014   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7015   pr "  list_builtin_commands ();\n";
7016   List.iter (
7017     fun (name, _, _, flags, _, shortdesc, _) ->
7018       let name = replace_char name '_' '-' in
7019       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7020         name shortdesc
7021   ) all_functions_sorted;
7022   pr "  printf (\"    %%s\\n\",";
7023   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7024   pr "}\n";
7025   pr "\n";
7026
7027   (* display_command function, which implements guestfish -h cmd *)
7028   pr "void display_command (const char *cmd)\n";
7029   pr "{\n";
7030   List.iter (
7031     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7032       let name2 = replace_char name '_' '-' in
7033       let alias =
7034         try find_map (function FishAlias n -> Some n | _ -> None) flags
7035         with Not_found -> name in
7036       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7037       let synopsis =
7038         match snd style with
7039         | [] -> name2
7040         | args ->
7041             sprintf "%s %s"
7042               name2 (String.concat " " (List.map name_of_argt args)) in
7043
7044       let warnings =
7045         if List.mem ProtocolLimitWarning flags then
7046           ("\n\n" ^ protocol_limit_warning)
7047         else "" in
7048
7049       (* For DangerWillRobinson commands, we should probably have
7050        * guestfish prompt before allowing you to use them (especially
7051        * in interactive mode). XXX
7052        *)
7053       let warnings =
7054         warnings ^
7055           if List.mem DangerWillRobinson flags then
7056             ("\n\n" ^ danger_will_robinson)
7057           else "" in
7058
7059       let warnings =
7060         warnings ^
7061           match deprecation_notice flags with
7062           | None -> ""
7063           | Some txt -> "\n\n" ^ txt in
7064
7065       let describe_alias =
7066         if name <> alias then
7067           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7068         else "" in
7069
7070       pr "  if (";
7071       pr "STRCASEEQ (cmd, \"%s\")" name;
7072       if name <> name2 then
7073         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7074       if name <> alias then
7075         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7076       pr ")\n";
7077       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7078         name2 shortdesc
7079         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7080          "=head1 DESCRIPTION\n\n" ^
7081          longdesc ^ warnings ^ describe_alias);
7082       pr "  else\n"
7083   ) all_functions;
7084   pr "    display_builtin_command (cmd);\n";
7085   pr "}\n";
7086   pr "\n";
7087
7088   let emit_print_list_function typ =
7089     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7090       typ typ typ;
7091     pr "{\n";
7092     pr "  unsigned int i;\n";
7093     pr "\n";
7094     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7095     pr "    printf (\"[%%d] = {\\n\", i);\n";
7096     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7097     pr "    printf (\"}\\n\");\n";
7098     pr "  }\n";
7099     pr "}\n";
7100     pr "\n";
7101   in
7102
7103   (* print_* functions *)
7104   List.iter (
7105     fun (typ, cols) ->
7106       let needs_i =
7107         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7108
7109       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7110       pr "{\n";
7111       if needs_i then (
7112         pr "  unsigned int i;\n";
7113         pr "\n"
7114       );
7115       List.iter (
7116         function
7117         | name, FString ->
7118             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7119         | name, FUUID ->
7120             pr "  printf (\"%%s%s: \", indent);\n" name;
7121             pr "  for (i = 0; i < 32; ++i)\n";
7122             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7123             pr "  printf (\"\\n\");\n"
7124         | name, FBuffer ->
7125             pr "  printf (\"%%s%s: \", indent);\n" name;
7126             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7127             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7128             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7129             pr "    else\n";
7130             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7131             pr "  printf (\"\\n\");\n"
7132         | name, (FUInt64|FBytes) ->
7133             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7134               name typ name
7135         | name, FInt64 ->
7136             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7137               name typ name
7138         | name, FUInt32 ->
7139             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7140               name typ name
7141         | name, FInt32 ->
7142             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7143               name typ name
7144         | name, FChar ->
7145             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7146               name typ name
7147         | name, FOptPercent ->
7148             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7149               typ name name typ name;
7150             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7151       ) cols;
7152       pr "}\n";
7153       pr "\n";
7154   ) structs;
7155
7156   (* Emit a print_TYPE_list function definition only if that function is used. *)
7157   List.iter (
7158     function
7159     | typ, (RStructListOnly | RStructAndList) ->
7160         (* generate the function for typ *)
7161         emit_print_list_function typ
7162     | typ, _ -> () (* empty *)
7163   ) (rstructs_used_by all_functions);
7164
7165   (* Emit a print_TYPE function definition only if that function is used. *)
7166   List.iter (
7167     function
7168     | typ, (RStructOnly | RStructAndList) ->
7169         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7170         pr "{\n";
7171         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7172         pr "}\n";
7173         pr "\n";
7174     | typ, _ -> () (* empty *)
7175   ) (rstructs_used_by all_functions);
7176
7177   (* run_<action> actions *)
7178   List.iter (
7179     fun (name, style, _, flags, _, _, _) ->
7180       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7181       pr "{\n";
7182       (match fst style with
7183        | RErr
7184        | RInt _
7185        | RBool _ -> pr "  int r;\n"
7186        | RInt64 _ -> pr "  int64_t r;\n"
7187        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7188        | RString _ -> pr "  char *r;\n"
7189        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7190        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7191        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7192        | RBufferOut _ ->
7193            pr "  char *r;\n";
7194            pr "  size_t size;\n";
7195       );
7196       List.iter (
7197         function
7198         | Device n
7199         | String n
7200         | OptString n
7201         | FileIn n
7202         | FileOut n -> pr "  const char *%s;\n" n
7203         | Pathname n
7204         | Dev_or_Path n -> pr "  char *%s;\n" n
7205         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7206         | Bool n -> pr "  int %s;\n" n
7207         | Int n -> pr "  int %s;\n" n
7208         | Int64 n -> pr "  int64_t %s;\n" n
7209       ) (snd style);
7210
7211       (* Check and convert parameters. *)
7212       let argc_expected = List.length (snd style) in
7213       pr "  if (argc != %d) {\n" argc_expected;
7214       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7215         argc_expected;
7216       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7217       pr "    return -1;\n";
7218       pr "  }\n";
7219
7220       let parse_integer fn fntyp rtyp range name i =
7221         pr "  {\n";
7222         pr "    strtol_error xerr;\n";
7223         pr "    %s r;\n" fntyp;
7224         pr "\n";
7225         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7226         pr "    if (xerr != LONGINT_OK) {\n";
7227         pr "      fprintf (stderr,\n";
7228         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7229         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7230         pr "      return -1;\n";
7231         pr "    }\n";
7232         (match range with
7233          | None -> ()
7234          | Some (min, max, comment) ->
7235              pr "    /* %s */\n" comment;
7236              pr "    if (r < %s || r > %s) {\n" min max;
7237              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7238                name;
7239              pr "      return -1;\n";
7240              pr "    }\n";
7241              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7242         );
7243         pr "    %s = r;\n" name;
7244         pr "  }\n";
7245       in
7246
7247       iteri (
7248         fun i ->
7249           function
7250           | Device name
7251           | String name ->
7252               pr "  %s = argv[%d];\n" name i
7253           | Pathname name
7254           | Dev_or_Path name ->
7255               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7256               pr "  if (%s == NULL) return -1;\n" name
7257           | OptString name ->
7258               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7259                 name i i
7260           | FileIn name ->
7261               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7262                 name i i
7263           | FileOut name ->
7264               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7265                 name i i
7266           | StringList name | DeviceList name ->
7267               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7268               pr "  if (%s == NULL) return -1;\n" name;
7269           | Bool name ->
7270               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7271           | Int name ->
7272               let range =
7273                 let min = "(-(2LL<<30))"
7274                 and max = "((2LL<<30)-1)"
7275                 and comment =
7276                   "The Int type in the generator is a signed 31 bit int." in
7277                 Some (min, max, comment) in
7278               parse_integer "xstrtoll" "long long" "int" range name i
7279           | Int64 name ->
7280               parse_integer "xstrtoll" "long long" "int64_t" None name i
7281       ) (snd style);
7282
7283       (* Call C API function. *)
7284       let fn =
7285         try find_map (function FishAction n -> Some n | _ -> None) flags
7286         with Not_found -> sprintf "guestfs_%s" name in
7287       pr "  r = %s " fn;
7288       generate_c_call_args ~handle:"g" style;
7289       pr ";\n";
7290
7291       List.iter (
7292         function
7293         | Device name | String name
7294         | OptString name | FileIn name | FileOut name | Bool name
7295         | Int name | Int64 name -> ()
7296         | Pathname name | Dev_or_Path name ->
7297             pr "  free (%s);\n" name
7298         | StringList name | DeviceList name ->
7299             pr "  free_strings (%s);\n" name
7300       ) (snd style);
7301
7302       (* Check return value for errors and display command results. *)
7303       (match fst style with
7304        | RErr -> pr "  return r;\n"
7305        | RInt _ ->
7306            pr "  if (r == -1) return -1;\n";
7307            pr "  printf (\"%%d\\n\", r);\n";
7308            pr "  return 0;\n"
7309        | RInt64 _ ->
7310            pr "  if (r == -1) return -1;\n";
7311            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7312            pr "  return 0;\n"
7313        | RBool _ ->
7314            pr "  if (r == -1) return -1;\n";
7315            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7316            pr "  return 0;\n"
7317        | RConstString _ ->
7318            pr "  if (r == NULL) return -1;\n";
7319            pr "  printf (\"%%s\\n\", r);\n";
7320            pr "  return 0;\n"
7321        | RConstOptString _ ->
7322            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7323            pr "  return 0;\n"
7324        | RString _ ->
7325            pr "  if (r == NULL) return -1;\n";
7326            pr "  printf (\"%%s\\n\", r);\n";
7327            pr "  free (r);\n";
7328            pr "  return 0;\n"
7329        | RStringList _ ->
7330            pr "  if (r == NULL) return -1;\n";
7331            pr "  print_strings (r);\n";
7332            pr "  free_strings (r);\n";
7333            pr "  return 0;\n"
7334        | RStruct (_, typ) ->
7335            pr "  if (r == NULL) return -1;\n";
7336            pr "  print_%s (r);\n" typ;
7337            pr "  guestfs_free_%s (r);\n" typ;
7338            pr "  return 0;\n"
7339        | RStructList (_, typ) ->
7340            pr "  if (r == NULL) return -1;\n";
7341            pr "  print_%s_list (r);\n" typ;
7342            pr "  guestfs_free_%s_list (r);\n" typ;
7343            pr "  return 0;\n"
7344        | RHashtable _ ->
7345            pr "  if (r == NULL) return -1;\n";
7346            pr "  print_table (r);\n";
7347            pr "  free_strings (r);\n";
7348            pr "  return 0;\n"
7349        | RBufferOut _ ->
7350            pr "  if (r == NULL) return -1;\n";
7351            pr "  if (full_write (1, r, size) != size) {\n";
7352            pr "    perror (\"write\");\n";
7353            pr "    free (r);\n";
7354            pr "    return -1;\n";
7355            pr "  }\n";
7356            pr "  free (r);\n";
7357            pr "  return 0;\n"
7358       );
7359       pr "}\n";
7360       pr "\n"
7361   ) all_functions;
7362
7363   (* run_action function *)
7364   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7365   pr "{\n";
7366   List.iter (
7367     fun (name, _, _, flags, _, _, _) ->
7368       let name2 = replace_char name '_' '-' in
7369       let alias =
7370         try find_map (function FishAlias n -> Some n | _ -> None) flags
7371         with Not_found -> name in
7372       pr "  if (";
7373       pr "STRCASEEQ (cmd, \"%s\")" name;
7374       if name <> name2 then
7375         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7376       if name <> alias then
7377         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7378       pr ")\n";
7379       pr "    return run_%s (cmd, argc, argv);\n" name;
7380       pr "  else\n";
7381   ) all_functions;
7382   pr "    {\n";
7383   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7384   pr "      return -1;\n";
7385   pr "    }\n";
7386   pr "  return 0;\n";
7387   pr "}\n";
7388   pr "\n"
7389
7390 (* Readline completion for guestfish. *)
7391 and generate_fish_completion () =
7392   generate_header CStyle GPLv2plus;
7393
7394   let all_functions =
7395     List.filter (
7396       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7397     ) all_functions in
7398
7399   pr "\
7400 #include <config.h>
7401
7402 #include <stdio.h>
7403 #include <stdlib.h>
7404 #include <string.h>
7405
7406 #ifdef HAVE_LIBREADLINE
7407 #include <readline/readline.h>
7408 #endif
7409
7410 #include \"fish.h\"
7411
7412 #ifdef HAVE_LIBREADLINE
7413
7414 static const char *const commands[] = {
7415   BUILTIN_COMMANDS_FOR_COMPLETION,
7416 ";
7417
7418   (* Get the commands, including the aliases.  They don't need to be
7419    * sorted - the generator() function just does a dumb linear search.
7420    *)
7421   let commands =
7422     List.map (
7423       fun (name, _, _, flags, _, _, _) ->
7424         let name2 = replace_char name '_' '-' in
7425         let alias =
7426           try find_map (function FishAlias n -> Some n | _ -> None) flags
7427           with Not_found -> name in
7428
7429         if name <> alias then [name2; alias] else [name2]
7430     ) all_functions in
7431   let commands = List.flatten commands in
7432
7433   List.iter (pr "  \"%s\",\n") commands;
7434
7435   pr "  NULL
7436 };
7437
7438 static char *
7439 generator (const char *text, int state)
7440 {
7441   static int index, len;
7442   const char *name;
7443
7444   if (!state) {
7445     index = 0;
7446     len = strlen (text);
7447   }
7448
7449   rl_attempted_completion_over = 1;
7450
7451   while ((name = commands[index]) != NULL) {
7452     index++;
7453     if (STRCASEEQLEN (name, text, len))
7454       return strdup (name);
7455   }
7456
7457   return NULL;
7458 }
7459
7460 #endif /* HAVE_LIBREADLINE */
7461
7462 char **do_completion (const char *text, int start, int end)
7463 {
7464   char **matches = NULL;
7465
7466 #ifdef HAVE_LIBREADLINE
7467   rl_completion_append_character = ' ';
7468
7469   if (start == 0)
7470     matches = rl_completion_matches (text, generator);
7471   else if (complete_dest_paths)
7472     matches = rl_completion_matches (text, complete_dest_paths_generator);
7473 #endif
7474
7475   return matches;
7476 }
7477 ";
7478
7479 (* Generate the POD documentation for guestfish. *)
7480 and generate_fish_actions_pod () =
7481   let all_functions_sorted =
7482     List.filter (
7483       fun (_, _, _, flags, _, _, _) ->
7484         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7485     ) all_functions_sorted in
7486
7487   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7488
7489   List.iter (
7490     fun (name, style, _, flags, _, _, longdesc) ->
7491       let longdesc =
7492         Str.global_substitute rex (
7493           fun s ->
7494             let sub =
7495               try Str.matched_group 1 s
7496               with Not_found ->
7497                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7498             "C<" ^ replace_char sub '_' '-' ^ ">"
7499         ) longdesc in
7500       let name = replace_char name '_' '-' in
7501       let alias =
7502         try find_map (function FishAlias n -> Some n | _ -> None) flags
7503         with Not_found -> name in
7504
7505       pr "=head2 %s" name;
7506       if name <> alias then
7507         pr " | %s" alias;
7508       pr "\n";
7509       pr "\n";
7510       pr " %s" name;
7511       List.iter (
7512         function
7513         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7514         | OptString n -> pr " %s" n
7515         | StringList n | DeviceList n -> pr " '%s ...'" n
7516         | Bool _ -> pr " true|false"
7517         | Int n -> pr " %s" n
7518         | Int64 n -> pr " %s" n
7519         | FileIn n | FileOut n -> pr " (%s|-)" n
7520       ) (snd style);
7521       pr "\n";
7522       pr "\n";
7523       pr "%s\n\n" longdesc;
7524
7525       if List.exists (function FileIn _ | FileOut _ -> true
7526                       | _ -> false) (snd style) then
7527         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7528
7529       if List.mem ProtocolLimitWarning flags then
7530         pr "%s\n\n" protocol_limit_warning;
7531
7532       if List.mem DangerWillRobinson flags then
7533         pr "%s\n\n" danger_will_robinson;
7534
7535       match deprecation_notice flags with
7536       | None -> ()
7537       | Some txt -> pr "%s\n\n" txt
7538   ) all_functions_sorted
7539
7540 (* Generate a C function prototype. *)
7541 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7542     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7543     ?(prefix = "")
7544     ?handle name style =
7545   if extern then pr "extern ";
7546   if static then pr "static ";
7547   (match fst style with
7548    | RErr -> pr "int "
7549    | RInt _ -> pr "int "
7550    | RInt64 _ -> pr "int64_t "
7551    | RBool _ -> pr "int "
7552    | RConstString _ | RConstOptString _ -> pr "const char *"
7553    | RString _ | RBufferOut _ -> pr "char *"
7554    | RStringList _ | RHashtable _ -> pr "char **"
7555    | RStruct (_, typ) ->
7556        if not in_daemon then pr "struct guestfs_%s *" typ
7557        else pr "guestfs_int_%s *" typ
7558    | RStructList (_, typ) ->
7559        if not in_daemon then pr "struct guestfs_%s_list *" typ
7560        else pr "guestfs_int_%s_list *" typ
7561   );
7562   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7563   pr "%s%s (" prefix name;
7564   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7565     pr "void"
7566   else (
7567     let comma = ref false in
7568     (match handle with
7569      | None -> ()
7570      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7571     );
7572     let next () =
7573       if !comma then (
7574         if single_line then pr ", " else pr ",\n\t\t"
7575       );
7576       comma := true
7577     in
7578     List.iter (
7579       function
7580       | Pathname n
7581       | Device n | Dev_or_Path n
7582       | String n
7583       | OptString n ->
7584           next ();
7585           pr "const char *%s" n
7586       | StringList n | DeviceList n ->
7587           next ();
7588           pr "char *const *%s" n
7589       | Bool n -> next (); pr "int %s" n
7590       | Int n -> next (); pr "int %s" n
7591       | Int64 n -> next (); pr "int64_t %s" n
7592       | FileIn n
7593       | FileOut n ->
7594           if not in_daemon then (next (); pr "const char *%s" n)
7595     ) (snd style);
7596     if is_RBufferOut then (next (); pr "size_t *size_r");
7597   );
7598   pr ")";
7599   if semicolon then pr ";";
7600   if newline then pr "\n"
7601
7602 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7603 and generate_c_call_args ?handle ?(decl = false) style =
7604   pr "(";
7605   let comma = ref false in
7606   let next () =
7607     if !comma then pr ", ";
7608     comma := true
7609   in
7610   (match handle with
7611    | None -> ()
7612    | Some handle -> pr "%s" handle; comma := true
7613   );
7614   List.iter (
7615     fun arg ->
7616       next ();
7617       pr "%s" (name_of_argt arg)
7618   ) (snd style);
7619   (* For RBufferOut calls, add implicit &size parameter. *)
7620   if not decl then (
7621     match fst style with
7622     | RBufferOut _ ->
7623         next ();
7624         pr "&size"
7625     | _ -> ()
7626   );
7627   pr ")"
7628
7629 (* Generate the OCaml bindings interface. *)
7630 and generate_ocaml_mli () =
7631   generate_header OCamlStyle LGPLv2plus;
7632
7633   pr "\
7634 (** For API documentation you should refer to the C API
7635     in the guestfs(3) manual page.  The OCaml API uses almost
7636     exactly the same calls. *)
7637
7638 type t
7639 (** A [guestfs_h] handle. *)
7640
7641 exception Error of string
7642 (** This exception is raised when there is an error. *)
7643
7644 exception Handle_closed of string
7645 (** This exception is raised if you use a {!Guestfs.t} handle
7646     after calling {!close} on it.  The string is the name of
7647     the function. *)
7648
7649 val create : unit -> t
7650 (** Create a {!Guestfs.t} handle. *)
7651
7652 val close : t -> unit
7653 (** Close the {!Guestfs.t} handle and free up all resources used
7654     by it immediately.
7655
7656     Handles are closed by the garbage collector when they become
7657     unreferenced, but callers can call this in order to provide
7658     predictable cleanup. *)
7659
7660 ";
7661   generate_ocaml_structure_decls ();
7662
7663   (* The actions. *)
7664   List.iter (
7665     fun (name, style, _, _, _, shortdesc, _) ->
7666       generate_ocaml_prototype name style;
7667       pr "(** %s *)\n" shortdesc;
7668       pr "\n"
7669   ) all_functions_sorted
7670
7671 (* Generate the OCaml bindings implementation. *)
7672 and generate_ocaml_ml () =
7673   generate_header OCamlStyle LGPLv2plus;
7674
7675   pr "\
7676 type t
7677
7678 exception Error of string
7679 exception Handle_closed of string
7680
7681 external create : unit -> t = \"ocaml_guestfs_create\"
7682 external close : t -> unit = \"ocaml_guestfs_close\"
7683
7684 (* Give the exceptions names, so they can be raised from the C code. *)
7685 let () =
7686   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7687   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7688
7689 ";
7690
7691   generate_ocaml_structure_decls ();
7692
7693   (* The actions. *)
7694   List.iter (
7695     fun (name, style, _, _, _, shortdesc, _) ->
7696       generate_ocaml_prototype ~is_external:true name style;
7697   ) all_functions_sorted
7698
7699 (* Generate the OCaml bindings C implementation. *)
7700 and generate_ocaml_c () =
7701   generate_header CStyle LGPLv2plus;
7702
7703   pr "\
7704 #include <stdio.h>
7705 #include <stdlib.h>
7706 #include <string.h>
7707
7708 #include <caml/config.h>
7709 #include <caml/alloc.h>
7710 #include <caml/callback.h>
7711 #include <caml/fail.h>
7712 #include <caml/memory.h>
7713 #include <caml/mlvalues.h>
7714 #include <caml/signals.h>
7715
7716 #include <guestfs.h>
7717
7718 #include \"guestfs_c.h\"
7719
7720 /* Copy a hashtable of string pairs into an assoc-list.  We return
7721  * the list in reverse order, but hashtables aren't supposed to be
7722  * ordered anyway.
7723  */
7724 static CAMLprim value
7725 copy_table (char * const * argv)
7726 {
7727   CAMLparam0 ();
7728   CAMLlocal5 (rv, pairv, kv, vv, cons);
7729   int i;
7730
7731   rv = Val_int (0);
7732   for (i = 0; argv[i] != NULL; i += 2) {
7733     kv = caml_copy_string (argv[i]);
7734     vv = caml_copy_string (argv[i+1]);
7735     pairv = caml_alloc (2, 0);
7736     Store_field (pairv, 0, kv);
7737     Store_field (pairv, 1, vv);
7738     cons = caml_alloc (2, 0);
7739     Store_field (cons, 1, rv);
7740     rv = cons;
7741     Store_field (cons, 0, pairv);
7742   }
7743
7744   CAMLreturn (rv);
7745 }
7746
7747 ";
7748
7749   (* Struct copy functions. *)
7750
7751   let emit_ocaml_copy_list_function typ =
7752     pr "static CAMLprim value\n";
7753     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7754     pr "{\n";
7755     pr "  CAMLparam0 ();\n";
7756     pr "  CAMLlocal2 (rv, v);\n";
7757     pr "  unsigned int i;\n";
7758     pr "\n";
7759     pr "  if (%ss->len == 0)\n" typ;
7760     pr "    CAMLreturn (Atom (0));\n";
7761     pr "  else {\n";
7762     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7763     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7764     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7765     pr "      caml_modify (&Field (rv, i), v);\n";
7766     pr "    }\n";
7767     pr "    CAMLreturn (rv);\n";
7768     pr "  }\n";
7769     pr "}\n";
7770     pr "\n";
7771   in
7772
7773   List.iter (
7774     fun (typ, cols) ->
7775       let has_optpercent_col =
7776         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7777
7778       pr "static CAMLprim value\n";
7779       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7780       pr "{\n";
7781       pr "  CAMLparam0 ();\n";
7782       if has_optpercent_col then
7783         pr "  CAMLlocal3 (rv, v, v2);\n"
7784       else
7785         pr "  CAMLlocal2 (rv, v);\n";
7786       pr "\n";
7787       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7788       iteri (
7789         fun i col ->
7790           (match col with
7791            | name, FString ->
7792                pr "  v = caml_copy_string (%s->%s);\n" typ name
7793            | name, FBuffer ->
7794                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7795                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7796                  typ name typ name
7797            | name, FUUID ->
7798                pr "  v = caml_alloc_string (32);\n";
7799                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7800            | name, (FBytes|FInt64|FUInt64) ->
7801                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7802            | name, (FInt32|FUInt32) ->
7803                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7804            | name, FOptPercent ->
7805                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7806                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7807                pr "    v = caml_alloc (1, 0);\n";
7808                pr "    Store_field (v, 0, v2);\n";
7809                pr "  } else /* None */\n";
7810                pr "    v = Val_int (0);\n";
7811            | name, FChar ->
7812                pr "  v = Val_int (%s->%s);\n" typ name
7813           );
7814           pr "  Store_field (rv, %d, v);\n" i
7815       ) cols;
7816       pr "  CAMLreturn (rv);\n";
7817       pr "}\n";
7818       pr "\n";
7819   ) structs;
7820
7821   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7822   List.iter (
7823     function
7824     | typ, (RStructListOnly | RStructAndList) ->
7825         (* generate the function for typ *)
7826         emit_ocaml_copy_list_function typ
7827     | typ, _ -> () (* empty *)
7828   ) (rstructs_used_by all_functions);
7829
7830   (* The wrappers. *)
7831   List.iter (
7832     fun (name, style, _, _, _, _, _) ->
7833       pr "/* Automatically generated wrapper for function\n";
7834       pr " * ";
7835       generate_ocaml_prototype name style;
7836       pr " */\n";
7837       pr "\n";
7838
7839       let params =
7840         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7841
7842       let needs_extra_vs =
7843         match fst style with RConstOptString _ -> true | _ -> false in
7844
7845       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7846       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7847       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7848       pr "\n";
7849
7850       pr "CAMLprim value\n";
7851       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7852       List.iter (pr ", value %s") (List.tl params);
7853       pr ")\n";
7854       pr "{\n";
7855
7856       (match params with
7857        | [p1; p2; p3; p4; p5] ->
7858            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7859        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7860            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7861            pr "  CAMLxparam%d (%s);\n"
7862              (List.length rest) (String.concat ", " rest)
7863        | ps ->
7864            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7865       );
7866       if not needs_extra_vs then
7867         pr "  CAMLlocal1 (rv);\n"
7868       else
7869         pr "  CAMLlocal3 (rv, v, v2);\n";
7870       pr "\n";
7871
7872       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7873       pr "  if (g == NULL)\n";
7874       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7875       pr "\n";
7876
7877       List.iter (
7878         function
7879         | Pathname n
7880         | Device n | Dev_or_Path n
7881         | String n
7882         | FileIn n
7883         | FileOut n ->
7884             pr "  const char *%s = String_val (%sv);\n" n n
7885         | OptString n ->
7886             pr "  const char *%s =\n" n;
7887             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7888               n n
7889         | StringList n | DeviceList n ->
7890             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7891         | Bool n ->
7892             pr "  int %s = Bool_val (%sv);\n" n n
7893         | Int n ->
7894             pr "  int %s = Int_val (%sv);\n" n n
7895         | Int64 n ->
7896             pr "  int64_t %s = Int64_val (%sv);\n" n n
7897       ) (snd style);
7898       let error_code =
7899         match fst style with
7900         | RErr -> pr "  int r;\n"; "-1"
7901         | RInt _ -> pr "  int r;\n"; "-1"
7902         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7903         | RBool _ -> pr "  int r;\n"; "-1"
7904         | RConstString _ | RConstOptString _ ->
7905             pr "  const char *r;\n"; "NULL"
7906         | RString _ -> pr "  char *r;\n"; "NULL"
7907         | RStringList _ ->
7908             pr "  int i;\n";
7909             pr "  char **r;\n";
7910             "NULL"
7911         | RStruct (_, typ) ->
7912             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7913         | RStructList (_, typ) ->
7914             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7915         | RHashtable _ ->
7916             pr "  int i;\n";
7917             pr "  char **r;\n";
7918             "NULL"
7919         | RBufferOut _ ->
7920             pr "  char *r;\n";
7921             pr "  size_t size;\n";
7922             "NULL" in
7923       pr "\n";
7924
7925       pr "  caml_enter_blocking_section ();\n";
7926       pr "  r = guestfs_%s " name;
7927       generate_c_call_args ~handle:"g" style;
7928       pr ";\n";
7929       pr "  caml_leave_blocking_section ();\n";
7930
7931       List.iter (
7932         function
7933         | StringList n | DeviceList n ->
7934             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7935         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7936         | Bool _ | Int _ | Int64 _
7937         | FileIn _ | FileOut _ -> ()
7938       ) (snd style);
7939
7940       pr "  if (r == %s)\n" error_code;
7941       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7942       pr "\n";
7943
7944       (match fst style with
7945        | RErr -> pr "  rv = Val_unit;\n"
7946        | RInt _ -> pr "  rv = Val_int (r);\n"
7947        | RInt64 _ ->
7948            pr "  rv = caml_copy_int64 (r);\n"
7949        | RBool _ -> pr "  rv = Val_bool (r);\n"
7950        | RConstString _ ->
7951            pr "  rv = caml_copy_string (r);\n"
7952        | RConstOptString _ ->
7953            pr "  if (r) { /* Some string */\n";
7954            pr "    v = caml_alloc (1, 0);\n";
7955            pr "    v2 = caml_copy_string (r);\n";
7956            pr "    Store_field (v, 0, v2);\n";
7957            pr "  } else /* None */\n";
7958            pr "    v = Val_int (0);\n";
7959        | RString _ ->
7960            pr "  rv = caml_copy_string (r);\n";
7961            pr "  free (r);\n"
7962        | RStringList _ ->
7963            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7964            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7965            pr "  free (r);\n"
7966        | RStruct (_, typ) ->
7967            pr "  rv = copy_%s (r);\n" typ;
7968            pr "  guestfs_free_%s (r);\n" typ;
7969        | RStructList (_, typ) ->
7970            pr "  rv = copy_%s_list (r);\n" typ;
7971            pr "  guestfs_free_%s_list (r);\n" typ;
7972        | RHashtable _ ->
7973            pr "  rv = copy_table (r);\n";
7974            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7975            pr "  free (r);\n";
7976        | RBufferOut _ ->
7977            pr "  rv = caml_alloc_string (size);\n";
7978            pr "  memcpy (String_val (rv), r, size);\n";
7979       );
7980
7981       pr "  CAMLreturn (rv);\n";
7982       pr "}\n";
7983       pr "\n";
7984
7985       if List.length params > 5 then (
7986         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7987         pr "CAMLprim value ";
7988         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7989         pr "CAMLprim value\n";
7990         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7991         pr "{\n";
7992         pr "  return ocaml_guestfs_%s (argv[0]" name;
7993         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7994         pr ");\n";
7995         pr "}\n";
7996         pr "\n"
7997       )
7998   ) all_functions_sorted
7999
8000 and generate_ocaml_structure_decls () =
8001   List.iter (
8002     fun (typ, cols) ->
8003       pr "type %s = {\n" typ;
8004       List.iter (
8005         function
8006         | name, FString -> pr "  %s : string;\n" name
8007         | name, FBuffer -> pr "  %s : string;\n" name
8008         | name, FUUID -> pr "  %s : string;\n" name
8009         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8010         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8011         | name, FChar -> pr "  %s : char;\n" name
8012         | name, FOptPercent -> pr "  %s : float option;\n" name
8013       ) cols;
8014       pr "}\n";
8015       pr "\n"
8016   ) structs
8017
8018 and generate_ocaml_prototype ?(is_external = false) name style =
8019   if is_external then pr "external " else pr "val ";
8020   pr "%s : t -> " name;
8021   List.iter (
8022     function
8023     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8024     | OptString _ -> pr "string option -> "
8025     | StringList _ | DeviceList _ -> pr "string array -> "
8026     | Bool _ -> pr "bool -> "
8027     | Int _ -> pr "int -> "
8028     | Int64 _ -> pr "int64 -> "
8029   ) (snd style);
8030   (match fst style with
8031    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8032    | RInt _ -> pr "int"
8033    | RInt64 _ -> pr "int64"
8034    | RBool _ -> pr "bool"
8035    | RConstString _ -> pr "string"
8036    | RConstOptString _ -> pr "string option"
8037    | RString _ | RBufferOut _ -> pr "string"
8038    | RStringList _ -> pr "string array"
8039    | RStruct (_, typ) -> pr "%s" typ
8040    | RStructList (_, typ) -> pr "%s array" typ
8041    | RHashtable _ -> pr "(string * string) list"
8042   );
8043   if is_external then (
8044     pr " = ";
8045     if List.length (snd style) + 1 > 5 then
8046       pr "\"ocaml_guestfs_%s_byte\" " name;
8047     pr "\"ocaml_guestfs_%s\"" name
8048   );
8049   pr "\n"
8050
8051 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8052 and generate_perl_xs () =
8053   generate_header CStyle LGPLv2plus;
8054
8055   pr "\
8056 #include \"EXTERN.h\"
8057 #include \"perl.h\"
8058 #include \"XSUB.h\"
8059
8060 #include <guestfs.h>
8061
8062 #ifndef PRId64
8063 #define PRId64 \"lld\"
8064 #endif
8065
8066 static SV *
8067 my_newSVll(long long val) {
8068 #ifdef USE_64_BIT_ALL
8069   return newSViv(val);
8070 #else
8071   char buf[100];
8072   int len;
8073   len = snprintf(buf, 100, \"%%\" PRId64, val);
8074   return newSVpv(buf, len);
8075 #endif
8076 }
8077
8078 #ifndef PRIu64
8079 #define PRIu64 \"llu\"
8080 #endif
8081
8082 static SV *
8083 my_newSVull(unsigned long long val) {
8084 #ifdef USE_64_BIT_ALL
8085   return newSVuv(val);
8086 #else
8087   char buf[100];
8088   int len;
8089   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8090   return newSVpv(buf, len);
8091 #endif
8092 }
8093
8094 /* http://www.perlmonks.org/?node_id=680842 */
8095 static char **
8096 XS_unpack_charPtrPtr (SV *arg) {
8097   char **ret;
8098   AV *av;
8099   I32 i;
8100
8101   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8102     croak (\"array reference expected\");
8103
8104   av = (AV *)SvRV (arg);
8105   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8106   if (!ret)
8107     croak (\"malloc failed\");
8108
8109   for (i = 0; i <= av_len (av); i++) {
8110     SV **elem = av_fetch (av, i, 0);
8111
8112     if (!elem || !*elem)
8113       croak (\"missing element in list\");
8114
8115     ret[i] = SvPV_nolen (*elem);
8116   }
8117
8118   ret[i] = NULL;
8119
8120   return ret;
8121 }
8122
8123 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8124
8125 PROTOTYPES: ENABLE
8126
8127 guestfs_h *
8128 _create ()
8129    CODE:
8130       RETVAL = guestfs_create ();
8131       if (!RETVAL)
8132         croak (\"could not create guestfs handle\");
8133       guestfs_set_error_handler (RETVAL, NULL, NULL);
8134  OUTPUT:
8135       RETVAL
8136
8137 void
8138 DESTROY (g)
8139       guestfs_h *g;
8140  PPCODE:
8141       guestfs_close (g);
8142
8143 ";
8144
8145   List.iter (
8146     fun (name, style, _, _, _, _, _) ->
8147       (match fst style with
8148        | RErr -> pr "void\n"
8149        | RInt _ -> pr "SV *\n"
8150        | RInt64 _ -> pr "SV *\n"
8151        | RBool _ -> pr "SV *\n"
8152        | RConstString _ -> pr "SV *\n"
8153        | RConstOptString _ -> pr "SV *\n"
8154        | RString _ -> pr "SV *\n"
8155        | RBufferOut _ -> pr "SV *\n"
8156        | RStringList _
8157        | RStruct _ | RStructList _
8158        | RHashtable _ ->
8159            pr "void\n" (* all lists returned implictly on the stack *)
8160       );
8161       (* Call and arguments. *)
8162       pr "%s " name;
8163       generate_c_call_args ~handle:"g" ~decl:true style;
8164       pr "\n";
8165       pr "      guestfs_h *g;\n";
8166       iteri (
8167         fun i ->
8168           function
8169           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8170               pr "      char *%s;\n" n
8171           | OptString n ->
8172               (* http://www.perlmonks.org/?node_id=554277
8173                * Note that the implicit handle argument means we have
8174                * to add 1 to the ST(x) operator.
8175                *)
8176               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8177           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8178           | Bool n -> pr "      int %s;\n" n
8179           | Int n -> pr "      int %s;\n" n
8180           | Int64 n -> pr "      int64_t %s;\n" n
8181       ) (snd style);
8182
8183       let do_cleanups () =
8184         List.iter (
8185           function
8186           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8187           | Bool _ | Int _ | Int64 _
8188           | FileIn _ | FileOut _ -> ()
8189           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8190         ) (snd style)
8191       in
8192
8193       (* Code. *)
8194       (match fst style with
8195        | RErr ->
8196            pr "PREINIT:\n";
8197            pr "      int r;\n";
8198            pr " PPCODE:\n";
8199            pr "      r = guestfs_%s " name;
8200            generate_c_call_args ~handle:"g" style;
8201            pr ";\n";
8202            do_cleanups ();
8203            pr "      if (r == -1)\n";
8204            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8205        | RInt n
8206        | RBool n ->
8207            pr "PREINIT:\n";
8208            pr "      int %s;\n" n;
8209            pr "   CODE:\n";
8210            pr "      %s = guestfs_%s " n name;
8211            generate_c_call_args ~handle:"g" style;
8212            pr ";\n";
8213            do_cleanups ();
8214            pr "      if (%s == -1)\n" n;
8215            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8216            pr "      RETVAL = newSViv (%s);\n" n;
8217            pr " OUTPUT:\n";
8218            pr "      RETVAL\n"
8219        | RInt64 n ->
8220            pr "PREINIT:\n";
8221            pr "      int64_t %s;\n" n;
8222            pr "   CODE:\n";
8223            pr "      %s = guestfs_%s " n name;
8224            generate_c_call_args ~handle:"g" style;
8225            pr ";\n";
8226            do_cleanups ();
8227            pr "      if (%s == -1)\n" n;
8228            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8229            pr "      RETVAL = my_newSVll (%s);\n" n;
8230            pr " OUTPUT:\n";
8231            pr "      RETVAL\n"
8232        | RConstString n ->
8233            pr "PREINIT:\n";
8234            pr "      const char *%s;\n" n;
8235            pr "   CODE:\n";
8236            pr "      %s = guestfs_%s " n name;
8237            generate_c_call_args ~handle:"g" style;
8238            pr ";\n";
8239            do_cleanups ();
8240            pr "      if (%s == NULL)\n" n;
8241            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8242            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8243            pr " OUTPUT:\n";
8244            pr "      RETVAL\n"
8245        | RConstOptString n ->
8246            pr "PREINIT:\n";
8247            pr "      const char *%s;\n" n;
8248            pr "   CODE:\n";
8249            pr "      %s = guestfs_%s " n name;
8250            generate_c_call_args ~handle:"g" style;
8251            pr ";\n";
8252            do_cleanups ();
8253            pr "      if (%s == NULL)\n" n;
8254            pr "        RETVAL = &PL_sv_undef;\n";
8255            pr "      else\n";
8256            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8257            pr " OUTPUT:\n";
8258            pr "      RETVAL\n"
8259        | RString n ->
8260            pr "PREINIT:\n";
8261            pr "      char *%s;\n" n;
8262            pr "   CODE:\n";
8263            pr "      %s = guestfs_%s " n name;
8264            generate_c_call_args ~handle:"g" style;
8265            pr ";\n";
8266            do_cleanups ();
8267            pr "      if (%s == NULL)\n" n;
8268            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8269            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8270            pr "      free (%s);\n" n;
8271            pr " OUTPUT:\n";
8272            pr "      RETVAL\n"
8273        | RStringList n | RHashtable n ->
8274            pr "PREINIT:\n";
8275            pr "      char **%s;\n" n;
8276            pr "      int i, n;\n";
8277            pr " PPCODE:\n";
8278            pr "      %s = guestfs_%s " n name;
8279            generate_c_call_args ~handle:"g" style;
8280            pr ";\n";
8281            do_cleanups ();
8282            pr "      if (%s == NULL)\n" n;
8283            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8284            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8285            pr "      EXTEND (SP, n);\n";
8286            pr "      for (i = 0; i < n; ++i) {\n";
8287            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8288            pr "        free (%s[i]);\n" n;
8289            pr "      }\n";
8290            pr "      free (%s);\n" n;
8291        | RStruct (n, typ) ->
8292            let cols = cols_of_struct typ in
8293            generate_perl_struct_code typ cols name style n do_cleanups
8294        | RStructList (n, typ) ->
8295            let cols = cols_of_struct typ in
8296            generate_perl_struct_list_code typ cols name style n do_cleanups
8297        | RBufferOut n ->
8298            pr "PREINIT:\n";
8299            pr "      char *%s;\n" n;
8300            pr "      size_t size;\n";
8301            pr "   CODE:\n";
8302            pr "      %s = guestfs_%s " n name;
8303            generate_c_call_args ~handle:"g" style;
8304            pr ";\n";
8305            do_cleanups ();
8306            pr "      if (%s == NULL)\n" n;
8307            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8308            pr "      RETVAL = newSVpv (%s, size);\n" n;
8309            pr "      free (%s);\n" n;
8310            pr " OUTPUT:\n";
8311            pr "      RETVAL\n"
8312       );
8313
8314       pr "\n"
8315   ) all_functions
8316
8317 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8318   pr "PREINIT:\n";
8319   pr "      struct guestfs_%s_list *%s;\n" typ n;
8320   pr "      int i;\n";
8321   pr "      HV *hv;\n";
8322   pr " PPCODE:\n";
8323   pr "      %s = guestfs_%s " n name;
8324   generate_c_call_args ~handle:"g" style;
8325   pr ";\n";
8326   do_cleanups ();
8327   pr "      if (%s == NULL)\n" n;
8328   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8329   pr "      EXTEND (SP, %s->len);\n" n;
8330   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8331   pr "        hv = newHV ();\n";
8332   List.iter (
8333     function
8334     | name, FString ->
8335         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8336           name (String.length name) n name
8337     | name, FUUID ->
8338         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8339           name (String.length name) n name
8340     | name, FBuffer ->
8341         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8342           name (String.length name) n name n name
8343     | name, (FBytes|FUInt64) ->
8344         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8345           name (String.length name) n name
8346     | name, FInt64 ->
8347         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8348           name (String.length name) n name
8349     | name, (FInt32|FUInt32) ->
8350         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8351           name (String.length name) n name
8352     | name, FChar ->
8353         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8354           name (String.length name) n name
8355     | name, FOptPercent ->
8356         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8357           name (String.length name) n name
8358   ) cols;
8359   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8360   pr "      }\n";
8361   pr "      guestfs_free_%s_list (%s);\n" typ n
8362
8363 and generate_perl_struct_code typ cols name style n do_cleanups =
8364   pr "PREINIT:\n";
8365   pr "      struct guestfs_%s *%s;\n" typ n;
8366   pr " PPCODE:\n";
8367   pr "      %s = guestfs_%s " n name;
8368   generate_c_call_args ~handle:"g" style;
8369   pr ";\n";
8370   do_cleanups ();
8371   pr "      if (%s == NULL)\n" n;
8372   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8373   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8374   List.iter (
8375     fun ((name, _) as col) ->
8376       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8377
8378       match col with
8379       | name, FString ->
8380           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8381             n name
8382       | name, FBuffer ->
8383           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8384             n name n name
8385       | name, FUUID ->
8386           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8387             n name
8388       | name, (FBytes|FUInt64) ->
8389           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8390             n name
8391       | name, FInt64 ->
8392           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8393             n name
8394       | name, (FInt32|FUInt32) ->
8395           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8396             n name
8397       | name, FChar ->
8398           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8399             n name
8400       | name, FOptPercent ->
8401           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8402             n name
8403   ) cols;
8404   pr "      free (%s);\n" n
8405
8406 (* Generate Sys/Guestfs.pm. *)
8407 and generate_perl_pm () =
8408   generate_header HashStyle LGPLv2plus;
8409
8410   pr "\
8411 =pod
8412
8413 =head1 NAME
8414
8415 Sys::Guestfs - Perl bindings for libguestfs
8416
8417 =head1 SYNOPSIS
8418
8419  use Sys::Guestfs;
8420
8421  my $h = Sys::Guestfs->new ();
8422  $h->add_drive ('guest.img');
8423  $h->launch ();
8424  $h->mount ('/dev/sda1', '/');
8425  $h->touch ('/hello');
8426  $h->sync ();
8427
8428 =head1 DESCRIPTION
8429
8430 The C<Sys::Guestfs> module provides a Perl XS binding to the
8431 libguestfs API for examining and modifying virtual machine
8432 disk images.
8433
8434 Amongst the things this is good for: making batch configuration
8435 changes to guests, getting disk used/free statistics (see also:
8436 virt-df), migrating between virtualization systems (see also:
8437 virt-p2v), performing partial backups, performing partial guest
8438 clones, cloning guests and changing registry/UUID/hostname info, and
8439 much else besides.
8440
8441 Libguestfs uses Linux kernel and qemu code, and can access any type of
8442 guest filesystem that Linux and qemu can, including but not limited
8443 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8444 schemes, qcow, qcow2, vmdk.
8445
8446 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8447 LVs, what filesystem is in each LV, etc.).  It can also run commands
8448 in the context of the guest.  Also you can access filesystems over
8449 FUSE.
8450
8451 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8452 functions for using libguestfs from Perl, including integration
8453 with libvirt.
8454
8455 =head1 ERRORS
8456
8457 All errors turn into calls to C<croak> (see L<Carp(3)>).
8458
8459 =head1 METHODS
8460
8461 =over 4
8462
8463 =cut
8464
8465 package Sys::Guestfs;
8466
8467 use strict;
8468 use warnings;
8469
8470 require XSLoader;
8471 XSLoader::load ('Sys::Guestfs');
8472
8473 =item $h = Sys::Guestfs->new ();
8474
8475 Create a new guestfs handle.
8476
8477 =cut
8478
8479 sub new {
8480   my $proto = shift;
8481   my $class = ref ($proto) || $proto;
8482
8483   my $self = Sys::Guestfs::_create ();
8484   bless $self, $class;
8485   return $self;
8486 }
8487
8488 ";
8489
8490   (* Actions.  We only need to print documentation for these as
8491    * they are pulled in from the XS code automatically.
8492    *)
8493   List.iter (
8494     fun (name, style, _, flags, _, _, longdesc) ->
8495       if not (List.mem NotInDocs flags) then (
8496         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8497         pr "=item ";
8498         generate_perl_prototype name style;
8499         pr "\n\n";
8500         pr "%s\n\n" longdesc;
8501         if List.mem ProtocolLimitWarning flags then
8502           pr "%s\n\n" protocol_limit_warning;
8503         if List.mem DangerWillRobinson flags then
8504           pr "%s\n\n" danger_will_robinson;
8505         match deprecation_notice flags with
8506         | None -> ()
8507         | Some txt -> pr "%s\n\n" txt
8508       )
8509   ) all_functions_sorted;
8510
8511   (* End of file. *)
8512   pr "\
8513 =cut
8514
8515 1;
8516
8517 =back
8518
8519 =head1 COPYRIGHT
8520
8521 Copyright (C) %s Red Hat Inc.
8522
8523 =head1 LICENSE
8524
8525 Please see the file COPYING.LIB for the full license.
8526
8527 =head1 SEE ALSO
8528
8529 L<guestfs(3)>,
8530 L<guestfish(1)>,
8531 L<http://libguestfs.org>,
8532 L<Sys::Guestfs::Lib(3)>.
8533
8534 =cut
8535 " copyright_years
8536
8537 and generate_perl_prototype name style =
8538   (match fst style with
8539    | RErr -> ()
8540    | RBool n
8541    | RInt n
8542    | RInt64 n
8543    | RConstString n
8544    | RConstOptString n
8545    | RString n
8546    | RBufferOut n -> pr "$%s = " n
8547    | RStruct (n,_)
8548    | RHashtable n -> pr "%%%s = " n
8549    | RStringList n
8550    | RStructList (n,_) -> pr "@%s = " n
8551   );
8552   pr "$h->%s (" name;
8553   let comma = ref false in
8554   List.iter (
8555     fun arg ->
8556       if !comma then pr ", ";
8557       comma := true;
8558       match arg with
8559       | Pathname n | Device n | Dev_or_Path n | String n
8560       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8561           pr "$%s" n
8562       | StringList n | DeviceList n ->
8563           pr "\\@%s" n
8564   ) (snd style);
8565   pr ");"
8566
8567 (* Generate Python C module. *)
8568 and generate_python_c () =
8569   generate_header CStyle LGPLv2plus;
8570
8571   pr "\
8572 #include <Python.h>
8573
8574 #include <stdio.h>
8575 #include <stdlib.h>
8576 #include <assert.h>
8577
8578 #include \"guestfs.h\"
8579
8580 typedef struct {
8581   PyObject_HEAD
8582   guestfs_h *g;
8583 } Pyguestfs_Object;
8584
8585 static guestfs_h *
8586 get_handle (PyObject *obj)
8587 {
8588   assert (obj);
8589   assert (obj != Py_None);
8590   return ((Pyguestfs_Object *) obj)->g;
8591 }
8592
8593 static PyObject *
8594 put_handle (guestfs_h *g)
8595 {
8596   assert (g);
8597   return
8598     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8599 }
8600
8601 /* This list should be freed (but not the strings) after use. */
8602 static char **
8603 get_string_list (PyObject *obj)
8604 {
8605   int i, len;
8606   char **r;
8607
8608   assert (obj);
8609
8610   if (!PyList_Check (obj)) {
8611     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8612     return NULL;
8613   }
8614
8615   len = PyList_Size (obj);
8616   r = malloc (sizeof (char *) * (len+1));
8617   if (r == NULL) {
8618     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8619     return NULL;
8620   }
8621
8622   for (i = 0; i < len; ++i)
8623     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8624   r[len] = NULL;
8625
8626   return r;
8627 }
8628
8629 static PyObject *
8630 put_string_list (char * const * const argv)
8631 {
8632   PyObject *list;
8633   int argc, i;
8634
8635   for (argc = 0; argv[argc] != NULL; ++argc)
8636     ;
8637
8638   list = PyList_New (argc);
8639   for (i = 0; i < argc; ++i)
8640     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8641
8642   return list;
8643 }
8644
8645 static PyObject *
8646 put_table (char * const * const argv)
8647 {
8648   PyObject *list, *item;
8649   int argc, i;
8650
8651   for (argc = 0; argv[argc] != NULL; ++argc)
8652     ;
8653
8654   list = PyList_New (argc >> 1);
8655   for (i = 0; i < argc; i += 2) {
8656     item = PyTuple_New (2);
8657     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8658     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8659     PyList_SetItem (list, i >> 1, item);
8660   }
8661
8662   return list;
8663 }
8664
8665 static void
8666 free_strings (char **argv)
8667 {
8668   int argc;
8669
8670   for (argc = 0; argv[argc] != NULL; ++argc)
8671     free (argv[argc]);
8672   free (argv);
8673 }
8674
8675 static PyObject *
8676 py_guestfs_create (PyObject *self, PyObject *args)
8677 {
8678   guestfs_h *g;
8679
8680   g = guestfs_create ();
8681   if (g == NULL) {
8682     PyErr_SetString (PyExc_RuntimeError,
8683                      \"guestfs.create: failed to allocate handle\");
8684     return NULL;
8685   }
8686   guestfs_set_error_handler (g, NULL, NULL);
8687   return put_handle (g);
8688 }
8689
8690 static PyObject *
8691 py_guestfs_close (PyObject *self, PyObject *args)
8692 {
8693   PyObject *py_g;
8694   guestfs_h *g;
8695
8696   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8697     return NULL;
8698   g = get_handle (py_g);
8699
8700   guestfs_close (g);
8701
8702   Py_INCREF (Py_None);
8703   return Py_None;
8704 }
8705
8706 ";
8707
8708   let emit_put_list_function typ =
8709     pr "static PyObject *\n";
8710     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8711     pr "{\n";
8712     pr "  PyObject *list;\n";
8713     pr "  int i;\n";
8714     pr "\n";
8715     pr "  list = PyList_New (%ss->len);\n" typ;
8716     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8717     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8718     pr "  return list;\n";
8719     pr "};\n";
8720     pr "\n"
8721   in
8722
8723   (* Structures, turned into Python dictionaries. *)
8724   List.iter (
8725     fun (typ, cols) ->
8726       pr "static PyObject *\n";
8727       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8728       pr "{\n";
8729       pr "  PyObject *dict;\n";
8730       pr "\n";
8731       pr "  dict = PyDict_New ();\n";
8732       List.iter (
8733         function
8734         | name, FString ->
8735             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8736             pr "                        PyString_FromString (%s->%s));\n"
8737               typ name
8738         | name, FBuffer ->
8739             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8740             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8741               typ name typ name
8742         | name, FUUID ->
8743             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8744             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8745               typ name
8746         | name, (FBytes|FUInt64) ->
8747             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8748             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8749               typ name
8750         | name, FInt64 ->
8751             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8752             pr "                        PyLong_FromLongLong (%s->%s));\n"
8753               typ name
8754         | name, FUInt32 ->
8755             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8756             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8757               typ name
8758         | name, FInt32 ->
8759             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8760             pr "                        PyLong_FromLong (%s->%s));\n"
8761               typ name
8762         | name, FOptPercent ->
8763             pr "  if (%s->%s >= 0)\n" typ name;
8764             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8765             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8766               typ name;
8767             pr "  else {\n";
8768             pr "    Py_INCREF (Py_None);\n";
8769             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8770             pr "  }\n"
8771         | name, FChar ->
8772             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8773             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8774       ) cols;
8775       pr "  return dict;\n";
8776       pr "};\n";
8777       pr "\n";
8778
8779   ) structs;
8780
8781   (* Emit a put_TYPE_list function definition only if that function is used. *)
8782   List.iter (
8783     function
8784     | typ, (RStructListOnly | RStructAndList) ->
8785         (* generate the function for typ *)
8786         emit_put_list_function typ
8787     | typ, _ -> () (* empty *)
8788   ) (rstructs_used_by all_functions);
8789
8790   (* Python wrapper functions. *)
8791   List.iter (
8792     fun (name, style, _, _, _, _, _) ->
8793       pr "static PyObject *\n";
8794       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8795       pr "{\n";
8796
8797       pr "  PyObject *py_g;\n";
8798       pr "  guestfs_h *g;\n";
8799       pr "  PyObject *py_r;\n";
8800
8801       let error_code =
8802         match fst style with
8803         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8804         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8805         | RConstString _ | RConstOptString _ ->
8806             pr "  const char *r;\n"; "NULL"
8807         | RString _ -> pr "  char *r;\n"; "NULL"
8808         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8809         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8810         | RStructList (_, typ) ->
8811             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8812         | RBufferOut _ ->
8813             pr "  char *r;\n";
8814             pr "  size_t size;\n";
8815             "NULL" in
8816
8817       List.iter (
8818         function
8819         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8820             pr "  const char *%s;\n" n
8821         | OptString n -> pr "  const char *%s;\n" n
8822         | StringList n | DeviceList n ->
8823             pr "  PyObject *py_%s;\n" n;
8824             pr "  char **%s;\n" n
8825         | Bool n -> pr "  int %s;\n" n
8826         | Int n -> pr "  int %s;\n" n
8827         | Int64 n -> pr "  long long %s;\n" n
8828       ) (snd style);
8829
8830       pr "\n";
8831
8832       (* Convert the parameters. *)
8833       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8834       List.iter (
8835         function
8836         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8837         | OptString _ -> pr "z"
8838         | StringList _ | DeviceList _ -> pr "O"
8839         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8840         | Int _ -> pr "i"
8841         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8842                              * emulate C's int/long/long long in Python?
8843                              *)
8844       ) (snd style);
8845       pr ":guestfs_%s\",\n" name;
8846       pr "                         &py_g";
8847       List.iter (
8848         function
8849         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8850         | OptString n -> pr ", &%s" n
8851         | StringList n | DeviceList n -> pr ", &py_%s" n
8852         | Bool n -> pr ", &%s" n
8853         | Int n -> pr ", &%s" n
8854         | Int64 n -> pr ", &%s" n
8855       ) (snd style);
8856
8857       pr "))\n";
8858       pr "    return NULL;\n";
8859
8860       pr "  g = get_handle (py_g);\n";
8861       List.iter (
8862         function
8863         | Pathname _ | Device _ | Dev_or_Path _ | String _
8864         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8865         | StringList n | DeviceList n ->
8866             pr "  %s = get_string_list (py_%s);\n" n n;
8867             pr "  if (!%s) return NULL;\n" n
8868       ) (snd style);
8869
8870       pr "\n";
8871
8872       pr "  r = guestfs_%s " name;
8873       generate_c_call_args ~handle:"g" style;
8874       pr ";\n";
8875
8876       List.iter (
8877         function
8878         | Pathname _ | Device _ | Dev_or_Path _ | String _
8879         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8880         | StringList n | DeviceList n ->
8881             pr "  free (%s);\n" n
8882       ) (snd style);
8883
8884       pr "  if (r == %s) {\n" error_code;
8885       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8886       pr "    return NULL;\n";
8887       pr "  }\n";
8888       pr "\n";
8889
8890       (match fst style with
8891        | RErr ->
8892            pr "  Py_INCREF (Py_None);\n";
8893            pr "  py_r = Py_None;\n"
8894        | RInt _
8895        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8896        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8897        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8898        | RConstOptString _ ->
8899            pr "  if (r)\n";
8900            pr "    py_r = PyString_FromString (r);\n";
8901            pr "  else {\n";
8902            pr "    Py_INCREF (Py_None);\n";
8903            pr "    py_r = Py_None;\n";
8904            pr "  }\n"
8905        | RString _ ->
8906            pr "  py_r = PyString_FromString (r);\n";
8907            pr "  free (r);\n"
8908        | RStringList _ ->
8909            pr "  py_r = put_string_list (r);\n";
8910            pr "  free_strings (r);\n"
8911        | RStruct (_, typ) ->
8912            pr "  py_r = put_%s (r);\n" typ;
8913            pr "  guestfs_free_%s (r);\n" typ
8914        | RStructList (_, typ) ->
8915            pr "  py_r = put_%s_list (r);\n" typ;
8916            pr "  guestfs_free_%s_list (r);\n" typ
8917        | RHashtable n ->
8918            pr "  py_r = put_table (r);\n";
8919            pr "  free_strings (r);\n"
8920        | RBufferOut _ ->
8921            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8922            pr "  free (r);\n"
8923       );
8924
8925       pr "  return py_r;\n";
8926       pr "}\n";
8927       pr "\n"
8928   ) all_functions;
8929
8930   (* Table of functions. *)
8931   pr "static PyMethodDef methods[] = {\n";
8932   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8933   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8934   List.iter (
8935     fun (name, _, _, _, _, _, _) ->
8936       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8937         name name
8938   ) all_functions;
8939   pr "  { NULL, NULL, 0, NULL }\n";
8940   pr "};\n";
8941   pr "\n";
8942
8943   (* Init function. *)
8944   pr "\
8945 void
8946 initlibguestfsmod (void)
8947 {
8948   static int initialized = 0;
8949
8950   if (initialized) return;
8951   Py_InitModule ((char *) \"libguestfsmod\", methods);
8952   initialized = 1;
8953 }
8954 "
8955
8956 (* Generate Python module. *)
8957 and generate_python_py () =
8958   generate_header HashStyle LGPLv2plus;
8959
8960   pr "\
8961 u\"\"\"Python bindings for libguestfs
8962
8963 import guestfs
8964 g = guestfs.GuestFS ()
8965 g.add_drive (\"guest.img\")
8966 g.launch ()
8967 parts = g.list_partitions ()
8968
8969 The guestfs module provides a Python binding to the libguestfs API
8970 for examining and modifying virtual machine disk images.
8971
8972 Amongst the things this is good for: making batch configuration
8973 changes to guests, getting disk used/free statistics (see also:
8974 virt-df), migrating between virtualization systems (see also:
8975 virt-p2v), performing partial backups, performing partial guest
8976 clones, cloning guests and changing registry/UUID/hostname info, and
8977 much else besides.
8978
8979 Libguestfs uses Linux kernel and qemu code, and can access any type of
8980 guest filesystem that Linux and qemu can, including but not limited
8981 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8982 schemes, qcow, qcow2, vmdk.
8983
8984 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8985 LVs, what filesystem is in each LV, etc.).  It can also run commands
8986 in the context of the guest.  Also you can access filesystems over
8987 FUSE.
8988
8989 Errors which happen while using the API are turned into Python
8990 RuntimeError exceptions.
8991
8992 To create a guestfs handle you usually have to perform the following
8993 sequence of calls:
8994
8995 # Create the handle, call add_drive at least once, and possibly
8996 # several times if the guest has multiple block devices:
8997 g = guestfs.GuestFS ()
8998 g.add_drive (\"guest.img\")
8999
9000 # Launch the qemu subprocess and wait for it to become ready:
9001 g.launch ()
9002
9003 # Now you can issue commands, for example:
9004 logvols = g.lvs ()
9005
9006 \"\"\"
9007
9008 import libguestfsmod
9009
9010 class GuestFS:
9011     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9012
9013     def __init__ (self):
9014         \"\"\"Create a new libguestfs handle.\"\"\"
9015         self._o = libguestfsmod.create ()
9016
9017     def __del__ (self):
9018         libguestfsmod.close (self._o)
9019
9020 ";
9021
9022   List.iter (
9023     fun (name, style, _, flags, _, _, longdesc) ->
9024       pr "    def %s " name;
9025       generate_py_call_args ~handle:"self" (snd style);
9026       pr ":\n";
9027
9028       if not (List.mem NotInDocs flags) then (
9029         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9030         let doc =
9031           match fst style with
9032           | RErr | RInt _ | RInt64 _ | RBool _
9033           | RConstOptString _ | RConstString _
9034           | RString _ | RBufferOut _ -> doc
9035           | RStringList _ ->
9036               doc ^ "\n\nThis function returns a list of strings."
9037           | RStruct (_, typ) ->
9038               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9039           | RStructList (_, typ) ->
9040               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9041           | RHashtable _ ->
9042               doc ^ "\n\nThis function returns a dictionary." in
9043         let doc =
9044           if List.mem ProtocolLimitWarning flags then
9045             doc ^ "\n\n" ^ protocol_limit_warning
9046           else doc in
9047         let doc =
9048           if List.mem DangerWillRobinson flags then
9049             doc ^ "\n\n" ^ danger_will_robinson
9050           else doc in
9051         let doc =
9052           match deprecation_notice flags with
9053           | None -> doc
9054           | Some txt -> doc ^ "\n\n" ^ txt in
9055         let doc = pod2text ~width:60 name doc in
9056         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9057         let doc = String.concat "\n        " doc in
9058         pr "        u\"\"\"%s\"\"\"\n" doc;
9059       );
9060       pr "        return libguestfsmod.%s " name;
9061       generate_py_call_args ~handle:"self._o" (snd style);
9062       pr "\n";
9063       pr "\n";
9064   ) all_functions
9065
9066 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9067 and generate_py_call_args ~handle args =
9068   pr "(%s" handle;
9069   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9070   pr ")"
9071
9072 (* Useful if you need the longdesc POD text as plain text.  Returns a
9073  * list of lines.
9074  *
9075  * Because this is very slow (the slowest part of autogeneration),
9076  * we memoize the results.
9077  *)
9078 and pod2text ~width name longdesc =
9079   let key = width, name, longdesc in
9080   try Hashtbl.find pod2text_memo key
9081   with Not_found ->
9082     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9083     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9084     close_out chan;
9085     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9086     let chan = open_process_in cmd in
9087     let lines = ref [] in
9088     let rec loop i =
9089       let line = input_line chan in
9090       if i = 1 then             (* discard the first line of output *)
9091         loop (i+1)
9092       else (
9093         let line = triml line in
9094         lines := line :: !lines;
9095         loop (i+1)
9096       ) in
9097     let lines = try loop 1 with End_of_file -> List.rev !lines in
9098     unlink filename;
9099     (match close_process_in chan with
9100      | WEXITED 0 -> ()
9101      | WEXITED i ->
9102          failwithf "pod2text: process exited with non-zero status (%d)" i
9103      | WSIGNALED i | WSTOPPED i ->
9104          failwithf "pod2text: process signalled or stopped by signal %d" i
9105     );
9106     Hashtbl.add pod2text_memo key lines;
9107     pod2text_memo_updated ();
9108     lines
9109
9110 (* Generate ruby bindings. *)
9111 and generate_ruby_c () =
9112   generate_header CStyle LGPLv2plus;
9113
9114   pr "\
9115 #include <stdio.h>
9116 #include <stdlib.h>
9117
9118 #include <ruby.h>
9119
9120 #include \"guestfs.h\"
9121
9122 #include \"extconf.h\"
9123
9124 /* For Ruby < 1.9 */
9125 #ifndef RARRAY_LEN
9126 #define RARRAY_LEN(r) (RARRAY((r))->len)
9127 #endif
9128
9129 static VALUE m_guestfs;                 /* guestfs module */
9130 static VALUE c_guestfs;                 /* guestfs_h handle */
9131 static VALUE e_Error;                   /* used for all errors */
9132
9133 static void ruby_guestfs_free (void *p)
9134 {
9135   if (!p) return;
9136   guestfs_close ((guestfs_h *) p);
9137 }
9138
9139 static VALUE ruby_guestfs_create (VALUE m)
9140 {
9141   guestfs_h *g;
9142
9143   g = guestfs_create ();
9144   if (!g)
9145     rb_raise (e_Error, \"failed to create guestfs handle\");
9146
9147   /* Don't print error messages to stderr by default. */
9148   guestfs_set_error_handler (g, NULL, NULL);
9149
9150   /* Wrap it, and make sure the close function is called when the
9151    * handle goes away.
9152    */
9153   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9154 }
9155
9156 static VALUE ruby_guestfs_close (VALUE gv)
9157 {
9158   guestfs_h *g;
9159   Data_Get_Struct (gv, guestfs_h, g);
9160
9161   ruby_guestfs_free (g);
9162   DATA_PTR (gv) = NULL;
9163
9164   return Qnil;
9165 }
9166
9167 ";
9168
9169   List.iter (
9170     fun (name, style, _, _, _, _, _) ->
9171       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9172       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9173       pr ")\n";
9174       pr "{\n";
9175       pr "  guestfs_h *g;\n";
9176       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9177       pr "  if (!g)\n";
9178       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9179         name;
9180       pr "\n";
9181
9182       List.iter (
9183         function
9184         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9185             pr "  Check_Type (%sv, T_STRING);\n" n;
9186             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9187             pr "  if (!%s)\n" n;
9188             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9189             pr "              \"%s\", \"%s\");\n" n name
9190         | OptString n ->
9191             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9192         | StringList n | DeviceList n ->
9193             pr "  char **%s;\n" n;
9194             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9195             pr "  {\n";
9196             pr "    int i, len;\n";
9197             pr "    len = RARRAY_LEN (%sv);\n" n;
9198             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9199               n;
9200             pr "    for (i = 0; i < len; ++i) {\n";
9201             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9202             pr "      %s[i] = StringValueCStr (v);\n" n;
9203             pr "    }\n";
9204             pr "    %s[len] = NULL;\n" n;
9205             pr "  }\n";
9206         | Bool n ->
9207             pr "  int %s = RTEST (%sv);\n" n n
9208         | Int n ->
9209             pr "  int %s = NUM2INT (%sv);\n" n n
9210         | Int64 n ->
9211             pr "  long long %s = NUM2LL (%sv);\n" n n
9212       ) (snd style);
9213       pr "\n";
9214
9215       let error_code =
9216         match fst style with
9217         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9218         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9219         | RConstString _ | RConstOptString _ ->
9220             pr "  const char *r;\n"; "NULL"
9221         | RString _ -> pr "  char *r;\n"; "NULL"
9222         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9223         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9224         | RStructList (_, typ) ->
9225             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9226         | RBufferOut _ ->
9227             pr "  char *r;\n";
9228             pr "  size_t size;\n";
9229             "NULL" in
9230       pr "\n";
9231
9232       pr "  r = guestfs_%s " name;
9233       generate_c_call_args ~handle:"g" style;
9234       pr ";\n";
9235
9236       List.iter (
9237         function
9238         | Pathname _ | Device _ | Dev_or_Path _ | String _
9239         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9240         | StringList n | DeviceList n ->
9241             pr "  free (%s);\n" n
9242       ) (snd style);
9243
9244       pr "  if (r == %s)\n" error_code;
9245       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9246       pr "\n";
9247
9248       (match fst style with
9249        | RErr ->
9250            pr "  return Qnil;\n"
9251        | RInt _ | RBool _ ->
9252            pr "  return INT2NUM (r);\n"
9253        | RInt64 _ ->
9254            pr "  return ULL2NUM (r);\n"
9255        | RConstString _ ->
9256            pr "  return rb_str_new2 (r);\n";
9257        | RConstOptString _ ->
9258            pr "  if (r)\n";
9259            pr "    return rb_str_new2 (r);\n";
9260            pr "  else\n";
9261            pr "    return Qnil;\n";
9262        | RString _ ->
9263            pr "  VALUE rv = rb_str_new2 (r);\n";
9264            pr "  free (r);\n";
9265            pr "  return rv;\n";
9266        | RStringList _ ->
9267            pr "  int i, len = 0;\n";
9268            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9269            pr "  VALUE rv = rb_ary_new2 (len);\n";
9270            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9271            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9272            pr "    free (r[i]);\n";
9273            pr "  }\n";
9274            pr "  free (r);\n";
9275            pr "  return rv;\n"
9276        | RStruct (_, typ) ->
9277            let cols = cols_of_struct typ in
9278            generate_ruby_struct_code typ cols
9279        | RStructList (_, typ) ->
9280            let cols = cols_of_struct typ in
9281            generate_ruby_struct_list_code typ cols
9282        | RHashtable _ ->
9283            pr "  VALUE rv = rb_hash_new ();\n";
9284            pr "  int i;\n";
9285            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9286            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9287            pr "    free (r[i]);\n";
9288            pr "    free (r[i+1]);\n";
9289            pr "  }\n";
9290            pr "  free (r);\n";
9291            pr "  return rv;\n"
9292        | RBufferOut _ ->
9293            pr "  VALUE rv = rb_str_new (r, size);\n";
9294            pr "  free (r);\n";
9295            pr "  return rv;\n";
9296       );
9297
9298       pr "}\n";
9299       pr "\n"
9300   ) all_functions;
9301
9302   pr "\
9303 /* Initialize the module. */
9304 void Init__guestfs ()
9305 {
9306   m_guestfs = rb_define_module (\"Guestfs\");
9307   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9308   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9309
9310   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9311   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9312
9313 ";
9314   (* Define the rest of the methods. *)
9315   List.iter (
9316     fun (name, style, _, _, _, _, _) ->
9317       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9318       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9319   ) all_functions;
9320
9321   pr "}\n"
9322
9323 (* Ruby code to return a struct. *)
9324 and generate_ruby_struct_code typ cols =
9325   pr "  VALUE rv = rb_hash_new ();\n";
9326   List.iter (
9327     function
9328     | name, FString ->
9329         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9330     | name, FBuffer ->
9331         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9332     | name, FUUID ->
9333         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9334     | name, (FBytes|FUInt64) ->
9335         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9336     | name, FInt64 ->
9337         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9338     | name, FUInt32 ->
9339         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9340     | name, FInt32 ->
9341         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9342     | name, FOptPercent ->
9343         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9344     | name, FChar -> (* XXX wrong? *)
9345         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9346   ) cols;
9347   pr "  guestfs_free_%s (r);\n" typ;
9348   pr "  return rv;\n"
9349
9350 (* Ruby code to return a struct list. *)
9351 and generate_ruby_struct_list_code typ cols =
9352   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9353   pr "  int i;\n";
9354   pr "  for (i = 0; i < r->len; ++i) {\n";
9355   pr "    VALUE hv = rb_hash_new ();\n";
9356   List.iter (
9357     function
9358     | name, FString ->
9359         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9360     | name, FBuffer ->
9361         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
9362     | name, FUUID ->
9363         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9364     | name, (FBytes|FUInt64) ->
9365         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9366     | name, FInt64 ->
9367         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9368     | name, FUInt32 ->
9369         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9370     | name, FInt32 ->
9371         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9372     | name, FOptPercent ->
9373         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9374     | name, FChar -> (* XXX wrong? *)
9375         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9376   ) cols;
9377   pr "    rb_ary_push (rv, hv);\n";
9378   pr "  }\n";
9379   pr "  guestfs_free_%s_list (r);\n" typ;
9380   pr "  return rv;\n"
9381
9382 (* Generate Java bindings GuestFS.java file. *)
9383 and generate_java_java () =
9384   generate_header CStyle LGPLv2plus;
9385
9386   pr "\
9387 package com.redhat.et.libguestfs;
9388
9389 import java.util.HashMap;
9390 import com.redhat.et.libguestfs.LibGuestFSException;
9391 import com.redhat.et.libguestfs.PV;
9392 import com.redhat.et.libguestfs.VG;
9393 import com.redhat.et.libguestfs.LV;
9394 import com.redhat.et.libguestfs.Stat;
9395 import com.redhat.et.libguestfs.StatVFS;
9396 import com.redhat.et.libguestfs.IntBool;
9397 import com.redhat.et.libguestfs.Dirent;
9398
9399 /**
9400  * The GuestFS object is a libguestfs handle.
9401  *
9402  * @author rjones
9403  */
9404 public class GuestFS {
9405   // Load the native code.
9406   static {
9407     System.loadLibrary (\"guestfs_jni\");
9408   }
9409
9410   /**
9411    * The native guestfs_h pointer.
9412    */
9413   long g;
9414
9415   /**
9416    * Create a libguestfs handle.
9417    *
9418    * @throws LibGuestFSException
9419    */
9420   public GuestFS () throws LibGuestFSException
9421   {
9422     g = _create ();
9423   }
9424   private native long _create () throws LibGuestFSException;
9425
9426   /**
9427    * Close a libguestfs handle.
9428    *
9429    * You can also leave handles to be collected by the garbage
9430    * collector, but this method ensures that the resources used
9431    * by the handle are freed up immediately.  If you call any
9432    * other methods after closing the handle, you will get an
9433    * exception.
9434    *
9435    * @throws LibGuestFSException
9436    */
9437   public void close () throws LibGuestFSException
9438   {
9439     if (g != 0)
9440       _close (g);
9441     g = 0;
9442   }
9443   private native void _close (long g) throws LibGuestFSException;
9444
9445   public void finalize () throws LibGuestFSException
9446   {
9447     close ();
9448   }
9449
9450 ";
9451
9452   List.iter (
9453     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9454       if not (List.mem NotInDocs flags); then (
9455         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9456         let doc =
9457           if List.mem ProtocolLimitWarning flags then
9458             doc ^ "\n\n" ^ protocol_limit_warning
9459           else doc in
9460         let doc =
9461           if List.mem DangerWillRobinson flags then
9462             doc ^ "\n\n" ^ danger_will_robinson
9463           else doc in
9464         let doc =
9465           match deprecation_notice flags with
9466           | None -> doc
9467           | Some txt -> doc ^ "\n\n" ^ txt in
9468         let doc = pod2text ~width:60 name doc in
9469         let doc = List.map (            (* RHBZ#501883 *)
9470           function
9471           | "" -> "<p>"
9472           | nonempty -> nonempty
9473         ) doc in
9474         let doc = String.concat "\n   * " doc in
9475
9476         pr "  /**\n";
9477         pr "   * %s\n" shortdesc;
9478         pr "   * <p>\n";
9479         pr "   * %s\n" doc;
9480         pr "   * @throws LibGuestFSException\n";
9481         pr "   */\n";
9482         pr "  ";
9483       );
9484       generate_java_prototype ~public:true ~semicolon:false name style;
9485       pr "\n";
9486       pr "  {\n";
9487       pr "    if (g == 0)\n";
9488       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9489         name;
9490       pr "    ";
9491       if fst style <> RErr then pr "return ";
9492       pr "_%s " name;
9493       generate_java_call_args ~handle:"g" (snd style);
9494       pr ";\n";
9495       pr "  }\n";
9496       pr "  ";
9497       generate_java_prototype ~privat:true ~native:true name style;
9498       pr "\n";
9499       pr "\n";
9500   ) all_functions;
9501
9502   pr "}\n"
9503
9504 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9505 and generate_java_call_args ~handle args =
9506   pr "(%s" handle;
9507   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9508   pr ")"
9509
9510 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9511     ?(semicolon=true) name style =
9512   if privat then pr "private ";
9513   if public then pr "public ";
9514   if native then pr "native ";
9515
9516   (* return type *)
9517   (match fst style with
9518    | RErr -> pr "void ";
9519    | RInt _ -> pr "int ";
9520    | RInt64 _ -> pr "long ";
9521    | RBool _ -> pr "boolean ";
9522    | RConstString _ | RConstOptString _ | RString _
9523    | RBufferOut _ -> pr "String ";
9524    | RStringList _ -> pr "String[] ";
9525    | RStruct (_, typ) ->
9526        let name = java_name_of_struct typ in
9527        pr "%s " name;
9528    | RStructList (_, typ) ->
9529        let name = java_name_of_struct typ in
9530        pr "%s[] " name;
9531    | RHashtable _ -> pr "HashMap<String,String> ";
9532   );
9533
9534   if native then pr "_%s " name else pr "%s " name;
9535   pr "(";
9536   let needs_comma = ref false in
9537   if native then (
9538     pr "long g";
9539     needs_comma := true
9540   );
9541
9542   (* args *)
9543   List.iter (
9544     fun arg ->
9545       if !needs_comma then pr ", ";
9546       needs_comma := true;
9547
9548       match arg with
9549       | Pathname n
9550       | Device n | Dev_or_Path n
9551       | String n
9552       | OptString n
9553       | FileIn n
9554       | FileOut n ->
9555           pr "String %s" n
9556       | StringList n | DeviceList n ->
9557           pr "String[] %s" n
9558       | Bool n ->
9559           pr "boolean %s" n
9560       | Int n ->
9561           pr "int %s" n
9562       | Int64 n ->
9563           pr "long %s" n
9564   ) (snd style);
9565
9566   pr ")\n";
9567   pr "    throws LibGuestFSException";
9568   if semicolon then pr ";"
9569
9570 and generate_java_struct jtyp cols () =
9571   generate_header CStyle LGPLv2plus;
9572
9573   pr "\
9574 package com.redhat.et.libguestfs;
9575
9576 /**
9577  * Libguestfs %s structure.
9578  *
9579  * @author rjones
9580  * @see GuestFS
9581  */
9582 public class %s {
9583 " jtyp jtyp;
9584
9585   List.iter (
9586     function
9587     | name, FString
9588     | name, FUUID
9589     | name, FBuffer -> pr "  public String %s;\n" name
9590     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9591     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9592     | name, FChar -> pr "  public char %s;\n" name
9593     | name, FOptPercent ->
9594         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9595         pr "  public float %s;\n" name
9596   ) cols;
9597
9598   pr "}\n"
9599
9600 and generate_java_c () =
9601   generate_header CStyle LGPLv2plus;
9602
9603   pr "\
9604 #include <stdio.h>
9605 #include <stdlib.h>
9606 #include <string.h>
9607
9608 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9609 #include \"guestfs.h\"
9610
9611 /* Note that this function returns.  The exception is not thrown
9612  * until after the wrapper function returns.
9613  */
9614 static void
9615 throw_exception (JNIEnv *env, const char *msg)
9616 {
9617   jclass cl;
9618   cl = (*env)->FindClass (env,
9619                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9620   (*env)->ThrowNew (env, cl, msg);
9621 }
9622
9623 JNIEXPORT jlong JNICALL
9624 Java_com_redhat_et_libguestfs_GuestFS__1create
9625   (JNIEnv *env, jobject obj)
9626 {
9627   guestfs_h *g;
9628
9629   g = guestfs_create ();
9630   if (g == NULL) {
9631     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9632     return 0;
9633   }
9634   guestfs_set_error_handler (g, NULL, NULL);
9635   return (jlong) (long) g;
9636 }
9637
9638 JNIEXPORT void JNICALL
9639 Java_com_redhat_et_libguestfs_GuestFS__1close
9640   (JNIEnv *env, jobject obj, jlong jg)
9641 {
9642   guestfs_h *g = (guestfs_h *) (long) jg;
9643   guestfs_close (g);
9644 }
9645
9646 ";
9647
9648   List.iter (
9649     fun (name, style, _, _, _, _, _) ->
9650       pr "JNIEXPORT ";
9651       (match fst style with
9652        | RErr -> pr "void ";
9653        | RInt _ -> pr "jint ";
9654        | RInt64 _ -> pr "jlong ";
9655        | RBool _ -> pr "jboolean ";
9656        | RConstString _ | RConstOptString _ | RString _
9657        | RBufferOut _ -> pr "jstring ";
9658        | RStruct _ | RHashtable _ ->
9659            pr "jobject ";
9660        | RStringList _ | RStructList _ ->
9661            pr "jobjectArray ";
9662       );
9663       pr "JNICALL\n";
9664       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9665       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9666       pr "\n";
9667       pr "  (JNIEnv *env, jobject obj, jlong jg";
9668       List.iter (
9669         function
9670         | Pathname n
9671         | Device n | Dev_or_Path n
9672         | String n
9673         | OptString n
9674         | FileIn n
9675         | FileOut n ->
9676             pr ", jstring j%s" n
9677         | StringList n | DeviceList n ->
9678             pr ", jobjectArray j%s" n
9679         | Bool n ->
9680             pr ", jboolean j%s" n
9681         | Int n ->
9682             pr ", jint j%s" n
9683         | Int64 n ->
9684             pr ", jlong j%s" n
9685       ) (snd style);
9686       pr ")\n";
9687       pr "{\n";
9688       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9689       let error_code, no_ret =
9690         match fst style with
9691         | RErr -> pr "  int r;\n"; "-1", ""
9692         | RBool _
9693         | RInt _ -> pr "  int r;\n"; "-1", "0"
9694         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9695         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9696         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9697         | RString _ ->
9698             pr "  jstring jr;\n";
9699             pr "  char *r;\n"; "NULL", "NULL"
9700         | RStringList _ ->
9701             pr "  jobjectArray jr;\n";
9702             pr "  int r_len;\n";
9703             pr "  jclass cl;\n";
9704             pr "  jstring jstr;\n";
9705             pr "  char **r;\n"; "NULL", "NULL"
9706         | RStruct (_, typ) ->
9707             pr "  jobject jr;\n";
9708             pr "  jclass cl;\n";
9709             pr "  jfieldID fl;\n";
9710             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9711         | RStructList (_, typ) ->
9712             pr "  jobjectArray jr;\n";
9713             pr "  jclass cl;\n";
9714             pr "  jfieldID fl;\n";
9715             pr "  jobject jfl;\n";
9716             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9717         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9718         | RBufferOut _ ->
9719             pr "  jstring jr;\n";
9720             pr "  char *r;\n";
9721             pr "  size_t size;\n";
9722             "NULL", "NULL" in
9723       List.iter (
9724         function
9725         | Pathname n
9726         | Device n | Dev_or_Path n
9727         | String n
9728         | OptString n
9729         | FileIn n
9730         | FileOut n ->
9731             pr "  const char *%s;\n" n
9732         | StringList n | DeviceList n ->
9733             pr "  int %s_len;\n" n;
9734             pr "  const char **%s;\n" n
9735         | Bool n
9736         | Int n ->
9737             pr "  int %s;\n" n
9738         | Int64 n ->
9739             pr "  int64_t %s;\n" n
9740       ) (snd style);
9741
9742       let needs_i =
9743         (match fst style with
9744          | RStringList _ | RStructList _ -> true
9745          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9746          | RConstOptString _
9747          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9748           List.exists (function
9749                        | StringList _ -> true
9750                        | DeviceList _ -> true
9751                        | _ -> false) (snd style) in
9752       if needs_i then
9753         pr "  int i;\n";
9754
9755       pr "\n";
9756
9757       (* Get the parameters. *)
9758       List.iter (
9759         function
9760         | Pathname n
9761         | Device n | Dev_or_Path n
9762         | String n
9763         | FileIn n
9764         | FileOut n ->
9765             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9766         | OptString n ->
9767             (* This is completely undocumented, but Java null becomes
9768              * a NULL parameter.
9769              *)
9770             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9771         | StringList n | DeviceList n ->
9772             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9773             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9774             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9775             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9776               n;
9777             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9778             pr "  }\n";
9779             pr "  %s[%s_len] = NULL;\n" n n;
9780         | Bool n
9781         | Int n
9782         | Int64 n ->
9783             pr "  %s = j%s;\n" n n
9784       ) (snd style);
9785
9786       (* Make the call. *)
9787       pr "  r = guestfs_%s " name;
9788       generate_c_call_args ~handle:"g" style;
9789       pr ";\n";
9790
9791       (* Release the parameters. *)
9792       List.iter (
9793         function
9794         | Pathname n
9795         | Device n | Dev_or_Path n
9796         | String n
9797         | FileIn n
9798         | FileOut n ->
9799             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9800         | OptString n ->
9801             pr "  if (j%s)\n" n;
9802             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9803         | StringList n | DeviceList n ->
9804             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9805             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9806               n;
9807             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9808             pr "  }\n";
9809             pr "  free (%s);\n" n
9810         | Bool n
9811         | Int n
9812         | Int64 n -> ()
9813       ) (snd style);
9814
9815       (* Check for errors. *)
9816       pr "  if (r == %s) {\n" error_code;
9817       pr "    throw_exception (env, guestfs_last_error (g));\n";
9818       pr "    return %s;\n" no_ret;
9819       pr "  }\n";
9820
9821       (* Return value. *)
9822       (match fst style with
9823        | RErr -> ()
9824        | RInt _ -> pr "  return (jint) r;\n"
9825        | RBool _ -> pr "  return (jboolean) r;\n"
9826        | RInt64 _ -> pr "  return (jlong) r;\n"
9827        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9828        | RConstOptString _ ->
9829            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9830        | RString _ ->
9831            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9832            pr "  free (r);\n";
9833            pr "  return jr;\n"
9834        | RStringList _ ->
9835            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9836            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9837            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9838            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9839            pr "  for (i = 0; i < r_len; ++i) {\n";
9840            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9841            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9842            pr "    free (r[i]);\n";
9843            pr "  }\n";
9844            pr "  free (r);\n";
9845            pr "  return jr;\n"
9846        | RStruct (_, typ) ->
9847            let jtyp = java_name_of_struct typ in
9848            let cols = cols_of_struct typ in
9849            generate_java_struct_return typ jtyp cols
9850        | RStructList (_, typ) ->
9851            let jtyp = java_name_of_struct typ in
9852            let cols = cols_of_struct typ in
9853            generate_java_struct_list_return typ jtyp cols
9854        | RHashtable _ ->
9855            (* XXX *)
9856            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9857            pr "  return NULL;\n"
9858        | RBufferOut _ ->
9859            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9860            pr "  free (r);\n";
9861            pr "  return jr;\n"
9862       );
9863
9864       pr "}\n";
9865       pr "\n"
9866   ) all_functions
9867
9868 and generate_java_struct_return typ jtyp cols =
9869   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9870   pr "  jr = (*env)->AllocObject (env, cl);\n";
9871   List.iter (
9872     function
9873     | name, FString ->
9874         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9875         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9876     | name, FUUID ->
9877         pr "  {\n";
9878         pr "    char s[33];\n";
9879         pr "    memcpy (s, r->%s, 32);\n" name;
9880         pr "    s[32] = 0;\n";
9881         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9882         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9883         pr "  }\n";
9884     | name, FBuffer ->
9885         pr "  {\n";
9886         pr "    int len = r->%s_len;\n" name;
9887         pr "    char s[len+1];\n";
9888         pr "    memcpy (s, r->%s, len);\n" name;
9889         pr "    s[len] = 0;\n";
9890         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9891         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9892         pr "  }\n";
9893     | name, (FBytes|FUInt64|FInt64) ->
9894         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9895         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9896     | name, (FUInt32|FInt32) ->
9897         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9898         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9899     | name, FOptPercent ->
9900         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9901         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9902     | name, FChar ->
9903         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9904         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9905   ) cols;
9906   pr "  free (r);\n";
9907   pr "  return jr;\n"
9908
9909 and generate_java_struct_list_return typ jtyp cols =
9910   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9911   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9912   pr "  for (i = 0; i < r->len; ++i) {\n";
9913   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9914   List.iter (
9915     function
9916     | name, FString ->
9917         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9918         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9919     | name, FUUID ->
9920         pr "    {\n";
9921         pr "      char s[33];\n";
9922         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9923         pr "      s[32] = 0;\n";
9924         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9925         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9926         pr "    }\n";
9927     | name, FBuffer ->
9928         pr "    {\n";
9929         pr "      int len = r->val[i].%s_len;\n" name;
9930         pr "      char s[len+1];\n";
9931         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9932         pr "      s[len] = 0;\n";
9933         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9934         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9935         pr "    }\n";
9936     | name, (FBytes|FUInt64|FInt64) ->
9937         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9938         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9939     | name, (FUInt32|FInt32) ->
9940         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9941         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9942     | name, FOptPercent ->
9943         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9944         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9945     | name, FChar ->
9946         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9947         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9948   ) cols;
9949   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9950   pr "  }\n";
9951   pr "  guestfs_free_%s_list (r);\n" typ;
9952   pr "  return jr;\n"
9953
9954 and generate_java_makefile_inc () =
9955   generate_header HashStyle GPLv2plus;
9956
9957   pr "java_built_sources = \\\n";
9958   List.iter (
9959     fun (typ, jtyp) ->
9960         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9961   ) java_structs;
9962   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9963
9964 and generate_haskell_hs () =
9965   generate_header HaskellStyle LGPLv2plus;
9966
9967   (* XXX We only know how to generate partial FFI for Haskell
9968    * at the moment.  Please help out!
9969    *)
9970   let can_generate style =
9971     match style with
9972     | RErr, _
9973     | RInt _, _
9974     | RInt64 _, _ -> true
9975     | RBool _, _
9976     | RConstString _, _
9977     | RConstOptString _, _
9978     | RString _, _
9979     | RStringList _, _
9980     | RStruct _, _
9981     | RStructList _, _
9982     | RHashtable _, _
9983     | RBufferOut _, _ -> false in
9984
9985   pr "\
9986 {-# INCLUDE <guestfs.h> #-}
9987 {-# LANGUAGE ForeignFunctionInterface #-}
9988
9989 module Guestfs (
9990   create";
9991
9992   (* List out the names of the actions we want to export. *)
9993   List.iter (
9994     fun (name, style, _, _, _, _, _) ->
9995       if can_generate style then pr ",\n  %s" name
9996   ) all_functions;
9997
9998   pr "
9999   ) where
10000
10001 -- Unfortunately some symbols duplicate ones already present
10002 -- in Prelude.  We don't know which, so we hard-code a list
10003 -- here.
10004 import Prelude hiding (truncate)
10005
10006 import Foreign
10007 import Foreign.C
10008 import Foreign.C.Types
10009 import IO
10010 import Control.Exception
10011 import Data.Typeable
10012
10013 data GuestfsS = GuestfsS            -- represents the opaque C struct
10014 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10015 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10016
10017 -- XXX define properly later XXX
10018 data PV = PV
10019 data VG = VG
10020 data LV = LV
10021 data IntBool = IntBool
10022 data Stat = Stat
10023 data StatVFS = StatVFS
10024 data Hashtable = Hashtable
10025
10026 foreign import ccall unsafe \"guestfs_create\" c_create
10027   :: IO GuestfsP
10028 foreign import ccall unsafe \"&guestfs_close\" c_close
10029   :: FunPtr (GuestfsP -> IO ())
10030 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10031   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10032
10033 create :: IO GuestfsH
10034 create = do
10035   p <- c_create
10036   c_set_error_handler p nullPtr nullPtr
10037   h <- newForeignPtr c_close p
10038   return h
10039
10040 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10041   :: GuestfsP -> IO CString
10042
10043 -- last_error :: GuestfsH -> IO (Maybe String)
10044 -- last_error h = do
10045 --   str <- withForeignPtr h (\\p -> c_last_error p)
10046 --   maybePeek peekCString str
10047
10048 last_error :: GuestfsH -> IO (String)
10049 last_error h = do
10050   str <- withForeignPtr h (\\p -> c_last_error p)
10051   if (str == nullPtr)
10052     then return \"no error\"
10053     else peekCString str
10054
10055 ";
10056
10057   (* Generate wrappers for each foreign function. *)
10058   List.iter (
10059     fun (name, style, _, _, _, _, _) ->
10060       if can_generate style then (
10061         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10062         pr "  :: ";
10063         generate_haskell_prototype ~handle:"GuestfsP" style;
10064         pr "\n";
10065         pr "\n";
10066         pr "%s :: " name;
10067         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10068         pr "\n";
10069         pr "%s %s = do\n" name
10070           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10071         pr "  r <- ";
10072         (* Convert pointer arguments using with* functions. *)
10073         List.iter (
10074           function
10075           | FileIn n
10076           | FileOut n
10077           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10078           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10079           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10080           | Bool _ | Int _ | Int64 _ -> ()
10081         ) (snd style);
10082         (* Convert integer arguments. *)
10083         let args =
10084           List.map (
10085             function
10086             | Bool n -> sprintf "(fromBool %s)" n
10087             | Int n -> sprintf "(fromIntegral %s)" n
10088             | Int64 n -> sprintf "(fromIntegral %s)" n
10089             | FileIn n | FileOut n
10090             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10091           ) (snd style) in
10092         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10093           (String.concat " " ("p" :: args));
10094         (match fst style with
10095          | RErr | RInt _ | RInt64 _ | RBool _ ->
10096              pr "  if (r == -1)\n";
10097              pr "    then do\n";
10098              pr "      err <- last_error h\n";
10099              pr "      fail err\n";
10100          | RConstString _ | RConstOptString _ | RString _
10101          | RStringList _ | RStruct _
10102          | RStructList _ | RHashtable _ | RBufferOut _ ->
10103              pr "  if (r == nullPtr)\n";
10104              pr "    then do\n";
10105              pr "      err <- last_error h\n";
10106              pr "      fail err\n";
10107         );
10108         (match fst style with
10109          | RErr ->
10110              pr "    else return ()\n"
10111          | RInt _ ->
10112              pr "    else return (fromIntegral r)\n"
10113          | RInt64 _ ->
10114              pr "    else return (fromIntegral r)\n"
10115          | RBool _ ->
10116              pr "    else return (toBool r)\n"
10117          | RConstString _
10118          | RConstOptString _
10119          | RString _
10120          | RStringList _
10121          | RStruct _
10122          | RStructList _
10123          | RHashtable _
10124          | RBufferOut _ ->
10125              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10126         );
10127         pr "\n";
10128       )
10129   ) all_functions
10130
10131 and generate_haskell_prototype ~handle ?(hs = false) style =
10132   pr "%s -> " handle;
10133   let string = if hs then "String" else "CString" in
10134   let int = if hs then "Int" else "CInt" in
10135   let bool = if hs then "Bool" else "CInt" in
10136   let int64 = if hs then "Integer" else "Int64" in
10137   List.iter (
10138     fun arg ->
10139       (match arg with
10140        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10141        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10142        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10143        | Bool _ -> pr "%s" bool
10144        | Int _ -> pr "%s" int
10145        | Int64 _ -> pr "%s" int
10146        | FileIn _ -> pr "%s" string
10147        | FileOut _ -> pr "%s" string
10148       );
10149       pr " -> ";
10150   ) (snd style);
10151   pr "IO (";
10152   (match fst style with
10153    | RErr -> if not hs then pr "CInt"
10154    | RInt _ -> pr "%s" int
10155    | RInt64 _ -> pr "%s" int64
10156    | RBool _ -> pr "%s" bool
10157    | RConstString _ -> pr "%s" string
10158    | RConstOptString _ -> pr "Maybe %s" string
10159    | RString _ -> pr "%s" string
10160    | RStringList _ -> pr "[%s]" string
10161    | RStruct (_, typ) ->
10162        let name = java_name_of_struct typ in
10163        pr "%s" name
10164    | RStructList (_, typ) ->
10165        let name = java_name_of_struct typ in
10166        pr "[%s]" name
10167    | RHashtable _ -> pr "Hashtable"
10168    | RBufferOut _ -> pr "%s" string
10169   );
10170   pr ")"
10171
10172 and generate_csharp () =
10173   generate_header CPlusPlusStyle LGPLv2plus;
10174
10175   (* XXX Make this configurable by the C# assembly users. *)
10176   let library = "libguestfs.so.0" in
10177
10178   pr "\
10179 // These C# bindings are highly experimental at present.
10180 //
10181 // Firstly they only work on Linux (ie. Mono).  In order to get them
10182 // to work on Windows (ie. .Net) you would need to port the library
10183 // itself to Windows first.
10184 //
10185 // The second issue is that some calls are known to be incorrect and
10186 // can cause Mono to segfault.  Particularly: calls which pass or
10187 // return string[], or return any structure value.  This is because
10188 // we haven't worked out the correct way to do this from C#.
10189 //
10190 // The third issue is that when compiling you get a lot of warnings.
10191 // We are not sure whether the warnings are important or not.
10192 //
10193 // Fourthly we do not routinely build or test these bindings as part
10194 // of the make && make check cycle, which means that regressions might
10195 // go unnoticed.
10196 //
10197 // Suggestions and patches are welcome.
10198
10199 // To compile:
10200 //
10201 // gmcs Libguestfs.cs
10202 // mono Libguestfs.exe
10203 //
10204 // (You'll probably want to add a Test class / static main function
10205 // otherwise this won't do anything useful).
10206
10207 using System;
10208 using System.IO;
10209 using System.Runtime.InteropServices;
10210 using System.Runtime.Serialization;
10211 using System.Collections;
10212
10213 namespace Guestfs
10214 {
10215   class Error : System.ApplicationException
10216   {
10217     public Error (string message) : base (message) {}
10218     protected Error (SerializationInfo info, StreamingContext context) {}
10219   }
10220
10221   class Guestfs
10222   {
10223     IntPtr _handle;
10224
10225     [DllImport (\"%s\")]
10226     static extern IntPtr guestfs_create ();
10227
10228     public Guestfs ()
10229     {
10230       _handle = guestfs_create ();
10231       if (_handle == IntPtr.Zero)
10232         throw new Error (\"could not create guestfs handle\");
10233     }
10234
10235     [DllImport (\"%s\")]
10236     static extern void guestfs_close (IntPtr h);
10237
10238     ~Guestfs ()
10239     {
10240       guestfs_close (_handle);
10241     }
10242
10243     [DllImport (\"%s\")]
10244     static extern string guestfs_last_error (IntPtr h);
10245
10246 " library library library;
10247
10248   (* Generate C# structure bindings.  We prefix struct names with
10249    * underscore because C# cannot have conflicting struct names and
10250    * method names (eg. "class stat" and "stat").
10251    *)
10252   List.iter (
10253     fun (typ, cols) ->
10254       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10255       pr "    public class _%s {\n" typ;
10256       List.iter (
10257         function
10258         | name, FChar -> pr "      char %s;\n" name
10259         | name, FString -> pr "      string %s;\n" name
10260         | name, FBuffer ->
10261             pr "      uint %s_len;\n" name;
10262             pr "      string %s;\n" name
10263         | name, FUUID ->
10264             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10265             pr "      string %s;\n" name
10266         | name, FUInt32 -> pr "      uint %s;\n" name
10267         | name, FInt32 -> pr "      int %s;\n" name
10268         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10269         | name, FInt64 -> pr "      long %s;\n" name
10270         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10271       ) cols;
10272       pr "    }\n";
10273       pr "\n"
10274   ) structs;
10275
10276   (* Generate C# function bindings. *)
10277   List.iter (
10278     fun (name, style, _, _, _, shortdesc, _) ->
10279       let rec csharp_return_type () =
10280         match fst style with
10281         | RErr -> "void"
10282         | RBool n -> "bool"
10283         | RInt n -> "int"
10284         | RInt64 n -> "long"
10285         | RConstString n
10286         | RConstOptString n
10287         | RString n
10288         | RBufferOut n -> "string"
10289         | RStruct (_,n) -> "_" ^ n
10290         | RHashtable n -> "Hashtable"
10291         | RStringList n -> "string[]"
10292         | RStructList (_,n) -> sprintf "_%s[]" n
10293
10294       and c_return_type () =
10295         match fst style with
10296         | RErr
10297         | RBool _
10298         | RInt _ -> "int"
10299         | RInt64 _ -> "long"
10300         | RConstString _
10301         | RConstOptString _
10302         | RString _
10303         | RBufferOut _ -> "string"
10304         | RStruct (_,n) -> "_" ^ n
10305         | RHashtable _
10306         | RStringList _ -> "string[]"
10307         | RStructList (_,n) -> sprintf "_%s[]" n
10308
10309       and c_error_comparison () =
10310         match fst style with
10311         | RErr
10312         | RBool _
10313         | RInt _
10314         | RInt64 _ -> "== -1"
10315         | RConstString _
10316         | RConstOptString _
10317         | RString _
10318         | RBufferOut _
10319         | RStruct (_,_)
10320         | RHashtable _
10321         | RStringList _
10322         | RStructList (_,_) -> "== null"
10323
10324       and generate_extern_prototype () =
10325         pr "    static extern %s guestfs_%s (IntPtr h"
10326           (c_return_type ()) name;
10327         List.iter (
10328           function
10329           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10330           | FileIn n | FileOut n ->
10331               pr ", [In] string %s" n
10332           | StringList n | DeviceList n ->
10333               pr ", [In] string[] %s" n
10334           | Bool n ->
10335               pr ", bool %s" n
10336           | Int n ->
10337               pr ", int %s" n
10338           | Int64 n ->
10339               pr ", long %s" n
10340         ) (snd style);
10341         pr ");\n"
10342
10343       and generate_public_prototype () =
10344         pr "    public %s %s (" (csharp_return_type ()) name;
10345         let comma = ref false in
10346         let next () =
10347           if !comma then pr ", ";
10348           comma := true
10349         in
10350         List.iter (
10351           function
10352           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10353           | FileIn n | FileOut n ->
10354               next (); pr "string %s" n
10355           | StringList n | DeviceList n ->
10356               next (); pr "string[] %s" n
10357           | Bool n ->
10358               next (); pr "bool %s" n
10359           | Int n ->
10360               next (); pr "int %s" n
10361           | Int64 n ->
10362               next (); pr "long %s" n
10363         ) (snd style);
10364         pr ")\n"
10365
10366       and generate_call () =
10367         pr "guestfs_%s (_handle" name;
10368         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10369         pr ");\n";
10370       in
10371
10372       pr "    [DllImport (\"%s\")]\n" library;
10373       generate_extern_prototype ();
10374       pr "\n";
10375       pr "    /// <summary>\n";
10376       pr "    /// %s\n" shortdesc;
10377       pr "    /// </summary>\n";
10378       generate_public_prototype ();
10379       pr "    {\n";
10380       pr "      %s r;\n" (c_return_type ());
10381       pr "      r = ";
10382       generate_call ();
10383       pr "      if (r %s)\n" (c_error_comparison ());
10384       pr "        throw new Error (guestfs_last_error (_handle));\n";
10385       (match fst style with
10386        | RErr -> ()
10387        | RBool _ ->
10388            pr "      return r != 0 ? true : false;\n"
10389        | RHashtable _ ->
10390            pr "      Hashtable rr = new Hashtable ();\n";
10391            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10392            pr "        rr.Add (r[i], r[i+1]);\n";
10393            pr "      return rr;\n"
10394        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10395        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10396        | RStructList _ ->
10397            pr "      return r;\n"
10398       );
10399       pr "    }\n";
10400       pr "\n";
10401   ) all_functions_sorted;
10402
10403   pr "  }
10404 }
10405 "
10406
10407 and generate_bindtests () =
10408   generate_header CStyle LGPLv2plus;
10409
10410   pr "\
10411 #include <stdio.h>
10412 #include <stdlib.h>
10413 #include <inttypes.h>
10414 #include <string.h>
10415
10416 #include \"guestfs.h\"
10417 #include \"guestfs-internal.h\"
10418 #include \"guestfs-internal-actions.h\"
10419 #include \"guestfs_protocol.h\"
10420
10421 #define error guestfs_error
10422 #define safe_calloc guestfs_safe_calloc
10423 #define safe_malloc guestfs_safe_malloc
10424
10425 static void
10426 print_strings (char *const *argv)
10427 {
10428   int argc;
10429
10430   printf (\"[\");
10431   for (argc = 0; argv[argc] != NULL; ++argc) {
10432     if (argc > 0) printf (\", \");
10433     printf (\"\\\"%%s\\\"\", argv[argc]);
10434   }
10435   printf (\"]\\n\");
10436 }
10437
10438 /* The test0 function prints its parameters to stdout. */
10439 ";
10440
10441   let test0, tests =
10442     match test_functions with
10443     | [] -> assert false
10444     | test0 :: tests -> test0, tests in
10445
10446   let () =
10447     let (name, style, _, _, _, _, _) = test0 in
10448     generate_prototype ~extern:false ~semicolon:false ~newline:true
10449       ~handle:"g" ~prefix:"guestfs__" name style;
10450     pr "{\n";
10451     List.iter (
10452       function
10453       | Pathname n
10454       | Device n | Dev_or_Path n
10455       | String n
10456       | FileIn n
10457       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10458       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10459       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10460       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10461       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10462       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10463     ) (snd style);
10464     pr "  /* Java changes stdout line buffering so we need this: */\n";
10465     pr "  fflush (stdout);\n";
10466     pr "  return 0;\n";
10467     pr "}\n";
10468     pr "\n" in
10469
10470   List.iter (
10471     fun (name, style, _, _, _, _, _) ->
10472       if String.sub name (String.length name - 3) 3 <> "err" then (
10473         pr "/* Test normal return. */\n";
10474         generate_prototype ~extern:false ~semicolon:false ~newline:true
10475           ~handle:"g" ~prefix:"guestfs__" name style;
10476         pr "{\n";
10477         (match fst style with
10478          | RErr ->
10479              pr "  return 0;\n"
10480          | RInt _ ->
10481              pr "  int r;\n";
10482              pr "  sscanf (val, \"%%d\", &r);\n";
10483              pr "  return r;\n"
10484          | RInt64 _ ->
10485              pr "  int64_t r;\n";
10486              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10487              pr "  return r;\n"
10488          | RBool _ ->
10489              pr "  return STREQ (val, \"true\");\n"
10490          | RConstString _
10491          | RConstOptString _ ->
10492              (* Can't return the input string here.  Return a static
10493               * string so we ensure we get a segfault if the caller
10494               * tries to free it.
10495               *)
10496              pr "  return \"static string\";\n"
10497          | RString _ ->
10498              pr "  return strdup (val);\n"
10499          | RStringList _ ->
10500              pr "  char **strs;\n";
10501              pr "  int n, i;\n";
10502              pr "  sscanf (val, \"%%d\", &n);\n";
10503              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10504              pr "  for (i = 0; i < n; ++i) {\n";
10505              pr "    strs[i] = safe_malloc (g, 16);\n";
10506              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10507              pr "  }\n";
10508              pr "  strs[n] = NULL;\n";
10509              pr "  return strs;\n"
10510          | RStruct (_, typ) ->
10511              pr "  struct guestfs_%s *r;\n" typ;
10512              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10513              pr "  return r;\n"
10514          | RStructList (_, typ) ->
10515              pr "  struct guestfs_%s_list *r;\n" typ;
10516              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10517              pr "  sscanf (val, \"%%d\", &r->len);\n";
10518              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10519              pr "  return r;\n"
10520          | RHashtable _ ->
10521              pr "  char **strs;\n";
10522              pr "  int n, i;\n";
10523              pr "  sscanf (val, \"%%d\", &n);\n";
10524              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10525              pr "  for (i = 0; i < n; ++i) {\n";
10526              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10527              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10528              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10529              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10530              pr "  }\n";
10531              pr "  strs[n*2] = NULL;\n";
10532              pr "  return strs;\n"
10533          | RBufferOut _ ->
10534              pr "  return strdup (val);\n"
10535         );
10536         pr "}\n";
10537         pr "\n"
10538       ) else (
10539         pr "/* Test error return. */\n";
10540         generate_prototype ~extern:false ~semicolon:false ~newline:true
10541           ~handle:"g" ~prefix:"guestfs__" name style;
10542         pr "{\n";
10543         pr "  error (g, \"error\");\n";
10544         (match fst style with
10545          | RErr | RInt _ | RInt64 _ | RBool _ ->
10546              pr "  return -1;\n"
10547          | RConstString _ | RConstOptString _
10548          | RString _ | RStringList _ | RStruct _
10549          | RStructList _
10550          | RHashtable _
10551          | RBufferOut _ ->
10552              pr "  return NULL;\n"
10553         );
10554         pr "}\n";
10555         pr "\n"
10556       )
10557   ) tests
10558
10559 and generate_ocaml_bindtests () =
10560   generate_header OCamlStyle GPLv2plus;
10561
10562   pr "\
10563 let () =
10564   let g = Guestfs.create () in
10565 ";
10566
10567   let mkargs args =
10568     String.concat " " (
10569       List.map (
10570         function
10571         | CallString s -> "\"" ^ s ^ "\""
10572         | CallOptString None -> "None"
10573         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10574         | CallStringList xs ->
10575             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10576         | CallInt i when i >= 0 -> string_of_int i
10577         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10578         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10579         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10580         | CallBool b -> string_of_bool b
10581       ) args
10582     )
10583   in
10584
10585   generate_lang_bindtests (
10586     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10587   );
10588
10589   pr "print_endline \"EOF\"\n"
10590
10591 and generate_perl_bindtests () =
10592   pr "#!/usr/bin/perl -w\n";
10593   generate_header HashStyle GPLv2plus;
10594
10595   pr "\
10596 use strict;
10597
10598 use Sys::Guestfs;
10599
10600 my $g = Sys::Guestfs->new ();
10601 ";
10602
10603   let mkargs args =
10604     String.concat ", " (
10605       List.map (
10606         function
10607         | CallString s -> "\"" ^ s ^ "\""
10608         | CallOptString None -> "undef"
10609         | CallOptString (Some s) -> sprintf "\"%s\"" s
10610         | CallStringList xs ->
10611             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10612         | CallInt i -> string_of_int i
10613         | CallInt64 i -> Int64.to_string i
10614         | CallBool b -> if b then "1" else "0"
10615       ) args
10616     )
10617   in
10618
10619   generate_lang_bindtests (
10620     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10621   );
10622
10623   pr "print \"EOF\\n\"\n"
10624
10625 and generate_python_bindtests () =
10626   generate_header HashStyle GPLv2plus;
10627
10628   pr "\
10629 import guestfs
10630
10631 g = guestfs.GuestFS ()
10632 ";
10633
10634   let mkargs args =
10635     String.concat ", " (
10636       List.map (
10637         function
10638         | CallString s -> "\"" ^ s ^ "\""
10639         | CallOptString None -> "None"
10640         | CallOptString (Some s) -> sprintf "\"%s\"" s
10641         | CallStringList xs ->
10642             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10643         | CallInt i -> string_of_int i
10644         | CallInt64 i -> Int64.to_string i
10645         | CallBool b -> if b then "1" else "0"
10646       ) args
10647     )
10648   in
10649
10650   generate_lang_bindtests (
10651     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10652   );
10653
10654   pr "print \"EOF\"\n"
10655
10656 and generate_ruby_bindtests () =
10657   generate_header HashStyle GPLv2plus;
10658
10659   pr "\
10660 require 'guestfs'
10661
10662 g = Guestfs::create()
10663 ";
10664
10665   let mkargs args =
10666     String.concat ", " (
10667       List.map (
10668         function
10669         | CallString s -> "\"" ^ s ^ "\""
10670         | CallOptString None -> "nil"
10671         | CallOptString (Some s) -> sprintf "\"%s\"" s
10672         | CallStringList xs ->
10673             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10674         | CallInt i -> string_of_int i
10675         | CallInt64 i -> Int64.to_string i
10676         | CallBool b -> string_of_bool b
10677       ) args
10678     )
10679   in
10680
10681   generate_lang_bindtests (
10682     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10683   );
10684
10685   pr "print \"EOF\\n\"\n"
10686
10687 and generate_java_bindtests () =
10688   generate_header CStyle GPLv2plus;
10689
10690   pr "\
10691 import com.redhat.et.libguestfs.*;
10692
10693 public class Bindtests {
10694     public static void main (String[] argv)
10695     {
10696         try {
10697             GuestFS g = new GuestFS ();
10698 ";
10699
10700   let mkargs args =
10701     String.concat ", " (
10702       List.map (
10703         function
10704         | CallString s -> "\"" ^ s ^ "\""
10705         | CallOptString None -> "null"
10706         | CallOptString (Some s) -> sprintf "\"%s\"" s
10707         | CallStringList xs ->
10708             "new String[]{" ^
10709               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10710         | CallInt i -> string_of_int i
10711         | CallInt64 i -> Int64.to_string i
10712         | CallBool b -> string_of_bool b
10713       ) args
10714     )
10715   in
10716
10717   generate_lang_bindtests (
10718     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10719   );
10720
10721   pr "
10722             System.out.println (\"EOF\");
10723         }
10724         catch (Exception exn) {
10725             System.err.println (exn);
10726             System.exit (1);
10727         }
10728     }
10729 }
10730 "
10731
10732 and generate_haskell_bindtests () =
10733   generate_header HaskellStyle GPLv2plus;
10734
10735   pr "\
10736 module Bindtests where
10737 import qualified Guestfs
10738
10739 main = do
10740   g <- Guestfs.create
10741 ";
10742
10743   let mkargs args =
10744     String.concat " " (
10745       List.map (
10746         function
10747         | CallString s -> "\"" ^ s ^ "\""
10748         | CallOptString None -> "Nothing"
10749         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10750         | CallStringList xs ->
10751             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10752         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10753         | CallInt i -> string_of_int i
10754         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10755         | CallInt64 i -> Int64.to_string i
10756         | CallBool true -> "True"
10757         | CallBool false -> "False"
10758       ) args
10759     )
10760   in
10761
10762   generate_lang_bindtests (
10763     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10764   );
10765
10766   pr "  putStrLn \"EOF\"\n"
10767
10768 (* Language-independent bindings tests - we do it this way to
10769  * ensure there is parity in testing bindings across all languages.
10770  *)
10771 and generate_lang_bindtests call =
10772   call "test0" [CallString "abc"; CallOptString (Some "def");
10773                 CallStringList []; CallBool false;
10774                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10775   call "test0" [CallString "abc"; CallOptString None;
10776                 CallStringList []; CallBool false;
10777                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10778   call "test0" [CallString ""; CallOptString (Some "def");
10779                 CallStringList []; CallBool false;
10780                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10781   call "test0" [CallString ""; CallOptString (Some "");
10782                 CallStringList []; CallBool false;
10783                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10784   call "test0" [CallString "abc"; CallOptString (Some "def");
10785                 CallStringList ["1"]; CallBool false;
10786                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10787   call "test0" [CallString "abc"; CallOptString (Some "def");
10788                 CallStringList ["1"; "2"]; CallBool false;
10789                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10790   call "test0" [CallString "abc"; CallOptString (Some "def");
10791                 CallStringList ["1"]; CallBool true;
10792                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10793   call "test0" [CallString "abc"; CallOptString (Some "def");
10794                 CallStringList ["1"]; CallBool false;
10795                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10796   call "test0" [CallString "abc"; CallOptString (Some "def");
10797                 CallStringList ["1"]; CallBool false;
10798                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10799   call "test0" [CallString "abc"; CallOptString (Some "def");
10800                 CallStringList ["1"]; CallBool false;
10801                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10802   call "test0" [CallString "abc"; CallOptString (Some "def");
10803                 CallStringList ["1"]; CallBool false;
10804                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10805   call "test0" [CallString "abc"; CallOptString (Some "def");
10806                 CallStringList ["1"]; CallBool false;
10807                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10808   call "test0" [CallString "abc"; CallOptString (Some "def");
10809                 CallStringList ["1"]; CallBool false;
10810                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10811
10812 (* XXX Add here tests of the return and error functions. *)
10813
10814 (* Code to generator bindings for virt-inspector.  Currently only
10815  * implemented for OCaml code (for virt-p2v 2.0).
10816  *)
10817 let rng_input = "inspector/virt-inspector.rng"
10818
10819 (* Read the input file and parse it into internal structures.  This is
10820  * by no means a complete RELAX NG parser, but is just enough to be
10821  * able to parse the specific input file.
10822  *)
10823 type rng =
10824   | Element of string * rng list        (* <element name=name/> *)
10825   | Attribute of string * rng list        (* <attribute name=name/> *)
10826   | Interleave of rng list                (* <interleave/> *)
10827   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10828   | OneOrMore of rng                        (* <oneOrMore/> *)
10829   | Optional of rng                        (* <optional/> *)
10830   | Choice of string list                (* <choice><value/>*</choice> *)
10831   | Value of string                        (* <value>str</value> *)
10832   | Text                                (* <text/> *)
10833
10834 let rec string_of_rng = function
10835   | Element (name, xs) ->
10836       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10837   | Attribute (name, xs) ->
10838       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10839   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10840   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10841   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10842   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10843   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10844   | Value value -> "Value \"" ^ value ^ "\""
10845   | Text -> "Text"
10846
10847 and string_of_rng_list xs =
10848   String.concat ", " (List.map string_of_rng xs)
10849
10850 let rec parse_rng ?defines context = function
10851   | [] -> []
10852   | Xml.Element ("element", ["name", name], children) :: rest ->
10853       Element (name, parse_rng ?defines context children)
10854       :: parse_rng ?defines context rest
10855   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10856       Attribute (name, parse_rng ?defines context children)
10857       :: parse_rng ?defines context rest
10858   | Xml.Element ("interleave", [], children) :: rest ->
10859       Interleave (parse_rng ?defines context children)
10860       :: parse_rng ?defines context rest
10861   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10862       let rng = parse_rng ?defines context [child] in
10863       (match rng with
10864        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10865        | _ ->
10866            failwithf "%s: <zeroOrMore> contains more than one child element"
10867              context
10868       )
10869   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10870       let rng = parse_rng ?defines context [child] in
10871       (match rng with
10872        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10873        | _ ->
10874            failwithf "%s: <oneOrMore> contains more than one child element"
10875              context
10876       )
10877   | Xml.Element ("optional", [], [child]) :: rest ->
10878       let rng = parse_rng ?defines context [child] in
10879       (match rng with
10880        | [child] -> Optional child :: parse_rng ?defines context rest
10881        | _ ->
10882            failwithf "%s: <optional> contains more than one child element"
10883              context
10884       )
10885   | Xml.Element ("choice", [], children) :: rest ->
10886       let values = List.map (
10887         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10888         | _ ->
10889             failwithf "%s: can't handle anything except <value> in <choice>"
10890               context
10891       ) children in
10892       Choice values
10893       :: parse_rng ?defines context rest
10894   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10895       Value value :: parse_rng ?defines context rest
10896   | Xml.Element ("text", [], []) :: rest ->
10897       Text :: parse_rng ?defines context rest
10898   | Xml.Element ("ref", ["name", name], []) :: rest ->
10899       (* Look up the reference.  Because of limitations in this parser,
10900        * we can't handle arbitrarily nested <ref> yet.  You can only
10901        * use <ref> from inside <start>.
10902        *)
10903       (match defines with
10904        | None ->
10905            failwithf "%s: contains <ref>, but no refs are defined yet" context
10906        | Some map ->
10907            let rng = StringMap.find name map in
10908            rng @ parse_rng ?defines context rest
10909       )
10910   | x :: _ ->
10911       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10912
10913 let grammar =
10914   let xml = Xml.parse_file rng_input in
10915   match xml with
10916   | Xml.Element ("grammar", _,
10917                  Xml.Element ("start", _, gram) :: defines) ->
10918       (* The <define/> elements are referenced in the <start> section,
10919        * so build a map of those first.
10920        *)
10921       let defines = List.fold_left (
10922         fun map ->
10923           function Xml.Element ("define", ["name", name], defn) ->
10924             StringMap.add name defn map
10925           | _ ->
10926               failwithf "%s: expected <define name=name/>" rng_input
10927       ) StringMap.empty defines in
10928       let defines = StringMap.mapi parse_rng defines in
10929
10930       (* Parse the <start> clause, passing the defines. *)
10931       parse_rng ~defines "<start>" gram
10932   | _ ->
10933       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10934         rng_input
10935
10936 let name_of_field = function
10937   | Element (name, _) | Attribute (name, _)
10938   | ZeroOrMore (Element (name, _))
10939   | OneOrMore (Element (name, _))
10940   | Optional (Element (name, _)) -> name
10941   | Optional (Attribute (name, _)) -> name
10942   | Text -> (* an unnamed field in an element *)
10943       "data"
10944   | rng ->
10945       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10946
10947 (* At the moment this function only generates OCaml types.  However we
10948  * should parameterize it later so it can generate types/structs in a
10949  * variety of languages.
10950  *)
10951 let generate_types xs =
10952   (* A simple type is one that can be printed out directly, eg.
10953    * "string option".  A complex type is one which has a name and has
10954    * to be defined via another toplevel definition, eg. a struct.
10955    *
10956    * generate_type generates code for either simple or complex types.
10957    * In the simple case, it returns the string ("string option").  In
10958    * the complex case, it returns the name ("mountpoint").  In the
10959    * complex case it has to print out the definition before returning,
10960    * so it should only be called when we are at the beginning of a
10961    * new line (BOL context).
10962    *)
10963   let rec generate_type = function
10964     | Text ->                                (* string *)
10965         "string", true
10966     | Choice values ->                        (* [`val1|`val2|...] *)
10967         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10968     | ZeroOrMore rng ->                        (* <rng> list *)
10969         let t, is_simple = generate_type rng in
10970         t ^ " list (* 0 or more *)", is_simple
10971     | OneOrMore rng ->                        (* <rng> list *)
10972         let t, is_simple = generate_type rng in
10973         t ^ " list (* 1 or more *)", is_simple
10974                                         (* virt-inspector hack: bool *)
10975     | Optional (Attribute (name, [Value "1"])) ->
10976         "bool", true
10977     | Optional rng ->                        (* <rng> list *)
10978         let t, is_simple = generate_type rng in
10979         t ^ " option", is_simple
10980                                         (* type name = { fields ... } *)
10981     | Element (name, fields) when is_attrs_interleave fields ->
10982         generate_type_struct name (get_attrs_interleave fields)
10983     | Element (name, [field])                (* type name = field *)
10984     | Attribute (name, [field]) ->
10985         let t, is_simple = generate_type field in
10986         if is_simple then (t, true)
10987         else (
10988           pr "type %s = %s\n" name t;
10989           name, false
10990         )
10991     | Element (name, fields) ->              (* type name = { fields ... } *)
10992         generate_type_struct name fields
10993     | rng ->
10994         failwithf "generate_type failed at: %s" (string_of_rng rng)
10995
10996   and is_attrs_interleave = function
10997     | [Interleave _] -> true
10998     | Attribute _ :: fields -> is_attrs_interleave fields
10999     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11000     | _ -> false
11001
11002   and get_attrs_interleave = function
11003     | [Interleave fields] -> fields
11004     | ((Attribute _) as field) :: fields
11005     | ((Optional (Attribute _)) as field) :: fields ->
11006         field :: get_attrs_interleave fields
11007     | _ -> assert false
11008
11009   and generate_types xs =
11010     List.iter (fun x -> ignore (generate_type x)) xs
11011
11012   and generate_type_struct name fields =
11013     (* Calculate the types of the fields first.  We have to do this
11014      * before printing anything so we are still in BOL context.
11015      *)
11016     let types = List.map fst (List.map generate_type fields) in
11017
11018     (* Special case of a struct containing just a string and another
11019      * field.  Turn it into an assoc list.
11020      *)
11021     match types with
11022     | ["string"; other] ->
11023         let fname1, fname2 =
11024           match fields with
11025           | [f1; f2] -> name_of_field f1, name_of_field f2
11026           | _ -> assert false in
11027         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11028         name, false
11029
11030     | types ->
11031         pr "type %s = {\n" name;
11032         List.iter (
11033           fun (field, ftype) ->
11034             let fname = name_of_field field in
11035             pr "  %s_%s : %s;\n" name fname ftype
11036         ) (List.combine fields types);
11037         pr "}\n";
11038         (* Return the name of this type, and
11039          * false because it's not a simple type.
11040          *)
11041         name, false
11042   in
11043
11044   generate_types xs
11045
11046 let generate_parsers xs =
11047   (* As for generate_type above, generate_parser makes a parser for
11048    * some type, and returns the name of the parser it has generated.
11049    * Because it (may) need to print something, it should always be
11050    * called in BOL context.
11051    *)
11052   let rec generate_parser = function
11053     | Text ->                                (* string *)
11054         "string_child_or_empty"
11055     | Choice values ->                        (* [`val1|`val2|...] *)
11056         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11057           (String.concat "|"
11058              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11059     | ZeroOrMore rng ->                        (* <rng> list *)
11060         let pa = generate_parser rng in
11061         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11062     | OneOrMore rng ->                        (* <rng> list *)
11063         let pa = generate_parser rng in
11064         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11065                                         (* virt-inspector hack: bool *)
11066     | Optional (Attribute (name, [Value "1"])) ->
11067         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11068     | Optional rng ->                        (* <rng> list *)
11069         let pa = generate_parser rng in
11070         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11071                                         (* type name = { fields ... } *)
11072     | Element (name, fields) when is_attrs_interleave fields ->
11073         generate_parser_struct name (get_attrs_interleave fields)
11074     | Element (name, [field]) ->        (* type name = field *)
11075         let pa = generate_parser field in
11076         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11077         pr "let %s =\n" parser_name;
11078         pr "  %s\n" pa;
11079         pr "let parse_%s = %s\n" name parser_name;
11080         parser_name
11081     | Attribute (name, [field]) ->
11082         let pa = generate_parser field in
11083         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11084         pr "let %s =\n" parser_name;
11085         pr "  %s\n" pa;
11086         pr "let parse_%s = %s\n" name parser_name;
11087         parser_name
11088     | Element (name, fields) ->              (* type name = { fields ... } *)
11089         generate_parser_struct name ([], fields)
11090     | rng ->
11091         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11092
11093   and is_attrs_interleave = function
11094     | [Interleave _] -> true
11095     | Attribute _ :: fields -> is_attrs_interleave fields
11096     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11097     | _ -> false
11098
11099   and get_attrs_interleave = function
11100     | [Interleave fields] -> [], fields
11101     | ((Attribute _) as field) :: fields
11102     | ((Optional (Attribute _)) as field) :: fields ->
11103         let attrs, interleaves = get_attrs_interleave fields in
11104         (field :: attrs), interleaves
11105     | _ -> assert false
11106
11107   and generate_parsers xs =
11108     List.iter (fun x -> ignore (generate_parser x)) xs
11109
11110   and generate_parser_struct name (attrs, interleaves) =
11111     (* Generate parsers for the fields first.  We have to do this
11112      * before printing anything so we are still in BOL context.
11113      *)
11114     let fields = attrs @ interleaves in
11115     let pas = List.map generate_parser fields in
11116
11117     (* Generate an intermediate tuple from all the fields first.
11118      * If the type is just a string + another field, then we will
11119      * return this directly, otherwise it is turned into a record.
11120      *
11121      * RELAX NG note: This code treats <interleave> and plain lists of
11122      * fields the same.  In other words, it doesn't bother enforcing
11123      * any ordering of fields in the XML.
11124      *)
11125     pr "let parse_%s x =\n" name;
11126     pr "  let t = (\n    ";
11127     let comma = ref false in
11128     List.iter (
11129       fun x ->
11130         if !comma then pr ",\n    ";
11131         comma := true;
11132         match x with
11133         | Optional (Attribute (fname, [field])), pa ->
11134             pr "%s x" pa
11135         | Optional (Element (fname, [field])), pa ->
11136             pr "%s (optional_child %S x)" pa fname
11137         | Attribute (fname, [Text]), _ ->
11138             pr "attribute %S x" fname
11139         | (ZeroOrMore _ | OneOrMore _), pa ->
11140             pr "%s x" pa
11141         | Text, pa ->
11142             pr "%s x" pa
11143         | (field, pa) ->
11144             let fname = name_of_field field in
11145             pr "%s (child %S x)" pa fname
11146     ) (List.combine fields pas);
11147     pr "\n  ) in\n";
11148
11149     (match fields with
11150      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11151          pr "  t\n"
11152
11153      | _ ->
11154          pr "  (Obj.magic t : %s)\n" name
11155 (*
11156          List.iter (
11157            function
11158            | (Optional (Attribute (fname, [field])), pa) ->
11159                pr "  %s_%s =\n" name fname;
11160                pr "    %s x;\n" pa
11161            | (Optional (Element (fname, [field])), pa) ->
11162                pr "  %s_%s =\n" name fname;
11163                pr "    (let x = optional_child %S x in\n" fname;
11164                pr "     %s x);\n" pa
11165            | (field, pa) ->
11166                let fname = name_of_field field in
11167                pr "  %s_%s =\n" name fname;
11168                pr "    (let x = child %S x in\n" fname;
11169                pr "     %s x);\n" pa
11170          ) (List.combine fields pas);
11171          pr "}\n"
11172 *)
11173     );
11174     sprintf "parse_%s" name
11175   in
11176
11177   generate_parsers xs
11178
11179 (* Generate ocaml/guestfs_inspector.mli. *)
11180 let generate_ocaml_inspector_mli () =
11181   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11182
11183   pr "\
11184 (** This is an OCaml language binding to the external [virt-inspector]
11185     program.
11186
11187     For more information, please read the man page [virt-inspector(1)].
11188 *)
11189
11190 ";
11191
11192   generate_types grammar;
11193   pr "(** The nested information returned from the {!inspect} function. *)\n";
11194   pr "\n";
11195
11196   pr "\
11197 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11198 (** To inspect a libvirt domain called [name], pass a singleton
11199     list: [inspect [name]].  When using libvirt only, you may
11200     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11201
11202     To inspect a disk image or images, pass a list of the filenames
11203     of the disk images: [inspect filenames]
11204
11205     This function inspects the given guest or disk images and
11206     returns a list of operating system(s) found and a large amount
11207     of information about them.  In the vast majority of cases,
11208     a virtual machine only contains a single operating system.
11209
11210     If the optional [~xml] parameter is given, then this function
11211     skips running the external virt-inspector program and just
11212     parses the given XML directly (which is expected to be XML
11213     produced from a previous run of virt-inspector).  The list of
11214     names and connect URI are ignored in this case.
11215
11216     This function can throw a wide variety of exceptions, for example
11217     if the external virt-inspector program cannot be found, or if
11218     it doesn't generate valid XML.
11219 *)
11220 "
11221
11222 (* Generate ocaml/guestfs_inspector.ml. *)
11223 let generate_ocaml_inspector_ml () =
11224   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11225
11226   pr "open Unix\n";
11227   pr "\n";
11228
11229   generate_types grammar;
11230   pr "\n";
11231
11232   pr "\
11233 (* Misc functions which are used by the parser code below. *)
11234 let first_child = function
11235   | Xml.Element (_, _, c::_) -> c
11236   | Xml.Element (name, _, []) ->
11237       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11238   | Xml.PCData str ->
11239       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11240
11241 let string_child_or_empty = function
11242   | Xml.Element (_, _, [Xml.PCData s]) -> s
11243   | Xml.Element (_, _, []) -> \"\"
11244   | Xml.Element (x, _, _) ->
11245       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11246                 x ^ \" instead\")
11247   | Xml.PCData str ->
11248       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11249
11250 let optional_child name xml =
11251   let children = Xml.children xml in
11252   try
11253     Some (List.find (function
11254                      | Xml.Element (n, _, _) when n = name -> true
11255                      | _ -> false) children)
11256   with
11257     Not_found -> None
11258
11259 let child name xml =
11260   match optional_child name xml with
11261   | Some c -> c
11262   | None ->
11263       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11264
11265 let attribute name xml =
11266   try Xml.attrib xml name
11267   with Xml.No_attribute _ ->
11268     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11269
11270 ";
11271
11272   generate_parsers grammar;
11273   pr "\n";
11274
11275   pr "\
11276 (* Run external virt-inspector, then use parser to parse the XML. *)
11277 let inspect ?connect ?xml names =
11278   let xml =
11279     match xml with
11280     | None ->
11281         if names = [] then invalid_arg \"inspect: no names given\";
11282         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11283           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11284           names in
11285         let cmd = List.map Filename.quote cmd in
11286         let cmd = String.concat \" \" cmd in
11287         let chan = open_process_in cmd in
11288         let xml = Xml.parse_in chan in
11289         (match close_process_in chan with
11290          | WEXITED 0 -> ()
11291          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11292          | WSIGNALED i | WSTOPPED i ->
11293              failwith (\"external virt-inspector command died or stopped on sig \" ^
11294                        string_of_int i)
11295         );
11296         xml
11297     | Some doc ->
11298         Xml.parse_string doc in
11299   parse_operatingsystems xml
11300 "
11301
11302 (* This is used to generate the src/MAX_PROC_NR file which
11303  * contains the maximum procedure number, a surrogate for the
11304  * ABI version number.  See src/Makefile.am for the details.
11305  *)
11306 and generate_max_proc_nr () =
11307   let proc_nrs = List.map (
11308     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11309   ) daemon_functions in
11310
11311   let max_proc_nr = List.fold_left max 0 proc_nrs in
11312
11313   pr "%d\n" max_proc_nr
11314
11315 let output_to filename k =
11316   let filename_new = filename ^ ".new" in
11317   chan := open_out filename_new;
11318   k ();
11319   close_out !chan;
11320   chan := Pervasives.stdout;
11321
11322   (* Is the new file different from the current file? *)
11323   if Sys.file_exists filename && files_equal filename filename_new then
11324     unlink filename_new                 (* same, so skip it *)
11325   else (
11326     (* different, overwrite old one *)
11327     (try chmod filename 0o644 with Unix_error _ -> ());
11328     rename filename_new filename;
11329     chmod filename 0o444;
11330     printf "written %s\n%!" filename;
11331   )
11332
11333 let perror msg = function
11334   | Unix_error (err, _, _) ->
11335       eprintf "%s: %s\n" msg (error_message err)
11336   | exn ->
11337       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11338
11339 (* Main program. *)
11340 let () =
11341   let lock_fd =
11342     try openfile "HACKING" [O_RDWR] 0
11343     with
11344     | Unix_error (ENOENT, _, _) ->
11345         eprintf "\
11346 You are probably running this from the wrong directory.
11347 Run it from the top source directory using the command
11348   src/generator.ml
11349 ";
11350         exit 1
11351     | exn ->
11352         perror "open: HACKING" exn;
11353         exit 1 in
11354
11355   (* Acquire a lock so parallel builds won't try to run the generator
11356    * twice at the same time.  Subsequent builds will wait for the first
11357    * one to finish.  Note the lock is released implicitly when the
11358    * program exits.
11359    *)
11360   (try lockf lock_fd F_LOCK 1
11361    with exn ->
11362      perror "lock: HACKING" exn;
11363      exit 1);
11364
11365   check_functions ();
11366
11367   output_to "src/guestfs_protocol.x" generate_xdr;
11368   output_to "src/guestfs-structs.h" generate_structs_h;
11369   output_to "src/guestfs-actions.h" generate_actions_h;
11370   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11371   output_to "src/guestfs-actions.c" generate_client_actions;
11372   output_to "src/guestfs-bindtests.c" generate_bindtests;
11373   output_to "src/guestfs-structs.pod" generate_structs_pod;
11374   output_to "src/guestfs-actions.pod" generate_actions_pod;
11375   output_to "src/guestfs-availability.pod" generate_availability_pod;
11376   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11377   output_to "src/libguestfs.syms" generate_linker_script;
11378   output_to "daemon/actions.h" generate_daemon_actions_h;
11379   output_to "daemon/stubs.c" generate_daemon_actions;
11380   output_to "daemon/names.c" generate_daemon_names;
11381   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11382   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11383   output_to "capitests/tests.c" generate_tests;
11384   output_to "fish/cmds.c" generate_fish_cmds;
11385   output_to "fish/completion.c" generate_fish_completion;
11386   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11387   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11388   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11389   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11390   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11391   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11392   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11393   output_to "perl/Guestfs.xs" generate_perl_xs;
11394   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11395   output_to "perl/bindtests.pl" generate_perl_bindtests;
11396   output_to "python/guestfs-py.c" generate_python_c;
11397   output_to "python/guestfs.py" generate_python_py;
11398   output_to "python/bindtests.py" generate_python_bindtests;
11399   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11400   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11401   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11402
11403   List.iter (
11404     fun (typ, jtyp) ->
11405       let cols = cols_of_struct typ in
11406       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11407       output_to filename (generate_java_struct jtyp cols);
11408   ) java_structs;
11409
11410   output_to "java/Makefile.inc" generate_java_makefile_inc;
11411   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11412   output_to "java/Bindtests.java" generate_java_bindtests;
11413   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11414   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11415   output_to "csharp/Libguestfs.cs" generate_csharp;
11416
11417   (* Always generate this file last, and unconditionally.  It's used
11418    * by the Makefile to know when we must re-run the generator.
11419    *)
11420   let chan = open_out "src/stamp-generator" in
11421   fprintf chan "1\n";
11422   close_out chan;
11423
11424   printf "generated %d lines of code\n" !lines