551b6bc61c109cfb2b765b592da41a167d439dd7
[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 #ifdef HAVE_RL_COMPLETION_MATCHES
7463 #define RL_COMPLETION_MATCHES rl_completion_matches
7464 #else
7465 #ifdef HAVE_COMPLETION_MATCHES
7466 #define RL_COMPLETION_MATCHES completion_matches
7467 #endif
7468 #endif /* else just fail if we don't have either symbol */
7469
7470 char **
7471 do_completion (const char *text, int start, int end)
7472 {
7473   char **matches = NULL;
7474
7475 #ifdef HAVE_LIBREADLINE
7476   rl_completion_append_character = ' ';
7477
7478   if (start == 0)
7479     matches = RL_COMPLETION_MATCHES (text, generator);
7480   else if (complete_dest_paths)
7481     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7482 #endif
7483
7484   return matches;
7485 }
7486 ";
7487
7488 (* Generate the POD documentation for guestfish. *)
7489 and generate_fish_actions_pod () =
7490   let all_functions_sorted =
7491     List.filter (
7492       fun (_, _, _, flags, _, _, _) ->
7493         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7494     ) all_functions_sorted in
7495
7496   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7497
7498   List.iter (
7499     fun (name, style, _, flags, _, _, longdesc) ->
7500       let longdesc =
7501         Str.global_substitute rex (
7502           fun s ->
7503             let sub =
7504               try Str.matched_group 1 s
7505               with Not_found ->
7506                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7507             "C<" ^ replace_char sub '_' '-' ^ ">"
7508         ) longdesc in
7509       let name = replace_char name '_' '-' in
7510       let alias =
7511         try find_map (function FishAlias n -> Some n | _ -> None) flags
7512         with Not_found -> name in
7513
7514       pr "=head2 %s" name;
7515       if name <> alias then
7516         pr " | %s" alias;
7517       pr "\n";
7518       pr "\n";
7519       pr " %s" name;
7520       List.iter (
7521         function
7522         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7523         | OptString n -> pr " %s" n
7524         | StringList n | DeviceList n -> pr " '%s ...'" n
7525         | Bool _ -> pr " true|false"
7526         | Int n -> pr " %s" n
7527         | Int64 n -> pr " %s" n
7528         | FileIn n | FileOut n -> pr " (%s|-)" n
7529       ) (snd style);
7530       pr "\n";
7531       pr "\n";
7532       pr "%s\n\n" longdesc;
7533
7534       if List.exists (function FileIn _ | FileOut _ -> true
7535                       | _ -> false) (snd style) then
7536         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7537
7538       if List.mem ProtocolLimitWarning flags then
7539         pr "%s\n\n" protocol_limit_warning;
7540
7541       if List.mem DangerWillRobinson flags then
7542         pr "%s\n\n" danger_will_robinson;
7543
7544       match deprecation_notice flags with
7545       | None -> ()
7546       | Some txt -> pr "%s\n\n" txt
7547   ) all_functions_sorted
7548
7549 (* Generate a C function prototype. *)
7550 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7551     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7552     ?(prefix = "")
7553     ?handle name style =
7554   if extern then pr "extern ";
7555   if static then pr "static ";
7556   (match fst style with
7557    | RErr -> pr "int "
7558    | RInt _ -> pr "int "
7559    | RInt64 _ -> pr "int64_t "
7560    | RBool _ -> pr "int "
7561    | RConstString _ | RConstOptString _ -> pr "const char *"
7562    | RString _ | RBufferOut _ -> pr "char *"
7563    | RStringList _ | RHashtable _ -> pr "char **"
7564    | RStruct (_, typ) ->
7565        if not in_daemon then pr "struct guestfs_%s *" typ
7566        else pr "guestfs_int_%s *" typ
7567    | RStructList (_, typ) ->
7568        if not in_daemon then pr "struct guestfs_%s_list *" typ
7569        else pr "guestfs_int_%s_list *" typ
7570   );
7571   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7572   pr "%s%s (" prefix name;
7573   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7574     pr "void"
7575   else (
7576     let comma = ref false in
7577     (match handle with
7578      | None -> ()
7579      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7580     );
7581     let next () =
7582       if !comma then (
7583         if single_line then pr ", " else pr ",\n\t\t"
7584       );
7585       comma := true
7586     in
7587     List.iter (
7588       function
7589       | Pathname n
7590       | Device n | Dev_or_Path n
7591       | String n
7592       | OptString n ->
7593           next ();
7594           pr "const char *%s" n
7595       | StringList n | DeviceList n ->
7596           next ();
7597           pr "char *const *%s" n
7598       | Bool n -> next (); pr "int %s" n
7599       | Int n -> next (); pr "int %s" n
7600       | Int64 n -> next (); pr "int64_t %s" n
7601       | FileIn n
7602       | FileOut n ->
7603           if not in_daemon then (next (); pr "const char *%s" n)
7604     ) (snd style);
7605     if is_RBufferOut then (next (); pr "size_t *size_r");
7606   );
7607   pr ")";
7608   if semicolon then pr ";";
7609   if newline then pr "\n"
7610
7611 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7612 and generate_c_call_args ?handle ?(decl = false) style =
7613   pr "(";
7614   let comma = ref false in
7615   let next () =
7616     if !comma then pr ", ";
7617     comma := true
7618   in
7619   (match handle with
7620    | None -> ()
7621    | Some handle -> pr "%s" handle; comma := true
7622   );
7623   List.iter (
7624     fun arg ->
7625       next ();
7626       pr "%s" (name_of_argt arg)
7627   ) (snd style);
7628   (* For RBufferOut calls, add implicit &size parameter. *)
7629   if not decl then (
7630     match fst style with
7631     | RBufferOut _ ->
7632         next ();
7633         pr "&size"
7634     | _ -> ()
7635   );
7636   pr ")"
7637
7638 (* Generate the OCaml bindings interface. *)
7639 and generate_ocaml_mli () =
7640   generate_header OCamlStyle LGPLv2plus;
7641
7642   pr "\
7643 (** For API documentation you should refer to the C API
7644     in the guestfs(3) manual page.  The OCaml API uses almost
7645     exactly the same calls. *)
7646
7647 type t
7648 (** A [guestfs_h] handle. *)
7649
7650 exception Error of string
7651 (** This exception is raised when there is an error. *)
7652
7653 exception Handle_closed of string
7654 (** This exception is raised if you use a {!Guestfs.t} handle
7655     after calling {!close} on it.  The string is the name of
7656     the function. *)
7657
7658 val create : unit -> t
7659 (** Create a {!Guestfs.t} handle. *)
7660
7661 val close : t -> unit
7662 (** Close the {!Guestfs.t} handle and free up all resources used
7663     by it immediately.
7664
7665     Handles are closed by the garbage collector when they become
7666     unreferenced, but callers can call this in order to provide
7667     predictable cleanup. *)
7668
7669 ";
7670   generate_ocaml_structure_decls ();
7671
7672   (* The actions. *)
7673   List.iter (
7674     fun (name, style, _, _, _, shortdesc, _) ->
7675       generate_ocaml_prototype name style;
7676       pr "(** %s *)\n" shortdesc;
7677       pr "\n"
7678   ) all_functions_sorted
7679
7680 (* Generate the OCaml bindings implementation. *)
7681 and generate_ocaml_ml () =
7682   generate_header OCamlStyle LGPLv2plus;
7683
7684   pr "\
7685 type t
7686
7687 exception Error of string
7688 exception Handle_closed of string
7689
7690 external create : unit -> t = \"ocaml_guestfs_create\"
7691 external close : t -> unit = \"ocaml_guestfs_close\"
7692
7693 (* Give the exceptions names, so they can be raised from the C code. *)
7694 let () =
7695   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7696   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7697
7698 ";
7699
7700   generate_ocaml_structure_decls ();
7701
7702   (* The actions. *)
7703   List.iter (
7704     fun (name, style, _, _, _, shortdesc, _) ->
7705       generate_ocaml_prototype ~is_external:true name style;
7706   ) all_functions_sorted
7707
7708 (* Generate the OCaml bindings C implementation. *)
7709 and generate_ocaml_c () =
7710   generate_header CStyle LGPLv2plus;
7711
7712   pr "\
7713 #include <stdio.h>
7714 #include <stdlib.h>
7715 #include <string.h>
7716
7717 #include <caml/config.h>
7718 #include <caml/alloc.h>
7719 #include <caml/callback.h>
7720 #include <caml/fail.h>
7721 #include <caml/memory.h>
7722 #include <caml/mlvalues.h>
7723 #include <caml/signals.h>
7724
7725 #include <guestfs.h>
7726
7727 #include \"guestfs_c.h\"
7728
7729 /* Copy a hashtable of string pairs into an assoc-list.  We return
7730  * the list in reverse order, but hashtables aren't supposed to be
7731  * ordered anyway.
7732  */
7733 static CAMLprim value
7734 copy_table (char * const * argv)
7735 {
7736   CAMLparam0 ();
7737   CAMLlocal5 (rv, pairv, kv, vv, cons);
7738   int i;
7739
7740   rv = Val_int (0);
7741   for (i = 0; argv[i] != NULL; i += 2) {
7742     kv = caml_copy_string (argv[i]);
7743     vv = caml_copy_string (argv[i+1]);
7744     pairv = caml_alloc (2, 0);
7745     Store_field (pairv, 0, kv);
7746     Store_field (pairv, 1, vv);
7747     cons = caml_alloc (2, 0);
7748     Store_field (cons, 1, rv);
7749     rv = cons;
7750     Store_field (cons, 0, pairv);
7751   }
7752
7753   CAMLreturn (rv);
7754 }
7755
7756 ";
7757
7758   (* Struct copy functions. *)
7759
7760   let emit_ocaml_copy_list_function typ =
7761     pr "static CAMLprim value\n";
7762     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7763     pr "{\n";
7764     pr "  CAMLparam0 ();\n";
7765     pr "  CAMLlocal2 (rv, v);\n";
7766     pr "  unsigned int i;\n";
7767     pr "\n";
7768     pr "  if (%ss->len == 0)\n" typ;
7769     pr "    CAMLreturn (Atom (0));\n";
7770     pr "  else {\n";
7771     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7772     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7773     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7774     pr "      caml_modify (&Field (rv, i), v);\n";
7775     pr "    }\n";
7776     pr "    CAMLreturn (rv);\n";
7777     pr "  }\n";
7778     pr "}\n";
7779     pr "\n";
7780   in
7781
7782   List.iter (
7783     fun (typ, cols) ->
7784       let has_optpercent_col =
7785         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7786
7787       pr "static CAMLprim value\n";
7788       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7789       pr "{\n";
7790       pr "  CAMLparam0 ();\n";
7791       if has_optpercent_col then
7792         pr "  CAMLlocal3 (rv, v, v2);\n"
7793       else
7794         pr "  CAMLlocal2 (rv, v);\n";
7795       pr "\n";
7796       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7797       iteri (
7798         fun i col ->
7799           (match col with
7800            | name, FString ->
7801                pr "  v = caml_copy_string (%s->%s);\n" typ name
7802            | name, FBuffer ->
7803                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7804                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7805                  typ name typ name
7806            | name, FUUID ->
7807                pr "  v = caml_alloc_string (32);\n";
7808                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7809            | name, (FBytes|FInt64|FUInt64) ->
7810                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7811            | name, (FInt32|FUInt32) ->
7812                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7813            | name, FOptPercent ->
7814                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7815                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7816                pr "    v = caml_alloc (1, 0);\n";
7817                pr "    Store_field (v, 0, v2);\n";
7818                pr "  } else /* None */\n";
7819                pr "    v = Val_int (0);\n";
7820            | name, FChar ->
7821                pr "  v = Val_int (%s->%s);\n" typ name
7822           );
7823           pr "  Store_field (rv, %d, v);\n" i
7824       ) cols;
7825       pr "  CAMLreturn (rv);\n";
7826       pr "}\n";
7827       pr "\n";
7828   ) structs;
7829
7830   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7831   List.iter (
7832     function
7833     | typ, (RStructListOnly | RStructAndList) ->
7834         (* generate the function for typ *)
7835         emit_ocaml_copy_list_function typ
7836     | typ, _ -> () (* empty *)
7837   ) (rstructs_used_by all_functions);
7838
7839   (* The wrappers. *)
7840   List.iter (
7841     fun (name, style, _, _, _, _, _) ->
7842       pr "/* Automatically generated wrapper for function\n";
7843       pr " * ";
7844       generate_ocaml_prototype name style;
7845       pr " */\n";
7846       pr "\n";
7847
7848       let params =
7849         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7850
7851       let needs_extra_vs =
7852         match fst style with RConstOptString _ -> true | _ -> false in
7853
7854       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7855       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7856       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7857       pr "\n";
7858
7859       pr "CAMLprim value\n";
7860       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7861       List.iter (pr ", value %s") (List.tl params);
7862       pr ")\n";
7863       pr "{\n";
7864
7865       (match params with
7866        | [p1; p2; p3; p4; p5] ->
7867            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7868        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7869            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7870            pr "  CAMLxparam%d (%s);\n"
7871              (List.length rest) (String.concat ", " rest)
7872        | ps ->
7873            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7874       );
7875       if not needs_extra_vs then
7876         pr "  CAMLlocal1 (rv);\n"
7877       else
7878         pr "  CAMLlocal3 (rv, v, v2);\n";
7879       pr "\n";
7880
7881       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7882       pr "  if (g == NULL)\n";
7883       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7884       pr "\n";
7885
7886       List.iter (
7887         function
7888         | Pathname n
7889         | Device n | Dev_or_Path n
7890         | String n
7891         | FileIn n
7892         | FileOut n ->
7893             pr "  const char *%s = String_val (%sv);\n" n n
7894         | OptString n ->
7895             pr "  const char *%s =\n" n;
7896             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7897               n n
7898         | StringList n | DeviceList n ->
7899             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7900         | Bool n ->
7901             pr "  int %s = Bool_val (%sv);\n" n n
7902         | Int n ->
7903             pr "  int %s = Int_val (%sv);\n" n n
7904         | Int64 n ->
7905             pr "  int64_t %s = Int64_val (%sv);\n" n n
7906       ) (snd style);
7907       let error_code =
7908         match fst style with
7909         | RErr -> pr "  int r;\n"; "-1"
7910         | RInt _ -> pr "  int r;\n"; "-1"
7911         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7912         | RBool _ -> pr "  int r;\n"; "-1"
7913         | RConstString _ | RConstOptString _ ->
7914             pr "  const char *r;\n"; "NULL"
7915         | RString _ -> pr "  char *r;\n"; "NULL"
7916         | RStringList _ ->
7917             pr "  int i;\n";
7918             pr "  char **r;\n";
7919             "NULL"
7920         | RStruct (_, typ) ->
7921             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7922         | RStructList (_, typ) ->
7923             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7924         | RHashtable _ ->
7925             pr "  int i;\n";
7926             pr "  char **r;\n";
7927             "NULL"
7928         | RBufferOut _ ->
7929             pr "  char *r;\n";
7930             pr "  size_t size;\n";
7931             "NULL" in
7932       pr "\n";
7933
7934       pr "  caml_enter_blocking_section ();\n";
7935       pr "  r = guestfs_%s " name;
7936       generate_c_call_args ~handle:"g" style;
7937       pr ";\n";
7938       pr "  caml_leave_blocking_section ();\n";
7939
7940       List.iter (
7941         function
7942         | StringList n | DeviceList n ->
7943             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7944         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7945         | Bool _ | Int _ | Int64 _
7946         | FileIn _ | FileOut _ -> ()
7947       ) (snd style);
7948
7949       pr "  if (r == %s)\n" error_code;
7950       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7951       pr "\n";
7952
7953       (match fst style with
7954        | RErr -> pr "  rv = Val_unit;\n"
7955        | RInt _ -> pr "  rv = Val_int (r);\n"
7956        | RInt64 _ ->
7957            pr "  rv = caml_copy_int64 (r);\n"
7958        | RBool _ -> pr "  rv = Val_bool (r);\n"
7959        | RConstString _ ->
7960            pr "  rv = caml_copy_string (r);\n"
7961        | RConstOptString _ ->
7962            pr "  if (r) { /* Some string */\n";
7963            pr "    v = caml_alloc (1, 0);\n";
7964            pr "    v2 = caml_copy_string (r);\n";
7965            pr "    Store_field (v, 0, v2);\n";
7966            pr "  } else /* None */\n";
7967            pr "    v = Val_int (0);\n";
7968        | RString _ ->
7969            pr "  rv = caml_copy_string (r);\n";
7970            pr "  free (r);\n"
7971        | RStringList _ ->
7972            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7973            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7974            pr "  free (r);\n"
7975        | RStruct (_, typ) ->
7976            pr "  rv = copy_%s (r);\n" typ;
7977            pr "  guestfs_free_%s (r);\n" typ;
7978        | RStructList (_, typ) ->
7979            pr "  rv = copy_%s_list (r);\n" typ;
7980            pr "  guestfs_free_%s_list (r);\n" typ;
7981        | RHashtable _ ->
7982            pr "  rv = copy_table (r);\n";
7983            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7984            pr "  free (r);\n";
7985        | RBufferOut _ ->
7986            pr "  rv = caml_alloc_string (size);\n";
7987            pr "  memcpy (String_val (rv), r, size);\n";
7988       );
7989
7990       pr "  CAMLreturn (rv);\n";
7991       pr "}\n";
7992       pr "\n";
7993
7994       if List.length params > 5 then (
7995         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7996         pr "CAMLprim value ";
7997         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7998         pr "CAMLprim value\n";
7999         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8000         pr "{\n";
8001         pr "  return ocaml_guestfs_%s (argv[0]" name;
8002         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8003         pr ");\n";
8004         pr "}\n";
8005         pr "\n"
8006       )
8007   ) all_functions_sorted
8008
8009 and generate_ocaml_structure_decls () =
8010   List.iter (
8011     fun (typ, cols) ->
8012       pr "type %s = {\n" typ;
8013       List.iter (
8014         function
8015         | name, FString -> pr "  %s : string;\n" name
8016         | name, FBuffer -> pr "  %s : string;\n" name
8017         | name, FUUID -> pr "  %s : string;\n" name
8018         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8019         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8020         | name, FChar -> pr "  %s : char;\n" name
8021         | name, FOptPercent -> pr "  %s : float option;\n" name
8022       ) cols;
8023       pr "}\n";
8024       pr "\n"
8025   ) structs
8026
8027 and generate_ocaml_prototype ?(is_external = false) name style =
8028   if is_external then pr "external " else pr "val ";
8029   pr "%s : t -> " name;
8030   List.iter (
8031     function
8032     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8033     | OptString _ -> pr "string option -> "
8034     | StringList _ | DeviceList _ -> pr "string array -> "
8035     | Bool _ -> pr "bool -> "
8036     | Int _ -> pr "int -> "
8037     | Int64 _ -> pr "int64 -> "
8038   ) (snd style);
8039   (match fst style with
8040    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8041    | RInt _ -> pr "int"
8042    | RInt64 _ -> pr "int64"
8043    | RBool _ -> pr "bool"
8044    | RConstString _ -> pr "string"
8045    | RConstOptString _ -> pr "string option"
8046    | RString _ | RBufferOut _ -> pr "string"
8047    | RStringList _ -> pr "string array"
8048    | RStruct (_, typ) -> pr "%s" typ
8049    | RStructList (_, typ) -> pr "%s array" typ
8050    | RHashtable _ -> pr "(string * string) list"
8051   );
8052   if is_external then (
8053     pr " = ";
8054     if List.length (snd style) + 1 > 5 then
8055       pr "\"ocaml_guestfs_%s_byte\" " name;
8056     pr "\"ocaml_guestfs_%s\"" name
8057   );
8058   pr "\n"
8059
8060 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8061 and generate_perl_xs () =
8062   generate_header CStyle LGPLv2plus;
8063
8064   pr "\
8065 #include \"EXTERN.h\"
8066 #include \"perl.h\"
8067 #include \"XSUB.h\"
8068
8069 #include <guestfs.h>
8070
8071 #ifndef PRId64
8072 #define PRId64 \"lld\"
8073 #endif
8074
8075 static SV *
8076 my_newSVll(long long val) {
8077 #ifdef USE_64_BIT_ALL
8078   return newSViv(val);
8079 #else
8080   char buf[100];
8081   int len;
8082   len = snprintf(buf, 100, \"%%\" PRId64, val);
8083   return newSVpv(buf, len);
8084 #endif
8085 }
8086
8087 #ifndef PRIu64
8088 #define PRIu64 \"llu\"
8089 #endif
8090
8091 static SV *
8092 my_newSVull(unsigned long long val) {
8093 #ifdef USE_64_BIT_ALL
8094   return newSVuv(val);
8095 #else
8096   char buf[100];
8097   int len;
8098   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8099   return newSVpv(buf, len);
8100 #endif
8101 }
8102
8103 /* http://www.perlmonks.org/?node_id=680842 */
8104 static char **
8105 XS_unpack_charPtrPtr (SV *arg) {
8106   char **ret;
8107   AV *av;
8108   I32 i;
8109
8110   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8111     croak (\"array reference expected\");
8112
8113   av = (AV *)SvRV (arg);
8114   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8115   if (!ret)
8116     croak (\"malloc failed\");
8117
8118   for (i = 0; i <= av_len (av); i++) {
8119     SV **elem = av_fetch (av, i, 0);
8120
8121     if (!elem || !*elem)
8122       croak (\"missing element in list\");
8123
8124     ret[i] = SvPV_nolen (*elem);
8125   }
8126
8127   ret[i] = NULL;
8128
8129   return ret;
8130 }
8131
8132 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8133
8134 PROTOTYPES: ENABLE
8135
8136 guestfs_h *
8137 _create ()
8138    CODE:
8139       RETVAL = guestfs_create ();
8140       if (!RETVAL)
8141         croak (\"could not create guestfs handle\");
8142       guestfs_set_error_handler (RETVAL, NULL, NULL);
8143  OUTPUT:
8144       RETVAL
8145
8146 void
8147 DESTROY (g)
8148       guestfs_h *g;
8149  PPCODE:
8150       guestfs_close (g);
8151
8152 ";
8153
8154   List.iter (
8155     fun (name, style, _, _, _, _, _) ->
8156       (match fst style with
8157        | RErr -> pr "void\n"
8158        | RInt _ -> pr "SV *\n"
8159        | RInt64 _ -> pr "SV *\n"
8160        | RBool _ -> pr "SV *\n"
8161        | RConstString _ -> pr "SV *\n"
8162        | RConstOptString _ -> pr "SV *\n"
8163        | RString _ -> pr "SV *\n"
8164        | RBufferOut _ -> pr "SV *\n"
8165        | RStringList _
8166        | RStruct _ | RStructList _
8167        | RHashtable _ ->
8168            pr "void\n" (* all lists returned implictly on the stack *)
8169       );
8170       (* Call and arguments. *)
8171       pr "%s " name;
8172       generate_c_call_args ~handle:"g" ~decl:true style;
8173       pr "\n";
8174       pr "      guestfs_h *g;\n";
8175       iteri (
8176         fun i ->
8177           function
8178           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8179               pr "      char *%s;\n" n
8180           | OptString n ->
8181               (* http://www.perlmonks.org/?node_id=554277
8182                * Note that the implicit handle argument means we have
8183                * to add 1 to the ST(x) operator.
8184                *)
8185               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8186           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8187           | Bool n -> pr "      int %s;\n" n
8188           | Int n -> pr "      int %s;\n" n
8189           | Int64 n -> pr "      int64_t %s;\n" n
8190       ) (snd style);
8191
8192       let do_cleanups () =
8193         List.iter (
8194           function
8195           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8196           | Bool _ | Int _ | Int64 _
8197           | FileIn _ | FileOut _ -> ()
8198           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8199         ) (snd style)
8200       in
8201
8202       (* Code. *)
8203       (match fst style with
8204        | RErr ->
8205            pr "PREINIT:\n";
8206            pr "      int r;\n";
8207            pr " PPCODE:\n";
8208            pr "      r = guestfs_%s " name;
8209            generate_c_call_args ~handle:"g" style;
8210            pr ";\n";
8211            do_cleanups ();
8212            pr "      if (r == -1)\n";
8213            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8214        | RInt n
8215        | RBool n ->
8216            pr "PREINIT:\n";
8217            pr "      int %s;\n" n;
8218            pr "   CODE:\n";
8219            pr "      %s = guestfs_%s " n name;
8220            generate_c_call_args ~handle:"g" style;
8221            pr ";\n";
8222            do_cleanups ();
8223            pr "      if (%s == -1)\n" n;
8224            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8225            pr "      RETVAL = newSViv (%s);\n" n;
8226            pr " OUTPUT:\n";
8227            pr "      RETVAL\n"
8228        | RInt64 n ->
8229            pr "PREINIT:\n";
8230            pr "      int64_t %s;\n" n;
8231            pr "   CODE:\n";
8232            pr "      %s = guestfs_%s " n name;
8233            generate_c_call_args ~handle:"g" style;
8234            pr ";\n";
8235            do_cleanups ();
8236            pr "      if (%s == -1)\n" n;
8237            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8238            pr "      RETVAL = my_newSVll (%s);\n" n;
8239            pr " OUTPUT:\n";
8240            pr "      RETVAL\n"
8241        | RConstString n ->
8242            pr "PREINIT:\n";
8243            pr "      const char *%s;\n" n;
8244            pr "   CODE:\n";
8245            pr "      %s = guestfs_%s " n name;
8246            generate_c_call_args ~handle:"g" style;
8247            pr ";\n";
8248            do_cleanups ();
8249            pr "      if (%s == NULL)\n" n;
8250            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8251            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8252            pr " OUTPUT:\n";
8253            pr "      RETVAL\n"
8254        | RConstOptString n ->
8255            pr "PREINIT:\n";
8256            pr "      const char *%s;\n" n;
8257            pr "   CODE:\n";
8258            pr "      %s = guestfs_%s " n name;
8259            generate_c_call_args ~handle:"g" style;
8260            pr ";\n";
8261            do_cleanups ();
8262            pr "      if (%s == NULL)\n" n;
8263            pr "        RETVAL = &PL_sv_undef;\n";
8264            pr "      else\n";
8265            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8266            pr " OUTPUT:\n";
8267            pr "      RETVAL\n"
8268        | RString n ->
8269            pr "PREINIT:\n";
8270            pr "      char *%s;\n" n;
8271            pr "   CODE:\n";
8272            pr "      %s = guestfs_%s " n name;
8273            generate_c_call_args ~handle:"g" style;
8274            pr ";\n";
8275            do_cleanups ();
8276            pr "      if (%s == NULL)\n" n;
8277            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8278            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8279            pr "      free (%s);\n" n;
8280            pr " OUTPUT:\n";
8281            pr "      RETVAL\n"
8282        | RStringList n | RHashtable n ->
8283            pr "PREINIT:\n";
8284            pr "      char **%s;\n" n;
8285            pr "      int i, n;\n";
8286            pr " PPCODE:\n";
8287            pr "      %s = guestfs_%s " n name;
8288            generate_c_call_args ~handle:"g" style;
8289            pr ";\n";
8290            do_cleanups ();
8291            pr "      if (%s == NULL)\n" n;
8292            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8293            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8294            pr "      EXTEND (SP, n);\n";
8295            pr "      for (i = 0; i < n; ++i) {\n";
8296            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8297            pr "        free (%s[i]);\n" n;
8298            pr "      }\n";
8299            pr "      free (%s);\n" n;
8300        | RStruct (n, typ) ->
8301            let cols = cols_of_struct typ in
8302            generate_perl_struct_code typ cols name style n do_cleanups
8303        | RStructList (n, typ) ->
8304            let cols = cols_of_struct typ in
8305            generate_perl_struct_list_code typ cols name style n do_cleanups
8306        | RBufferOut n ->
8307            pr "PREINIT:\n";
8308            pr "      char *%s;\n" n;
8309            pr "      size_t size;\n";
8310            pr "   CODE:\n";
8311            pr "      %s = guestfs_%s " n name;
8312            generate_c_call_args ~handle:"g" style;
8313            pr ";\n";
8314            do_cleanups ();
8315            pr "      if (%s == NULL)\n" n;
8316            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8317            pr "      RETVAL = newSVpv (%s, size);\n" n;
8318            pr "      free (%s);\n" n;
8319            pr " OUTPUT:\n";
8320            pr "      RETVAL\n"
8321       );
8322
8323       pr "\n"
8324   ) all_functions
8325
8326 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8327   pr "PREINIT:\n";
8328   pr "      struct guestfs_%s_list *%s;\n" typ n;
8329   pr "      int i;\n";
8330   pr "      HV *hv;\n";
8331   pr " PPCODE:\n";
8332   pr "      %s = guestfs_%s " n name;
8333   generate_c_call_args ~handle:"g" style;
8334   pr ";\n";
8335   do_cleanups ();
8336   pr "      if (%s == NULL)\n" n;
8337   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8338   pr "      EXTEND (SP, %s->len);\n" n;
8339   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8340   pr "        hv = newHV ();\n";
8341   List.iter (
8342     function
8343     | name, FString ->
8344         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8345           name (String.length name) n name
8346     | name, FUUID ->
8347         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8348           name (String.length name) n name
8349     | name, FBuffer ->
8350         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8351           name (String.length name) n name n name
8352     | name, (FBytes|FUInt64) ->
8353         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8354           name (String.length name) n name
8355     | name, FInt64 ->
8356         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8357           name (String.length name) n name
8358     | name, (FInt32|FUInt32) ->
8359         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8360           name (String.length name) n name
8361     | name, FChar ->
8362         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8363           name (String.length name) n name
8364     | name, FOptPercent ->
8365         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8366           name (String.length name) n name
8367   ) cols;
8368   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8369   pr "      }\n";
8370   pr "      guestfs_free_%s_list (%s);\n" typ n
8371
8372 and generate_perl_struct_code typ cols name style n do_cleanups =
8373   pr "PREINIT:\n";
8374   pr "      struct guestfs_%s *%s;\n" typ n;
8375   pr " PPCODE:\n";
8376   pr "      %s = guestfs_%s " n name;
8377   generate_c_call_args ~handle:"g" style;
8378   pr ";\n";
8379   do_cleanups ();
8380   pr "      if (%s == NULL)\n" n;
8381   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8382   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8383   List.iter (
8384     fun ((name, _) as col) ->
8385       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8386
8387       match col with
8388       | name, FString ->
8389           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8390             n name
8391       | name, FBuffer ->
8392           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8393             n name n name
8394       | name, FUUID ->
8395           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8396             n name
8397       | name, (FBytes|FUInt64) ->
8398           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8399             n name
8400       | name, FInt64 ->
8401           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8402             n name
8403       | name, (FInt32|FUInt32) ->
8404           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8405             n name
8406       | name, FChar ->
8407           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8408             n name
8409       | name, FOptPercent ->
8410           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8411             n name
8412   ) cols;
8413   pr "      free (%s);\n" n
8414
8415 (* Generate Sys/Guestfs.pm. *)
8416 and generate_perl_pm () =
8417   generate_header HashStyle LGPLv2plus;
8418
8419   pr "\
8420 =pod
8421
8422 =head1 NAME
8423
8424 Sys::Guestfs - Perl bindings for libguestfs
8425
8426 =head1 SYNOPSIS
8427
8428  use Sys::Guestfs;
8429
8430  my $h = Sys::Guestfs->new ();
8431  $h->add_drive ('guest.img');
8432  $h->launch ();
8433  $h->mount ('/dev/sda1', '/');
8434  $h->touch ('/hello');
8435  $h->sync ();
8436
8437 =head1 DESCRIPTION
8438
8439 The C<Sys::Guestfs> module provides a Perl XS binding to the
8440 libguestfs API for examining and modifying virtual machine
8441 disk images.
8442
8443 Amongst the things this is good for: making batch configuration
8444 changes to guests, getting disk used/free statistics (see also:
8445 virt-df), migrating between virtualization systems (see also:
8446 virt-p2v), performing partial backups, performing partial guest
8447 clones, cloning guests and changing registry/UUID/hostname info, and
8448 much else besides.
8449
8450 Libguestfs uses Linux kernel and qemu code, and can access any type of
8451 guest filesystem that Linux and qemu can, including but not limited
8452 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8453 schemes, qcow, qcow2, vmdk.
8454
8455 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8456 LVs, what filesystem is in each LV, etc.).  It can also run commands
8457 in the context of the guest.  Also you can access filesystems over
8458 FUSE.
8459
8460 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8461 functions for using libguestfs from Perl, including integration
8462 with libvirt.
8463
8464 =head1 ERRORS
8465
8466 All errors turn into calls to C<croak> (see L<Carp(3)>).
8467
8468 =head1 METHODS
8469
8470 =over 4
8471
8472 =cut
8473
8474 package Sys::Guestfs;
8475
8476 use strict;
8477 use warnings;
8478
8479 require XSLoader;
8480 XSLoader::load ('Sys::Guestfs');
8481
8482 =item $h = Sys::Guestfs->new ();
8483
8484 Create a new guestfs handle.
8485
8486 =cut
8487
8488 sub new {
8489   my $proto = shift;
8490   my $class = ref ($proto) || $proto;
8491
8492   my $self = Sys::Guestfs::_create ();
8493   bless $self, $class;
8494   return $self;
8495 }
8496
8497 ";
8498
8499   (* Actions.  We only need to print documentation for these as
8500    * they are pulled in from the XS code automatically.
8501    *)
8502   List.iter (
8503     fun (name, style, _, flags, _, _, longdesc) ->
8504       if not (List.mem NotInDocs flags) then (
8505         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8506         pr "=item ";
8507         generate_perl_prototype name style;
8508         pr "\n\n";
8509         pr "%s\n\n" longdesc;
8510         if List.mem ProtocolLimitWarning flags then
8511           pr "%s\n\n" protocol_limit_warning;
8512         if List.mem DangerWillRobinson flags then
8513           pr "%s\n\n" danger_will_robinson;
8514         match deprecation_notice flags with
8515         | None -> ()
8516         | Some txt -> pr "%s\n\n" txt
8517       )
8518   ) all_functions_sorted;
8519
8520   (* End of file. *)
8521   pr "\
8522 =cut
8523
8524 1;
8525
8526 =back
8527
8528 =head1 COPYRIGHT
8529
8530 Copyright (C) %s Red Hat Inc.
8531
8532 =head1 LICENSE
8533
8534 Please see the file COPYING.LIB for the full license.
8535
8536 =head1 SEE ALSO
8537
8538 L<guestfs(3)>,
8539 L<guestfish(1)>,
8540 L<http://libguestfs.org>,
8541 L<Sys::Guestfs::Lib(3)>.
8542
8543 =cut
8544 " copyright_years
8545
8546 and generate_perl_prototype name style =
8547   (match fst style with
8548    | RErr -> ()
8549    | RBool n
8550    | RInt n
8551    | RInt64 n
8552    | RConstString n
8553    | RConstOptString n
8554    | RString n
8555    | RBufferOut n -> pr "$%s = " n
8556    | RStruct (n,_)
8557    | RHashtable n -> pr "%%%s = " n
8558    | RStringList n
8559    | RStructList (n,_) -> pr "@%s = " n
8560   );
8561   pr "$h->%s (" name;
8562   let comma = ref false in
8563   List.iter (
8564     fun arg ->
8565       if !comma then pr ", ";
8566       comma := true;
8567       match arg with
8568       | Pathname n | Device n | Dev_or_Path n | String n
8569       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8570           pr "$%s" n
8571       | StringList n | DeviceList n ->
8572           pr "\\@%s" n
8573   ) (snd style);
8574   pr ");"
8575
8576 (* Generate Python C module. *)
8577 and generate_python_c () =
8578   generate_header CStyle LGPLv2plus;
8579
8580   pr "\
8581 #include <Python.h>
8582
8583 #include <stdio.h>
8584 #include <stdlib.h>
8585 #include <assert.h>
8586
8587 #include \"guestfs.h\"
8588
8589 typedef struct {
8590   PyObject_HEAD
8591   guestfs_h *g;
8592 } Pyguestfs_Object;
8593
8594 static guestfs_h *
8595 get_handle (PyObject *obj)
8596 {
8597   assert (obj);
8598   assert (obj != Py_None);
8599   return ((Pyguestfs_Object *) obj)->g;
8600 }
8601
8602 static PyObject *
8603 put_handle (guestfs_h *g)
8604 {
8605   assert (g);
8606   return
8607     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8608 }
8609
8610 /* This list should be freed (but not the strings) after use. */
8611 static char **
8612 get_string_list (PyObject *obj)
8613 {
8614   int i, len;
8615   char **r;
8616
8617   assert (obj);
8618
8619   if (!PyList_Check (obj)) {
8620     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8621     return NULL;
8622   }
8623
8624   len = PyList_Size (obj);
8625   r = malloc (sizeof (char *) * (len+1));
8626   if (r == NULL) {
8627     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8628     return NULL;
8629   }
8630
8631   for (i = 0; i < len; ++i)
8632     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8633   r[len] = NULL;
8634
8635   return r;
8636 }
8637
8638 static PyObject *
8639 put_string_list (char * const * const argv)
8640 {
8641   PyObject *list;
8642   int argc, i;
8643
8644   for (argc = 0; argv[argc] != NULL; ++argc)
8645     ;
8646
8647   list = PyList_New (argc);
8648   for (i = 0; i < argc; ++i)
8649     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8650
8651   return list;
8652 }
8653
8654 static PyObject *
8655 put_table (char * const * const argv)
8656 {
8657   PyObject *list, *item;
8658   int argc, i;
8659
8660   for (argc = 0; argv[argc] != NULL; ++argc)
8661     ;
8662
8663   list = PyList_New (argc >> 1);
8664   for (i = 0; i < argc; i += 2) {
8665     item = PyTuple_New (2);
8666     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8667     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8668     PyList_SetItem (list, i >> 1, item);
8669   }
8670
8671   return list;
8672 }
8673
8674 static void
8675 free_strings (char **argv)
8676 {
8677   int argc;
8678
8679   for (argc = 0; argv[argc] != NULL; ++argc)
8680     free (argv[argc]);
8681   free (argv);
8682 }
8683
8684 static PyObject *
8685 py_guestfs_create (PyObject *self, PyObject *args)
8686 {
8687   guestfs_h *g;
8688
8689   g = guestfs_create ();
8690   if (g == NULL) {
8691     PyErr_SetString (PyExc_RuntimeError,
8692                      \"guestfs.create: failed to allocate handle\");
8693     return NULL;
8694   }
8695   guestfs_set_error_handler (g, NULL, NULL);
8696   return put_handle (g);
8697 }
8698
8699 static PyObject *
8700 py_guestfs_close (PyObject *self, PyObject *args)
8701 {
8702   PyObject *py_g;
8703   guestfs_h *g;
8704
8705   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8706     return NULL;
8707   g = get_handle (py_g);
8708
8709   guestfs_close (g);
8710
8711   Py_INCREF (Py_None);
8712   return Py_None;
8713 }
8714
8715 ";
8716
8717   let emit_put_list_function typ =
8718     pr "static PyObject *\n";
8719     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8720     pr "{\n";
8721     pr "  PyObject *list;\n";
8722     pr "  int i;\n";
8723     pr "\n";
8724     pr "  list = PyList_New (%ss->len);\n" typ;
8725     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8726     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8727     pr "  return list;\n";
8728     pr "};\n";
8729     pr "\n"
8730   in
8731
8732   (* Structures, turned into Python dictionaries. *)
8733   List.iter (
8734     fun (typ, cols) ->
8735       pr "static PyObject *\n";
8736       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8737       pr "{\n";
8738       pr "  PyObject *dict;\n";
8739       pr "\n";
8740       pr "  dict = PyDict_New ();\n";
8741       List.iter (
8742         function
8743         | name, FString ->
8744             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8745             pr "                        PyString_FromString (%s->%s));\n"
8746               typ name
8747         | name, FBuffer ->
8748             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8749             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8750               typ name typ name
8751         | name, FUUID ->
8752             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8753             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8754               typ name
8755         | name, (FBytes|FUInt64) ->
8756             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8757             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8758               typ name
8759         | name, FInt64 ->
8760             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8761             pr "                        PyLong_FromLongLong (%s->%s));\n"
8762               typ name
8763         | name, FUInt32 ->
8764             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8765             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8766               typ name
8767         | name, FInt32 ->
8768             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8769             pr "                        PyLong_FromLong (%s->%s));\n"
8770               typ name
8771         | name, FOptPercent ->
8772             pr "  if (%s->%s >= 0)\n" typ name;
8773             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8774             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8775               typ name;
8776             pr "  else {\n";
8777             pr "    Py_INCREF (Py_None);\n";
8778             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8779             pr "  }\n"
8780         | name, FChar ->
8781             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8782             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8783       ) cols;
8784       pr "  return dict;\n";
8785       pr "};\n";
8786       pr "\n";
8787
8788   ) structs;
8789
8790   (* Emit a put_TYPE_list function definition only if that function is used. *)
8791   List.iter (
8792     function
8793     | typ, (RStructListOnly | RStructAndList) ->
8794         (* generate the function for typ *)
8795         emit_put_list_function typ
8796     | typ, _ -> () (* empty *)
8797   ) (rstructs_used_by all_functions);
8798
8799   (* Python wrapper functions. *)
8800   List.iter (
8801     fun (name, style, _, _, _, _, _) ->
8802       pr "static PyObject *\n";
8803       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8804       pr "{\n";
8805
8806       pr "  PyObject *py_g;\n";
8807       pr "  guestfs_h *g;\n";
8808       pr "  PyObject *py_r;\n";
8809
8810       let error_code =
8811         match fst style with
8812         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8813         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8814         | RConstString _ | RConstOptString _ ->
8815             pr "  const char *r;\n"; "NULL"
8816         | RString _ -> pr "  char *r;\n"; "NULL"
8817         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8818         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8819         | RStructList (_, typ) ->
8820             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8821         | RBufferOut _ ->
8822             pr "  char *r;\n";
8823             pr "  size_t size;\n";
8824             "NULL" in
8825
8826       List.iter (
8827         function
8828         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8829             pr "  const char *%s;\n" n
8830         | OptString n -> pr "  const char *%s;\n" n
8831         | StringList n | DeviceList n ->
8832             pr "  PyObject *py_%s;\n" n;
8833             pr "  char **%s;\n" n
8834         | Bool n -> pr "  int %s;\n" n
8835         | Int n -> pr "  int %s;\n" n
8836         | Int64 n -> pr "  long long %s;\n" n
8837       ) (snd style);
8838
8839       pr "\n";
8840
8841       (* Convert the parameters. *)
8842       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8843       List.iter (
8844         function
8845         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8846         | OptString _ -> pr "z"
8847         | StringList _ | DeviceList _ -> pr "O"
8848         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8849         | Int _ -> pr "i"
8850         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8851                              * emulate C's int/long/long long in Python?
8852                              *)
8853       ) (snd style);
8854       pr ":guestfs_%s\",\n" name;
8855       pr "                         &py_g";
8856       List.iter (
8857         function
8858         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8859         | OptString n -> pr ", &%s" n
8860         | StringList n | DeviceList n -> pr ", &py_%s" n
8861         | Bool n -> pr ", &%s" n
8862         | Int n -> pr ", &%s" n
8863         | Int64 n -> pr ", &%s" n
8864       ) (snd style);
8865
8866       pr "))\n";
8867       pr "    return NULL;\n";
8868
8869       pr "  g = get_handle (py_g);\n";
8870       List.iter (
8871         function
8872         | Pathname _ | Device _ | Dev_or_Path _ | String _
8873         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8874         | StringList n | DeviceList n ->
8875             pr "  %s = get_string_list (py_%s);\n" n n;
8876             pr "  if (!%s) return NULL;\n" n
8877       ) (snd style);
8878
8879       pr "\n";
8880
8881       pr "  r = guestfs_%s " name;
8882       generate_c_call_args ~handle:"g" style;
8883       pr ";\n";
8884
8885       List.iter (
8886         function
8887         | Pathname _ | Device _ | Dev_or_Path _ | String _
8888         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8889         | StringList n | DeviceList n ->
8890             pr "  free (%s);\n" n
8891       ) (snd style);
8892
8893       pr "  if (r == %s) {\n" error_code;
8894       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8895       pr "    return NULL;\n";
8896       pr "  }\n";
8897       pr "\n";
8898
8899       (match fst style with
8900        | RErr ->
8901            pr "  Py_INCREF (Py_None);\n";
8902            pr "  py_r = Py_None;\n"
8903        | RInt _
8904        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8905        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8906        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8907        | RConstOptString _ ->
8908            pr "  if (r)\n";
8909            pr "    py_r = PyString_FromString (r);\n";
8910            pr "  else {\n";
8911            pr "    Py_INCREF (Py_None);\n";
8912            pr "    py_r = Py_None;\n";
8913            pr "  }\n"
8914        | RString _ ->
8915            pr "  py_r = PyString_FromString (r);\n";
8916            pr "  free (r);\n"
8917        | RStringList _ ->
8918            pr "  py_r = put_string_list (r);\n";
8919            pr "  free_strings (r);\n"
8920        | RStruct (_, typ) ->
8921            pr "  py_r = put_%s (r);\n" typ;
8922            pr "  guestfs_free_%s (r);\n" typ
8923        | RStructList (_, typ) ->
8924            pr "  py_r = put_%s_list (r);\n" typ;
8925            pr "  guestfs_free_%s_list (r);\n" typ
8926        | RHashtable n ->
8927            pr "  py_r = put_table (r);\n";
8928            pr "  free_strings (r);\n"
8929        | RBufferOut _ ->
8930            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8931            pr "  free (r);\n"
8932       );
8933
8934       pr "  return py_r;\n";
8935       pr "}\n";
8936       pr "\n"
8937   ) all_functions;
8938
8939   (* Table of functions. *)
8940   pr "static PyMethodDef methods[] = {\n";
8941   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8942   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8943   List.iter (
8944     fun (name, _, _, _, _, _, _) ->
8945       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8946         name name
8947   ) all_functions;
8948   pr "  { NULL, NULL, 0, NULL }\n";
8949   pr "};\n";
8950   pr "\n";
8951
8952   (* Init function. *)
8953   pr "\
8954 void
8955 initlibguestfsmod (void)
8956 {
8957   static int initialized = 0;
8958
8959   if (initialized) return;
8960   Py_InitModule ((char *) \"libguestfsmod\", methods);
8961   initialized = 1;
8962 }
8963 "
8964
8965 (* Generate Python module. *)
8966 and generate_python_py () =
8967   generate_header HashStyle LGPLv2plus;
8968
8969   pr "\
8970 u\"\"\"Python bindings for libguestfs
8971
8972 import guestfs
8973 g = guestfs.GuestFS ()
8974 g.add_drive (\"guest.img\")
8975 g.launch ()
8976 parts = g.list_partitions ()
8977
8978 The guestfs module provides a Python binding to the libguestfs API
8979 for examining and modifying virtual machine disk images.
8980
8981 Amongst the things this is good for: making batch configuration
8982 changes to guests, getting disk used/free statistics (see also:
8983 virt-df), migrating between virtualization systems (see also:
8984 virt-p2v), performing partial backups, performing partial guest
8985 clones, cloning guests and changing registry/UUID/hostname info, and
8986 much else besides.
8987
8988 Libguestfs uses Linux kernel and qemu code, and can access any type of
8989 guest filesystem that Linux and qemu can, including but not limited
8990 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8991 schemes, qcow, qcow2, vmdk.
8992
8993 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8994 LVs, what filesystem is in each LV, etc.).  It can also run commands
8995 in the context of the guest.  Also you can access filesystems over
8996 FUSE.
8997
8998 Errors which happen while using the API are turned into Python
8999 RuntimeError exceptions.
9000
9001 To create a guestfs handle you usually have to perform the following
9002 sequence of calls:
9003
9004 # Create the handle, call add_drive at least once, and possibly
9005 # several times if the guest has multiple block devices:
9006 g = guestfs.GuestFS ()
9007 g.add_drive (\"guest.img\")
9008
9009 # Launch the qemu subprocess and wait for it to become ready:
9010 g.launch ()
9011
9012 # Now you can issue commands, for example:
9013 logvols = g.lvs ()
9014
9015 \"\"\"
9016
9017 import libguestfsmod
9018
9019 class GuestFS:
9020     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9021
9022     def __init__ (self):
9023         \"\"\"Create a new libguestfs handle.\"\"\"
9024         self._o = libguestfsmod.create ()
9025
9026     def __del__ (self):
9027         libguestfsmod.close (self._o)
9028
9029 ";
9030
9031   List.iter (
9032     fun (name, style, _, flags, _, _, longdesc) ->
9033       pr "    def %s " name;
9034       generate_py_call_args ~handle:"self" (snd style);
9035       pr ":\n";
9036
9037       if not (List.mem NotInDocs flags) then (
9038         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9039         let doc =
9040           match fst style with
9041           | RErr | RInt _ | RInt64 _ | RBool _
9042           | RConstOptString _ | RConstString _
9043           | RString _ | RBufferOut _ -> doc
9044           | RStringList _ ->
9045               doc ^ "\n\nThis function returns a list of strings."
9046           | RStruct (_, typ) ->
9047               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9048           | RStructList (_, typ) ->
9049               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9050           | RHashtable _ ->
9051               doc ^ "\n\nThis function returns a dictionary." in
9052         let doc =
9053           if List.mem ProtocolLimitWarning flags then
9054             doc ^ "\n\n" ^ protocol_limit_warning
9055           else doc in
9056         let doc =
9057           if List.mem DangerWillRobinson flags then
9058             doc ^ "\n\n" ^ danger_will_robinson
9059           else doc in
9060         let doc =
9061           match deprecation_notice flags with
9062           | None -> doc
9063           | Some txt -> doc ^ "\n\n" ^ txt in
9064         let doc = pod2text ~width:60 name doc in
9065         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9066         let doc = String.concat "\n        " doc in
9067         pr "        u\"\"\"%s\"\"\"\n" doc;
9068       );
9069       pr "        return libguestfsmod.%s " name;
9070       generate_py_call_args ~handle:"self._o" (snd style);
9071       pr "\n";
9072       pr "\n";
9073   ) all_functions
9074
9075 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9076 and generate_py_call_args ~handle args =
9077   pr "(%s" handle;
9078   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9079   pr ")"
9080
9081 (* Useful if you need the longdesc POD text as plain text.  Returns a
9082  * list of lines.
9083  *
9084  * Because this is very slow (the slowest part of autogeneration),
9085  * we memoize the results.
9086  *)
9087 and pod2text ~width name longdesc =
9088   let key = width, name, longdesc in
9089   try Hashtbl.find pod2text_memo key
9090   with Not_found ->
9091     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9092     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9093     close_out chan;
9094     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9095     let chan = open_process_in cmd in
9096     let lines = ref [] in
9097     let rec loop i =
9098       let line = input_line chan in
9099       if i = 1 then             (* discard the first line of output *)
9100         loop (i+1)
9101       else (
9102         let line = triml line in
9103         lines := line :: !lines;
9104         loop (i+1)
9105       ) in
9106     let lines = try loop 1 with End_of_file -> List.rev !lines in
9107     unlink filename;
9108     (match close_process_in chan with
9109      | WEXITED 0 -> ()
9110      | WEXITED i ->
9111          failwithf "pod2text: process exited with non-zero status (%d)" i
9112      | WSIGNALED i | WSTOPPED i ->
9113          failwithf "pod2text: process signalled or stopped by signal %d" i
9114     );
9115     Hashtbl.add pod2text_memo key lines;
9116     pod2text_memo_updated ();
9117     lines
9118
9119 (* Generate ruby bindings. *)
9120 and generate_ruby_c () =
9121   generate_header CStyle LGPLv2plus;
9122
9123   pr "\
9124 #include <stdio.h>
9125 #include <stdlib.h>
9126
9127 #include <ruby.h>
9128
9129 #include \"guestfs.h\"
9130
9131 #include \"extconf.h\"
9132
9133 /* For Ruby < 1.9 */
9134 #ifndef RARRAY_LEN
9135 #define RARRAY_LEN(r) (RARRAY((r))->len)
9136 #endif
9137
9138 static VALUE m_guestfs;                 /* guestfs module */
9139 static VALUE c_guestfs;                 /* guestfs_h handle */
9140 static VALUE e_Error;                   /* used for all errors */
9141
9142 static void ruby_guestfs_free (void *p)
9143 {
9144   if (!p) return;
9145   guestfs_close ((guestfs_h *) p);
9146 }
9147
9148 static VALUE ruby_guestfs_create (VALUE m)
9149 {
9150   guestfs_h *g;
9151
9152   g = guestfs_create ();
9153   if (!g)
9154     rb_raise (e_Error, \"failed to create guestfs handle\");
9155
9156   /* Don't print error messages to stderr by default. */
9157   guestfs_set_error_handler (g, NULL, NULL);
9158
9159   /* Wrap it, and make sure the close function is called when the
9160    * handle goes away.
9161    */
9162   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9163 }
9164
9165 static VALUE ruby_guestfs_close (VALUE gv)
9166 {
9167   guestfs_h *g;
9168   Data_Get_Struct (gv, guestfs_h, g);
9169
9170   ruby_guestfs_free (g);
9171   DATA_PTR (gv) = NULL;
9172
9173   return Qnil;
9174 }
9175
9176 ";
9177
9178   List.iter (
9179     fun (name, style, _, _, _, _, _) ->
9180       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9181       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9182       pr ")\n";
9183       pr "{\n";
9184       pr "  guestfs_h *g;\n";
9185       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9186       pr "  if (!g)\n";
9187       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9188         name;
9189       pr "\n";
9190
9191       List.iter (
9192         function
9193         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9194             pr "  Check_Type (%sv, T_STRING);\n" n;
9195             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9196             pr "  if (!%s)\n" n;
9197             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9198             pr "              \"%s\", \"%s\");\n" n name
9199         | OptString n ->
9200             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9201         | StringList n | DeviceList n ->
9202             pr "  char **%s;\n" n;
9203             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9204             pr "  {\n";
9205             pr "    int i, len;\n";
9206             pr "    len = RARRAY_LEN (%sv);\n" n;
9207             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9208               n;
9209             pr "    for (i = 0; i < len; ++i) {\n";
9210             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9211             pr "      %s[i] = StringValueCStr (v);\n" n;
9212             pr "    }\n";
9213             pr "    %s[len] = NULL;\n" n;
9214             pr "  }\n";
9215         | Bool n ->
9216             pr "  int %s = RTEST (%sv);\n" n n
9217         | Int n ->
9218             pr "  int %s = NUM2INT (%sv);\n" n n
9219         | Int64 n ->
9220             pr "  long long %s = NUM2LL (%sv);\n" n n
9221       ) (snd style);
9222       pr "\n";
9223
9224       let error_code =
9225         match fst style with
9226         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9227         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9228         | RConstString _ | RConstOptString _ ->
9229             pr "  const char *r;\n"; "NULL"
9230         | RString _ -> pr "  char *r;\n"; "NULL"
9231         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9232         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9233         | RStructList (_, typ) ->
9234             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9235         | RBufferOut _ ->
9236             pr "  char *r;\n";
9237             pr "  size_t size;\n";
9238             "NULL" in
9239       pr "\n";
9240
9241       pr "  r = guestfs_%s " name;
9242       generate_c_call_args ~handle:"g" style;
9243       pr ";\n";
9244
9245       List.iter (
9246         function
9247         | Pathname _ | Device _ | Dev_or_Path _ | String _
9248         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9249         | StringList n | DeviceList n ->
9250             pr "  free (%s);\n" n
9251       ) (snd style);
9252
9253       pr "  if (r == %s)\n" error_code;
9254       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9255       pr "\n";
9256
9257       (match fst style with
9258        | RErr ->
9259            pr "  return Qnil;\n"
9260        | RInt _ | RBool _ ->
9261            pr "  return INT2NUM (r);\n"
9262        | RInt64 _ ->
9263            pr "  return ULL2NUM (r);\n"
9264        | RConstString _ ->
9265            pr "  return rb_str_new2 (r);\n";
9266        | RConstOptString _ ->
9267            pr "  if (r)\n";
9268            pr "    return rb_str_new2 (r);\n";
9269            pr "  else\n";
9270            pr "    return Qnil;\n";
9271        | RString _ ->
9272            pr "  VALUE rv = rb_str_new2 (r);\n";
9273            pr "  free (r);\n";
9274            pr "  return rv;\n";
9275        | RStringList _ ->
9276            pr "  int i, len = 0;\n";
9277            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9278            pr "  VALUE rv = rb_ary_new2 (len);\n";
9279            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9280            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9281            pr "    free (r[i]);\n";
9282            pr "  }\n";
9283            pr "  free (r);\n";
9284            pr "  return rv;\n"
9285        | RStruct (_, typ) ->
9286            let cols = cols_of_struct typ in
9287            generate_ruby_struct_code typ cols
9288        | RStructList (_, typ) ->
9289            let cols = cols_of_struct typ in
9290            generate_ruby_struct_list_code typ cols
9291        | RHashtable _ ->
9292            pr "  VALUE rv = rb_hash_new ();\n";
9293            pr "  int i;\n";
9294            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9295            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9296            pr "    free (r[i]);\n";
9297            pr "    free (r[i+1]);\n";
9298            pr "  }\n";
9299            pr "  free (r);\n";
9300            pr "  return rv;\n"
9301        | RBufferOut _ ->
9302            pr "  VALUE rv = rb_str_new (r, size);\n";
9303            pr "  free (r);\n";
9304            pr "  return rv;\n";
9305       );
9306
9307       pr "}\n";
9308       pr "\n"
9309   ) all_functions;
9310
9311   pr "\
9312 /* Initialize the module. */
9313 void Init__guestfs ()
9314 {
9315   m_guestfs = rb_define_module (\"Guestfs\");
9316   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9317   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9318
9319   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9320   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9321
9322 ";
9323   (* Define the rest of the methods. *)
9324   List.iter (
9325     fun (name, style, _, _, _, _, _) ->
9326       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9327       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9328   ) all_functions;
9329
9330   pr "}\n"
9331
9332 (* Ruby code to return a struct. *)
9333 and generate_ruby_struct_code typ cols =
9334   pr "  VALUE rv = rb_hash_new ();\n";
9335   List.iter (
9336     function
9337     | name, FString ->
9338         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9339     | name, FBuffer ->
9340         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9341     | name, FUUID ->
9342         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9343     | name, (FBytes|FUInt64) ->
9344         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9345     | name, FInt64 ->
9346         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9347     | name, FUInt32 ->
9348         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9349     | name, FInt32 ->
9350         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9351     | name, FOptPercent ->
9352         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9353     | name, FChar -> (* XXX wrong? *)
9354         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9355   ) cols;
9356   pr "  guestfs_free_%s (r);\n" typ;
9357   pr "  return rv;\n"
9358
9359 (* Ruby code to return a struct list. *)
9360 and generate_ruby_struct_list_code typ cols =
9361   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9362   pr "  int i;\n";
9363   pr "  for (i = 0; i < r->len; ++i) {\n";
9364   pr "    VALUE hv = rb_hash_new ();\n";
9365   List.iter (
9366     function
9367     | name, FString ->
9368         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9369     | name, FBuffer ->
9370         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
9371     | name, FUUID ->
9372         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9373     | name, (FBytes|FUInt64) ->
9374         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9375     | name, FInt64 ->
9376         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9377     | name, FUInt32 ->
9378         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9379     | name, FInt32 ->
9380         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9381     | name, FOptPercent ->
9382         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9383     | name, FChar -> (* XXX wrong? *)
9384         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9385   ) cols;
9386   pr "    rb_ary_push (rv, hv);\n";
9387   pr "  }\n";
9388   pr "  guestfs_free_%s_list (r);\n" typ;
9389   pr "  return rv;\n"
9390
9391 (* Generate Java bindings GuestFS.java file. *)
9392 and generate_java_java () =
9393   generate_header CStyle LGPLv2plus;
9394
9395   pr "\
9396 package com.redhat.et.libguestfs;
9397
9398 import java.util.HashMap;
9399 import com.redhat.et.libguestfs.LibGuestFSException;
9400 import com.redhat.et.libguestfs.PV;
9401 import com.redhat.et.libguestfs.VG;
9402 import com.redhat.et.libguestfs.LV;
9403 import com.redhat.et.libguestfs.Stat;
9404 import com.redhat.et.libguestfs.StatVFS;
9405 import com.redhat.et.libguestfs.IntBool;
9406 import com.redhat.et.libguestfs.Dirent;
9407
9408 /**
9409  * The GuestFS object is a libguestfs handle.
9410  *
9411  * @author rjones
9412  */
9413 public class GuestFS {
9414   // Load the native code.
9415   static {
9416     System.loadLibrary (\"guestfs_jni\");
9417   }
9418
9419   /**
9420    * The native guestfs_h pointer.
9421    */
9422   long g;
9423
9424   /**
9425    * Create a libguestfs handle.
9426    *
9427    * @throws LibGuestFSException
9428    */
9429   public GuestFS () throws LibGuestFSException
9430   {
9431     g = _create ();
9432   }
9433   private native long _create () throws LibGuestFSException;
9434
9435   /**
9436    * Close a libguestfs handle.
9437    *
9438    * You can also leave handles to be collected by the garbage
9439    * collector, but this method ensures that the resources used
9440    * by the handle are freed up immediately.  If you call any
9441    * other methods after closing the handle, you will get an
9442    * exception.
9443    *
9444    * @throws LibGuestFSException
9445    */
9446   public void close () throws LibGuestFSException
9447   {
9448     if (g != 0)
9449       _close (g);
9450     g = 0;
9451   }
9452   private native void _close (long g) throws LibGuestFSException;
9453
9454   public void finalize () throws LibGuestFSException
9455   {
9456     close ();
9457   }
9458
9459 ";
9460
9461   List.iter (
9462     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9463       if not (List.mem NotInDocs flags); then (
9464         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9465         let doc =
9466           if List.mem ProtocolLimitWarning flags then
9467             doc ^ "\n\n" ^ protocol_limit_warning
9468           else doc in
9469         let doc =
9470           if List.mem DangerWillRobinson flags then
9471             doc ^ "\n\n" ^ danger_will_robinson
9472           else doc in
9473         let doc =
9474           match deprecation_notice flags with
9475           | None -> doc
9476           | Some txt -> doc ^ "\n\n" ^ txt in
9477         let doc = pod2text ~width:60 name doc in
9478         let doc = List.map (            (* RHBZ#501883 *)
9479           function
9480           | "" -> "<p>"
9481           | nonempty -> nonempty
9482         ) doc in
9483         let doc = String.concat "\n   * " doc in
9484
9485         pr "  /**\n";
9486         pr "   * %s\n" shortdesc;
9487         pr "   * <p>\n";
9488         pr "   * %s\n" doc;
9489         pr "   * @throws LibGuestFSException\n";
9490         pr "   */\n";
9491         pr "  ";
9492       );
9493       generate_java_prototype ~public:true ~semicolon:false name style;
9494       pr "\n";
9495       pr "  {\n";
9496       pr "    if (g == 0)\n";
9497       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9498         name;
9499       pr "    ";
9500       if fst style <> RErr then pr "return ";
9501       pr "_%s " name;
9502       generate_java_call_args ~handle:"g" (snd style);
9503       pr ";\n";
9504       pr "  }\n";
9505       pr "  ";
9506       generate_java_prototype ~privat:true ~native:true name style;
9507       pr "\n";
9508       pr "\n";
9509   ) all_functions;
9510
9511   pr "}\n"
9512
9513 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9514 and generate_java_call_args ~handle args =
9515   pr "(%s" handle;
9516   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9517   pr ")"
9518
9519 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9520     ?(semicolon=true) name style =
9521   if privat then pr "private ";
9522   if public then pr "public ";
9523   if native then pr "native ";
9524
9525   (* return type *)
9526   (match fst style with
9527    | RErr -> pr "void ";
9528    | RInt _ -> pr "int ";
9529    | RInt64 _ -> pr "long ";
9530    | RBool _ -> pr "boolean ";
9531    | RConstString _ | RConstOptString _ | RString _
9532    | RBufferOut _ -> pr "String ";
9533    | RStringList _ -> pr "String[] ";
9534    | RStruct (_, typ) ->
9535        let name = java_name_of_struct typ in
9536        pr "%s " name;
9537    | RStructList (_, typ) ->
9538        let name = java_name_of_struct typ in
9539        pr "%s[] " name;
9540    | RHashtable _ -> pr "HashMap<String,String> ";
9541   );
9542
9543   if native then pr "_%s " name else pr "%s " name;
9544   pr "(";
9545   let needs_comma = ref false in
9546   if native then (
9547     pr "long g";
9548     needs_comma := true
9549   );
9550
9551   (* args *)
9552   List.iter (
9553     fun arg ->
9554       if !needs_comma then pr ", ";
9555       needs_comma := true;
9556
9557       match arg with
9558       | Pathname n
9559       | Device n | Dev_or_Path n
9560       | String n
9561       | OptString n
9562       | FileIn n
9563       | FileOut n ->
9564           pr "String %s" n
9565       | StringList n | DeviceList n ->
9566           pr "String[] %s" n
9567       | Bool n ->
9568           pr "boolean %s" n
9569       | Int n ->
9570           pr "int %s" n
9571       | Int64 n ->
9572           pr "long %s" n
9573   ) (snd style);
9574
9575   pr ")\n";
9576   pr "    throws LibGuestFSException";
9577   if semicolon then pr ";"
9578
9579 and generate_java_struct jtyp cols () =
9580   generate_header CStyle LGPLv2plus;
9581
9582   pr "\
9583 package com.redhat.et.libguestfs;
9584
9585 /**
9586  * Libguestfs %s structure.
9587  *
9588  * @author rjones
9589  * @see GuestFS
9590  */
9591 public class %s {
9592 " jtyp jtyp;
9593
9594   List.iter (
9595     function
9596     | name, FString
9597     | name, FUUID
9598     | name, FBuffer -> pr "  public String %s;\n" name
9599     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9600     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9601     | name, FChar -> pr "  public char %s;\n" name
9602     | name, FOptPercent ->
9603         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9604         pr "  public float %s;\n" name
9605   ) cols;
9606
9607   pr "}\n"
9608
9609 and generate_java_c () =
9610   generate_header CStyle LGPLv2plus;
9611
9612   pr "\
9613 #include <stdio.h>
9614 #include <stdlib.h>
9615 #include <string.h>
9616
9617 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9618 #include \"guestfs.h\"
9619
9620 /* Note that this function returns.  The exception is not thrown
9621  * until after the wrapper function returns.
9622  */
9623 static void
9624 throw_exception (JNIEnv *env, const char *msg)
9625 {
9626   jclass cl;
9627   cl = (*env)->FindClass (env,
9628                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9629   (*env)->ThrowNew (env, cl, msg);
9630 }
9631
9632 JNIEXPORT jlong JNICALL
9633 Java_com_redhat_et_libguestfs_GuestFS__1create
9634   (JNIEnv *env, jobject obj)
9635 {
9636   guestfs_h *g;
9637
9638   g = guestfs_create ();
9639   if (g == NULL) {
9640     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9641     return 0;
9642   }
9643   guestfs_set_error_handler (g, NULL, NULL);
9644   return (jlong) (long) g;
9645 }
9646
9647 JNIEXPORT void JNICALL
9648 Java_com_redhat_et_libguestfs_GuestFS__1close
9649   (JNIEnv *env, jobject obj, jlong jg)
9650 {
9651   guestfs_h *g = (guestfs_h *) (long) jg;
9652   guestfs_close (g);
9653 }
9654
9655 ";
9656
9657   List.iter (
9658     fun (name, style, _, _, _, _, _) ->
9659       pr "JNIEXPORT ";
9660       (match fst style with
9661        | RErr -> pr "void ";
9662        | RInt _ -> pr "jint ";
9663        | RInt64 _ -> pr "jlong ";
9664        | RBool _ -> pr "jboolean ";
9665        | RConstString _ | RConstOptString _ | RString _
9666        | RBufferOut _ -> pr "jstring ";
9667        | RStruct _ | RHashtable _ ->
9668            pr "jobject ";
9669        | RStringList _ | RStructList _ ->
9670            pr "jobjectArray ";
9671       );
9672       pr "JNICALL\n";
9673       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9674       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9675       pr "\n";
9676       pr "  (JNIEnv *env, jobject obj, jlong jg";
9677       List.iter (
9678         function
9679         | Pathname n
9680         | Device n | Dev_or_Path n
9681         | String n
9682         | OptString n
9683         | FileIn n
9684         | FileOut n ->
9685             pr ", jstring j%s" n
9686         | StringList n | DeviceList n ->
9687             pr ", jobjectArray j%s" n
9688         | Bool n ->
9689             pr ", jboolean j%s" n
9690         | Int n ->
9691             pr ", jint j%s" n
9692         | Int64 n ->
9693             pr ", jlong j%s" n
9694       ) (snd style);
9695       pr ")\n";
9696       pr "{\n";
9697       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9698       let error_code, no_ret =
9699         match fst style with
9700         | RErr -> pr "  int r;\n"; "-1", ""
9701         | RBool _
9702         | RInt _ -> pr "  int r;\n"; "-1", "0"
9703         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9704         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9705         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9706         | RString _ ->
9707             pr "  jstring jr;\n";
9708             pr "  char *r;\n"; "NULL", "NULL"
9709         | RStringList _ ->
9710             pr "  jobjectArray jr;\n";
9711             pr "  int r_len;\n";
9712             pr "  jclass cl;\n";
9713             pr "  jstring jstr;\n";
9714             pr "  char **r;\n"; "NULL", "NULL"
9715         | RStruct (_, typ) ->
9716             pr "  jobject jr;\n";
9717             pr "  jclass cl;\n";
9718             pr "  jfieldID fl;\n";
9719             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9720         | RStructList (_, typ) ->
9721             pr "  jobjectArray jr;\n";
9722             pr "  jclass cl;\n";
9723             pr "  jfieldID fl;\n";
9724             pr "  jobject jfl;\n";
9725             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9726         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9727         | RBufferOut _ ->
9728             pr "  jstring jr;\n";
9729             pr "  char *r;\n";
9730             pr "  size_t size;\n";
9731             "NULL", "NULL" in
9732       List.iter (
9733         function
9734         | Pathname n
9735         | Device n | Dev_or_Path n
9736         | String n
9737         | OptString n
9738         | FileIn n
9739         | FileOut n ->
9740             pr "  const char *%s;\n" n
9741         | StringList n | DeviceList n ->
9742             pr "  int %s_len;\n" n;
9743             pr "  const char **%s;\n" n
9744         | Bool n
9745         | Int n ->
9746             pr "  int %s;\n" n
9747         | Int64 n ->
9748             pr "  int64_t %s;\n" n
9749       ) (snd style);
9750
9751       let needs_i =
9752         (match fst style with
9753          | RStringList _ | RStructList _ -> true
9754          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9755          | RConstOptString _
9756          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9757           List.exists (function
9758                        | StringList _ -> true
9759                        | DeviceList _ -> true
9760                        | _ -> false) (snd style) in
9761       if needs_i then
9762         pr "  int i;\n";
9763
9764       pr "\n";
9765
9766       (* Get the parameters. *)
9767       List.iter (
9768         function
9769         | Pathname n
9770         | Device n | Dev_or_Path n
9771         | String n
9772         | FileIn n
9773         | FileOut n ->
9774             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9775         | OptString n ->
9776             (* This is completely undocumented, but Java null becomes
9777              * a NULL parameter.
9778              *)
9779             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9780         | StringList n | DeviceList n ->
9781             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9782             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9783             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9784             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9785               n;
9786             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9787             pr "  }\n";
9788             pr "  %s[%s_len] = NULL;\n" n n;
9789         | Bool n
9790         | Int n
9791         | Int64 n ->
9792             pr "  %s = j%s;\n" n n
9793       ) (snd style);
9794
9795       (* Make the call. *)
9796       pr "  r = guestfs_%s " name;
9797       generate_c_call_args ~handle:"g" style;
9798       pr ";\n";
9799
9800       (* Release the parameters. *)
9801       List.iter (
9802         function
9803         | Pathname n
9804         | Device n | Dev_or_Path n
9805         | String n
9806         | FileIn n
9807         | FileOut n ->
9808             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9809         | OptString n ->
9810             pr "  if (j%s)\n" n;
9811             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9812         | StringList n | DeviceList n ->
9813             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9814             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9815               n;
9816             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9817             pr "  }\n";
9818             pr "  free (%s);\n" n
9819         | Bool n
9820         | Int n
9821         | Int64 n -> ()
9822       ) (snd style);
9823
9824       (* Check for errors. *)
9825       pr "  if (r == %s) {\n" error_code;
9826       pr "    throw_exception (env, guestfs_last_error (g));\n";
9827       pr "    return %s;\n" no_ret;
9828       pr "  }\n";
9829
9830       (* Return value. *)
9831       (match fst style with
9832        | RErr -> ()
9833        | RInt _ -> pr "  return (jint) r;\n"
9834        | RBool _ -> pr "  return (jboolean) r;\n"
9835        | RInt64 _ -> pr "  return (jlong) r;\n"
9836        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9837        | RConstOptString _ ->
9838            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9839        | RString _ ->
9840            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9841            pr "  free (r);\n";
9842            pr "  return jr;\n"
9843        | RStringList _ ->
9844            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9845            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9846            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9847            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9848            pr "  for (i = 0; i < r_len; ++i) {\n";
9849            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9850            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9851            pr "    free (r[i]);\n";
9852            pr "  }\n";
9853            pr "  free (r);\n";
9854            pr "  return jr;\n"
9855        | RStruct (_, typ) ->
9856            let jtyp = java_name_of_struct typ in
9857            let cols = cols_of_struct typ in
9858            generate_java_struct_return typ jtyp cols
9859        | RStructList (_, typ) ->
9860            let jtyp = java_name_of_struct typ in
9861            let cols = cols_of_struct typ in
9862            generate_java_struct_list_return typ jtyp cols
9863        | RHashtable _ ->
9864            (* XXX *)
9865            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9866            pr "  return NULL;\n"
9867        | RBufferOut _ ->
9868            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9869            pr "  free (r);\n";
9870            pr "  return jr;\n"
9871       );
9872
9873       pr "}\n";
9874       pr "\n"
9875   ) all_functions
9876
9877 and generate_java_struct_return typ jtyp cols =
9878   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9879   pr "  jr = (*env)->AllocObject (env, cl);\n";
9880   List.iter (
9881     function
9882     | name, FString ->
9883         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9884         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9885     | name, FUUID ->
9886         pr "  {\n";
9887         pr "    char s[33];\n";
9888         pr "    memcpy (s, r->%s, 32);\n" name;
9889         pr "    s[32] = 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, FBuffer ->
9894         pr "  {\n";
9895         pr "    int len = r->%s_len;\n" name;
9896         pr "    char s[len+1];\n";
9897         pr "    memcpy (s, r->%s, len);\n" name;
9898         pr "    s[len] = 0;\n";
9899         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9900         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9901         pr "  }\n";
9902     | name, (FBytes|FUInt64|FInt64) ->
9903         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9904         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9905     | name, (FUInt32|FInt32) ->
9906         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9907         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9908     | name, FOptPercent ->
9909         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9910         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9911     | name, FChar ->
9912         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9913         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9914   ) cols;
9915   pr "  free (r);\n";
9916   pr "  return jr;\n"
9917
9918 and generate_java_struct_list_return typ jtyp cols =
9919   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9920   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9921   pr "  for (i = 0; i < r->len; ++i) {\n";
9922   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9923   List.iter (
9924     function
9925     | name, FString ->
9926         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9927         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9928     | name, FUUID ->
9929         pr "    {\n";
9930         pr "      char s[33];\n";
9931         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9932         pr "      s[32] = 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, FBuffer ->
9937         pr "    {\n";
9938         pr "      int len = r->val[i].%s_len;\n" name;
9939         pr "      char s[len+1];\n";
9940         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9941         pr "      s[len] = 0;\n";
9942         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9943         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9944         pr "    }\n";
9945     | name, (FBytes|FUInt64|FInt64) ->
9946         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9947         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9948     | name, (FUInt32|FInt32) ->
9949         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9950         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9951     | name, FOptPercent ->
9952         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9953         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9954     | name, FChar ->
9955         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9956         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9957   ) cols;
9958   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9959   pr "  }\n";
9960   pr "  guestfs_free_%s_list (r);\n" typ;
9961   pr "  return jr;\n"
9962
9963 and generate_java_makefile_inc () =
9964   generate_header HashStyle GPLv2plus;
9965
9966   pr "java_built_sources = \\\n";
9967   List.iter (
9968     fun (typ, jtyp) ->
9969         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9970   ) java_structs;
9971   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9972
9973 and generate_haskell_hs () =
9974   generate_header HaskellStyle LGPLv2plus;
9975
9976   (* XXX We only know how to generate partial FFI for Haskell
9977    * at the moment.  Please help out!
9978    *)
9979   let can_generate style =
9980     match style with
9981     | RErr, _
9982     | RInt _, _
9983     | RInt64 _, _ -> true
9984     | RBool _, _
9985     | RConstString _, _
9986     | RConstOptString _, _
9987     | RString _, _
9988     | RStringList _, _
9989     | RStruct _, _
9990     | RStructList _, _
9991     | RHashtable _, _
9992     | RBufferOut _, _ -> false in
9993
9994   pr "\
9995 {-# INCLUDE <guestfs.h> #-}
9996 {-# LANGUAGE ForeignFunctionInterface #-}
9997
9998 module Guestfs (
9999   create";
10000
10001   (* List out the names of the actions we want to export. *)
10002   List.iter (
10003     fun (name, style, _, _, _, _, _) ->
10004       if can_generate style then pr ",\n  %s" name
10005   ) all_functions;
10006
10007   pr "
10008   ) where
10009
10010 -- Unfortunately some symbols duplicate ones already present
10011 -- in Prelude.  We don't know which, so we hard-code a list
10012 -- here.
10013 import Prelude hiding (truncate)
10014
10015 import Foreign
10016 import Foreign.C
10017 import Foreign.C.Types
10018 import IO
10019 import Control.Exception
10020 import Data.Typeable
10021
10022 data GuestfsS = GuestfsS            -- represents the opaque C struct
10023 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10024 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10025
10026 -- XXX define properly later XXX
10027 data PV = PV
10028 data VG = VG
10029 data LV = LV
10030 data IntBool = IntBool
10031 data Stat = Stat
10032 data StatVFS = StatVFS
10033 data Hashtable = Hashtable
10034
10035 foreign import ccall unsafe \"guestfs_create\" c_create
10036   :: IO GuestfsP
10037 foreign import ccall unsafe \"&guestfs_close\" c_close
10038   :: FunPtr (GuestfsP -> IO ())
10039 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10040   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10041
10042 create :: IO GuestfsH
10043 create = do
10044   p <- c_create
10045   c_set_error_handler p nullPtr nullPtr
10046   h <- newForeignPtr c_close p
10047   return h
10048
10049 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10050   :: GuestfsP -> IO CString
10051
10052 -- last_error :: GuestfsH -> IO (Maybe String)
10053 -- last_error h = do
10054 --   str <- withForeignPtr h (\\p -> c_last_error p)
10055 --   maybePeek peekCString str
10056
10057 last_error :: GuestfsH -> IO (String)
10058 last_error h = do
10059   str <- withForeignPtr h (\\p -> c_last_error p)
10060   if (str == nullPtr)
10061     then return \"no error\"
10062     else peekCString str
10063
10064 ";
10065
10066   (* Generate wrappers for each foreign function. *)
10067   List.iter (
10068     fun (name, style, _, _, _, _, _) ->
10069       if can_generate style then (
10070         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10071         pr "  :: ";
10072         generate_haskell_prototype ~handle:"GuestfsP" style;
10073         pr "\n";
10074         pr "\n";
10075         pr "%s :: " name;
10076         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10077         pr "\n";
10078         pr "%s %s = do\n" name
10079           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10080         pr "  r <- ";
10081         (* Convert pointer arguments using with* functions. *)
10082         List.iter (
10083           function
10084           | FileIn n
10085           | FileOut n
10086           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10087           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10088           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10089           | Bool _ | Int _ | Int64 _ -> ()
10090         ) (snd style);
10091         (* Convert integer arguments. *)
10092         let args =
10093           List.map (
10094             function
10095             | Bool n -> sprintf "(fromBool %s)" n
10096             | Int n -> sprintf "(fromIntegral %s)" n
10097             | Int64 n -> sprintf "(fromIntegral %s)" n
10098             | FileIn n | FileOut n
10099             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10100           ) (snd style) in
10101         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10102           (String.concat " " ("p" :: args));
10103         (match fst style with
10104          | RErr | RInt _ | RInt64 _ | RBool _ ->
10105              pr "  if (r == -1)\n";
10106              pr "    then do\n";
10107              pr "      err <- last_error h\n";
10108              pr "      fail err\n";
10109          | RConstString _ | RConstOptString _ | RString _
10110          | RStringList _ | RStruct _
10111          | RStructList _ | RHashtable _ | RBufferOut _ ->
10112              pr "  if (r == nullPtr)\n";
10113              pr "    then do\n";
10114              pr "      err <- last_error h\n";
10115              pr "      fail err\n";
10116         );
10117         (match fst style with
10118          | RErr ->
10119              pr "    else return ()\n"
10120          | RInt _ ->
10121              pr "    else return (fromIntegral r)\n"
10122          | RInt64 _ ->
10123              pr "    else return (fromIntegral r)\n"
10124          | RBool _ ->
10125              pr "    else return (toBool r)\n"
10126          | RConstString _
10127          | RConstOptString _
10128          | RString _
10129          | RStringList _
10130          | RStruct _
10131          | RStructList _
10132          | RHashtable _
10133          | RBufferOut _ ->
10134              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10135         );
10136         pr "\n";
10137       )
10138   ) all_functions
10139
10140 and generate_haskell_prototype ~handle ?(hs = false) style =
10141   pr "%s -> " handle;
10142   let string = if hs then "String" else "CString" in
10143   let int = if hs then "Int" else "CInt" in
10144   let bool = if hs then "Bool" else "CInt" in
10145   let int64 = if hs then "Integer" else "Int64" in
10146   List.iter (
10147     fun arg ->
10148       (match arg with
10149        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10150        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10151        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10152        | Bool _ -> pr "%s" bool
10153        | Int _ -> pr "%s" int
10154        | Int64 _ -> pr "%s" int
10155        | FileIn _ -> pr "%s" string
10156        | FileOut _ -> pr "%s" string
10157       );
10158       pr " -> ";
10159   ) (snd style);
10160   pr "IO (";
10161   (match fst style with
10162    | RErr -> if not hs then pr "CInt"
10163    | RInt _ -> pr "%s" int
10164    | RInt64 _ -> pr "%s" int64
10165    | RBool _ -> pr "%s" bool
10166    | RConstString _ -> pr "%s" string
10167    | RConstOptString _ -> pr "Maybe %s" string
10168    | RString _ -> pr "%s" string
10169    | RStringList _ -> pr "[%s]" string
10170    | RStruct (_, typ) ->
10171        let name = java_name_of_struct typ in
10172        pr "%s" name
10173    | RStructList (_, typ) ->
10174        let name = java_name_of_struct typ in
10175        pr "[%s]" name
10176    | RHashtable _ -> pr "Hashtable"
10177    | RBufferOut _ -> pr "%s" string
10178   );
10179   pr ")"
10180
10181 and generate_csharp () =
10182   generate_header CPlusPlusStyle LGPLv2plus;
10183
10184   (* XXX Make this configurable by the C# assembly users. *)
10185   let library = "libguestfs.so.0" in
10186
10187   pr "\
10188 // These C# bindings are highly experimental at present.
10189 //
10190 // Firstly they only work on Linux (ie. Mono).  In order to get them
10191 // to work on Windows (ie. .Net) you would need to port the library
10192 // itself to Windows first.
10193 //
10194 // The second issue is that some calls are known to be incorrect and
10195 // can cause Mono to segfault.  Particularly: calls which pass or
10196 // return string[], or return any structure value.  This is because
10197 // we haven't worked out the correct way to do this from C#.
10198 //
10199 // The third issue is that when compiling you get a lot of warnings.
10200 // We are not sure whether the warnings are important or not.
10201 //
10202 // Fourthly we do not routinely build or test these bindings as part
10203 // of the make && make check cycle, which means that regressions might
10204 // go unnoticed.
10205 //
10206 // Suggestions and patches are welcome.
10207
10208 // To compile:
10209 //
10210 // gmcs Libguestfs.cs
10211 // mono Libguestfs.exe
10212 //
10213 // (You'll probably want to add a Test class / static main function
10214 // otherwise this won't do anything useful).
10215
10216 using System;
10217 using System.IO;
10218 using System.Runtime.InteropServices;
10219 using System.Runtime.Serialization;
10220 using System.Collections;
10221
10222 namespace Guestfs
10223 {
10224   class Error : System.ApplicationException
10225   {
10226     public Error (string message) : base (message) {}
10227     protected Error (SerializationInfo info, StreamingContext context) {}
10228   }
10229
10230   class Guestfs
10231   {
10232     IntPtr _handle;
10233
10234     [DllImport (\"%s\")]
10235     static extern IntPtr guestfs_create ();
10236
10237     public Guestfs ()
10238     {
10239       _handle = guestfs_create ();
10240       if (_handle == IntPtr.Zero)
10241         throw new Error (\"could not create guestfs handle\");
10242     }
10243
10244     [DllImport (\"%s\")]
10245     static extern void guestfs_close (IntPtr h);
10246
10247     ~Guestfs ()
10248     {
10249       guestfs_close (_handle);
10250     }
10251
10252     [DllImport (\"%s\")]
10253     static extern string guestfs_last_error (IntPtr h);
10254
10255 " library library library;
10256
10257   (* Generate C# structure bindings.  We prefix struct names with
10258    * underscore because C# cannot have conflicting struct names and
10259    * method names (eg. "class stat" and "stat").
10260    *)
10261   List.iter (
10262     fun (typ, cols) ->
10263       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10264       pr "    public class _%s {\n" typ;
10265       List.iter (
10266         function
10267         | name, FChar -> pr "      char %s;\n" name
10268         | name, FString -> pr "      string %s;\n" name
10269         | name, FBuffer ->
10270             pr "      uint %s_len;\n" name;
10271             pr "      string %s;\n" name
10272         | name, FUUID ->
10273             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10274             pr "      string %s;\n" name
10275         | name, FUInt32 -> pr "      uint %s;\n" name
10276         | name, FInt32 -> pr "      int %s;\n" name
10277         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10278         | name, FInt64 -> pr "      long %s;\n" name
10279         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10280       ) cols;
10281       pr "    }\n";
10282       pr "\n"
10283   ) structs;
10284
10285   (* Generate C# function bindings. *)
10286   List.iter (
10287     fun (name, style, _, _, _, shortdesc, _) ->
10288       let rec csharp_return_type () =
10289         match fst style with
10290         | RErr -> "void"
10291         | RBool n -> "bool"
10292         | RInt n -> "int"
10293         | RInt64 n -> "long"
10294         | RConstString n
10295         | RConstOptString n
10296         | RString n
10297         | RBufferOut n -> "string"
10298         | RStruct (_,n) -> "_" ^ n
10299         | RHashtable n -> "Hashtable"
10300         | RStringList n -> "string[]"
10301         | RStructList (_,n) -> sprintf "_%s[]" n
10302
10303       and c_return_type () =
10304         match fst style with
10305         | RErr
10306         | RBool _
10307         | RInt _ -> "int"
10308         | RInt64 _ -> "long"
10309         | RConstString _
10310         | RConstOptString _
10311         | RString _
10312         | RBufferOut _ -> "string"
10313         | RStruct (_,n) -> "_" ^ n
10314         | RHashtable _
10315         | RStringList _ -> "string[]"
10316         | RStructList (_,n) -> sprintf "_%s[]" n
10317
10318       and c_error_comparison () =
10319         match fst style with
10320         | RErr
10321         | RBool _
10322         | RInt _
10323         | RInt64 _ -> "== -1"
10324         | RConstString _
10325         | RConstOptString _
10326         | RString _
10327         | RBufferOut _
10328         | RStruct (_,_)
10329         | RHashtable _
10330         | RStringList _
10331         | RStructList (_,_) -> "== null"
10332
10333       and generate_extern_prototype () =
10334         pr "    static extern %s guestfs_%s (IntPtr h"
10335           (c_return_type ()) name;
10336         List.iter (
10337           function
10338           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10339           | FileIn n | FileOut n ->
10340               pr ", [In] string %s" n
10341           | StringList n | DeviceList n ->
10342               pr ", [In] string[] %s" n
10343           | Bool n ->
10344               pr ", bool %s" n
10345           | Int n ->
10346               pr ", int %s" n
10347           | Int64 n ->
10348               pr ", long %s" n
10349         ) (snd style);
10350         pr ");\n"
10351
10352       and generate_public_prototype () =
10353         pr "    public %s %s (" (csharp_return_type ()) name;
10354         let comma = ref false in
10355         let next () =
10356           if !comma then pr ", ";
10357           comma := true
10358         in
10359         List.iter (
10360           function
10361           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10362           | FileIn n | FileOut n ->
10363               next (); pr "string %s" n
10364           | StringList n | DeviceList n ->
10365               next (); pr "string[] %s" n
10366           | Bool n ->
10367               next (); pr "bool %s" n
10368           | Int n ->
10369               next (); pr "int %s" n
10370           | Int64 n ->
10371               next (); pr "long %s" n
10372         ) (snd style);
10373         pr ")\n"
10374
10375       and generate_call () =
10376         pr "guestfs_%s (_handle" name;
10377         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10378         pr ");\n";
10379       in
10380
10381       pr "    [DllImport (\"%s\")]\n" library;
10382       generate_extern_prototype ();
10383       pr "\n";
10384       pr "    /// <summary>\n";
10385       pr "    /// %s\n" shortdesc;
10386       pr "    /// </summary>\n";
10387       generate_public_prototype ();
10388       pr "    {\n";
10389       pr "      %s r;\n" (c_return_type ());
10390       pr "      r = ";
10391       generate_call ();
10392       pr "      if (r %s)\n" (c_error_comparison ());
10393       pr "        throw new Error (guestfs_last_error (_handle));\n";
10394       (match fst style with
10395        | RErr -> ()
10396        | RBool _ ->
10397            pr "      return r != 0 ? true : false;\n"
10398        | RHashtable _ ->
10399            pr "      Hashtable rr = new Hashtable ();\n";
10400            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10401            pr "        rr.Add (r[i], r[i+1]);\n";
10402            pr "      return rr;\n"
10403        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10404        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10405        | RStructList _ ->
10406            pr "      return r;\n"
10407       );
10408       pr "    }\n";
10409       pr "\n";
10410   ) all_functions_sorted;
10411
10412   pr "  }
10413 }
10414 "
10415
10416 and generate_bindtests () =
10417   generate_header CStyle LGPLv2plus;
10418
10419   pr "\
10420 #include <stdio.h>
10421 #include <stdlib.h>
10422 #include <inttypes.h>
10423 #include <string.h>
10424
10425 #include \"guestfs.h\"
10426 #include \"guestfs-internal.h\"
10427 #include \"guestfs-internal-actions.h\"
10428 #include \"guestfs_protocol.h\"
10429
10430 #define error guestfs_error
10431 #define safe_calloc guestfs_safe_calloc
10432 #define safe_malloc guestfs_safe_malloc
10433
10434 static void
10435 print_strings (char *const *argv)
10436 {
10437   int argc;
10438
10439   printf (\"[\");
10440   for (argc = 0; argv[argc] != NULL; ++argc) {
10441     if (argc > 0) printf (\", \");
10442     printf (\"\\\"%%s\\\"\", argv[argc]);
10443   }
10444   printf (\"]\\n\");
10445 }
10446
10447 /* The test0 function prints its parameters to stdout. */
10448 ";
10449
10450   let test0, tests =
10451     match test_functions with
10452     | [] -> assert false
10453     | test0 :: tests -> test0, tests in
10454
10455   let () =
10456     let (name, style, _, _, _, _, _) = test0 in
10457     generate_prototype ~extern:false ~semicolon:false ~newline:true
10458       ~handle:"g" ~prefix:"guestfs__" name style;
10459     pr "{\n";
10460     List.iter (
10461       function
10462       | Pathname n
10463       | Device n | Dev_or_Path n
10464       | String n
10465       | FileIn n
10466       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10467       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10468       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10469       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10470       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10471       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10472     ) (snd style);
10473     pr "  /* Java changes stdout line buffering so we need this: */\n";
10474     pr "  fflush (stdout);\n";
10475     pr "  return 0;\n";
10476     pr "}\n";
10477     pr "\n" in
10478
10479   List.iter (
10480     fun (name, style, _, _, _, _, _) ->
10481       if String.sub name (String.length name - 3) 3 <> "err" then (
10482         pr "/* Test normal return. */\n";
10483         generate_prototype ~extern:false ~semicolon:false ~newline:true
10484           ~handle:"g" ~prefix:"guestfs__" name style;
10485         pr "{\n";
10486         (match fst style with
10487          | RErr ->
10488              pr "  return 0;\n"
10489          | RInt _ ->
10490              pr "  int r;\n";
10491              pr "  sscanf (val, \"%%d\", &r);\n";
10492              pr "  return r;\n"
10493          | RInt64 _ ->
10494              pr "  int64_t r;\n";
10495              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10496              pr "  return r;\n"
10497          | RBool _ ->
10498              pr "  return STREQ (val, \"true\");\n"
10499          | RConstString _
10500          | RConstOptString _ ->
10501              (* Can't return the input string here.  Return a static
10502               * string so we ensure we get a segfault if the caller
10503               * tries to free it.
10504               *)
10505              pr "  return \"static string\";\n"
10506          | RString _ ->
10507              pr "  return strdup (val);\n"
10508          | RStringList _ ->
10509              pr "  char **strs;\n";
10510              pr "  int n, i;\n";
10511              pr "  sscanf (val, \"%%d\", &n);\n";
10512              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10513              pr "  for (i = 0; i < n; ++i) {\n";
10514              pr "    strs[i] = safe_malloc (g, 16);\n";
10515              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10516              pr "  }\n";
10517              pr "  strs[n] = NULL;\n";
10518              pr "  return strs;\n"
10519          | RStruct (_, typ) ->
10520              pr "  struct guestfs_%s *r;\n" typ;
10521              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10522              pr "  return r;\n"
10523          | RStructList (_, typ) ->
10524              pr "  struct guestfs_%s_list *r;\n" typ;
10525              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10526              pr "  sscanf (val, \"%%d\", &r->len);\n";
10527              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10528              pr "  return r;\n"
10529          | RHashtable _ ->
10530              pr "  char **strs;\n";
10531              pr "  int n, i;\n";
10532              pr "  sscanf (val, \"%%d\", &n);\n";
10533              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10534              pr "  for (i = 0; i < n; ++i) {\n";
10535              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10536              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10537              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10538              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10539              pr "  }\n";
10540              pr "  strs[n*2] = NULL;\n";
10541              pr "  return strs;\n"
10542          | RBufferOut _ ->
10543              pr "  return strdup (val);\n"
10544         );
10545         pr "}\n";
10546         pr "\n"
10547       ) else (
10548         pr "/* Test error return. */\n";
10549         generate_prototype ~extern:false ~semicolon:false ~newline:true
10550           ~handle:"g" ~prefix:"guestfs__" name style;
10551         pr "{\n";
10552         pr "  error (g, \"error\");\n";
10553         (match fst style with
10554          | RErr | RInt _ | RInt64 _ | RBool _ ->
10555              pr "  return -1;\n"
10556          | RConstString _ | RConstOptString _
10557          | RString _ | RStringList _ | RStruct _
10558          | RStructList _
10559          | RHashtable _
10560          | RBufferOut _ ->
10561              pr "  return NULL;\n"
10562         );
10563         pr "}\n";
10564         pr "\n"
10565       )
10566   ) tests
10567
10568 and generate_ocaml_bindtests () =
10569   generate_header OCamlStyle GPLv2plus;
10570
10571   pr "\
10572 let () =
10573   let g = Guestfs.create () in
10574 ";
10575
10576   let mkargs args =
10577     String.concat " " (
10578       List.map (
10579         function
10580         | CallString s -> "\"" ^ s ^ "\""
10581         | CallOptString None -> "None"
10582         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10583         | CallStringList xs ->
10584             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10585         | CallInt i when i >= 0 -> string_of_int i
10586         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10587         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10588         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10589         | CallBool b -> string_of_bool b
10590       ) args
10591     )
10592   in
10593
10594   generate_lang_bindtests (
10595     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10596   );
10597
10598   pr "print_endline \"EOF\"\n"
10599
10600 and generate_perl_bindtests () =
10601   pr "#!/usr/bin/perl -w\n";
10602   generate_header HashStyle GPLv2plus;
10603
10604   pr "\
10605 use strict;
10606
10607 use Sys::Guestfs;
10608
10609 my $g = Sys::Guestfs->new ();
10610 ";
10611
10612   let mkargs args =
10613     String.concat ", " (
10614       List.map (
10615         function
10616         | CallString s -> "\"" ^ s ^ "\""
10617         | CallOptString None -> "undef"
10618         | CallOptString (Some s) -> sprintf "\"%s\"" s
10619         | CallStringList xs ->
10620             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10621         | CallInt i -> string_of_int i
10622         | CallInt64 i -> Int64.to_string i
10623         | CallBool b -> if b then "1" else "0"
10624       ) args
10625     )
10626   in
10627
10628   generate_lang_bindtests (
10629     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10630   );
10631
10632   pr "print \"EOF\\n\"\n"
10633
10634 and generate_python_bindtests () =
10635   generate_header HashStyle GPLv2plus;
10636
10637   pr "\
10638 import guestfs
10639
10640 g = guestfs.GuestFS ()
10641 ";
10642
10643   let mkargs args =
10644     String.concat ", " (
10645       List.map (
10646         function
10647         | CallString s -> "\"" ^ s ^ "\""
10648         | CallOptString None -> "None"
10649         | CallOptString (Some s) -> sprintf "\"%s\"" s
10650         | CallStringList xs ->
10651             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10652         | CallInt i -> string_of_int i
10653         | CallInt64 i -> Int64.to_string i
10654         | CallBool b -> if b then "1" else "0"
10655       ) args
10656     )
10657   in
10658
10659   generate_lang_bindtests (
10660     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10661   );
10662
10663   pr "print \"EOF\"\n"
10664
10665 and generate_ruby_bindtests () =
10666   generate_header HashStyle GPLv2plus;
10667
10668   pr "\
10669 require 'guestfs'
10670
10671 g = Guestfs::create()
10672 ";
10673
10674   let mkargs args =
10675     String.concat ", " (
10676       List.map (
10677         function
10678         | CallString s -> "\"" ^ s ^ "\""
10679         | CallOptString None -> "nil"
10680         | CallOptString (Some s) -> sprintf "\"%s\"" s
10681         | CallStringList xs ->
10682             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10683         | CallInt i -> string_of_int i
10684         | CallInt64 i -> Int64.to_string i
10685         | CallBool b -> string_of_bool b
10686       ) args
10687     )
10688   in
10689
10690   generate_lang_bindtests (
10691     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10692   );
10693
10694   pr "print \"EOF\\n\"\n"
10695
10696 and generate_java_bindtests () =
10697   generate_header CStyle GPLv2plus;
10698
10699   pr "\
10700 import com.redhat.et.libguestfs.*;
10701
10702 public class Bindtests {
10703     public static void main (String[] argv)
10704     {
10705         try {
10706             GuestFS g = new GuestFS ();
10707 ";
10708
10709   let mkargs args =
10710     String.concat ", " (
10711       List.map (
10712         function
10713         | CallString s -> "\"" ^ s ^ "\""
10714         | CallOptString None -> "null"
10715         | CallOptString (Some s) -> sprintf "\"%s\"" s
10716         | CallStringList xs ->
10717             "new String[]{" ^
10718               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10719         | CallInt i -> string_of_int i
10720         | CallInt64 i -> Int64.to_string i
10721         | CallBool b -> string_of_bool b
10722       ) args
10723     )
10724   in
10725
10726   generate_lang_bindtests (
10727     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10728   );
10729
10730   pr "
10731             System.out.println (\"EOF\");
10732         }
10733         catch (Exception exn) {
10734             System.err.println (exn);
10735             System.exit (1);
10736         }
10737     }
10738 }
10739 "
10740
10741 and generate_haskell_bindtests () =
10742   generate_header HaskellStyle GPLv2plus;
10743
10744   pr "\
10745 module Bindtests where
10746 import qualified Guestfs
10747
10748 main = do
10749   g <- Guestfs.create
10750 ";
10751
10752   let mkargs args =
10753     String.concat " " (
10754       List.map (
10755         function
10756         | CallString s -> "\"" ^ s ^ "\""
10757         | CallOptString None -> "Nothing"
10758         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10759         | CallStringList xs ->
10760             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10761         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10762         | CallInt i -> string_of_int i
10763         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10764         | CallInt64 i -> Int64.to_string i
10765         | CallBool true -> "True"
10766         | CallBool false -> "False"
10767       ) args
10768     )
10769   in
10770
10771   generate_lang_bindtests (
10772     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10773   );
10774
10775   pr "  putStrLn \"EOF\"\n"
10776
10777 (* Language-independent bindings tests - we do it this way to
10778  * ensure there is parity in testing bindings across all languages.
10779  *)
10780 and generate_lang_bindtests call =
10781   call "test0" [CallString "abc"; CallOptString (Some "def");
10782                 CallStringList []; CallBool false;
10783                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10784   call "test0" [CallString "abc"; CallOptString None;
10785                 CallStringList []; CallBool false;
10786                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10787   call "test0" [CallString ""; CallOptString (Some "def");
10788                 CallStringList []; CallBool false;
10789                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10790   call "test0" [CallString ""; CallOptString (Some "");
10791                 CallStringList []; CallBool false;
10792                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10793   call "test0" [CallString "abc"; CallOptString (Some "def");
10794                 CallStringList ["1"]; CallBool false;
10795                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10796   call "test0" [CallString "abc"; CallOptString (Some "def");
10797                 CallStringList ["1"; "2"]; CallBool false;
10798                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10799   call "test0" [CallString "abc"; CallOptString (Some "def");
10800                 CallStringList ["1"]; CallBool true;
10801                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10802   call "test0" [CallString "abc"; CallOptString (Some "def");
10803                 CallStringList ["1"]; CallBool false;
10804                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10805   call "test0" [CallString "abc"; CallOptString (Some "def");
10806                 CallStringList ["1"]; CallBool false;
10807                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10808   call "test0" [CallString "abc"; CallOptString (Some "def");
10809                 CallStringList ["1"]; CallBool false;
10810                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10811   call "test0" [CallString "abc"; CallOptString (Some "def");
10812                 CallStringList ["1"]; CallBool false;
10813                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10814   call "test0" [CallString "abc"; CallOptString (Some "def");
10815                 CallStringList ["1"]; CallBool false;
10816                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10817   call "test0" [CallString "abc"; CallOptString (Some "def");
10818                 CallStringList ["1"]; CallBool false;
10819                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10820
10821 (* XXX Add here tests of the return and error functions. *)
10822
10823 (* Code to generator bindings for virt-inspector.  Currently only
10824  * implemented for OCaml code (for virt-p2v 2.0).
10825  *)
10826 let rng_input = "inspector/virt-inspector.rng"
10827
10828 (* Read the input file and parse it into internal structures.  This is
10829  * by no means a complete RELAX NG parser, but is just enough to be
10830  * able to parse the specific input file.
10831  *)
10832 type rng =
10833   | Element of string * rng list        (* <element name=name/> *)
10834   | Attribute of string * rng list        (* <attribute name=name/> *)
10835   | Interleave of rng list                (* <interleave/> *)
10836   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10837   | OneOrMore of rng                        (* <oneOrMore/> *)
10838   | Optional of rng                        (* <optional/> *)
10839   | Choice of string list                (* <choice><value/>*</choice> *)
10840   | Value of string                        (* <value>str</value> *)
10841   | Text                                (* <text/> *)
10842
10843 let rec string_of_rng = function
10844   | Element (name, xs) ->
10845       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10846   | Attribute (name, xs) ->
10847       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10848   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10849   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10850   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10851   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10852   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10853   | Value value -> "Value \"" ^ value ^ "\""
10854   | Text -> "Text"
10855
10856 and string_of_rng_list xs =
10857   String.concat ", " (List.map string_of_rng xs)
10858
10859 let rec parse_rng ?defines context = function
10860   | [] -> []
10861   | Xml.Element ("element", ["name", name], children) :: rest ->
10862       Element (name, parse_rng ?defines context children)
10863       :: parse_rng ?defines context rest
10864   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10865       Attribute (name, parse_rng ?defines context children)
10866       :: parse_rng ?defines context rest
10867   | Xml.Element ("interleave", [], children) :: rest ->
10868       Interleave (parse_rng ?defines context children)
10869       :: parse_rng ?defines context rest
10870   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10871       let rng = parse_rng ?defines context [child] in
10872       (match rng with
10873        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10874        | _ ->
10875            failwithf "%s: <zeroOrMore> contains more than one child element"
10876              context
10877       )
10878   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10879       let rng = parse_rng ?defines context [child] in
10880       (match rng with
10881        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10882        | _ ->
10883            failwithf "%s: <oneOrMore> contains more than one child element"
10884              context
10885       )
10886   | Xml.Element ("optional", [], [child]) :: rest ->
10887       let rng = parse_rng ?defines context [child] in
10888       (match rng with
10889        | [child] -> Optional child :: parse_rng ?defines context rest
10890        | _ ->
10891            failwithf "%s: <optional> contains more than one child element"
10892              context
10893       )
10894   | Xml.Element ("choice", [], children) :: rest ->
10895       let values = List.map (
10896         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10897         | _ ->
10898             failwithf "%s: can't handle anything except <value> in <choice>"
10899               context
10900       ) children in
10901       Choice values
10902       :: parse_rng ?defines context rest
10903   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10904       Value value :: parse_rng ?defines context rest
10905   | Xml.Element ("text", [], []) :: rest ->
10906       Text :: parse_rng ?defines context rest
10907   | Xml.Element ("ref", ["name", name], []) :: rest ->
10908       (* Look up the reference.  Because of limitations in this parser,
10909        * we can't handle arbitrarily nested <ref> yet.  You can only
10910        * use <ref> from inside <start>.
10911        *)
10912       (match defines with
10913        | None ->
10914            failwithf "%s: contains <ref>, but no refs are defined yet" context
10915        | Some map ->
10916            let rng = StringMap.find name map in
10917            rng @ parse_rng ?defines context rest
10918       )
10919   | x :: _ ->
10920       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10921
10922 let grammar =
10923   let xml = Xml.parse_file rng_input in
10924   match xml with
10925   | Xml.Element ("grammar", _,
10926                  Xml.Element ("start", _, gram) :: defines) ->
10927       (* The <define/> elements are referenced in the <start> section,
10928        * so build a map of those first.
10929        *)
10930       let defines = List.fold_left (
10931         fun map ->
10932           function Xml.Element ("define", ["name", name], defn) ->
10933             StringMap.add name defn map
10934           | _ ->
10935               failwithf "%s: expected <define name=name/>" rng_input
10936       ) StringMap.empty defines in
10937       let defines = StringMap.mapi parse_rng defines in
10938
10939       (* Parse the <start> clause, passing the defines. *)
10940       parse_rng ~defines "<start>" gram
10941   | _ ->
10942       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10943         rng_input
10944
10945 let name_of_field = function
10946   | Element (name, _) | Attribute (name, _)
10947   | ZeroOrMore (Element (name, _))
10948   | OneOrMore (Element (name, _))
10949   | Optional (Element (name, _)) -> name
10950   | Optional (Attribute (name, _)) -> name
10951   | Text -> (* an unnamed field in an element *)
10952       "data"
10953   | rng ->
10954       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10955
10956 (* At the moment this function only generates OCaml types.  However we
10957  * should parameterize it later so it can generate types/structs in a
10958  * variety of languages.
10959  *)
10960 let generate_types xs =
10961   (* A simple type is one that can be printed out directly, eg.
10962    * "string option".  A complex type is one which has a name and has
10963    * to be defined via another toplevel definition, eg. a struct.
10964    *
10965    * generate_type generates code for either simple or complex types.
10966    * In the simple case, it returns the string ("string option").  In
10967    * the complex case, it returns the name ("mountpoint").  In the
10968    * complex case it has to print out the definition before returning,
10969    * so it should only be called when we are at the beginning of a
10970    * new line (BOL context).
10971    *)
10972   let rec generate_type = function
10973     | Text ->                                (* string *)
10974         "string", true
10975     | Choice values ->                        (* [`val1|`val2|...] *)
10976         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10977     | ZeroOrMore rng ->                        (* <rng> list *)
10978         let t, is_simple = generate_type rng in
10979         t ^ " list (* 0 or more *)", is_simple
10980     | OneOrMore rng ->                        (* <rng> list *)
10981         let t, is_simple = generate_type rng in
10982         t ^ " list (* 1 or more *)", is_simple
10983                                         (* virt-inspector hack: bool *)
10984     | Optional (Attribute (name, [Value "1"])) ->
10985         "bool", true
10986     | Optional rng ->                        (* <rng> list *)
10987         let t, is_simple = generate_type rng in
10988         t ^ " option", is_simple
10989                                         (* type name = { fields ... } *)
10990     | Element (name, fields) when is_attrs_interleave fields ->
10991         generate_type_struct name (get_attrs_interleave fields)
10992     | Element (name, [field])                (* type name = field *)
10993     | Attribute (name, [field]) ->
10994         let t, is_simple = generate_type field in
10995         if is_simple then (t, true)
10996         else (
10997           pr "type %s = %s\n" name t;
10998           name, false
10999         )
11000     | Element (name, fields) ->              (* type name = { fields ... } *)
11001         generate_type_struct name fields
11002     | rng ->
11003         failwithf "generate_type failed at: %s" (string_of_rng rng)
11004
11005   and is_attrs_interleave = function
11006     | [Interleave _] -> true
11007     | Attribute _ :: fields -> is_attrs_interleave fields
11008     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11009     | _ -> false
11010
11011   and get_attrs_interleave = function
11012     | [Interleave fields] -> fields
11013     | ((Attribute _) as field) :: fields
11014     | ((Optional (Attribute _)) as field) :: fields ->
11015         field :: get_attrs_interleave fields
11016     | _ -> assert false
11017
11018   and generate_types xs =
11019     List.iter (fun x -> ignore (generate_type x)) xs
11020
11021   and generate_type_struct name fields =
11022     (* Calculate the types of the fields first.  We have to do this
11023      * before printing anything so we are still in BOL context.
11024      *)
11025     let types = List.map fst (List.map generate_type fields) in
11026
11027     (* Special case of a struct containing just a string and another
11028      * field.  Turn it into an assoc list.
11029      *)
11030     match types with
11031     | ["string"; other] ->
11032         let fname1, fname2 =
11033           match fields with
11034           | [f1; f2] -> name_of_field f1, name_of_field f2
11035           | _ -> assert false in
11036         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11037         name, false
11038
11039     | types ->
11040         pr "type %s = {\n" name;
11041         List.iter (
11042           fun (field, ftype) ->
11043             let fname = name_of_field field in
11044             pr "  %s_%s : %s;\n" name fname ftype
11045         ) (List.combine fields types);
11046         pr "}\n";
11047         (* Return the name of this type, and
11048          * false because it's not a simple type.
11049          *)
11050         name, false
11051   in
11052
11053   generate_types xs
11054
11055 let generate_parsers xs =
11056   (* As for generate_type above, generate_parser makes a parser for
11057    * some type, and returns the name of the parser it has generated.
11058    * Because it (may) need to print something, it should always be
11059    * called in BOL context.
11060    *)
11061   let rec generate_parser = function
11062     | Text ->                                (* string *)
11063         "string_child_or_empty"
11064     | Choice values ->                        (* [`val1|`val2|...] *)
11065         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11066           (String.concat "|"
11067              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11068     | ZeroOrMore rng ->                        (* <rng> list *)
11069         let pa = generate_parser rng in
11070         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11071     | OneOrMore rng ->                        (* <rng> list *)
11072         let pa = generate_parser rng in
11073         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11074                                         (* virt-inspector hack: bool *)
11075     | Optional (Attribute (name, [Value "1"])) ->
11076         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11077     | Optional rng ->                        (* <rng> list *)
11078         let pa = generate_parser rng in
11079         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11080                                         (* type name = { fields ... } *)
11081     | Element (name, fields) when is_attrs_interleave fields ->
11082         generate_parser_struct name (get_attrs_interleave fields)
11083     | Element (name, [field]) ->        (* type name = field *)
11084         let pa = generate_parser field in
11085         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11086         pr "let %s =\n" parser_name;
11087         pr "  %s\n" pa;
11088         pr "let parse_%s = %s\n" name parser_name;
11089         parser_name
11090     | Attribute (name, [field]) ->
11091         let pa = generate_parser field in
11092         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11093         pr "let %s =\n" parser_name;
11094         pr "  %s\n" pa;
11095         pr "let parse_%s = %s\n" name parser_name;
11096         parser_name
11097     | Element (name, fields) ->              (* type name = { fields ... } *)
11098         generate_parser_struct name ([], fields)
11099     | rng ->
11100         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11101
11102   and is_attrs_interleave = function
11103     | [Interleave _] -> true
11104     | Attribute _ :: fields -> is_attrs_interleave fields
11105     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11106     | _ -> false
11107
11108   and get_attrs_interleave = function
11109     | [Interleave fields] -> [], fields
11110     | ((Attribute _) as field) :: fields
11111     | ((Optional (Attribute _)) as field) :: fields ->
11112         let attrs, interleaves = get_attrs_interleave fields in
11113         (field :: attrs), interleaves
11114     | _ -> assert false
11115
11116   and generate_parsers xs =
11117     List.iter (fun x -> ignore (generate_parser x)) xs
11118
11119   and generate_parser_struct name (attrs, interleaves) =
11120     (* Generate parsers for the fields first.  We have to do this
11121      * before printing anything so we are still in BOL context.
11122      *)
11123     let fields = attrs @ interleaves in
11124     let pas = List.map generate_parser fields in
11125
11126     (* Generate an intermediate tuple from all the fields first.
11127      * If the type is just a string + another field, then we will
11128      * return this directly, otherwise it is turned into a record.
11129      *
11130      * RELAX NG note: This code treats <interleave> and plain lists of
11131      * fields the same.  In other words, it doesn't bother enforcing
11132      * any ordering of fields in the XML.
11133      *)
11134     pr "let parse_%s x =\n" name;
11135     pr "  let t = (\n    ";
11136     let comma = ref false in
11137     List.iter (
11138       fun x ->
11139         if !comma then pr ",\n    ";
11140         comma := true;
11141         match x with
11142         | Optional (Attribute (fname, [field])), pa ->
11143             pr "%s x" pa
11144         | Optional (Element (fname, [field])), pa ->
11145             pr "%s (optional_child %S x)" pa fname
11146         | Attribute (fname, [Text]), _ ->
11147             pr "attribute %S x" fname
11148         | (ZeroOrMore _ | OneOrMore _), pa ->
11149             pr "%s x" pa
11150         | Text, pa ->
11151             pr "%s x" pa
11152         | (field, pa) ->
11153             let fname = name_of_field field in
11154             pr "%s (child %S x)" pa fname
11155     ) (List.combine fields pas);
11156     pr "\n  ) in\n";
11157
11158     (match fields with
11159      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11160          pr "  t\n"
11161
11162      | _ ->
11163          pr "  (Obj.magic t : %s)\n" name
11164 (*
11165          List.iter (
11166            function
11167            | (Optional (Attribute (fname, [field])), pa) ->
11168                pr "  %s_%s =\n" name fname;
11169                pr "    %s x;\n" pa
11170            | (Optional (Element (fname, [field])), pa) ->
11171                pr "  %s_%s =\n" name fname;
11172                pr "    (let x = optional_child %S x in\n" fname;
11173                pr "     %s x);\n" pa
11174            | (field, pa) ->
11175                let fname = name_of_field field in
11176                pr "  %s_%s =\n" name fname;
11177                pr "    (let x = child %S x in\n" fname;
11178                pr "     %s x);\n" pa
11179          ) (List.combine fields pas);
11180          pr "}\n"
11181 *)
11182     );
11183     sprintf "parse_%s" name
11184   in
11185
11186   generate_parsers xs
11187
11188 (* Generate ocaml/guestfs_inspector.mli. *)
11189 let generate_ocaml_inspector_mli () =
11190   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11191
11192   pr "\
11193 (** This is an OCaml language binding to the external [virt-inspector]
11194     program.
11195
11196     For more information, please read the man page [virt-inspector(1)].
11197 *)
11198
11199 ";
11200
11201   generate_types grammar;
11202   pr "(** The nested information returned from the {!inspect} function. *)\n";
11203   pr "\n";
11204
11205   pr "\
11206 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11207 (** To inspect a libvirt domain called [name], pass a singleton
11208     list: [inspect [name]].  When using libvirt only, you may
11209     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11210
11211     To inspect a disk image or images, pass a list of the filenames
11212     of the disk images: [inspect filenames]
11213
11214     This function inspects the given guest or disk images and
11215     returns a list of operating system(s) found and a large amount
11216     of information about them.  In the vast majority of cases,
11217     a virtual machine only contains a single operating system.
11218
11219     If the optional [~xml] parameter is given, then this function
11220     skips running the external virt-inspector program and just
11221     parses the given XML directly (which is expected to be XML
11222     produced from a previous run of virt-inspector).  The list of
11223     names and connect URI are ignored in this case.
11224
11225     This function can throw a wide variety of exceptions, for example
11226     if the external virt-inspector program cannot be found, or if
11227     it doesn't generate valid XML.
11228 *)
11229 "
11230
11231 (* Generate ocaml/guestfs_inspector.ml. *)
11232 let generate_ocaml_inspector_ml () =
11233   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11234
11235   pr "open Unix\n";
11236   pr "\n";
11237
11238   generate_types grammar;
11239   pr "\n";
11240
11241   pr "\
11242 (* Misc functions which are used by the parser code below. *)
11243 let first_child = function
11244   | Xml.Element (_, _, c::_) -> c
11245   | Xml.Element (name, _, []) ->
11246       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11247   | Xml.PCData str ->
11248       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11249
11250 let string_child_or_empty = function
11251   | Xml.Element (_, _, [Xml.PCData s]) -> s
11252   | Xml.Element (_, _, []) -> \"\"
11253   | Xml.Element (x, _, _) ->
11254       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11255                 x ^ \" instead\")
11256   | Xml.PCData str ->
11257       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11258
11259 let optional_child name xml =
11260   let children = Xml.children xml in
11261   try
11262     Some (List.find (function
11263                      | Xml.Element (n, _, _) when n = name -> true
11264                      | _ -> false) children)
11265   with
11266     Not_found -> None
11267
11268 let child name xml =
11269   match optional_child name xml with
11270   | Some c -> c
11271   | None ->
11272       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11273
11274 let attribute name xml =
11275   try Xml.attrib xml name
11276   with Xml.No_attribute _ ->
11277     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11278
11279 ";
11280
11281   generate_parsers grammar;
11282   pr "\n";
11283
11284   pr "\
11285 (* Run external virt-inspector, then use parser to parse the XML. *)
11286 let inspect ?connect ?xml names =
11287   let xml =
11288     match xml with
11289     | None ->
11290         if names = [] then invalid_arg \"inspect: no names given\";
11291         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11292           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11293           names in
11294         let cmd = List.map Filename.quote cmd in
11295         let cmd = String.concat \" \" cmd in
11296         let chan = open_process_in cmd in
11297         let xml = Xml.parse_in chan in
11298         (match close_process_in chan with
11299          | WEXITED 0 -> ()
11300          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11301          | WSIGNALED i | WSTOPPED i ->
11302              failwith (\"external virt-inspector command died or stopped on sig \" ^
11303                        string_of_int i)
11304         );
11305         xml
11306     | Some doc ->
11307         Xml.parse_string doc in
11308   parse_operatingsystems xml
11309 "
11310
11311 (* This is used to generate the src/MAX_PROC_NR file which
11312  * contains the maximum procedure number, a surrogate for the
11313  * ABI version number.  See src/Makefile.am for the details.
11314  *)
11315 and generate_max_proc_nr () =
11316   let proc_nrs = List.map (
11317     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11318   ) daemon_functions in
11319
11320   let max_proc_nr = List.fold_left max 0 proc_nrs in
11321
11322   pr "%d\n" max_proc_nr
11323
11324 let output_to filename k =
11325   let filename_new = filename ^ ".new" in
11326   chan := open_out filename_new;
11327   k ();
11328   close_out !chan;
11329   chan := Pervasives.stdout;
11330
11331   (* Is the new file different from the current file? *)
11332   if Sys.file_exists filename && files_equal filename filename_new then
11333     unlink filename_new                 (* same, so skip it *)
11334   else (
11335     (* different, overwrite old one *)
11336     (try chmod filename 0o644 with Unix_error _ -> ());
11337     rename filename_new filename;
11338     chmod filename 0o444;
11339     printf "written %s\n%!" filename;
11340   )
11341
11342 let perror msg = function
11343   | Unix_error (err, _, _) ->
11344       eprintf "%s: %s\n" msg (error_message err)
11345   | exn ->
11346       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11347
11348 (* Main program. *)
11349 let () =
11350   let lock_fd =
11351     try openfile "HACKING" [O_RDWR] 0
11352     with
11353     | Unix_error (ENOENT, _, _) ->
11354         eprintf "\
11355 You are probably running this from the wrong directory.
11356 Run it from the top source directory using the command
11357   src/generator.ml
11358 ";
11359         exit 1
11360     | exn ->
11361         perror "open: HACKING" exn;
11362         exit 1 in
11363
11364   (* Acquire a lock so parallel builds won't try to run the generator
11365    * twice at the same time.  Subsequent builds will wait for the first
11366    * one to finish.  Note the lock is released implicitly when the
11367    * program exits.
11368    *)
11369   (try lockf lock_fd F_LOCK 1
11370    with exn ->
11371      perror "lock: HACKING" exn;
11372      exit 1);
11373
11374   check_functions ();
11375
11376   output_to "src/guestfs_protocol.x" generate_xdr;
11377   output_to "src/guestfs-structs.h" generate_structs_h;
11378   output_to "src/guestfs-actions.h" generate_actions_h;
11379   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11380   output_to "src/guestfs-actions.c" generate_client_actions;
11381   output_to "src/guestfs-bindtests.c" generate_bindtests;
11382   output_to "src/guestfs-structs.pod" generate_structs_pod;
11383   output_to "src/guestfs-actions.pod" generate_actions_pod;
11384   output_to "src/guestfs-availability.pod" generate_availability_pod;
11385   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11386   output_to "src/libguestfs.syms" generate_linker_script;
11387   output_to "daemon/actions.h" generate_daemon_actions_h;
11388   output_to "daemon/stubs.c" generate_daemon_actions;
11389   output_to "daemon/names.c" generate_daemon_names;
11390   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11391   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11392   output_to "capitests/tests.c" generate_tests;
11393   output_to "fish/cmds.c" generate_fish_cmds;
11394   output_to "fish/completion.c" generate_fish_completion;
11395   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11396   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11397   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11398   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11399   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11400   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11401   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11402   output_to "perl/Guestfs.xs" generate_perl_xs;
11403   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11404   output_to "perl/bindtests.pl" generate_perl_bindtests;
11405   output_to "python/guestfs-py.c" generate_python_c;
11406   output_to "python/guestfs.py" generate_python_py;
11407   output_to "python/bindtests.py" generate_python_bindtests;
11408   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11409   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11410   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11411
11412   List.iter (
11413     fun (typ, jtyp) ->
11414       let cols = cols_of_struct typ in
11415       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11416       output_to filename (generate_java_struct jtyp cols);
11417   ) java_structs;
11418
11419   output_to "java/Makefile.inc" generate_java_makefile_inc;
11420   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11421   output_to "java/Bindtests.java" generate_java_bindtests;
11422   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11423   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11424   output_to "csharp/Libguestfs.cs" generate_csharp;
11425
11426   (* Always generate this file last, and unconditionally.  It's used
11427    * by the Makefile to know when we must re-run the generator.
11428    *)
11429   let chan = open_out "src/stamp-generator" in
11430   fprintf chan "1\n";
11431   close_out chan;
11432
11433   printf "generated %d lines of code\n" !lines