Fix typo in description of echo-daemon command.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use dynamic linker functions
795 to find out if this symbol exists (if it doesn't, then
796 it's an earlier version).
797
798 The call returns a structure with four elements.  The first
799 three (C<major>, C<minor> and C<release>) are numbers and
800 correspond to the usual version triplet.  The fourth element
801 (C<extra>) is a string and is normally empty, but may be
802 used for distro-specific information.
803
804 To construct the original version string:
805 C<$major.$minor.$release$extra>
806
807 I<Note:> Don't use this call to test for availability
808 of features.  Distro backports makes this unreliable.  Use
809 C<guestfs_available> instead.");
810
811   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
812    [InitNone, Always, TestOutputTrue (
813       [["set_selinux"; "true"];
814        ["get_selinux"]])],
815    "set SELinux enabled or disabled at appliance boot",
816    "\
817 This sets the selinux flag that is passed to the appliance
818 at boot time.  The default is C<selinux=0> (disabled).
819
820 Note that if SELinux is enabled, it is always in
821 Permissive mode (C<enforcing=0>).
822
823 For more information on the architecture of libguestfs,
824 see L<guestfs(3)>.");
825
826   ("get_selinux", (RBool "selinux", []), -1, [],
827    [],
828    "get SELinux enabled flag",
829    "\
830 This returns the current setting of the selinux flag which
831 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
832
833 For more information on the architecture of libguestfs,
834 see L<guestfs(3)>.");
835
836   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
837    [InitNone, Always, TestOutputFalse (
838       [["set_trace"; "false"];
839        ["get_trace"]])],
840    "enable or disable command traces",
841    "\
842 If the command trace flag is set to 1, then commands are
843 printed on stdout before they are executed in a format
844 which is very similar to the one used by guestfish.  In
845 other words, you can run a program with this enabled, and
846 you will get out a script which you can feed to guestfish
847 to perform the same set of actions.
848
849 If you want to trace C API calls into libguestfs (and
850 other libraries) then possibly a better way is to use
851 the external ltrace(1) command.
852
853 Command traces are disabled unless the environment variable
854 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
855
856   ("get_trace", (RBool "trace", []), -1, [],
857    [],
858    "get command trace enabled flag",
859    "\
860 Return the command trace flag.");
861
862   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
863    [InitNone, Always, TestOutputFalse (
864       [["set_direct"; "false"];
865        ["get_direct"]])],
866    "enable or disable direct appliance mode",
867    "\
868 If the direct appliance mode flag is enabled, then stdin and
869 stdout are passed directly through to the appliance once it
870 is launched.
871
872 One consequence of this is that log messages aren't caught
873 by the library and handled by C<guestfs_set_log_message_callback>,
874 but go straight to stdout.
875
876 You probably don't want to use this unless you know what you
877 are doing.
878
879 The default is disabled.");
880
881   ("get_direct", (RBool "direct", []), -1, [],
882    [],
883    "get direct appliance mode flag",
884    "\
885 Return the direct appliance mode flag.");
886
887   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
888    [InitNone, Always, TestOutputTrue (
889       [["set_recovery_proc"; "true"];
890        ["get_recovery_proc"]])],
891    "enable or disable the recovery process",
892    "\
893 If this is called with the parameter C<false> then
894 C<guestfs_launch> does not create a recovery process.  The
895 purpose of the recovery process is to stop runaway qemu
896 processes in the case where the main program aborts abruptly.
897
898 This only has any effect if called before C<guestfs_launch>,
899 and the default is true.
900
901 About the only time when you would want to disable this is
902 if the main process will fork itself into the background
903 (\"daemonize\" itself).  In this case the recovery process
904 thinks that the main program has disappeared and so kills
905 qemu, which is not very helpful.");
906
907   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
908    [],
909    "get recovery process enabled flag",
910    "\
911 Return the recovery process enabled flag.");
912
913   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
914    [],
915    "add a drive specifying the QEMU block emulation to use",
916    "\
917 This is the same as C<guestfs_add_drive> but it allows you
918 to specify the QEMU interface emulation to use at run time.");
919
920   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921    [],
922    "add a drive read-only specifying the QEMU block emulation to use",
923    "\
924 This is the same as C<guestfs_add_drive_ro> but it allows you
925 to specify the QEMU interface emulation to use at run time.");
926
927 ]
928
929 (* daemon_functions are any functions which cause some action
930  * to take place in the daemon.
931  *)
932
933 let daemon_functions = [
934   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
935    [InitEmpty, Always, TestOutput (
936       [["part_disk"; "/dev/sda"; "mbr"];
937        ["mkfs"; "ext2"; "/dev/sda1"];
938        ["mount"; "/dev/sda1"; "/"];
939        ["write_file"; "/new"; "new file contents"; "0"];
940        ["cat"; "/new"]], "new file contents")],
941    "mount a guest disk at a position in the filesystem",
942    "\
943 Mount a guest disk at a position in the filesystem.  Block devices
944 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
945 the guest.  If those block devices contain partitions, they will have
946 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
947 names can be used.
948
949 The rules are the same as for L<mount(2)>:  A filesystem must
950 first be mounted on C</> before others can be mounted.  Other
951 filesystems can only be mounted on directories which already
952 exist.
953
954 The mounted filesystem is writable, if we have sufficient permissions
955 on the underlying device.
956
957 B<Important note:>
958 When you use this call, the filesystem options C<sync> and C<noatime>
959 are set implicitly.  This was originally done because we thought it
960 would improve reliability, but it turns out that I<-o sync> has a
961 very large negative performance impact and negligible effect on
962 reliability.  Therefore we recommend that you avoid using
963 C<guestfs_mount> in any code that needs performance, and instead
964 use C<guestfs_mount_options> (use an empty string for the first
965 parameter if you don't want any options).");
966
967   ("sync", (RErr, []), 2, [],
968    [ InitEmpty, Always, TestRun [["sync"]]],
969    "sync disks, writes are flushed through to the disk image",
970    "\
971 This syncs the disk, so that any writes are flushed through to the
972 underlying disk image.
973
974 You should always call this if you have modified a disk image, before
975 closing the handle.");
976
977   ("touch", (RErr, [Pathname "path"]), 3, [],
978    [InitBasicFS, Always, TestOutputTrue (
979       [["touch"; "/new"];
980        ["exists"; "/new"]])],
981    "update file timestamps or create a new file",
982    "\
983 Touch acts like the L<touch(1)> command.  It can be used to
984 update the timestamps on a file, or, if the file does not exist,
985 to create a new zero-length file.");
986
987   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
988    [InitISOFS, Always, TestOutput (
989       [["cat"; "/known-2"]], "abcdef\n")],
990    "list the contents of a file",
991    "\
992 Return the contents of the file named C<path>.
993
994 Note that this function cannot correctly handle binary files
995 (specifically, files containing C<\\0> character which is treated
996 as end of string).  For those you need to use the C<guestfs_read_file>
997 or C<guestfs_download> functions which have a more complex interface.");
998
999   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1000    [], (* XXX Tricky to test because it depends on the exact format
1001         * of the 'ls -l' command, which changes between F10 and F11.
1002         *)
1003    "list the files in a directory (long format)",
1004    "\
1005 List the files in C<directory> (relative to the root directory,
1006 there is no cwd) in the format of 'ls -la'.
1007
1008 This command is mostly useful for interactive sessions.  It
1009 is I<not> intended that you try to parse the output string.");
1010
1011   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1012    [InitBasicFS, Always, TestOutputList (
1013       [["touch"; "/new"];
1014        ["touch"; "/newer"];
1015        ["touch"; "/newest"];
1016        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1017    "list the files in a directory",
1018    "\
1019 List the files in C<directory> (relative to the root directory,
1020 there is no cwd).  The '.' and '..' entries are not returned, but
1021 hidden files are shown.
1022
1023 This command is mostly useful for interactive sessions.  Programs
1024 should probably use C<guestfs_readdir> instead.");
1025
1026   ("list_devices", (RStringList "devices", []), 7, [],
1027    [InitEmpty, Always, TestOutputListOfDevices (
1028       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1029    "list the block devices",
1030    "\
1031 List all the block devices.
1032
1033 The full block device names are returned, eg. C</dev/sda>");
1034
1035   ("list_partitions", (RStringList "partitions", []), 8, [],
1036    [InitBasicFS, Always, TestOutputListOfDevices (
1037       [["list_partitions"]], ["/dev/sda1"]);
1038     InitEmpty, Always, TestOutputListOfDevices (
1039       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1040        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1041    "list the partitions",
1042    "\
1043 List all the partitions detected on all block devices.
1044
1045 The full partition device names are returned, eg. C</dev/sda1>
1046
1047 This does not return logical volumes.  For that you will need to
1048 call C<guestfs_lvs>.");
1049
1050   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1051    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1052       [["pvs"]], ["/dev/sda1"]);
1053     InitEmpty, Always, TestOutputListOfDevices (
1054       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1055        ["pvcreate"; "/dev/sda1"];
1056        ["pvcreate"; "/dev/sda2"];
1057        ["pvcreate"; "/dev/sda3"];
1058        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1059    "list the LVM physical volumes (PVs)",
1060    "\
1061 List all the physical volumes detected.  This is the equivalent
1062 of the L<pvs(8)> command.
1063
1064 This returns a list of just the device names that contain
1065 PVs (eg. C</dev/sda2>).
1066
1067 See also C<guestfs_pvs_full>.");
1068
1069   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1070    [InitBasicFSonLVM, Always, TestOutputList (
1071       [["vgs"]], ["VG"]);
1072     InitEmpty, Always, TestOutputList (
1073       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1074        ["pvcreate"; "/dev/sda1"];
1075        ["pvcreate"; "/dev/sda2"];
1076        ["pvcreate"; "/dev/sda3"];
1077        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1078        ["vgcreate"; "VG2"; "/dev/sda3"];
1079        ["vgs"]], ["VG1"; "VG2"])],
1080    "list the LVM volume groups (VGs)",
1081    "\
1082 List all the volumes groups detected.  This is the equivalent
1083 of the L<vgs(8)> command.
1084
1085 This returns a list of just the volume group names that were
1086 detected (eg. C<VolGroup00>).
1087
1088 See also C<guestfs_vgs_full>.");
1089
1090   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1091    [InitBasicFSonLVM, Always, TestOutputList (
1092       [["lvs"]], ["/dev/VG/LV"]);
1093     InitEmpty, Always, TestOutputList (
1094       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1095        ["pvcreate"; "/dev/sda1"];
1096        ["pvcreate"; "/dev/sda2"];
1097        ["pvcreate"; "/dev/sda3"];
1098        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1099        ["vgcreate"; "VG2"; "/dev/sda3"];
1100        ["lvcreate"; "LV1"; "VG1"; "50"];
1101        ["lvcreate"; "LV2"; "VG1"; "50"];
1102        ["lvcreate"; "LV3"; "VG2"; "50"];
1103        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1104    "list the LVM logical volumes (LVs)",
1105    "\
1106 List all the logical volumes detected.  This is the equivalent
1107 of the L<lvs(8)> command.
1108
1109 This returns a list of the logical volume device names
1110 (eg. C</dev/VolGroup00/LogVol00>).
1111
1112 See also C<guestfs_lvs_full>.");
1113
1114   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1115    [], (* XXX how to test? *)
1116    "list the LVM physical volumes (PVs)",
1117    "\
1118 List all the physical volumes detected.  This is the equivalent
1119 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1120
1121   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1122    [], (* XXX how to test? *)
1123    "list the LVM volume groups (VGs)",
1124    "\
1125 List all the volumes groups detected.  This is the equivalent
1126 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1127
1128   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1129    [], (* XXX how to test? *)
1130    "list the LVM logical volumes (LVs)",
1131    "\
1132 List all the logical volumes detected.  This is the equivalent
1133 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1134
1135   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1136    [InitISOFS, Always, TestOutputList (
1137       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1138     InitISOFS, Always, TestOutputList (
1139       [["read_lines"; "/empty"]], [])],
1140    "read file as lines",
1141    "\
1142 Return the contents of the file named C<path>.
1143
1144 The file contents are returned as a list of lines.  Trailing
1145 C<LF> and C<CRLF> character sequences are I<not> returned.
1146
1147 Note that this function cannot correctly handle binary files
1148 (specifically, files containing C<\\0> character which is treated
1149 as end of line).  For those you need to use the C<guestfs_read_file>
1150 function which has a more complex interface.");
1151
1152   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1153    [], (* XXX Augeas code needs tests. *)
1154    "create a new Augeas handle",
1155    "\
1156 Create a new Augeas handle for editing configuration files.
1157 If there was any previous Augeas handle associated with this
1158 guestfs session, then it is closed.
1159
1160 You must call this before using any other C<guestfs_aug_*>
1161 commands.
1162
1163 C<root> is the filesystem root.  C<root> must not be NULL,
1164 use C</> instead.
1165
1166 The flags are the same as the flags defined in
1167 E<lt>augeas.hE<gt>, the logical I<or> of the following
1168 integers:
1169
1170 =over 4
1171
1172 =item C<AUG_SAVE_BACKUP> = 1
1173
1174 Keep the original file with a C<.augsave> extension.
1175
1176 =item C<AUG_SAVE_NEWFILE> = 2
1177
1178 Save changes into a file with extension C<.augnew>, and
1179 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1180
1181 =item C<AUG_TYPE_CHECK> = 4
1182
1183 Typecheck lenses (can be expensive).
1184
1185 =item C<AUG_NO_STDINC> = 8
1186
1187 Do not use standard load path for modules.
1188
1189 =item C<AUG_SAVE_NOOP> = 16
1190
1191 Make save a no-op, just record what would have been changed.
1192
1193 =item C<AUG_NO_LOAD> = 32
1194
1195 Do not load the tree in C<guestfs_aug_init>.
1196
1197 =back
1198
1199 To close the handle, you can call C<guestfs_aug_close>.
1200
1201 To find out more about Augeas, see L<http://augeas.net/>.");
1202
1203   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1204    [], (* XXX Augeas code needs tests. *)
1205    "close the current Augeas handle",
1206    "\
1207 Close the current Augeas handle and free up any resources
1208 used by it.  After calling this, you have to call
1209 C<guestfs_aug_init> again before you can use any other
1210 Augeas functions.");
1211
1212   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1213    [], (* XXX Augeas code needs tests. *)
1214    "define an Augeas variable",
1215    "\
1216 Defines an Augeas variable C<name> whose value is the result
1217 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1218 undefined.
1219
1220 On success this returns the number of nodes in C<expr>, or
1221 C<0> if C<expr> evaluates to something which is not a nodeset.");
1222
1223   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1224    [], (* XXX Augeas code needs tests. *)
1225    "define an Augeas node",
1226    "\
1227 Defines a variable C<name> whose value is the result of
1228 evaluating C<expr>.
1229
1230 If C<expr> evaluates to an empty nodeset, a node is created,
1231 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1232 C<name> will be the nodeset containing that single node.
1233
1234 On success this returns a pair containing the
1235 number of nodes in the nodeset, and a boolean flag
1236 if a node was created.");
1237
1238   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1239    [], (* XXX Augeas code needs tests. *)
1240    "look up the value of an Augeas path",
1241    "\
1242 Look up the value associated with C<path>.  If C<path>
1243 matches exactly one node, the C<value> is returned.");
1244
1245   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1246    [], (* XXX Augeas code needs tests. *)
1247    "set Augeas path to value",
1248    "\
1249 Set the value associated with C<path> to C<value>.");
1250
1251   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1252    [], (* XXX Augeas code needs tests. *)
1253    "insert a sibling Augeas node",
1254    "\
1255 Create a new sibling C<label> for C<path>, inserting it into
1256 the tree before or after C<path> (depending on the boolean
1257 flag C<before>).
1258
1259 C<path> must match exactly one existing node in the tree, and
1260 C<label> must be a label, ie. not contain C</>, C<*> or end
1261 with a bracketed index C<[N]>.");
1262
1263   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "remove an Augeas path",
1266    "\
1267 Remove C<path> and all of its children.
1268
1269 On success this returns the number of entries which were removed.");
1270
1271   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1272    [], (* XXX Augeas code needs tests. *)
1273    "move Augeas node",
1274    "\
1275 Move the node C<src> to C<dest>.  C<src> must match exactly
1276 one node.  C<dest> is overwritten if it exists.");
1277
1278   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "return Augeas nodes which match augpath",
1281    "\
1282 Returns a list of paths which match the path expression C<path>.
1283 The returned paths are sufficiently qualified so that they match
1284 exactly one node in the current tree.");
1285
1286   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "write all pending Augeas changes to disk",
1289    "\
1290 This writes all pending changes to disk.
1291
1292 The flags which were passed to C<guestfs_aug_init> affect exactly
1293 how files are saved.");
1294
1295   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "load files into the tree",
1298    "\
1299 Load files into the tree.
1300
1301 See C<aug_load> in the Augeas documentation for the full gory
1302 details.");
1303
1304   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "list Augeas nodes under augpath",
1307    "\
1308 This is just a shortcut for listing C<guestfs_aug_match>
1309 C<path/*> and sorting the resulting nodes into alphabetical order.");
1310
1311   ("rm", (RErr, [Pathname "path"]), 29, [],
1312    [InitBasicFS, Always, TestRun
1313       [["touch"; "/new"];
1314        ["rm"; "/new"]];
1315     InitBasicFS, Always, TestLastFail
1316       [["rm"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["mkdir"; "/new"];
1319        ["rm"; "/new"]]],
1320    "remove a file",
1321    "\
1322 Remove the single file C<path>.");
1323
1324   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1325    [InitBasicFS, Always, TestRun
1326       [["mkdir"; "/new"];
1327        ["rmdir"; "/new"]];
1328     InitBasicFS, Always, TestLastFail
1329       [["rmdir"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["touch"; "/new"];
1332        ["rmdir"; "/new"]]],
1333    "remove a directory",
1334    "\
1335 Remove the single directory C<path>.");
1336
1337   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1338    [InitBasicFS, Always, TestOutputFalse
1339       [["mkdir"; "/new"];
1340        ["mkdir"; "/new/foo"];
1341        ["touch"; "/new/foo/bar"];
1342        ["rm_rf"; "/new"];
1343        ["exists"; "/new"]]],
1344    "remove a file or directory recursively",
1345    "\
1346 Remove the file or directory C<path>, recursively removing the
1347 contents if its a directory.  This is like the C<rm -rf> shell
1348 command.");
1349
1350   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1351    [InitBasicFS, Always, TestOutputTrue
1352       [["mkdir"; "/new"];
1353        ["is_dir"; "/new"]];
1354     InitBasicFS, Always, TestLastFail
1355       [["mkdir"; "/new/foo/bar"]]],
1356    "create a directory",
1357    "\
1358 Create a directory named C<path>.");
1359
1360   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1361    [InitBasicFS, Always, TestOutputTrue
1362       [["mkdir_p"; "/new/foo/bar"];
1363        ["is_dir"; "/new/foo/bar"]];
1364     InitBasicFS, Always, TestOutputTrue
1365       [["mkdir_p"; "/new/foo/bar"];
1366        ["is_dir"; "/new/foo"]];
1367     InitBasicFS, Always, TestOutputTrue
1368       [["mkdir_p"; "/new/foo/bar"];
1369        ["is_dir"; "/new"]];
1370     (* Regression tests for RHBZ#503133: *)
1371     InitBasicFS, Always, TestRun
1372       [["mkdir"; "/new"];
1373        ["mkdir_p"; "/new"]];
1374     InitBasicFS, Always, TestLastFail
1375       [["touch"; "/new"];
1376        ["mkdir_p"; "/new"]]],
1377    "create a directory and parents",
1378    "\
1379 Create a directory named C<path>, creating any parent directories
1380 as necessary.  This is like the C<mkdir -p> shell command.");
1381
1382   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1383    [], (* XXX Need stat command to test *)
1384    "change file mode",
1385    "\
1386 Change the mode (permissions) of C<path> to C<mode>.  Only
1387 numeric modes are supported.
1388
1389 I<Note>: When using this command from guestfish, C<mode>
1390 by default would be decimal, unless you prefix it with
1391 C<0> to get octal, ie. use C<0700> not C<700>.
1392
1393 The mode actually set is affected by the umask.");
1394
1395   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1396    [], (* XXX Need stat command to test *)
1397    "change file owner and group",
1398    "\
1399 Change the file owner to C<owner> and group to C<group>.
1400
1401 Only numeric uid and gid are supported.  If you want to use
1402 names, you will need to locate and parse the password file
1403 yourself (Augeas support makes this relatively easy).");
1404
1405   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1406    [InitISOFS, Always, TestOutputTrue (
1407       [["exists"; "/empty"]]);
1408     InitISOFS, Always, TestOutputTrue (
1409       [["exists"; "/directory"]])],
1410    "test if file or directory exists",
1411    "\
1412 This returns C<true> if and only if there is a file, directory
1413 (or anything) with the given C<path> name.
1414
1415 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1416
1417   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1418    [InitISOFS, Always, TestOutputTrue (
1419       [["is_file"; "/known-1"]]);
1420     InitISOFS, Always, TestOutputFalse (
1421       [["is_file"; "/directory"]])],
1422    "test if file exists",
1423    "\
1424 This returns C<true> if and only if there is a file
1425 with the given C<path> name.  Note that it returns false for
1426 other objects like directories.
1427
1428 See also C<guestfs_stat>.");
1429
1430   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1431    [InitISOFS, Always, TestOutputFalse (
1432       [["is_dir"; "/known-3"]]);
1433     InitISOFS, Always, TestOutputTrue (
1434       [["is_dir"; "/directory"]])],
1435    "test if file exists",
1436    "\
1437 This returns C<true> if and only if there is a directory
1438 with the given C<path> name.  Note that it returns false for
1439 other objects like files.
1440
1441 See also C<guestfs_stat>.");
1442
1443   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1444    [InitEmpty, Always, TestOutputListOfDevices (
1445       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1446        ["pvcreate"; "/dev/sda1"];
1447        ["pvcreate"; "/dev/sda2"];
1448        ["pvcreate"; "/dev/sda3"];
1449        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1450    "create an LVM physical volume",
1451    "\
1452 This creates an LVM physical volume on the named C<device>,
1453 where C<device> should usually be a partition name such
1454 as C</dev/sda1>.");
1455
1456   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1457    [InitEmpty, Always, TestOutputList (
1458       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1459        ["pvcreate"; "/dev/sda1"];
1460        ["pvcreate"; "/dev/sda2"];
1461        ["pvcreate"; "/dev/sda3"];
1462        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1463        ["vgcreate"; "VG2"; "/dev/sda3"];
1464        ["vgs"]], ["VG1"; "VG2"])],
1465    "create an LVM volume group",
1466    "\
1467 This creates an LVM volume group called C<volgroup>
1468 from the non-empty list of physical volumes C<physvols>.");
1469
1470   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1471    [InitEmpty, Always, TestOutputList (
1472       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1473        ["pvcreate"; "/dev/sda1"];
1474        ["pvcreate"; "/dev/sda2"];
1475        ["pvcreate"; "/dev/sda3"];
1476        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1477        ["vgcreate"; "VG2"; "/dev/sda3"];
1478        ["lvcreate"; "LV1"; "VG1"; "50"];
1479        ["lvcreate"; "LV2"; "VG1"; "50"];
1480        ["lvcreate"; "LV3"; "VG2"; "50"];
1481        ["lvcreate"; "LV4"; "VG2"; "50"];
1482        ["lvcreate"; "LV5"; "VG2"; "50"];
1483        ["lvs"]],
1484       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1485        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1486    "create an LVM logical volume",
1487    "\
1488 This creates an LVM logical volume called C<logvol>
1489 on the volume group C<volgroup>, with C<size> megabytes.");
1490
1491   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1492    [InitEmpty, Always, TestOutput (
1493       [["part_disk"; "/dev/sda"; "mbr"];
1494        ["mkfs"; "ext2"; "/dev/sda1"];
1495        ["mount_options"; ""; "/dev/sda1"; "/"];
1496        ["write_file"; "/new"; "new file contents"; "0"];
1497        ["cat"; "/new"]], "new file contents")],
1498    "make a filesystem",
1499    "\
1500 This creates a filesystem on C<device> (usually a partition
1501 or LVM logical volume).  The filesystem type is C<fstype>, for
1502 example C<ext3>.");
1503
1504   ("sfdisk", (RErr, [Device "device";
1505                      Int "cyls"; Int "heads"; Int "sectors";
1506                      StringList "lines"]), 43, [DangerWillRobinson],
1507    [],
1508    "create partitions on a block device",
1509    "\
1510 This is a direct interface to the L<sfdisk(8)> program for creating
1511 partitions on block devices.
1512
1513 C<device> should be a block device, for example C</dev/sda>.
1514
1515 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1516 and sectors on the device, which are passed directly to sfdisk as
1517 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1518 of these, then the corresponding parameter is omitted.  Usually for
1519 'large' disks, you can just pass C<0> for these, but for small
1520 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1521 out the right geometry and you will need to tell it.
1522
1523 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1524 information refer to the L<sfdisk(8)> manpage.
1525
1526 To create a single partition occupying the whole disk, you would
1527 pass C<lines> as a single element list, when the single element being
1528 the string C<,> (comma).
1529
1530 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1531 C<guestfs_part_init>");
1532
1533   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1534    [InitBasicFS, Always, TestOutput (
1535       [["write_file"; "/new"; "new file contents"; "0"];
1536        ["cat"; "/new"]], "new file contents");
1537     InitBasicFS, Always, TestOutput (
1538       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1539        ["cat"; "/new"]], "\nnew file contents\n");
1540     InitBasicFS, Always, TestOutput (
1541       [["write_file"; "/new"; "\n\n"; "0"];
1542        ["cat"; "/new"]], "\n\n");
1543     InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; ""; "0"];
1545        ["cat"; "/new"]], "");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\n\n\n"; "0"];
1548        ["cat"; "/new"]], "\n\n\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n"; "0"];
1551        ["cat"; "/new"]], "\n")],
1552    "create a file",
1553    "\
1554 This call creates a file called C<path>.  The contents of the
1555 file is the string C<content> (which can contain any 8 bit data),
1556 with length C<size>.
1557
1558 As a special case, if C<size> is C<0>
1559 then the length is calculated using C<strlen> (so in this case
1560 the content cannot contain embedded ASCII NULs).
1561
1562 I<NB.> Owing to a bug, writing content containing ASCII NUL
1563 characters does I<not> work, even if the length is specified.
1564 We hope to resolve this bug in a future version.  In the meantime
1565 use C<guestfs_upload>.");
1566
1567   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1568    [InitEmpty, Always, TestOutputListOfDevices (
1569       [["part_disk"; "/dev/sda"; "mbr"];
1570        ["mkfs"; "ext2"; "/dev/sda1"];
1571        ["mount_options"; ""; "/dev/sda1"; "/"];
1572        ["mounts"]], ["/dev/sda1"]);
1573     InitEmpty, Always, TestOutputList (
1574       [["part_disk"; "/dev/sda"; "mbr"];
1575        ["mkfs"; "ext2"; "/dev/sda1"];
1576        ["mount_options"; ""; "/dev/sda1"; "/"];
1577        ["umount"; "/"];
1578        ["mounts"]], [])],
1579    "unmount a filesystem",
1580    "\
1581 This unmounts the given filesystem.  The filesystem may be
1582 specified either by its mountpoint (path) or the device which
1583 contains the filesystem.");
1584
1585   ("mounts", (RStringList "devices", []), 46, [],
1586    [InitBasicFS, Always, TestOutputListOfDevices (
1587       [["mounts"]], ["/dev/sda1"])],
1588    "show mounted filesystems",
1589    "\
1590 This returns the list of currently mounted filesystems.  It returns
1591 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1592
1593 Some internal mounts are not shown.
1594
1595 See also: C<guestfs_mountpoints>");
1596
1597   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1598    [InitBasicFS, Always, TestOutputList (
1599       [["umount_all"];
1600        ["mounts"]], []);
1601     (* check that umount_all can unmount nested mounts correctly: *)
1602     InitEmpty, Always, TestOutputList (
1603       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1604        ["mkfs"; "ext2"; "/dev/sda1"];
1605        ["mkfs"; "ext2"; "/dev/sda2"];
1606        ["mkfs"; "ext2"; "/dev/sda3"];
1607        ["mount_options"; ""; "/dev/sda1"; "/"];
1608        ["mkdir"; "/mp1"];
1609        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1610        ["mkdir"; "/mp1/mp2"];
1611        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1612        ["mkdir"; "/mp1/mp2/mp3"];
1613        ["umount_all"];
1614        ["mounts"]], [])],
1615    "unmount all filesystems",
1616    "\
1617 This unmounts all mounted filesystems.
1618
1619 Some internal mounts are not unmounted by this call.");
1620
1621   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1622    [],
1623    "remove all LVM LVs, VGs and PVs",
1624    "\
1625 This command removes all LVM logical volumes, volume groups
1626 and physical volumes.");
1627
1628   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1629    [InitISOFS, Always, TestOutput (
1630       [["file"; "/empty"]], "empty");
1631     InitISOFS, Always, TestOutput (
1632       [["file"; "/known-1"]], "ASCII text");
1633     InitISOFS, Always, TestLastFail (
1634       [["file"; "/notexists"]])],
1635    "determine file type",
1636    "\
1637 This call uses the standard L<file(1)> command to determine
1638 the type or contents of the file.  This also works on devices,
1639 for example to find out whether a partition contains a filesystem.
1640
1641 This call will also transparently look inside various types
1642 of compressed file.
1643
1644 The exact command which runs is C<file -zbsL path>.  Note in
1645 particular that the filename is not prepended to the output
1646 (the C<-b> option).");
1647
1648   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1649    [InitBasicFS, Always, TestOutput (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command"; "/test-command 1"]], "Result1");
1653     InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 2"]], "Result2\n");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 3"]], "\nResult3");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 4"]], "\nResult4\n");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 5"]], "\nResult5\n\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 7"]], "");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 8"]], "\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 9"]], "\n\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1693     InitBasicFS, Always, TestLastFail (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command"]])],
1697    "run a command from the guest filesystem",
1698    "\
1699 This call runs a command from the guest filesystem.  The
1700 filesystem must be mounted, and must contain a compatible
1701 operating system (ie. something Linux, with the same
1702 or compatible processor architecture).
1703
1704 The single parameter is an argv-style list of arguments.
1705 The first element is the name of the program to run.
1706 Subsequent elements are parameters.  The list must be
1707 non-empty (ie. must contain a program name).  Note that
1708 the command runs directly, and is I<not> invoked via
1709 the shell (see C<guestfs_sh>).
1710
1711 The return value is anything printed to I<stdout> by
1712 the command.
1713
1714 If the command returns a non-zero exit status, then
1715 this function returns an error message.  The error message
1716 string is the content of I<stderr> from the command.
1717
1718 The C<$PATH> environment variable will contain at least
1719 C</usr/bin> and C</bin>.  If you require a program from
1720 another location, you should provide the full path in the
1721 first parameter.
1722
1723 Shared libraries and data files required by the program
1724 must be available on filesystems which are mounted in the
1725 correct places.  It is the caller's responsibility to ensure
1726 all filesystems that are needed are mounted at the right
1727 locations.");
1728
1729   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1730    [InitBasicFS, Always, TestOutputList (
1731       [["upload"; "test-command"; "/test-command"];
1732        ["chmod"; "0o755"; "/test-command"];
1733        ["command_lines"; "/test-command 1"]], ["Result1"]);
1734     InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 2"]], ["Result2"]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 7"]], []);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 8"]], [""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 9"]], ["";""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1774    "run a command, returning lines",
1775    "\
1776 This is the same as C<guestfs_command>, but splits the
1777 result into a list of lines.
1778
1779 See also: C<guestfs_sh_lines>");
1780
1781   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1782    [InitISOFS, Always, TestOutputStruct (
1783       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1784    "get file information",
1785    "\
1786 Returns file information for the given C<path>.
1787
1788 This is the same as the C<stat(2)> system call.");
1789
1790   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information for a symbolic link",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as C<guestfs_stat> except that if C<path>
1798 is a symbolic link, then the link is stat-ed, not the file it
1799 refers to.
1800
1801 This is the same as the C<lstat(2)> system call.");
1802
1803   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1804    [InitISOFS, Always, TestOutputStruct (
1805       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1806    "get file system statistics",
1807    "\
1808 Returns file system statistics for any mounted file system.
1809 C<path> should be a file or directory in the mounted file system
1810 (typically it is the mount point itself, but it doesn't need to be).
1811
1812 This is the same as the C<statvfs(2)> system call.");
1813
1814   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1815    [], (* XXX test *)
1816    "get ext2/ext3/ext4 superblock details",
1817    "\
1818 This returns the contents of the ext2, ext3 or ext4 filesystem
1819 superblock on C<device>.
1820
1821 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1822 manpage for more details.  The list of fields returned isn't
1823 clearly defined, and depends on both the version of C<tune2fs>
1824 that libguestfs was built against, and the filesystem itself.");
1825
1826   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1827    [InitEmpty, Always, TestOutputTrue (
1828       [["blockdev_setro"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-only",
1831    "\
1832 Sets the block device named C<device> to read-only.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1837    [InitEmpty, Always, TestOutputFalse (
1838       [["blockdev_setrw"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "set block device to read-write",
1841    "\
1842 Sets the block device named C<device> to read-write.
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1847    [InitEmpty, Always, TestOutputTrue (
1848       [["blockdev_setro"; "/dev/sda"];
1849        ["blockdev_getro"; "/dev/sda"]])],
1850    "is block device set to read-only",
1851    "\
1852 Returns a boolean indicating if the block device is read-only
1853 (true if read-only, false if not).
1854
1855 This uses the L<blockdev(8)> command.");
1856
1857   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1858    [InitEmpty, Always, TestOutputInt (
1859       [["blockdev_getss"; "/dev/sda"]], 512)],
1860    "get sectorsize of block device",
1861    "\
1862 This returns the size of sectors on a block device.
1863 Usually 512, but can be larger for modern devices.
1864
1865 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1866 for that).
1867
1868 This uses the L<blockdev(8)> command.");
1869
1870   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1871    [InitEmpty, Always, TestOutputInt (
1872       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1873    "get blocksize of block device",
1874    "\
1875 This returns the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1883    [], (* XXX test *)
1884    "set blocksize of block device",
1885    "\
1886 This sets the block size of a device.
1887
1888 (Note this is different from both I<size in blocks> and
1889 I<filesystem block size>).
1890
1891 This uses the L<blockdev(8)> command.");
1892
1893   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1894    [InitEmpty, Always, TestOutputInt (
1895       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1896    "get total size of device in 512-byte sectors",
1897    "\
1898 This returns the size of the device in units of 512-byte sectors
1899 (even if the sectorsize isn't 512 bytes ... weird).
1900
1901 See also C<guestfs_blockdev_getss> for the real sector size of
1902 the device, and C<guestfs_blockdev_getsize64> for the more
1903 useful I<size in bytes>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1908    [InitEmpty, Always, TestOutputInt (
1909       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1910    "get total size of device in bytes",
1911    "\
1912 This returns the size of the device in bytes.
1913
1914 See also C<guestfs_blockdev_getsz>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_flushbufs"; "/dev/sda"]]],
1921    "flush device buffers",
1922    "\
1923 This tells the kernel to flush internal buffers associated
1924 with C<device>.
1925
1926 This uses the L<blockdev(8)> command.");
1927
1928   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1929    [InitEmpty, Always, TestRun
1930       [["blockdev_rereadpt"; "/dev/sda"]]],
1931    "reread partition table",
1932    "\
1933 Reread the partition table on C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1938    [InitBasicFS, Always, TestOutput (
1939       (* Pick a file from cwd which isn't likely to change. *)
1940       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1941        ["checksum"; "md5"; "/COPYING.LIB"]],
1942       Digest.to_hex (Digest.file "COPYING.LIB"))],
1943    "upload a file from the local machine",
1944    "\
1945 Upload local file C<filename> to C<remotefilename> on the
1946 filesystem.
1947
1948 C<filename> can also be a named pipe.
1949
1950 See also C<guestfs_download>.");
1951
1952   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1953    [InitBasicFS, Always, TestOutput (
1954       (* Pick a file from cwd which isn't likely to change. *)
1955       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1956        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1957        ["upload"; "testdownload.tmp"; "/upload"];
1958        ["checksum"; "md5"; "/upload"]],
1959       Digest.to_hex (Digest.file "COPYING.LIB"))],
1960    "download a file to the local machine",
1961    "\
1962 Download file C<remotefilename> and save it as C<filename>
1963 on the local machine.
1964
1965 C<filename> can also be a named pipe.
1966
1967 See also C<guestfs_upload>, C<guestfs_cat>.");
1968
1969   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1970    [InitISOFS, Always, TestOutput (
1971       [["checksum"; "crc"; "/known-3"]], "2891671662");
1972     InitISOFS, Always, TestLastFail (
1973       [["checksum"; "crc"; "/notexists"]]);
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1986    "compute MD5, SHAx or CRC checksum of file",
1987    "\
1988 This call computes the MD5, SHAx or CRC checksum of the
1989 file named C<path>.
1990
1991 The type of checksum to compute is given by the C<csumtype>
1992 parameter which must have one of the following values:
1993
1994 =over 4
1995
1996 =item C<crc>
1997
1998 Compute the cyclic redundancy check (CRC) specified by POSIX
1999 for the C<cksum> command.
2000
2001 =item C<md5>
2002
2003 Compute the MD5 hash (using the C<md5sum> program).
2004
2005 =item C<sha1>
2006
2007 Compute the SHA1 hash (using the C<sha1sum> program).
2008
2009 =item C<sha224>
2010
2011 Compute the SHA224 hash (using the C<sha224sum> program).
2012
2013 =item C<sha256>
2014
2015 Compute the SHA256 hash (using the C<sha256sum> program).
2016
2017 =item C<sha384>
2018
2019 Compute the SHA384 hash (using the C<sha384sum> program).
2020
2021 =item C<sha512>
2022
2023 Compute the SHA512 hash (using the C<sha512sum> program).
2024
2025 =back
2026
2027 The checksum is returned as a printable string.");
2028
2029   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2030    [InitBasicFS, Always, TestOutput (
2031       [["tar_in"; "../images/helloworld.tar"; "/"];
2032        ["cat"; "/hello"]], "hello\n")],
2033    "unpack tarfile to directory",
2034    "\
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2037
2038 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2039
2040   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2041    [],
2042    "pack directory into tarfile",
2043    "\
2044 This command packs the contents of C<directory> and downloads
2045 it to local file C<tarfile>.
2046
2047 To download a compressed tarball, use C<guestfs_tgz_out>.");
2048
2049   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2050    [InitBasicFS, Always, TestOutput (
2051       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2052        ["cat"; "/hello"]], "hello\n")],
2053    "unpack compressed tarball to directory",
2054    "\
2055 This command uploads and unpacks local file C<tarball> (a
2056 I<gzip compressed> tar file) into C<directory>.
2057
2058 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2059
2060   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2061    [],
2062    "pack directory into compressed tarball",
2063    "\
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarball>.
2066
2067 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2068
2069   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2070    [InitBasicFS, Always, TestLastFail (
2071       [["umount"; "/"];
2072        ["mount_ro"; "/dev/sda1"; "/"];
2073        ["touch"; "/new"]]);
2074     InitBasicFS, Always, TestOutput (
2075       [["write_file"; "/new"; "data"; "0"];
2076        ["umount"; "/"];
2077        ["mount_ro"; "/dev/sda1"; "/"];
2078        ["cat"; "/new"]], "data")],
2079    "mount a guest disk, read-only",
2080    "\
2081 This is the same as the C<guestfs_mount> command, but it
2082 mounts the filesystem with the read-only (I<-o ro>) flag.");
2083
2084   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2085    [],
2086    "mount a guest disk with mount options",
2087    "\
2088 This is the same as the C<guestfs_mount> command, but it
2089 allows you to set the mount options as for the
2090 L<mount(8)> I<-o> flag.
2091
2092 If the C<options> parameter is an empty string, then
2093 no options are passed (all options default to whatever
2094 the filesystem uses).");
2095
2096   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2097    [],
2098    "mount a guest disk with mount options and vfstype",
2099    "\
2100 This is the same as the C<guestfs_mount> command, but it
2101 allows you to set both the mount options and the vfstype
2102 as for the L<mount(8)> I<-o> and I<-t> flags.");
2103
2104   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2105    [],
2106    "debugging and internals",
2107    "\
2108 The C<guestfs_debug> command exposes some internals of
2109 C<guestfsd> (the guestfs daemon) that runs inside the
2110 qemu subprocess.
2111
2112 There is no comprehensive help for this command.  You have
2113 to look at the file C<daemon/debug.c> in the libguestfs source
2114 to find out what you can do.");
2115
2116   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2117    [InitEmpty, Always, TestOutputList (
2118       [["part_disk"; "/dev/sda"; "mbr"];
2119        ["pvcreate"; "/dev/sda1"];
2120        ["vgcreate"; "VG"; "/dev/sda1"];
2121        ["lvcreate"; "LV1"; "VG"; "50"];
2122        ["lvcreate"; "LV2"; "VG"; "50"];
2123        ["lvremove"; "/dev/VG/LV1"];
2124        ["lvs"]], ["/dev/VG/LV2"]);
2125     InitEmpty, Always, TestOutputList (
2126       [["part_disk"; "/dev/sda"; "mbr"];
2127        ["pvcreate"; "/dev/sda1"];
2128        ["vgcreate"; "VG"; "/dev/sda1"];
2129        ["lvcreate"; "LV1"; "VG"; "50"];
2130        ["lvcreate"; "LV2"; "VG"; "50"];
2131        ["lvremove"; "/dev/VG"];
2132        ["lvs"]], []);
2133     InitEmpty, Always, TestOutputList (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["lvremove"; "/dev/VG"];
2140        ["vgs"]], ["VG"])],
2141    "remove an LVM logical volume",
2142    "\
2143 Remove an LVM logical volume C<device>, where C<device> is
2144 the path to the LV, such as C</dev/VG/LV>.
2145
2146 You can also remove all LVs in a volume group by specifying
2147 the VG name, C</dev/VG>.");
2148
2149   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2150    [InitEmpty, Always, TestOutputList (
2151       [["part_disk"; "/dev/sda"; "mbr"];
2152        ["pvcreate"; "/dev/sda1"];
2153        ["vgcreate"; "VG"; "/dev/sda1"];
2154        ["lvcreate"; "LV1"; "VG"; "50"];
2155        ["lvcreate"; "LV2"; "VG"; "50"];
2156        ["vgremove"; "VG"];
2157        ["lvs"]], []);
2158     InitEmpty, Always, TestOutputList (
2159       [["part_disk"; "/dev/sda"; "mbr"];
2160        ["pvcreate"; "/dev/sda1"];
2161        ["vgcreate"; "VG"; "/dev/sda1"];
2162        ["lvcreate"; "LV1"; "VG"; "50"];
2163        ["lvcreate"; "LV2"; "VG"; "50"];
2164        ["vgremove"; "VG"];
2165        ["vgs"]], [])],
2166    "remove an LVM volume group",
2167    "\
2168 Remove an LVM volume group C<vgname>, (for example C<VG>).
2169
2170 This also forcibly removes all logical volumes in the volume
2171 group (if any).");
2172
2173   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2174    [InitEmpty, Always, TestOutputListOfDevices (
2175       [["part_disk"; "/dev/sda"; "mbr"];
2176        ["pvcreate"; "/dev/sda1"];
2177        ["vgcreate"; "VG"; "/dev/sda1"];
2178        ["lvcreate"; "LV1"; "VG"; "50"];
2179        ["lvcreate"; "LV2"; "VG"; "50"];
2180        ["vgremove"; "VG"];
2181        ["pvremove"; "/dev/sda1"];
2182        ["lvs"]], []);
2183     InitEmpty, Always, TestOutputListOfDevices (
2184       [["part_disk"; "/dev/sda"; "mbr"];
2185        ["pvcreate"; "/dev/sda1"];
2186        ["vgcreate"; "VG"; "/dev/sda1"];
2187        ["lvcreate"; "LV1"; "VG"; "50"];
2188        ["lvcreate"; "LV2"; "VG"; "50"];
2189        ["vgremove"; "VG"];
2190        ["pvremove"; "/dev/sda1"];
2191        ["vgs"]], []);
2192     InitEmpty, Always, TestOutputListOfDevices (
2193       [["part_disk"; "/dev/sda"; "mbr"];
2194        ["pvcreate"; "/dev/sda1"];
2195        ["vgcreate"; "VG"; "/dev/sda1"];
2196        ["lvcreate"; "LV1"; "VG"; "50"];
2197        ["lvcreate"; "LV2"; "VG"; "50"];
2198        ["vgremove"; "VG"];
2199        ["pvremove"; "/dev/sda1"];
2200        ["pvs"]], [])],
2201    "remove an LVM physical volume",
2202    "\
2203 This wipes a physical volume C<device> so that LVM will no longer
2204 recognise it.
2205
2206 The implementation uses the C<pvremove> command which refuses to
2207 wipe physical volumes that contain any volume groups, so you have
2208 to remove those first.");
2209
2210   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2211    [InitBasicFS, Always, TestOutput (
2212       [["set_e2label"; "/dev/sda1"; "testlabel"];
2213        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2214    "set the ext2/3/4 filesystem label",
2215    "\
2216 This sets the ext2/3/4 filesystem label of the filesystem on
2217 C<device> to C<label>.  Filesystem labels are limited to
2218 16 characters.
2219
2220 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2221 to return the existing label on a filesystem.");
2222
2223   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2224    [],
2225    "get the ext2/3/4 filesystem label",
2226    "\
2227 This returns the ext2/3/4 filesystem label of the filesystem on
2228 C<device>.");
2229
2230   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2231    (let uuid = uuidgen () in
2232     [InitBasicFS, Always, TestOutput (
2233        [["set_e2uuid"; "/dev/sda1"; uuid];
2234         ["get_e2uuid"; "/dev/sda1"]], uuid);
2235      InitBasicFS, Always, TestOutput (
2236        [["set_e2uuid"; "/dev/sda1"; "clear"];
2237         ["get_e2uuid"; "/dev/sda1"]], "");
2238      (* We can't predict what UUIDs will be, so just check the commands run. *)
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2243    "set the ext2/3/4 filesystem UUID",
2244    "\
2245 This sets the ext2/3/4 filesystem UUID of the filesystem on
2246 C<device> to C<uuid>.  The format of the UUID and alternatives
2247 such as C<clear>, C<random> and C<time> are described in the
2248 L<tune2fs(8)> manpage.
2249
2250 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2251 to return the existing UUID of a filesystem.");
2252
2253   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2254    [],
2255    "get the ext2/3/4 filesystem UUID",
2256    "\
2257 This returns the ext2/3/4 filesystem UUID of the filesystem on
2258 C<device>.");
2259
2260   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2261    [InitBasicFS, Always, TestOutputInt (
2262       [["umount"; "/dev/sda1"];
2263        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2264     InitBasicFS, Always, TestOutputInt (
2265       [["umount"; "/dev/sda1"];
2266        ["zero"; "/dev/sda1"];
2267        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2268    "run the filesystem checker",
2269    "\
2270 This runs the filesystem checker (fsck) on C<device> which
2271 should have filesystem type C<fstype>.
2272
2273 The returned integer is the status.  See L<fsck(8)> for the
2274 list of status codes from C<fsck>.
2275
2276 Notes:
2277
2278 =over 4
2279
2280 =item *
2281
2282 Multiple status codes can be summed together.
2283
2284 =item *
2285
2286 A non-zero return code can mean \"success\", for example if
2287 errors have been corrected on the filesystem.
2288
2289 =item *
2290
2291 Checking or repairing NTFS volumes is not supported
2292 (by linux-ntfs).
2293
2294 =back
2295
2296 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2297
2298   ("zero", (RErr, [Device "device"]), 85, [],
2299    [InitBasicFS, Always, TestOutput (
2300       [["umount"; "/dev/sda1"];
2301        ["zero"; "/dev/sda1"];
2302        ["file"; "/dev/sda1"]], "data")],
2303    "write zeroes to the device",
2304    "\
2305 This command writes zeroes over the first few blocks of C<device>.
2306
2307 How many blocks are zeroed isn't specified (but it's I<not> enough
2308 to securely wipe the device).  It should be sufficient to remove
2309 any partition tables, filesystem superblocks and so on.
2310
2311 See also: C<guestfs_scrub_device>.");
2312
2313   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2314    (* Test disabled because grub-install incompatible with virtio-blk driver.
2315     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2316     *)
2317    [InitBasicFS, Disabled, TestOutputTrue (
2318       [["grub_install"; "/"; "/dev/sda1"];
2319        ["is_dir"; "/boot"]])],
2320    "install GRUB",
2321    "\
2322 This command installs GRUB (the Grand Unified Bootloader) on
2323 C<device>, with the root directory being C<root>.");
2324
2325   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2326    [InitBasicFS, Always, TestOutput (
2327       [["write_file"; "/old"; "file content"; "0"];
2328        ["cp"; "/old"; "/new"];
2329        ["cat"; "/new"]], "file content");
2330     InitBasicFS, Always, TestOutputTrue (
2331       [["write_file"; "/old"; "file content"; "0"];
2332        ["cp"; "/old"; "/new"];
2333        ["is_file"; "/old"]]);
2334     InitBasicFS, Always, TestOutput (
2335       [["write_file"; "/old"; "file content"; "0"];
2336        ["mkdir"; "/dir"];
2337        ["cp"; "/old"; "/dir/new"];
2338        ["cat"; "/dir/new"]], "file content")],
2339    "copy a file",
2340    "\
2341 This copies a file from C<src> to C<dest> where C<dest> is
2342 either a destination filename or destination directory.");
2343
2344   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2345    [InitBasicFS, Always, TestOutput (
2346       [["mkdir"; "/olddir"];
2347        ["mkdir"; "/newdir"];
2348        ["write_file"; "/olddir/file"; "file content"; "0"];
2349        ["cp_a"; "/olddir"; "/newdir"];
2350        ["cat"; "/newdir/olddir/file"]], "file content")],
2351    "copy a file or directory recursively",
2352    "\
2353 This copies a file or directory from C<src> to C<dest>
2354 recursively using the C<cp -a> command.");
2355
2356   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2357    [InitBasicFS, Always, TestOutput (
2358       [["write_file"; "/old"; "file content"; "0"];
2359        ["mv"; "/old"; "/new"];
2360        ["cat"; "/new"]], "file content");
2361     InitBasicFS, Always, TestOutputFalse (
2362       [["write_file"; "/old"; "file content"; "0"];
2363        ["mv"; "/old"; "/new"];
2364        ["is_file"; "/old"]])],
2365    "move a file",
2366    "\
2367 This moves a file from C<src> to C<dest> where C<dest> is
2368 either a destination filename or destination directory.");
2369
2370   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2371    [InitEmpty, Always, TestRun (
2372       [["drop_caches"; "3"]])],
2373    "drop kernel page cache, dentries and inodes",
2374    "\
2375 This instructs the guest kernel to drop its page cache,
2376 and/or dentries and inode caches.  The parameter C<whattodrop>
2377 tells the kernel what precisely to drop, see
2378 L<http://linux-mm.org/Drop_Caches>
2379
2380 Setting C<whattodrop> to 3 should drop everything.
2381
2382 This automatically calls L<sync(2)> before the operation,
2383 so that the maximum guest memory is freed.");
2384
2385   ("dmesg", (RString "kmsgs", []), 91, [],
2386    [InitEmpty, Always, TestRun (
2387       [["dmesg"]])],
2388    "return kernel messages",
2389    "\
2390 This returns the kernel messages (C<dmesg> output) from
2391 the guest kernel.  This is sometimes useful for extended
2392 debugging of problems.
2393
2394 Another way to get the same information is to enable
2395 verbose messages with C<guestfs_set_verbose> or by setting
2396 the environment variable C<LIBGUESTFS_DEBUG=1> before
2397 running the program.");
2398
2399   ("ping_daemon", (RErr, []), 92, [],
2400    [InitEmpty, Always, TestRun (
2401       [["ping_daemon"]])],
2402    "ping the guest daemon",
2403    "\
2404 This is a test probe into the guestfs daemon running inside
2405 the qemu subprocess.  Calling this function checks that the
2406 daemon responds to the ping message, without affecting the daemon
2407 or attached block device(s) in any other way.");
2408
2409   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2410    [InitBasicFS, Always, TestOutputTrue (
2411       [["write_file"; "/file1"; "contents of a file"; "0"];
2412        ["cp"; "/file1"; "/file2"];
2413        ["equal"; "/file1"; "/file2"]]);
2414     InitBasicFS, Always, TestOutputFalse (
2415       [["write_file"; "/file1"; "contents of a file"; "0"];
2416        ["write_file"; "/file2"; "contents of another file"; "0"];
2417        ["equal"; "/file1"; "/file2"]]);
2418     InitBasicFS, Always, TestLastFail (
2419       [["equal"; "/file1"; "/file2"]])],
2420    "test if two files have equal contents",
2421    "\
2422 This compares the two files C<file1> and C<file2> and returns
2423 true if their content is exactly equal, or false otherwise.
2424
2425 The external L<cmp(1)> program is used for the comparison.");
2426
2427   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2428    [InitISOFS, Always, TestOutputList (
2429       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2430     InitISOFS, Always, TestOutputList (
2431       [["strings"; "/empty"]], [])],
2432    "print the printable strings in a file",
2433    "\
2434 This runs the L<strings(1)> command on a file and returns
2435 the list of printable strings found.");
2436
2437   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2438    [InitISOFS, Always, TestOutputList (
2439       [["strings_e"; "b"; "/known-5"]], []);
2440     InitBasicFS, Disabled, TestOutputList (
2441       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2442        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2443    "print the printable strings in a file",
2444    "\
2445 This is like the C<guestfs_strings> command, but allows you to
2446 specify the encoding of strings that are looked for in
2447 the source file C<path>.
2448
2449 Allowed encodings are:
2450
2451 =over 4
2452
2453 =item s
2454
2455 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2456 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2457
2458 =item S
2459
2460 Single 8-bit-byte characters.
2461
2462 =item b
2463
2464 16-bit big endian strings such as those encoded in
2465 UTF-16BE or UCS-2BE.
2466
2467 =item l (lower case letter L)
2468
2469 16-bit little endian such as UTF-16LE and UCS-2LE.
2470 This is useful for examining binaries in Windows guests.
2471
2472 =item B
2473
2474 32-bit big endian such as UCS-4BE.
2475
2476 =item L
2477
2478 32-bit little endian such as UCS-4LE.
2479
2480 =back
2481
2482 The returned strings are transcoded to UTF-8.");
2483
2484   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2485    [InitISOFS, Always, TestOutput (
2486       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2487     (* Test for RHBZ#501888c2 regression which caused large hexdump
2488      * commands to segfault.
2489      *)
2490     InitISOFS, Always, TestRun (
2491       [["hexdump"; "/100krandom"]])],
2492    "dump a file in hexadecimal",
2493    "\
2494 This runs C<hexdump -C> on the given C<path>.  The result is
2495 the human-readable, canonical hex dump of the file.");
2496
2497   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2498    [InitNone, Always, TestOutput (
2499       [["part_disk"; "/dev/sda"; "mbr"];
2500        ["mkfs"; "ext3"; "/dev/sda1"];
2501        ["mount_options"; ""; "/dev/sda1"; "/"];
2502        ["write_file"; "/new"; "test file"; "0"];
2503        ["umount"; "/dev/sda1"];
2504        ["zerofree"; "/dev/sda1"];
2505        ["mount_options"; ""; "/dev/sda1"; "/"];
2506        ["cat"; "/new"]], "test file")],
2507    "zero unused inodes and disk blocks on ext2/3 filesystem",
2508    "\
2509 This runs the I<zerofree> program on C<device>.  This program
2510 claims to zero unused inodes and disk blocks on an ext2/3
2511 filesystem, thus making it possible to compress the filesystem
2512 more effectively.
2513
2514 You should B<not> run this program if the filesystem is
2515 mounted.
2516
2517 It is possible that using this program can damage the filesystem
2518 or data on the filesystem.");
2519
2520   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2521    [],
2522    "resize an LVM physical volume",
2523    "\
2524 This resizes (expands or shrinks) an existing LVM physical
2525 volume to match the new size of the underlying device.");
2526
2527   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2528                        Int "cyls"; Int "heads"; Int "sectors";
2529                        String "line"]), 99, [DangerWillRobinson],
2530    [],
2531    "modify a single partition on a block device",
2532    "\
2533 This runs L<sfdisk(8)> option to modify just the single
2534 partition C<n> (note: C<n> counts from 1).
2535
2536 For other parameters, see C<guestfs_sfdisk>.  You should usually
2537 pass C<0> for the cyls/heads/sectors parameters.
2538
2539 See also: C<guestfs_part_add>");
2540
2541   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2542    [],
2543    "display the partition table",
2544    "\
2545 This displays the partition table on C<device>, in the
2546 human-readable output of the L<sfdisk(8)> command.  It is
2547 not intended to be parsed.
2548
2549 See also: C<guestfs_part_list>");
2550
2551   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2552    [],
2553    "display the kernel geometry",
2554    "\
2555 This displays the kernel's idea of the geometry of C<device>.
2556
2557 The result is in human-readable format, and not designed to
2558 be parsed.");
2559
2560   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2561    [],
2562    "display the disk geometry from the partition table",
2563    "\
2564 This displays the disk geometry of C<device> read from the
2565 partition table.  Especially in the case where the underlying
2566 block device has been resized, this can be different from the
2567 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2568
2569 The result is in human-readable format, and not designed to
2570 be parsed.");
2571
2572   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2573    [],
2574    "activate or deactivate all volume groups",
2575    "\
2576 This command activates or (if C<activate> is false) deactivates
2577 all logical volumes in all volume groups.
2578 If activated, then they are made known to the
2579 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2580 then those devices disappear.
2581
2582 This command is the same as running C<vgchange -a y|n>");
2583
2584   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2585    [],
2586    "activate or deactivate some volume groups",
2587    "\
2588 This command activates or (if C<activate> is false) deactivates
2589 all logical volumes in the listed volume groups C<volgroups>.
2590 If activated, then they are made known to the
2591 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2592 then those devices disappear.
2593
2594 This command is the same as running C<vgchange -a y|n volgroups...>
2595
2596 Note that if C<volgroups> is an empty list then B<all> volume groups
2597 are activated or deactivated.");
2598
2599   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2600    [InitNone, Always, TestOutput (
2601       [["part_disk"; "/dev/sda"; "mbr"];
2602        ["pvcreate"; "/dev/sda1"];
2603        ["vgcreate"; "VG"; "/dev/sda1"];
2604        ["lvcreate"; "LV"; "VG"; "10"];
2605        ["mkfs"; "ext2"; "/dev/VG/LV"];
2606        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2607        ["write_file"; "/new"; "test content"; "0"];
2608        ["umount"; "/"];
2609        ["lvresize"; "/dev/VG/LV"; "20"];
2610        ["e2fsck_f"; "/dev/VG/LV"];
2611        ["resize2fs"; "/dev/VG/LV"];
2612        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2613        ["cat"; "/new"]], "test content");
2614     InitNone, Always, TestRun (
2615       (* Make an LV smaller to test RHBZ#587484. *)
2616       [["part_disk"; "/dev/sda"; "mbr"];
2617        ["pvcreate"; "/dev/sda1"];
2618        ["vgcreate"; "VG"; "/dev/sda1"];
2619        ["lvcreate"; "LV"; "VG"; "20"];
2620        ["lvresize"; "/dev/VG/LV"; "10"]])],
2621    "resize an LVM logical volume",
2622    "\
2623 This resizes (expands or shrinks) an existing LVM logical
2624 volume to C<mbytes>.  When reducing, data in the reduced part
2625 is lost.");
2626
2627   ("resize2fs", (RErr, [Device "device"]), 106, [],
2628    [], (* lvresize tests this *)
2629    "resize an ext2/ext3 filesystem",
2630    "\
2631 This resizes an ext2 or ext3 filesystem to match the size of
2632 the underlying device.
2633
2634 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2635 on the C<device> before calling this command.  For unknown reasons
2636 C<resize2fs> sometimes gives an error about this and sometimes not.
2637 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2638 calling this function.");
2639
2640   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2641    [InitBasicFS, Always, TestOutputList (
2642       [["find"; "/"]], ["lost+found"]);
2643     InitBasicFS, Always, TestOutputList (
2644       [["touch"; "/a"];
2645        ["mkdir"; "/b"];
2646        ["touch"; "/b/c"];
2647        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2648     InitBasicFS, Always, TestOutputList (
2649       [["mkdir_p"; "/a/b/c"];
2650        ["touch"; "/a/b/c/d"];
2651        ["find"; "/a/b/"]], ["c"; "c/d"])],
2652    "find all files and directories",
2653    "\
2654 This command lists out all files and directories, recursively,
2655 starting at C<directory>.  It is essentially equivalent to
2656 running the shell command C<find directory -print> but some
2657 post-processing happens on the output, described below.
2658
2659 This returns a list of strings I<without any prefix>.  Thus
2660 if the directory structure was:
2661
2662  /tmp/a
2663  /tmp/b
2664  /tmp/c/d
2665
2666 then the returned list from C<guestfs_find> C</tmp> would be
2667 4 elements:
2668
2669  a
2670  b
2671  c
2672  c/d
2673
2674 If C<directory> is not a directory, then this command returns
2675 an error.
2676
2677 The returned list is sorted.
2678
2679 See also C<guestfs_find0>.");
2680
2681   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2682    [], (* lvresize tests this *)
2683    "check an ext2/ext3 filesystem",
2684    "\
2685 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2686 filesystem checker on C<device>, noninteractively (C<-p>),
2687 even if the filesystem appears to be clean (C<-f>).
2688
2689 This command is only needed because of C<guestfs_resize2fs>
2690 (q.v.).  Normally you should use C<guestfs_fsck>.");
2691
2692   ("sleep", (RErr, [Int "secs"]), 109, [],
2693    [InitNone, Always, TestRun (
2694       [["sleep"; "1"]])],
2695    "sleep for some seconds",
2696    "\
2697 Sleep for C<secs> seconds.");
2698
2699   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2700    [InitNone, Always, TestOutputInt (
2701       [["part_disk"; "/dev/sda"; "mbr"];
2702        ["mkfs"; "ntfs"; "/dev/sda1"];
2703        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2704     InitNone, Always, TestOutputInt (
2705       [["part_disk"; "/dev/sda"; "mbr"];
2706        ["mkfs"; "ext2"; "/dev/sda1"];
2707        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2708    "probe NTFS volume",
2709    "\
2710 This command runs the L<ntfs-3g.probe(8)> command which probes
2711 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2712 be mounted read-write, and some cannot be mounted at all).
2713
2714 C<rw> is a boolean flag.  Set it to true if you want to test
2715 if the volume can be mounted read-write.  Set it to false if
2716 you want to test if the volume can be mounted read-only.
2717
2718 The return value is an integer which C<0> if the operation
2719 would succeed, or some non-zero value documented in the
2720 L<ntfs-3g.probe(8)> manual page.");
2721
2722   ("sh", (RString "output", [String "command"]), 111, [],
2723    [], (* XXX needs tests *)
2724    "run a command via the shell",
2725    "\
2726 This call runs a command from the guest filesystem via the
2727 guest's C</bin/sh>.
2728
2729 This is like C<guestfs_command>, but passes the command to:
2730
2731  /bin/sh -c \"command\"
2732
2733 Depending on the guest's shell, this usually results in
2734 wildcards being expanded, shell expressions being interpolated
2735 and so on.
2736
2737 All the provisos about C<guestfs_command> apply to this call.");
2738
2739   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2740    [], (* XXX needs tests *)
2741    "run a command via the shell returning lines",
2742    "\
2743 This is the same as C<guestfs_sh>, but splits the result
2744 into a list of lines.
2745
2746 See also: C<guestfs_command_lines>");
2747
2748   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2749    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2750     * code in stubs.c, since all valid glob patterns must start with "/".
2751     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2752     *)
2753    [InitBasicFS, Always, TestOutputList (
2754       [["mkdir_p"; "/a/b/c"];
2755        ["touch"; "/a/b/c/d"];
2756        ["touch"; "/a/b/c/e"];
2757        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2758     InitBasicFS, Always, TestOutputList (
2759       [["mkdir_p"; "/a/b/c"];
2760        ["touch"; "/a/b/c/d"];
2761        ["touch"; "/a/b/c/e"];
2762        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2763     InitBasicFS, Always, TestOutputList (
2764       [["mkdir_p"; "/a/b/c"];
2765        ["touch"; "/a/b/c/d"];
2766        ["touch"; "/a/b/c/e"];
2767        ["glob_expand"; "/a/*/x/*"]], [])],
2768    "expand a wildcard path",
2769    "\
2770 This command searches for all the pathnames matching
2771 C<pattern> according to the wildcard expansion rules
2772 used by the shell.
2773
2774 If no paths match, then this returns an empty list
2775 (note: not an error).
2776
2777 It is just a wrapper around the C L<glob(3)> function
2778 with flags C<GLOB_MARK|GLOB_BRACE>.
2779 See that manual page for more details.");
2780
2781   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2782    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2783       [["scrub_device"; "/dev/sdc"]])],
2784    "scrub (securely wipe) a device",
2785    "\
2786 This command writes patterns over C<device> to make data retrieval
2787 more difficult.
2788
2789 It is an interface to the L<scrub(1)> program.  See that
2790 manual page for more details.");
2791
2792   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2793    [InitBasicFS, Always, TestRun (
2794       [["write_file"; "/file"; "content"; "0"];
2795        ["scrub_file"; "/file"]])],
2796    "scrub (securely wipe) a file",
2797    "\
2798 This command writes patterns over a file to make data retrieval
2799 more difficult.
2800
2801 The file is I<removed> after scrubbing.
2802
2803 It is an interface to the L<scrub(1)> program.  See that
2804 manual page for more details.");
2805
2806   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2807    [], (* XXX needs testing *)
2808    "scrub (securely wipe) free space",
2809    "\
2810 This command creates the directory C<dir> and then fills it
2811 with files until the filesystem is full, and scrubs the files
2812 as for C<guestfs_scrub_file>, and deletes them.
2813 The intention is to scrub any free space on the partition
2814 containing C<dir>.
2815
2816 It is an interface to the L<scrub(1)> program.  See that
2817 manual page for more details.");
2818
2819   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2820    [InitBasicFS, Always, TestRun (
2821       [["mkdir"; "/tmp"];
2822        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2823    "create a temporary directory",
2824    "\
2825 This command creates a temporary directory.  The
2826 C<template> parameter should be a full pathname for the
2827 temporary directory name with the final six characters being
2828 \"XXXXXX\".
2829
2830 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2831 the second one being suitable for Windows filesystems.
2832
2833 The name of the temporary directory that was created
2834 is returned.
2835
2836 The temporary directory is created with mode 0700
2837 and is owned by root.
2838
2839 The caller is responsible for deleting the temporary
2840 directory and its contents after use.
2841
2842 See also: L<mkdtemp(3)>");
2843
2844   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2845    [InitISOFS, Always, TestOutputInt (
2846       [["wc_l"; "/10klines"]], 10000)],
2847    "count lines in a file",
2848    "\
2849 This command counts the lines in a file, using the
2850 C<wc -l> external command.");
2851
2852   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2853    [InitISOFS, Always, TestOutputInt (
2854       [["wc_w"; "/10klines"]], 10000)],
2855    "count words in a file",
2856    "\
2857 This command counts the words in a file, using the
2858 C<wc -w> external command.");
2859
2860   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2861    [InitISOFS, Always, TestOutputInt (
2862       [["wc_c"; "/100kallspaces"]], 102400)],
2863    "count characters in a file",
2864    "\
2865 This command counts the characters in a file, using the
2866 C<wc -c> external command.");
2867
2868   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2869    [InitISOFS, Always, TestOutputList (
2870       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2871    "return first 10 lines of a file",
2872    "\
2873 This command returns up to the first 10 lines of a file as
2874 a list of strings.");
2875
2876   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2877    [InitISOFS, Always, TestOutputList (
2878       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2879     InitISOFS, Always, TestOutputList (
2880       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2881     InitISOFS, Always, TestOutputList (
2882       [["head_n"; "0"; "/10klines"]], [])],
2883    "return first N lines of a file",
2884    "\
2885 If the parameter C<nrlines> is a positive number, this returns the first
2886 C<nrlines> lines of the file C<path>.
2887
2888 If the parameter C<nrlines> is a negative number, this returns lines
2889 from the file C<path>, excluding the last C<nrlines> lines.
2890
2891 If the parameter C<nrlines> is zero, this returns an empty list.");
2892
2893   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2894    [InitISOFS, Always, TestOutputList (
2895       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2896    "return last 10 lines of a file",
2897    "\
2898 This command returns up to the last 10 lines of a file as
2899 a list of strings.");
2900
2901   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2902    [InitISOFS, Always, TestOutputList (
2903       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2904     InitISOFS, Always, TestOutputList (
2905       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2906     InitISOFS, Always, TestOutputList (
2907       [["tail_n"; "0"; "/10klines"]], [])],
2908    "return last N lines of a file",
2909    "\
2910 If the parameter C<nrlines> is a positive number, this returns the last
2911 C<nrlines> lines of the file C<path>.
2912
2913 If the parameter C<nrlines> is a negative number, this returns lines
2914 from the file C<path>, starting with the C<-nrlines>th line.
2915
2916 If the parameter C<nrlines> is zero, this returns an empty list.");
2917
2918   ("df", (RString "output", []), 125, [],
2919    [], (* XXX Tricky to test because it depends on the exact format
2920         * of the 'df' command and other imponderables.
2921         *)
2922    "report file system disk space usage",
2923    "\
2924 This command runs the C<df> command to report disk space used.
2925
2926 This command is mostly useful for interactive sessions.  It
2927 is I<not> intended that you try to parse the output string.
2928 Use C<statvfs> from programs.");
2929
2930   ("df_h", (RString "output", []), 126, [],
2931    [], (* XXX Tricky to test because it depends on the exact format
2932         * of the 'df' command and other imponderables.
2933         *)
2934    "report file system disk space usage (human readable)",
2935    "\
2936 This command runs the C<df -h> command to report disk space used
2937 in human-readable format.
2938
2939 This command is mostly useful for interactive sessions.  It
2940 is I<not> intended that you try to parse the output string.
2941 Use C<statvfs> from programs.");
2942
2943   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2944    [InitISOFS, Always, TestOutputInt (
2945       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2946    "estimate file space usage",
2947    "\
2948 This command runs the C<du -s> command to estimate file space
2949 usage for C<path>.
2950
2951 C<path> can be a file or a directory.  If C<path> is a directory
2952 then the estimate includes the contents of the directory and all
2953 subdirectories (recursively).
2954
2955 The result is the estimated size in I<kilobytes>
2956 (ie. units of 1024 bytes).");
2957
2958   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2959    [InitISOFS, Always, TestOutputList (
2960       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2961    "list files in an initrd",
2962    "\
2963 This command lists out files contained in an initrd.
2964
2965 The files are listed without any initial C</> character.  The
2966 files are listed in the order they appear (not necessarily
2967 alphabetical).  Directory names are listed as separate items.
2968
2969 Old Linux kernels (2.4 and earlier) used a compressed ext2
2970 filesystem as initrd.  We I<only> support the newer initramfs
2971 format (compressed cpio files).");
2972
2973   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2974    [],
2975    "mount a file using the loop device",
2976    "\
2977 This command lets you mount C<file> (a filesystem image
2978 in a file) on a mount point.  It is entirely equivalent to
2979 the command C<mount -o loop file mountpoint>.");
2980
2981   ("mkswap", (RErr, [Device "device"]), 130, [],
2982    [InitEmpty, Always, TestRun (
2983       [["part_disk"; "/dev/sda"; "mbr"];
2984        ["mkswap"; "/dev/sda1"]])],
2985    "create a swap partition",
2986    "\
2987 Create a swap partition on C<device>.");
2988
2989   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2990    [InitEmpty, Always, TestRun (
2991       [["part_disk"; "/dev/sda"; "mbr"];
2992        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2993    "create a swap partition with a label",
2994    "\
2995 Create a swap partition on C<device> with label C<label>.
2996
2997 Note that you cannot attach a swap label to a block device
2998 (eg. C</dev/sda>), just to a partition.  This appears to be
2999 a limitation of the kernel or swap tools.");
3000
3001   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3002    (let uuid = uuidgen () in
3003     [InitEmpty, Always, TestRun (
3004        [["part_disk"; "/dev/sda"; "mbr"];
3005         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3006    "create a swap partition with an explicit UUID",
3007    "\
3008 Create a swap partition on C<device> with UUID C<uuid>.");
3009
3010   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3011    [InitBasicFS, Always, TestOutputStruct (
3012       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3013        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3014        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3015     InitBasicFS, Always, TestOutputStruct (
3016       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3017        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3018    "make block, character or FIFO devices",
3019    "\
3020 This call creates block or character special devices, or
3021 named pipes (FIFOs).
3022
3023 The C<mode> parameter should be the mode, using the standard
3024 constants.  C<devmajor> and C<devminor> are the
3025 device major and minor numbers, only used when creating block
3026 and character special devices.
3027
3028 Note that, just like L<mknod(2)>, the mode must be bitwise
3029 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3030 just creates a regular file).  These constants are
3031 available in the standard Linux header files, or you can use
3032 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3033 which are wrappers around this command which bitwise OR
3034 in the appropriate constant for you.
3035
3036 The mode actually set is affected by the umask.");
3037
3038   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3039    [InitBasicFS, Always, TestOutputStruct (
3040       [["mkfifo"; "0o777"; "/node"];
3041        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3042    "make FIFO (named pipe)",
3043    "\
3044 This call creates a FIFO (named pipe) called C<path> with
3045 mode C<mode>.  It is just a convenient wrapper around
3046 C<guestfs_mknod>.
3047
3048 The mode actually set is affected by the umask.");
3049
3050   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3051    [InitBasicFS, Always, TestOutputStruct (
3052       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3053        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3054    "make block device node",
3055    "\
3056 This call creates a block device node called C<path> with
3057 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3058 It is just a convenient wrapper around C<guestfs_mknod>.
3059
3060 The mode actually set is affected by the umask.");
3061
3062   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3063    [InitBasicFS, Always, TestOutputStruct (
3064       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3065        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3066    "make char device node",
3067    "\
3068 This call creates a char device node called C<path> with
3069 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3070 It is just a convenient wrapper around C<guestfs_mknod>.
3071
3072 The mode actually set is affected by the umask.");
3073
3074   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3075    [InitEmpty, Always, TestOutputInt (
3076       [["umask"; "0o22"]], 0o22)],
3077    "set file mode creation mask (umask)",
3078    "\
3079 This function sets the mask used for creating new files and
3080 device nodes to C<mask & 0777>.
3081
3082 Typical umask values would be C<022> which creates new files
3083 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3084 C<002> which creates new files with permissions like
3085 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3086
3087 The default umask is C<022>.  This is important because it
3088 means that directories and device nodes will be created with
3089 C<0644> or C<0755> mode even if you specify C<0777>.
3090
3091 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3092
3093 This call returns the previous umask.");
3094
3095   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3096    [],
3097    "read directories entries",
3098    "\
3099 This returns the list of directory entries in directory C<dir>.
3100
3101 All entries in the directory are returned, including C<.> and
3102 C<..>.  The entries are I<not> sorted, but returned in the same
3103 order as the underlying filesystem.
3104
3105 Also this call returns basic file type information about each
3106 file.  The C<ftyp> field will contain one of the following characters:
3107
3108 =over 4
3109
3110 =item 'b'
3111
3112 Block special
3113
3114 =item 'c'
3115
3116 Char special
3117
3118 =item 'd'
3119
3120 Directory
3121
3122 =item 'f'
3123
3124 FIFO (named pipe)
3125
3126 =item 'l'
3127
3128 Symbolic link
3129
3130 =item 'r'
3131
3132 Regular file
3133
3134 =item 's'
3135
3136 Socket
3137
3138 =item 'u'
3139
3140 Unknown file type
3141
3142 =item '?'
3143
3144 The L<readdir(3)> returned a C<d_type> field with an
3145 unexpected value
3146
3147 =back
3148
3149 This function is primarily intended for use by programs.  To
3150 get a simple list of names, use C<guestfs_ls>.  To get a printable
3151 directory for human consumption, use C<guestfs_ll>.");
3152
3153   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3154    [],
3155    "create partitions on a block device",
3156    "\
3157 This is a simplified interface to the C<guestfs_sfdisk>
3158 command, where partition sizes are specified in megabytes
3159 only (rounded to the nearest cylinder) and you don't need
3160 to specify the cyls, heads and sectors parameters which
3161 were rarely if ever used anyway.
3162
3163 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3164 and C<guestfs_part_disk>");
3165
3166   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3167    [],
3168    "determine file type inside a compressed file",
3169    "\
3170 This command runs C<file> after first decompressing C<path>
3171 using C<method>.
3172
3173 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3174
3175 Since 1.0.63, use C<guestfs_file> instead which can now
3176 process compressed files.");
3177
3178   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3179    [],
3180    "list extended attributes of a file or directory",
3181    "\
3182 This call lists the extended attributes of the file or directory
3183 C<path>.
3184
3185 At the system call level, this is a combination of the
3186 L<listxattr(2)> and L<getxattr(2)> calls.
3187
3188 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3189
3190   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3191    [],
3192    "list extended attributes of a file or directory",
3193    "\
3194 This is the same as C<guestfs_getxattrs>, but if C<path>
3195 is a symbolic link, then it returns the extended attributes
3196 of the link itself.");
3197
3198   ("setxattr", (RErr, [String "xattr";
3199                        String "val"; Int "vallen"; (* will be BufferIn *)
3200                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3201    [],
3202    "set extended attribute of a file or directory",
3203    "\
3204 This call sets the extended attribute named C<xattr>
3205 of the file C<path> to the value C<val> (of length C<vallen>).
3206 The value is arbitrary 8 bit data.
3207
3208 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3209
3210   ("lsetxattr", (RErr, [String "xattr";
3211                         String "val"; Int "vallen"; (* will be BufferIn *)
3212                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3213    [],
3214    "set extended attribute of a file or directory",
3215    "\
3216 This is the same as C<guestfs_setxattr>, but if C<path>
3217 is a symbolic link, then it sets an extended attribute
3218 of the link itself.");
3219
3220   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3221    [],
3222    "remove extended attribute of a file or directory",
3223    "\
3224 This call removes the extended attribute named C<xattr>
3225 of the file C<path>.
3226
3227 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3228
3229   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3230    [],
3231    "remove extended attribute of a file or directory",
3232    "\
3233 This is the same as C<guestfs_removexattr>, but if C<path>
3234 is a symbolic link, then it removes an extended attribute
3235 of the link itself.");
3236
3237   ("mountpoints", (RHashtable "mps", []), 147, [],
3238    [],
3239    "show mountpoints",
3240    "\
3241 This call is similar to C<guestfs_mounts>.  That call returns
3242 a list of devices.  This one returns a hash table (map) of
3243 device name to directory where the device is mounted.");
3244
3245   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3246    (* This is a special case: while you would expect a parameter
3247     * of type "Pathname", that doesn't work, because it implies
3248     * NEED_ROOT in the generated calling code in stubs.c, and
3249     * this function cannot use NEED_ROOT.
3250     *)
3251    [],
3252    "create a mountpoint",
3253    "\
3254 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3255 specialized calls that can be used to create extra mountpoints
3256 before mounting the first filesystem.
3257
3258 These calls are I<only> necessary in some very limited circumstances,
3259 mainly the case where you want to mount a mix of unrelated and/or
3260 read-only filesystems together.
3261
3262 For example, live CDs often contain a \"Russian doll\" nest of
3263 filesystems, an ISO outer layer, with a squashfs image inside, with
3264 an ext2/3 image inside that.  You can unpack this as follows
3265 in guestfish:
3266
3267  add-ro Fedora-11-i686-Live.iso
3268  run
3269  mkmountpoint /cd
3270  mkmountpoint /squash
3271  mkmountpoint /ext3
3272  mount /dev/sda /cd
3273  mount-loop /cd/LiveOS/squashfs.img /squash
3274  mount-loop /squash/LiveOS/ext3fs.img /ext3
3275
3276 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3277
3278   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3279    [],
3280    "remove a mountpoint",
3281    "\
3282 This calls removes a mountpoint that was previously created
3283 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3284 for full details.");
3285
3286   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3287    [InitISOFS, Always, TestOutputBuffer (
3288       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3289     (* Test various near large, large and too large files (RHBZ#589039). *)
3290     InitBasicFS, Always, TestLastFail (
3291       [["touch"; "/a"];
3292        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3293        ["read_file"; "/a"]]);
3294     InitBasicFS, Always, TestLastFail (
3295       [["touch"; "/a"];
3296        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3297        ["read_file"; "/a"]]);
3298     InitBasicFS, Always, TestLastFail (
3299       [["touch"; "/a"];
3300        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3301        ["read_file"; "/a"]])],
3302    "read a file",
3303    "\
3304 This calls returns the contents of the file C<path> as a
3305 buffer.
3306
3307 Unlike C<guestfs_cat>, this function can correctly
3308 handle files that contain embedded ASCII NUL characters.
3309 However unlike C<guestfs_download>, this function is limited
3310 in the total size of file that can be handled.");
3311
3312   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3313    [InitISOFS, Always, TestOutputList (
3314       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3315     InitISOFS, Always, TestOutputList (
3316       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3317    "return lines matching a pattern",
3318    "\
3319 This calls the external C<grep> program and returns the
3320 matching lines.");
3321
3322   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3323    [InitISOFS, Always, TestOutputList (
3324       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3325    "return lines matching a pattern",
3326    "\
3327 This calls the external C<egrep> program and returns the
3328 matching lines.");
3329
3330   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3331    [InitISOFS, Always, TestOutputList (
3332       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3333    "return lines matching a pattern",
3334    "\
3335 This calls the external C<fgrep> program and returns the
3336 matching lines.");
3337
3338   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3339    [InitISOFS, Always, TestOutputList (
3340       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3341    "return lines matching a pattern",
3342    "\
3343 This calls the external C<grep -i> program and returns the
3344 matching lines.");
3345
3346   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3347    [InitISOFS, Always, TestOutputList (
3348       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3349    "return lines matching a pattern",
3350    "\
3351 This calls the external C<egrep -i> program and returns the
3352 matching lines.");
3353
3354   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3355    [InitISOFS, Always, TestOutputList (
3356       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3357    "return lines matching a pattern",
3358    "\
3359 This calls the external C<fgrep -i> program and returns the
3360 matching lines.");
3361
3362   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3363    [InitISOFS, Always, TestOutputList (
3364       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3365    "return lines matching a pattern",
3366    "\
3367 This calls the external C<zgrep> program and returns the
3368 matching lines.");
3369
3370   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3371    [InitISOFS, Always, TestOutputList (
3372       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3373    "return lines matching a pattern",
3374    "\
3375 This calls the external C<zegrep> program and returns the
3376 matching lines.");
3377
3378   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3379    [InitISOFS, Always, TestOutputList (
3380       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<zfgrep> program and returns the
3384 matching lines.");
3385
3386   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<zgrep -i> program and returns the
3392 matching lines.");
3393
3394   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<zegrep -i> program and returns the
3400 matching lines.");
3401
3402   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3403    [InitISOFS, Always, TestOutputList (
3404       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3405    "return lines matching a pattern",
3406    "\
3407 This calls the external C<zfgrep -i> program and returns the
3408 matching lines.");
3409
3410   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3411    [InitISOFS, Always, TestOutput (
3412       [["realpath"; "/../directory"]], "/directory")],
3413    "canonicalized absolute pathname",
3414    "\
3415 Return the canonicalized absolute pathname of C<path>.  The
3416 returned path has no C<.>, C<..> or symbolic link path elements.");
3417
3418   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3419    [InitBasicFS, Always, TestOutputStruct (
3420       [["touch"; "/a"];
3421        ["ln"; "/a"; "/b"];
3422        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3423    "create a hard link",
3424    "\
3425 This command creates a hard link using the C<ln> command.");
3426
3427   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3428    [InitBasicFS, Always, TestOutputStruct (
3429       [["touch"; "/a"];
3430        ["touch"; "/b"];
3431        ["ln_f"; "/a"; "/b"];
3432        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3433    "create a hard link",
3434    "\
3435 This command creates a hard link using the C<ln -f> command.
3436 The C<-f> option removes the link (C<linkname>) if it exists already.");
3437
3438   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3439    [InitBasicFS, Always, TestOutputStruct (
3440       [["touch"; "/a"];
3441        ["ln_s"; "a"; "/b"];
3442        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3443    "create a symbolic link",
3444    "\
3445 This command creates a symbolic link using the C<ln -s> command.");
3446
3447   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3448    [InitBasicFS, Always, TestOutput (
3449       [["mkdir_p"; "/a/b"];
3450        ["touch"; "/a/b/c"];
3451        ["ln_sf"; "../d"; "/a/b/c"];
3452        ["readlink"; "/a/b/c"]], "../d")],
3453    "create a symbolic link",
3454    "\
3455 This command creates a symbolic link using the C<ln -sf> command,
3456 The C<-f> option removes the link (C<linkname>) if it exists already.");
3457
3458   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3459    [] (* XXX tested above *),
3460    "read the target of a symbolic link",
3461    "\
3462 This command reads the target of a symbolic link.");
3463
3464   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3465    [InitBasicFS, Always, TestOutputStruct (
3466       [["fallocate"; "/a"; "1000000"];
3467        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3468    "preallocate a file in the guest filesystem",
3469    "\
3470 This command preallocates a file (containing zero bytes) named
3471 C<path> of size C<len> bytes.  If the file exists already, it
3472 is overwritten.
3473
3474 Do not confuse this with the guestfish-specific
3475 C<alloc> command which allocates a file in the host and
3476 attaches it as a device.");
3477
3478   ("swapon_device", (RErr, [Device "device"]), 170, [],
3479    [InitPartition, Always, TestRun (
3480       [["mkswap"; "/dev/sda1"];
3481        ["swapon_device"; "/dev/sda1"];
3482        ["swapoff_device"; "/dev/sda1"]])],
3483    "enable swap on device",
3484    "\
3485 This command enables the libguestfs appliance to use the
3486 swap device or partition named C<device>.  The increased
3487 memory is made available for all commands, for example
3488 those run using C<guestfs_command> or C<guestfs_sh>.
3489
3490 Note that you should not swap to existing guest swap
3491 partitions unless you know what you are doing.  They may
3492 contain hibernation information, or other information that
3493 the guest doesn't want you to trash.  You also risk leaking
3494 information about the host to the guest this way.  Instead,
3495 attach a new host device to the guest and swap on that.");
3496
3497   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3498    [], (* XXX tested by swapon_device *)
3499    "disable swap on device",
3500    "\
3501 This command disables the libguestfs appliance swap
3502 device or partition named C<device>.
3503 See C<guestfs_swapon_device>.");
3504
3505   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3506    [InitBasicFS, Always, TestRun (
3507       [["fallocate"; "/swap"; "8388608"];
3508        ["mkswap_file"; "/swap"];
3509        ["swapon_file"; "/swap"];
3510        ["swapoff_file"; "/swap"]])],
3511    "enable swap on file",
3512    "\
3513 This command enables swap to a file.
3514 See C<guestfs_swapon_device> for other notes.");
3515
3516   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3517    [], (* XXX tested by swapon_file *)
3518    "disable swap on file",
3519    "\
3520 This command disables the libguestfs appliance swap on file.");
3521
3522   ("swapon_label", (RErr, [String "label"]), 174, [],
3523    [InitEmpty, Always, TestRun (
3524       [["part_disk"; "/dev/sdb"; "mbr"];
3525        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3526        ["swapon_label"; "swapit"];
3527        ["swapoff_label"; "swapit"];
3528        ["zero"; "/dev/sdb"];
3529        ["blockdev_rereadpt"; "/dev/sdb"]])],
3530    "enable swap on labeled swap partition",
3531    "\
3532 This command enables swap to a labeled swap partition.
3533 See C<guestfs_swapon_device> for other notes.");
3534
3535   ("swapoff_label", (RErr, [String "label"]), 175, [],
3536    [], (* XXX tested by swapon_label *)
3537    "disable swap on labeled swap partition",
3538    "\
3539 This command disables the libguestfs appliance swap on
3540 labeled swap partition.");
3541
3542   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3543    (let uuid = uuidgen () in
3544     [InitEmpty, Always, TestRun (
3545        [["mkswap_U"; uuid; "/dev/sdb"];
3546         ["swapon_uuid"; uuid];
3547         ["swapoff_uuid"; uuid]])]),
3548    "enable swap on swap partition by UUID",
3549    "\
3550 This command enables swap to a swap partition with the given UUID.
3551 See C<guestfs_swapon_device> for other notes.");
3552
3553   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3554    [], (* XXX tested by swapon_uuid *)
3555    "disable swap on swap partition by UUID",
3556    "\
3557 This command disables the libguestfs appliance swap partition
3558 with the given UUID.");
3559
3560   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3561    [InitBasicFS, Always, TestRun (
3562       [["fallocate"; "/swap"; "8388608"];
3563        ["mkswap_file"; "/swap"]])],
3564    "create a swap file",
3565    "\
3566 Create a swap file.
3567
3568 This command just writes a swap file signature to an existing
3569 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3570
3571   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3572    [InitISOFS, Always, TestRun (
3573       [["inotify_init"; "0"]])],
3574    "create an inotify handle",
3575    "\
3576 This command creates a new inotify handle.
3577 The inotify subsystem can be used to notify events which happen to
3578 objects in the guest filesystem.
3579
3580 C<maxevents> is the maximum number of events which will be
3581 queued up between calls to C<guestfs_inotify_read> or
3582 C<guestfs_inotify_files>.
3583 If this is passed as C<0>, then the kernel (or previously set)
3584 default is used.  For Linux 2.6.29 the default was 16384 events.
3585 Beyond this limit, the kernel throws away events, but records
3586 the fact that it threw them away by setting a flag
3587 C<IN_Q_OVERFLOW> in the returned structure list (see
3588 C<guestfs_inotify_read>).
3589
3590 Before any events are generated, you have to add some
3591 watches to the internal watch list.  See:
3592 C<guestfs_inotify_add_watch>,
3593 C<guestfs_inotify_rm_watch> and
3594 C<guestfs_inotify_watch_all>.
3595
3596 Queued up events should be read periodically by calling
3597 C<guestfs_inotify_read>
3598 (or C<guestfs_inotify_files> which is just a helpful
3599 wrapper around C<guestfs_inotify_read>).  If you don't
3600 read the events out often enough then you risk the internal
3601 queue overflowing.
3602
3603 The handle should be closed after use by calling
3604 C<guestfs_inotify_close>.  This also removes any
3605 watches automatically.
3606
3607 See also L<inotify(7)> for an overview of the inotify interface
3608 as exposed by the Linux kernel, which is roughly what we expose
3609 via libguestfs.  Note that there is one global inotify handle
3610 per libguestfs instance.");
3611
3612   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3613    [InitBasicFS, Always, TestOutputList (
3614       [["inotify_init"; "0"];
3615        ["inotify_add_watch"; "/"; "1073741823"];
3616        ["touch"; "/a"];
3617        ["touch"; "/b"];
3618        ["inotify_files"]], ["a"; "b"])],
3619    "add an inotify watch",
3620    "\
3621 Watch C<path> for the events listed in C<mask>.
3622
3623 Note that if C<path> is a directory then events within that
3624 directory are watched, but this does I<not> happen recursively
3625 (in subdirectories).
3626
3627 Note for non-C or non-Linux callers: the inotify events are
3628 defined by the Linux kernel ABI and are listed in
3629 C</usr/include/sys/inotify.h>.");
3630
3631   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3632    [],
3633    "remove an inotify watch",
3634    "\
3635 Remove a previously defined inotify watch.
3636 See C<guestfs_inotify_add_watch>.");
3637
3638   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3639    [],
3640    "return list of inotify events",
3641    "\
3642 Return the complete queue of events that have happened
3643 since the previous read call.
3644
3645 If no events have happened, this returns an empty list.
3646
3647 I<Note>: In order to make sure that all events have been
3648 read, you must call this function repeatedly until it
3649 returns an empty list.  The reason is that the call will
3650 read events up to the maximum appliance-to-host message
3651 size and leave remaining events in the queue.");
3652
3653   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3654    [],
3655    "return list of watched files that had events",
3656    "\
3657 This function is a helpful wrapper around C<guestfs_inotify_read>
3658 which just returns a list of pathnames of objects that were
3659 touched.  The returned pathnames are sorted and deduplicated.");
3660
3661   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3662    [],
3663    "close the inotify handle",
3664    "\
3665 This closes the inotify handle which was previously
3666 opened by inotify_init.  It removes all watches, throws
3667 away any pending events, and deallocates all resources.");
3668
3669   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3670    [],
3671    "set SELinux security context",
3672    "\
3673 This sets the SELinux security context of the daemon
3674 to the string C<context>.
3675
3676 See the documentation about SELINUX in L<guestfs(3)>.");
3677
3678   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3679    [],
3680    "get SELinux security context",
3681    "\
3682 This gets the SELinux security context of the daemon.
3683
3684 See the documentation about SELINUX in L<guestfs(3)>,
3685 and C<guestfs_setcon>");
3686
3687   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3688    [InitEmpty, Always, TestOutput (
3689       [["part_disk"; "/dev/sda"; "mbr"];
3690        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3691        ["mount_options"; ""; "/dev/sda1"; "/"];
3692        ["write_file"; "/new"; "new file contents"; "0"];
3693        ["cat"; "/new"]], "new file contents")],
3694    "make a filesystem with block size",
3695    "\
3696 This call is similar to C<guestfs_mkfs>, but it allows you to
3697 control the block size of the resulting filesystem.  Supported
3698 block sizes depend on the filesystem type, but typically they
3699 are C<1024>, C<2048> or C<4096> only.");
3700
3701   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3702    [InitEmpty, Always, TestOutput (
3703       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3704        ["mke2journal"; "4096"; "/dev/sda1"];
3705        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3706        ["mount_options"; ""; "/dev/sda2"; "/"];
3707        ["write_file"; "/new"; "new file contents"; "0"];
3708        ["cat"; "/new"]], "new file contents")],
3709    "make ext2/3/4 external journal",
3710    "\
3711 This creates an ext2 external journal on C<device>.  It is equivalent
3712 to the command:
3713
3714  mke2fs -O journal_dev -b blocksize device");
3715
3716   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3717    [InitEmpty, Always, TestOutput (
3718       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3719        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3720        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3721        ["mount_options"; ""; "/dev/sda2"; "/"];
3722        ["write_file"; "/new"; "new file contents"; "0"];
3723        ["cat"; "/new"]], "new file contents")],
3724    "make ext2/3/4 external journal with label",
3725    "\
3726 This creates an ext2 external journal on C<device> with label C<label>.");
3727
3728   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3729    (let uuid = uuidgen () in
3730     [InitEmpty, Always, TestOutput (
3731        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3732         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3733         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3734         ["mount_options"; ""; "/dev/sda2"; "/"];
3735         ["write_file"; "/new"; "new file contents"; "0"];
3736         ["cat"; "/new"]], "new file contents")]),
3737    "make ext2/3/4 external journal with UUID",
3738    "\
3739 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3740
3741   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3742    [],
3743    "make ext2/3/4 filesystem with external journal",
3744    "\
3745 This creates an ext2/3/4 filesystem on C<device> with
3746 an external journal on C<journal>.  It is equivalent
3747 to the command:
3748
3749  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3750
3751 See also C<guestfs_mke2journal>.");
3752
3753   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3754    [],
3755    "make ext2/3/4 filesystem with external journal",
3756    "\
3757 This creates an ext2/3/4 filesystem on C<device> with
3758 an external journal on the journal labeled C<label>.
3759
3760 See also C<guestfs_mke2journal_L>.");
3761
3762   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3763    [],
3764    "make ext2/3/4 filesystem with external journal",
3765    "\
3766 This creates an ext2/3/4 filesystem on C<device> with
3767 an external journal on the journal with UUID C<uuid>.
3768
3769 See also C<guestfs_mke2journal_U>.");
3770
3771   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3772    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3773    "load a kernel module",
3774    "\
3775 This loads a kernel module in the appliance.
3776
3777 The kernel module must have been whitelisted when libguestfs
3778 was built (see C<appliance/kmod.whitelist.in> in the source).");
3779
3780   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3781    [InitNone, Always, TestOutput (
3782       [["echo_daemon"; "This is a test"]], "This is a test"
3783     )],
3784    "echo arguments back to the client",
3785    "\
3786 This command concatenates the list of C<words> passed with single spaces
3787 between them and returns the resulting string.
3788
3789 You can use this command to test the connection through to the daemon.
3790
3791 See also C<guestfs_ping_daemon>.");
3792
3793   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3794    [], (* There is a regression test for this. *)
3795    "find all files and directories, returning NUL-separated list",
3796    "\
3797 This command lists out all files and directories, recursively,
3798 starting at C<directory>, placing the resulting list in the
3799 external file called C<files>.
3800
3801 This command works the same way as C<guestfs_find> with the
3802 following exceptions:
3803
3804 =over 4
3805
3806 =item *
3807
3808 The resulting list is written to an external file.
3809
3810 =item *
3811
3812 Items (filenames) in the result are separated
3813 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3814
3815 =item *
3816
3817 This command is not limited in the number of names that it
3818 can return.
3819
3820 =item *
3821
3822 The result list is not sorted.
3823
3824 =back");
3825
3826   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3827    [InitISOFS, Always, TestOutput (
3828       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3829     InitISOFS, Always, TestOutput (
3830       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3831     InitISOFS, Always, TestOutput (
3832       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3833     InitISOFS, Always, TestLastFail (
3834       [["case_sensitive_path"; "/Known-1/"]]);
3835     InitBasicFS, Always, TestOutput (
3836       [["mkdir"; "/a"];
3837        ["mkdir"; "/a/bbb"];
3838        ["touch"; "/a/bbb/c"];
3839        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3840     InitBasicFS, Always, TestOutput (
3841       [["mkdir"; "/a"];
3842        ["mkdir"; "/a/bbb"];
3843        ["touch"; "/a/bbb/c"];
3844        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3845     InitBasicFS, Always, TestLastFail (
3846       [["mkdir"; "/a"];
3847        ["mkdir"; "/a/bbb"];
3848        ["touch"; "/a/bbb/c"];
3849        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3850    "return true path on case-insensitive filesystem",
3851    "\
3852 This can be used to resolve case insensitive paths on
3853 a filesystem which is case sensitive.  The use case is
3854 to resolve paths which you have read from Windows configuration
3855 files or the Windows Registry, to the true path.
3856
3857 The command handles a peculiarity of the Linux ntfs-3g
3858 filesystem driver (and probably others), which is that although
3859 the underlying filesystem is case-insensitive, the driver
3860 exports the filesystem to Linux as case-sensitive.
3861
3862 One consequence of this is that special directories such
3863 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3864 (or other things) depending on the precise details of how
3865 they were created.  In Windows itself this would not be
3866 a problem.
3867
3868 Bug or feature?  You decide:
3869 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3870
3871 This function resolves the true case of each element in the
3872 path and returns the case-sensitive path.
3873
3874 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3875 might return C<\"/WINDOWS/system32\"> (the exact return value
3876 would depend on details of how the directories were originally
3877 created under Windows).
3878
3879 I<Note>:
3880 This function does not handle drive names, backslashes etc.
3881
3882 See also C<guestfs_realpath>.");
3883
3884   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3885    [InitBasicFS, Always, TestOutput (
3886       [["vfs_type"; "/dev/sda1"]], "ext2")],
3887    "get the Linux VFS type corresponding to a mounted device",
3888    "\
3889 This command gets the block device type corresponding to
3890 a mounted device called C<device>.
3891
3892 Usually the result is the name of the Linux VFS module that
3893 is used to mount this device (probably determined automatically
3894 if you used the C<guestfs_mount> call).");
3895
3896   ("truncate", (RErr, [Pathname "path"]), 199, [],
3897    [InitBasicFS, Always, TestOutputStruct (
3898       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3899        ["truncate"; "/test"];
3900        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3901    "truncate a file to zero size",
3902    "\
3903 This command truncates C<path> to a zero-length file.  The
3904 file must exist already.");
3905
3906   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3907    [InitBasicFS, Always, TestOutputStruct (
3908       [["touch"; "/test"];
3909        ["truncate_size"; "/test"; "1000"];
3910        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3911    "truncate a file to a particular size",
3912    "\
3913 This command truncates C<path> to size C<size> bytes.  The file
3914 must exist already.  If the file is smaller than C<size> then
3915 the file is extended to the required size with null bytes.");
3916
3917   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3918    [InitBasicFS, Always, TestOutputStruct (
3919       [["touch"; "/test"];
3920        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3921        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3922    "set timestamp of a file with nanosecond precision",
3923    "\
3924 This command sets the timestamps of a file with nanosecond
3925 precision.
3926
3927 C<atsecs, atnsecs> are the last access time (atime) in secs and
3928 nanoseconds from the epoch.
3929
3930 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3931 secs and nanoseconds from the epoch.
3932
3933 If the C<*nsecs> field contains the special value C<-1> then
3934 the corresponding timestamp is set to the current time.  (The
3935 C<*secs> field is ignored in this case).
3936
3937 If the C<*nsecs> field contains the special value C<-2> then
3938 the corresponding timestamp is left unchanged.  (The
3939 C<*secs> field is ignored in this case).");
3940
3941   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3942    [InitBasicFS, Always, TestOutputStruct (
3943       [["mkdir_mode"; "/test"; "0o111"];
3944        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3945    "create a directory with a particular mode",
3946    "\
3947 This command creates a directory, setting the initial permissions
3948 of the directory to C<mode>.
3949
3950 For common Linux filesystems, the actual mode which is set will
3951 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3952 interpret the mode in other ways.
3953
3954 See also C<guestfs_mkdir>, C<guestfs_umask>");
3955
3956   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3957    [], (* XXX *)
3958    "change file owner and group",
3959    "\
3960 Change the file owner to C<owner> and group to C<group>.
3961 This is like C<guestfs_chown> but if C<path> is a symlink then
3962 the link itself is changed, not the target.
3963
3964 Only numeric uid and gid are supported.  If you want to use
3965 names, you will need to locate and parse the password file
3966 yourself (Augeas support makes this relatively easy).");
3967
3968   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3969    [], (* XXX *)
3970    "lstat on multiple files",
3971    "\
3972 This call allows you to perform the C<guestfs_lstat> operation
3973 on multiple files, where all files are in the directory C<path>.
3974 C<names> is the list of files from this directory.
3975
3976 On return you get a list of stat structs, with a one-to-one
3977 correspondence to the C<names> list.  If any name did not exist
3978 or could not be lstat'd, then the C<ino> field of that structure
3979 is set to C<-1>.
3980
3981 This call is intended for programs that want to efficiently
3982 list a directory contents without making many round-trips.
3983 See also C<guestfs_lxattrlist> for a similarly efficient call
3984 for getting extended attributes.  Very long directory listings
3985 might cause the protocol message size to be exceeded, causing
3986 this call to fail.  The caller must split up such requests
3987 into smaller groups of names.");
3988
3989   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3990    [], (* XXX *)
3991    "lgetxattr on multiple files",
3992    "\
3993 This call allows you to get the extended attributes
3994 of multiple files, where all files are in the directory C<path>.
3995 C<names> is the list of files from this directory.
3996
3997 On return you get a flat list of xattr structs which must be
3998 interpreted sequentially.  The first xattr struct always has a zero-length
3999 C<attrname>.  C<attrval> in this struct is zero-length
4000 to indicate there was an error doing C<lgetxattr> for this
4001 file, I<or> is a C string which is a decimal number
4002 (the number of following attributes for this file, which could
4003 be C<\"0\">).  Then after the first xattr struct are the
4004 zero or more attributes for the first named file.
4005 This repeats for the second and subsequent files.
4006
4007 This call is intended for programs that want to efficiently
4008 list a directory contents without making many round-trips.
4009 See also C<guestfs_lstatlist> for a similarly efficient call
4010 for getting standard stats.  Very long directory listings
4011 might cause the protocol message size to be exceeded, causing
4012 this call to fail.  The caller must split up such requests
4013 into smaller groups of names.");
4014
4015   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4016    [], (* XXX *)
4017    "readlink on multiple files",
4018    "\
4019 This call allows you to do a C<readlink> operation
4020 on multiple files, where all files are in the directory C<path>.
4021 C<names> is the list of files from this directory.
4022
4023 On return you get a list of strings, with a one-to-one
4024 correspondence to the C<names> list.  Each string is the
4025 value of the symbol link.
4026
4027 If the C<readlink(2)> operation fails on any name, then
4028 the corresponding result string is the empty string C<\"\">.
4029 However the whole operation is completed even if there
4030 were C<readlink(2)> errors, and so you can call this
4031 function with names where you don't know if they are
4032 symbolic links already (albeit slightly less efficient).
4033
4034 This call is intended for programs that want to efficiently
4035 list a directory contents without making many round-trips.
4036 Very long directory listings might cause the protocol
4037 message size to be exceeded, causing
4038 this call to fail.  The caller must split up such requests
4039 into smaller groups of names.");
4040
4041   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4042    [InitISOFS, Always, TestOutputBuffer (
4043       [["pread"; "/known-4"; "1"; "3"]], "\n");
4044     InitISOFS, Always, TestOutputBuffer (
4045       [["pread"; "/empty"; "0"; "100"]], "")],
4046    "read part of a file",
4047    "\
4048 This command lets you read part of a file.  It reads C<count>
4049 bytes of the file, starting at C<offset>, from file C<path>.
4050
4051 This may read fewer bytes than requested.  For further details
4052 see the L<pread(2)> system call.");
4053
4054   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4055    [InitEmpty, Always, TestRun (
4056       [["part_init"; "/dev/sda"; "gpt"]])],
4057    "create an empty partition table",
4058    "\
4059 This creates an empty partition table on C<device> of one of the
4060 partition types listed below.  Usually C<parttype> should be
4061 either C<msdos> or C<gpt> (for large disks).
4062
4063 Initially there are no partitions.  Following this, you should
4064 call C<guestfs_part_add> for each partition required.
4065
4066 Possible values for C<parttype> are:
4067
4068 =over 4
4069
4070 =item B<efi> | B<gpt>
4071
4072 Intel EFI / GPT partition table.
4073
4074 This is recommended for >= 2 TB partitions that will be accessed
4075 from Linux and Intel-based Mac OS X.  It also has limited backwards
4076 compatibility with the C<mbr> format.
4077
4078 =item B<mbr> | B<msdos>
4079
4080 The standard PC \"Master Boot Record\" (MBR) format used
4081 by MS-DOS and Windows.  This partition type will B<only> work
4082 for device sizes up to 2 TB.  For large disks we recommend
4083 using C<gpt>.
4084
4085 =back
4086
4087 Other partition table types that may work but are not
4088 supported include:
4089
4090 =over 4
4091
4092 =item B<aix>
4093
4094 AIX disk labels.
4095
4096 =item B<amiga> | B<rdb>
4097
4098 Amiga \"Rigid Disk Block\" format.
4099
4100 =item B<bsd>
4101
4102 BSD disk labels.
4103
4104 =item B<dasd>
4105
4106 DASD, used on IBM mainframes.
4107
4108 =item B<dvh>
4109
4110 MIPS/SGI volumes.
4111
4112 =item B<mac>
4113
4114 Old Mac partition format.  Modern Macs use C<gpt>.
4115
4116 =item B<pc98>
4117
4118 NEC PC-98 format, common in Japan apparently.
4119
4120 =item B<sun>
4121
4122 Sun disk labels.
4123
4124 =back");
4125
4126   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4127    [InitEmpty, Always, TestRun (
4128       [["part_init"; "/dev/sda"; "mbr"];
4129        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4130     InitEmpty, Always, TestRun (
4131       [["part_init"; "/dev/sda"; "gpt"];
4132        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4133        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4134     InitEmpty, Always, TestRun (
4135       [["part_init"; "/dev/sda"; "mbr"];
4136        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4137        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4138        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4139        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4140    "add a partition to the device",
4141    "\
4142 This command adds a partition to C<device>.  If there is no partition
4143 table on the device, call C<guestfs_part_init> first.
4144
4145 The C<prlogex> parameter is the type of partition.  Normally you
4146 should pass C<p> or C<primary> here, but MBR partition tables also
4147 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4148 types.
4149
4150 C<startsect> and C<endsect> are the start and end of the partition
4151 in I<sectors>.  C<endsect> may be negative, which means it counts
4152 backwards from the end of the disk (C<-1> is the last sector).
4153
4154 Creating a partition which covers the whole disk is not so easy.
4155 Use C<guestfs_part_disk> to do that.");
4156
4157   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4158    [InitEmpty, Always, TestRun (
4159       [["part_disk"; "/dev/sda"; "mbr"]]);
4160     InitEmpty, Always, TestRun (
4161       [["part_disk"; "/dev/sda"; "gpt"]])],
4162    "partition whole disk with a single primary partition",
4163    "\
4164 This command is simply a combination of C<guestfs_part_init>
4165 followed by C<guestfs_part_add> to create a single primary partition
4166 covering the whole disk.
4167
4168 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4169 but other possible values are described in C<guestfs_part_init>.");
4170
4171   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4172    [InitEmpty, Always, TestRun (
4173       [["part_disk"; "/dev/sda"; "mbr"];
4174        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4175    "make a partition bootable",
4176    "\
4177 This sets the bootable flag on partition numbered C<partnum> on
4178 device C<device>.  Note that partitions are numbered from 1.
4179
4180 The bootable flag is used by some operating systems (notably
4181 Windows) to determine which partition to boot from.  It is by
4182 no means universally recognized.");
4183
4184   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4185    [InitEmpty, Always, TestRun (
4186       [["part_disk"; "/dev/sda"; "gpt"];
4187        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4188    "set partition name",
4189    "\
4190 This sets the partition name on partition numbered C<partnum> on
4191 device C<device>.  Note that partitions are numbered from 1.
4192
4193 The partition name can only be set on certain types of partition
4194 table.  This works on C<gpt> but not on C<mbr> partitions.");
4195
4196   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4197    [], (* XXX Add a regression test for this. *)
4198    "list partitions on a device",
4199    "\
4200 This command parses the partition table on C<device> and
4201 returns the list of partitions found.
4202
4203 The fields in the returned structure are:
4204
4205 =over 4
4206
4207 =item B<part_num>
4208
4209 Partition number, counting from 1.
4210
4211 =item B<part_start>
4212
4213 Start of the partition I<in bytes>.  To get sectors you have to
4214 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4215
4216 =item B<part_end>
4217
4218 End of the partition in bytes.
4219
4220 =item B<part_size>
4221
4222 Size of the partition in bytes.
4223
4224 =back");
4225
4226   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4227    [InitEmpty, Always, TestOutput (
4228       [["part_disk"; "/dev/sda"; "gpt"];
4229        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4230    "get the partition table type",
4231    "\
4232 This command examines the partition table on C<device> and
4233 returns the partition table type (format) being used.
4234
4235 Common return values include: C<msdos> (a DOS/Windows style MBR
4236 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4237 values are possible, although unusual.  See C<guestfs_part_init>
4238 for a full list.");
4239
4240   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4241    [InitBasicFS, Always, TestOutputBuffer (
4242       [["fill"; "0x63"; "10"; "/test"];
4243        ["read_file"; "/test"]], "cccccccccc")],
4244    "fill a file with octets",
4245    "\
4246 This command creates a new file called C<path>.  The initial
4247 content of the file is C<len> octets of C<c>, where C<c>
4248 must be a number in the range C<[0..255]>.
4249
4250 To fill a file with zero bytes (sparsely), it is
4251 much more efficient to use C<guestfs_truncate_size>.");
4252
4253   ("available", (RErr, [StringList "groups"]), 216, [],
4254    [InitNone, Always, TestRun [["available"; ""]]],
4255    "test availability of some parts of the API",
4256    "\
4257 This command is used to check the availability of some
4258 groups of functionality in the appliance, which not all builds of
4259 the libguestfs appliance will be able to provide.
4260
4261 The libguestfs groups, and the functions that those
4262 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4263
4264 The argument C<groups> is a list of group names, eg:
4265 C<[\"inotify\", \"augeas\"]> would check for the availability of
4266 the Linux inotify functions and Augeas (configuration file
4267 editing) functions.
4268
4269 The command returns no error if I<all> requested groups are available.
4270
4271 It fails with an error if one or more of the requested
4272 groups is unavailable in the appliance.
4273
4274 If an unknown group name is included in the
4275 list of groups then an error is always returned.
4276
4277 I<Notes:>
4278
4279 =over 4
4280
4281 =item *
4282
4283 You must call C<guestfs_launch> before calling this function.
4284
4285 The reason is because we don't know what groups are
4286 supported by the appliance/daemon until it is running and can
4287 be queried.
4288
4289 =item *
4290
4291 If a group of functions is available, this does not necessarily
4292 mean that they will work.  You still have to check for errors
4293 when calling individual API functions even if they are
4294 available.
4295
4296 =item *
4297
4298 It is usually the job of distro packagers to build
4299 complete functionality into the libguestfs appliance.
4300 Upstream libguestfs, if built from source with all
4301 requirements satisfied, will support everything.
4302
4303 =item *
4304
4305 This call was added in version C<1.0.80>.  In previous
4306 versions of libguestfs all you could do would be to speculatively
4307 execute a command to find out if the daemon implemented it.
4308 See also C<guestfs_version>.
4309
4310 =back");
4311
4312   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4313    [InitBasicFS, Always, TestOutputBuffer (
4314       [["write_file"; "/src"; "hello, world"; "0"];
4315        ["dd"; "/src"; "/dest"];
4316        ["read_file"; "/dest"]], "hello, world")],
4317    "copy from source to destination using dd",
4318    "\
4319 This command copies from one source device or file C<src>
4320 to another destination device or file C<dest>.  Normally you
4321 would use this to copy to or from a device or partition, for
4322 example to duplicate a filesystem.
4323
4324 If the destination is a device, it must be as large or larger
4325 than the source file or device, otherwise the copy will fail.
4326 This command cannot do partial copies (see C<guestfs_copy_size>).");
4327
4328   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4329    [InitBasicFS, Always, TestOutputInt (
4330       [["write_file"; "/file"; "hello, world"; "0"];
4331        ["filesize"; "/file"]], 12)],
4332    "return the size of the file in bytes",
4333    "\
4334 This command returns the size of C<file> in bytes.
4335
4336 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4337 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4338 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4339
4340   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4341    [InitBasicFSonLVM, Always, TestOutputList (
4342       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4343        ["lvs"]], ["/dev/VG/LV2"])],
4344    "rename an LVM logical volume",
4345    "\
4346 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4347
4348   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4349    [InitBasicFSonLVM, Always, TestOutputList (
4350       [["umount"; "/"];
4351        ["vg_activate"; "false"; "VG"];
4352        ["vgrename"; "VG"; "VG2"];
4353        ["vg_activate"; "true"; "VG2"];
4354        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4355        ["vgs"]], ["VG2"])],
4356    "rename an LVM volume group",
4357    "\
4358 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4359
4360   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4361    [InitISOFS, Always, TestOutputBuffer (
4362       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4363    "list the contents of a single file in an initrd",
4364    "\
4365 This command unpacks the file C<filename> from the initrd file
4366 called C<initrdpath>.  The filename must be given I<without> the
4367 initial C</> character.
4368
4369 For example, in guestfish you could use the following command
4370 to examine the boot script (usually called C</init>)
4371 contained in a Linux initrd or initramfs image:
4372
4373  initrd-cat /boot/initrd-<version>.img init
4374
4375 See also C<guestfs_initrd_list>.");
4376
4377   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4378    [],
4379    "get the UUID of a physical volume",
4380    "\
4381 This command returns the UUID of the LVM PV C<device>.");
4382
4383   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4384    [],
4385    "get the UUID of a volume group",
4386    "\
4387 This command returns the UUID of the LVM VG named C<vgname>.");
4388
4389   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4390    [],
4391    "get the UUID of a logical volume",
4392    "\
4393 This command returns the UUID of the LVM LV C<device>.");
4394
4395   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4396    [],
4397    "get the PV UUIDs containing the volume group",
4398    "\
4399 Given a VG called C<vgname>, this returns the UUIDs of all
4400 the physical volumes that this volume group resides on.
4401
4402 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4403 calls to associate physical volumes and volume groups.
4404
4405 See also C<guestfs_vglvuuids>.");
4406
4407   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4408    [],
4409    "get the LV UUIDs of all LVs in the volume group",
4410    "\
4411 Given a VG called C<vgname>, this returns the UUIDs of all
4412 the logical volumes created in this volume group.
4413
4414 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4415 calls to associate logical volumes and volume groups.
4416
4417 See also C<guestfs_vgpvuuids>.");
4418
4419   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4420    [InitBasicFS, Always, TestOutputBuffer (
4421       [["write_file"; "/src"; "hello, world"; "0"];
4422        ["copy_size"; "/src"; "/dest"; "5"];
4423        ["read_file"; "/dest"]], "hello")],
4424    "copy size bytes from source to destination using dd",
4425    "\
4426 This command copies exactly C<size> bytes from one source device
4427 or file C<src> to another destination device or file C<dest>.
4428
4429 Note this will fail if the source is too short or if the destination
4430 is not large enough.");
4431
4432   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4433    [InitEmpty, Always, TestRun (
4434       [["part_init"; "/dev/sda"; "mbr"];
4435        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4436        ["part_del"; "/dev/sda"; "1"]])],
4437    "delete a partition",
4438    "\
4439 This command deletes the partition numbered C<partnum> on C<device>.
4440
4441 Note that in the case of MBR partitioning, deleting an
4442 extended partition also deletes any logical partitions
4443 it contains.");
4444
4445   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4446    [InitEmpty, Always, TestOutputTrue (
4447       [["part_init"; "/dev/sda"; "mbr"];
4448        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4449        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4450        ["part_get_bootable"; "/dev/sda"; "1"]])],
4451    "return true if a partition is bootable",
4452    "\
4453 This command returns true if the partition C<partnum> on
4454 C<device> has the bootable flag set.
4455
4456 See also C<guestfs_part_set_bootable>.");
4457
4458   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4459    [InitEmpty, Always, TestOutputInt (
4460       [["part_init"; "/dev/sda"; "mbr"];
4461        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4462        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4463        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4464    "get the MBR type byte (ID byte) from a partition",
4465    "\
4466 Returns the MBR type byte (also known as the ID byte) from
4467 the numbered partition C<partnum>.
4468
4469 Note that only MBR (old DOS-style) partitions have type bytes.
4470 You will get undefined results for other partition table
4471 types (see C<guestfs_part_get_parttype>).");
4472
4473   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4474    [], (* tested by part_get_mbr_id *)
4475    "set the MBR type byte (ID byte) of a partition",
4476    "\
4477 Sets the MBR type byte (also known as the ID byte) of
4478 the numbered partition C<partnum> to C<idbyte>.  Note
4479 that the type bytes quoted in most documentation are
4480 in fact hexadecimal numbers, but usually documented
4481 without any leading \"0x\" which might be confusing.
4482
4483 Note that only MBR (old DOS-style) partitions have type bytes.
4484 You will get undefined results for other partition table
4485 types (see C<guestfs_part_get_parttype>).");
4486
4487 ]
4488
4489 let all_functions = non_daemon_functions @ daemon_functions
4490
4491 (* In some places we want the functions to be displayed sorted
4492  * alphabetically, so this is useful:
4493  *)
4494 let all_functions_sorted =
4495   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4496                compare n1 n2) all_functions
4497
4498 (* Field types for structures. *)
4499 type field =
4500   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4501   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4502   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4503   | FUInt32
4504   | FInt32
4505   | FUInt64
4506   | FInt64
4507   | FBytes                      (* Any int measure that counts bytes. *)
4508   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4509   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4510
4511 (* Because we generate extra parsing code for LVM command line tools,
4512  * we have to pull out the LVM columns separately here.
4513  *)
4514 let lvm_pv_cols = [
4515   "pv_name", FString;
4516   "pv_uuid", FUUID;
4517   "pv_fmt", FString;
4518   "pv_size", FBytes;
4519   "dev_size", FBytes;
4520   "pv_free", FBytes;
4521   "pv_used", FBytes;
4522   "pv_attr", FString (* XXX *);
4523   "pv_pe_count", FInt64;
4524   "pv_pe_alloc_count", FInt64;
4525   "pv_tags", FString;
4526   "pe_start", FBytes;
4527   "pv_mda_count", FInt64;
4528   "pv_mda_free", FBytes;
4529   (* Not in Fedora 10:
4530      "pv_mda_size", FBytes;
4531   *)
4532 ]
4533 let lvm_vg_cols = [
4534   "vg_name", FString;
4535   "vg_uuid", FUUID;
4536   "vg_fmt", FString;
4537   "vg_attr", FString (* XXX *);
4538   "vg_size", FBytes;
4539   "vg_free", FBytes;
4540   "vg_sysid", FString;
4541   "vg_extent_size", FBytes;
4542   "vg_extent_count", FInt64;
4543   "vg_free_count", FInt64;
4544   "max_lv", FInt64;
4545   "max_pv", FInt64;
4546   "pv_count", FInt64;
4547   "lv_count", FInt64;
4548   "snap_count", FInt64;
4549   "vg_seqno", FInt64;
4550   "vg_tags", FString;
4551   "vg_mda_count", FInt64;
4552   "vg_mda_free", FBytes;
4553   (* Not in Fedora 10:
4554      "vg_mda_size", FBytes;
4555   *)
4556 ]
4557 let lvm_lv_cols = [
4558   "lv_name", FString;
4559   "lv_uuid", FUUID;
4560   "lv_attr", FString (* XXX *);
4561   "lv_major", FInt64;
4562   "lv_minor", FInt64;
4563   "lv_kernel_major", FInt64;
4564   "lv_kernel_minor", FInt64;
4565   "lv_size", FBytes;
4566   "seg_count", FInt64;
4567   "origin", FString;
4568   "snap_percent", FOptPercent;
4569   "copy_percent", FOptPercent;
4570   "move_pv", FString;
4571   "lv_tags", FString;
4572   "mirror_log", FString;
4573   "modules", FString;
4574 ]
4575
4576 (* Names and fields in all structures (in RStruct and RStructList)
4577  * that we support.
4578  *)
4579 let structs = [
4580   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4581    * not use this struct in any new code.
4582    *)
4583   "int_bool", [
4584     "i", FInt32;                (* for historical compatibility *)
4585     "b", FInt32;                (* for historical compatibility *)
4586   ];
4587
4588   (* LVM PVs, VGs, LVs. *)
4589   "lvm_pv", lvm_pv_cols;
4590   "lvm_vg", lvm_vg_cols;
4591   "lvm_lv", lvm_lv_cols;
4592
4593   (* Column names and types from stat structures.
4594    * NB. Can't use things like 'st_atime' because glibc header files
4595    * define some of these as macros.  Ugh.
4596    *)
4597   "stat", [
4598     "dev", FInt64;
4599     "ino", FInt64;
4600     "mode", FInt64;
4601     "nlink", FInt64;
4602     "uid", FInt64;
4603     "gid", FInt64;
4604     "rdev", FInt64;
4605     "size", FInt64;
4606     "blksize", FInt64;
4607     "blocks", FInt64;
4608     "atime", FInt64;
4609     "mtime", FInt64;
4610     "ctime", FInt64;
4611   ];
4612   "statvfs", [
4613     "bsize", FInt64;
4614     "frsize", FInt64;
4615     "blocks", FInt64;
4616     "bfree", FInt64;
4617     "bavail", FInt64;
4618     "files", FInt64;
4619     "ffree", FInt64;
4620     "favail", FInt64;
4621     "fsid", FInt64;
4622     "flag", FInt64;
4623     "namemax", FInt64;
4624   ];
4625
4626   (* Column names in dirent structure. *)
4627   "dirent", [
4628     "ino", FInt64;
4629     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4630     "ftyp", FChar;
4631     "name", FString;
4632   ];
4633
4634   (* Version numbers. *)
4635   "version", [
4636     "major", FInt64;
4637     "minor", FInt64;
4638     "release", FInt64;
4639     "extra", FString;
4640   ];
4641
4642   (* Extended attribute. *)
4643   "xattr", [
4644     "attrname", FString;
4645     "attrval", FBuffer;
4646   ];
4647
4648   (* Inotify events. *)
4649   "inotify_event", [
4650     "in_wd", FInt64;
4651     "in_mask", FUInt32;
4652     "in_cookie", FUInt32;
4653     "in_name", FString;
4654   ];
4655
4656   (* Partition table entry. *)
4657   "partition", [
4658     "part_num", FInt32;
4659     "part_start", FBytes;
4660     "part_end", FBytes;
4661     "part_size", FBytes;
4662   ];
4663 ] (* end of structs *)
4664
4665 (* Ugh, Java has to be different ..
4666  * These names are also used by the Haskell bindings.
4667  *)
4668 let java_structs = [
4669   "int_bool", "IntBool";
4670   "lvm_pv", "PV";
4671   "lvm_vg", "VG";
4672   "lvm_lv", "LV";
4673   "stat", "Stat";
4674   "statvfs", "StatVFS";
4675   "dirent", "Dirent";
4676   "version", "Version";
4677   "xattr", "XAttr";
4678   "inotify_event", "INotifyEvent";
4679   "partition", "Partition";
4680 ]
4681
4682 (* What structs are actually returned. *)
4683 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4684
4685 (* Returns a list of RStruct/RStructList structs that are returned
4686  * by any function.  Each element of returned list is a pair:
4687  *
4688  * (structname, RStructOnly)
4689  *    == there exists function which returns RStruct (_, structname)
4690  * (structname, RStructListOnly)
4691  *    == there exists function which returns RStructList (_, structname)
4692  * (structname, RStructAndList)
4693  *    == there are functions returning both RStruct (_, structname)
4694  *                                      and RStructList (_, structname)
4695  *)
4696 let rstructs_used_by functions =
4697   (* ||| is a "logical OR" for rstructs_used_t *)
4698   let (|||) a b =
4699     match a, b with
4700     | RStructAndList, _
4701     | _, RStructAndList -> RStructAndList
4702     | RStructOnly, RStructListOnly
4703     | RStructListOnly, RStructOnly -> RStructAndList
4704     | RStructOnly, RStructOnly -> RStructOnly
4705     | RStructListOnly, RStructListOnly -> RStructListOnly
4706   in
4707
4708   let h = Hashtbl.create 13 in
4709
4710   (* if elem->oldv exists, update entry using ||| operator,
4711    * else just add elem->newv to the hash
4712    *)
4713   let update elem newv =
4714     try  let oldv = Hashtbl.find h elem in
4715          Hashtbl.replace h elem (newv ||| oldv)
4716     with Not_found -> Hashtbl.add h elem newv
4717   in
4718
4719   List.iter (
4720     fun (_, style, _, _, _, _, _) ->
4721       match fst style with
4722       | RStruct (_, structname) -> update structname RStructOnly
4723       | RStructList (_, structname) -> update structname RStructListOnly
4724       | _ -> ()
4725   ) functions;
4726
4727   (* return key->values as a list of (key,value) *)
4728   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4729
4730 (* Used for testing language bindings. *)
4731 type callt =
4732   | CallString of string
4733   | CallOptString of string option
4734   | CallStringList of string list
4735   | CallInt of int
4736   | CallInt64 of int64
4737   | CallBool of bool
4738
4739 (* Used to memoize the result of pod2text. *)
4740 let pod2text_memo_filename = "src/.pod2text.data"
4741 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4742   try
4743     let chan = open_in pod2text_memo_filename in
4744     let v = input_value chan in
4745     close_in chan;
4746     v
4747   with
4748     _ -> Hashtbl.create 13
4749 let pod2text_memo_updated () =
4750   let chan = open_out pod2text_memo_filename in
4751   output_value chan pod2text_memo;
4752   close_out chan
4753
4754 (* Useful functions.
4755  * Note we don't want to use any external OCaml libraries which
4756  * makes this a bit harder than it should be.
4757  *)
4758 module StringMap = Map.Make (String)
4759
4760 let failwithf fs = ksprintf failwith fs
4761
4762 let unique = let i = ref 0 in fun () -> incr i; !i
4763
4764 let replace_char s c1 c2 =
4765   let s2 = String.copy s in
4766   let r = ref false in
4767   for i = 0 to String.length s2 - 1 do
4768     if String.unsafe_get s2 i = c1 then (
4769       String.unsafe_set s2 i c2;
4770       r := true
4771     )
4772   done;
4773   if not !r then s else s2
4774
4775 let isspace c =
4776   c = ' '
4777   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4778
4779 let triml ?(test = isspace) str =
4780   let i = ref 0 in
4781   let n = ref (String.length str) in
4782   while !n > 0 && test str.[!i]; do
4783     decr n;
4784     incr i
4785   done;
4786   if !i = 0 then str
4787   else String.sub str !i !n
4788
4789 let trimr ?(test = isspace) str =
4790   let n = ref (String.length str) in
4791   while !n > 0 && test str.[!n-1]; do
4792     decr n
4793   done;
4794   if !n = String.length str then str
4795   else String.sub str 0 !n
4796
4797 let trim ?(test = isspace) str =
4798   trimr ~test (triml ~test str)
4799
4800 let rec find s sub =
4801   let len = String.length s in
4802   let sublen = String.length sub in
4803   let rec loop i =
4804     if i <= len-sublen then (
4805       let rec loop2 j =
4806         if j < sublen then (
4807           if s.[i+j] = sub.[j] then loop2 (j+1)
4808           else -1
4809         ) else
4810           i (* found *)
4811       in
4812       let r = loop2 0 in
4813       if r = -1 then loop (i+1) else r
4814     ) else
4815       -1 (* not found *)
4816   in
4817   loop 0
4818
4819 let rec replace_str s s1 s2 =
4820   let len = String.length s in
4821   let sublen = String.length s1 in
4822   let i = find s s1 in
4823   if i = -1 then s
4824   else (
4825     let s' = String.sub s 0 i in
4826     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4827     s' ^ s2 ^ replace_str s'' s1 s2
4828   )
4829
4830 let rec string_split sep str =
4831   let len = String.length str in
4832   let seplen = String.length sep in
4833   let i = find str sep in
4834   if i = -1 then [str]
4835   else (
4836     let s' = String.sub str 0 i in
4837     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4838     s' :: string_split sep s''
4839   )
4840
4841 let files_equal n1 n2 =
4842   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4843   match Sys.command cmd with
4844   | 0 -> true
4845   | 1 -> false
4846   | i -> failwithf "%s: failed with error code %d" cmd i
4847
4848 let rec filter_map f = function
4849   | [] -> []
4850   | x :: xs ->
4851       match f x with
4852       | Some y -> y :: filter_map f xs
4853       | None -> filter_map f xs
4854
4855 let rec find_map f = function
4856   | [] -> raise Not_found
4857   | x :: xs ->
4858       match f x with
4859       | Some y -> y
4860       | None -> find_map f xs
4861
4862 let iteri f xs =
4863   let rec loop i = function
4864     | [] -> ()
4865     | x :: xs -> f i x; loop (i+1) xs
4866   in
4867   loop 0 xs
4868
4869 let mapi f xs =
4870   let rec loop i = function
4871     | [] -> []
4872     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4873   in
4874   loop 0 xs
4875
4876 let count_chars c str =
4877   let count = ref 0 in
4878   for i = 0 to String.length str - 1 do
4879     if c = String.unsafe_get str i then incr count
4880   done;
4881   !count
4882
4883 let name_of_argt = function
4884   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4885   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4886   | FileIn n | FileOut n -> n
4887
4888 let java_name_of_struct typ =
4889   try List.assoc typ java_structs
4890   with Not_found ->
4891     failwithf
4892       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4893
4894 let cols_of_struct typ =
4895   try List.assoc typ structs
4896   with Not_found ->
4897     failwithf "cols_of_struct: unknown struct %s" typ
4898
4899 let seq_of_test = function
4900   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4901   | TestOutputListOfDevices (s, _)
4902   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4903   | TestOutputTrue s | TestOutputFalse s
4904   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4905   | TestOutputStruct (s, _)
4906   | TestLastFail s -> s
4907
4908 (* Handling for function flags. *)
4909 let protocol_limit_warning =
4910   "Because of the message protocol, there is a transfer limit
4911 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4912
4913 let danger_will_robinson =
4914   "B<This command is dangerous.  Without careful use you
4915 can easily destroy all your data>."
4916
4917 let deprecation_notice flags =
4918   try
4919     let alt =
4920       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4921     let txt =
4922       sprintf "This function is deprecated.
4923 In new code, use the C<%s> call instead.
4924
4925 Deprecated functions will not be removed from the API, but the
4926 fact that they are deprecated indicates that there are problems
4927 with correct use of these functions." alt in
4928     Some txt
4929   with
4930     Not_found -> None
4931
4932 (* Create list of optional groups. *)
4933 let optgroups =
4934   let h = Hashtbl.create 13 in
4935   List.iter (
4936     fun (name, _, _, flags, _, _, _) ->
4937       List.iter (
4938         function
4939         | Optional group ->
4940             let names = try Hashtbl.find h group with Not_found -> [] in
4941             Hashtbl.replace h group (name :: names)
4942         | _ -> ()
4943       ) flags
4944   ) daemon_functions;
4945   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4946   let groups =
4947     List.map (
4948       fun group -> group, List.sort compare (Hashtbl.find h group)
4949     ) groups in
4950   List.sort (fun x y -> compare (fst x) (fst y)) groups
4951
4952 (* Check function names etc. for consistency. *)
4953 let check_functions () =
4954   let contains_uppercase str =
4955     let len = String.length str in
4956     let rec loop i =
4957       if i >= len then false
4958       else (
4959         let c = str.[i] in
4960         if c >= 'A' && c <= 'Z' then true
4961         else loop (i+1)
4962       )
4963     in
4964     loop 0
4965   in
4966
4967   (* Check function names. *)
4968   List.iter (
4969     fun (name, _, _, _, _, _, _) ->
4970       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4971         failwithf "function name %s does not need 'guestfs' prefix" name;
4972       if name = "" then
4973         failwithf "function name is empty";
4974       if name.[0] < 'a' || name.[0] > 'z' then
4975         failwithf "function name %s must start with lowercase a-z" name;
4976       if String.contains name '-' then
4977         failwithf "function name %s should not contain '-', use '_' instead."
4978           name
4979   ) all_functions;
4980
4981   (* Check function parameter/return names. *)
4982   List.iter (
4983     fun (name, style, _, _, _, _, _) ->
4984       let check_arg_ret_name n =
4985         if contains_uppercase n then
4986           failwithf "%s param/ret %s should not contain uppercase chars"
4987             name n;
4988         if String.contains n '-' || String.contains n '_' then
4989           failwithf "%s param/ret %s should not contain '-' or '_'"
4990             name n;
4991         if n = "value" then
4992           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;
4993         if n = "int" || n = "char" || n = "short" || n = "long" then
4994           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4995         if n = "i" || n = "n" then
4996           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4997         if n = "argv" || n = "args" then
4998           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4999
5000         (* List Haskell, OCaml and C keywords here.
5001          * http://www.haskell.org/haskellwiki/Keywords
5002          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5003          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5004          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5005          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5006          * Omitting _-containing words, since they're handled above.
5007          * Omitting the OCaml reserved word, "val", is ok,
5008          * and saves us from renaming several parameters.
5009          *)
5010         let reserved = [
5011           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5012           "char"; "class"; "const"; "constraint"; "continue"; "data";
5013           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5014           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5015           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5016           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5017           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5018           "interface";
5019           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5020           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5021           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5022           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5023           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5024           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5025           "volatile"; "when"; "where"; "while";
5026           ] in
5027         if List.mem n reserved then
5028           failwithf "%s has param/ret using reserved word %s" name n;
5029       in
5030
5031       (match fst style with
5032        | RErr -> ()
5033        | RInt n | RInt64 n | RBool n
5034        | RConstString n | RConstOptString n | RString n
5035        | RStringList n | RStruct (n, _) | RStructList (n, _)
5036        | RHashtable n | RBufferOut n ->
5037            check_arg_ret_name n
5038       );
5039       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5040   ) all_functions;
5041
5042   (* Check short descriptions. *)
5043   List.iter (
5044     fun (name, _, _, _, _, shortdesc, _) ->
5045       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5046         failwithf "short description of %s should begin with lowercase." name;
5047       let c = shortdesc.[String.length shortdesc-1] in
5048       if c = '\n' || c = '.' then
5049         failwithf "short description of %s should not end with . or \\n." name
5050   ) all_functions;
5051
5052   (* Check long descriptions. *)
5053   List.iter (
5054     fun (name, _, _, _, _, _, longdesc) ->
5055       if longdesc.[String.length longdesc-1] = '\n' then
5056         failwithf "long description of %s should not end with \\n." name
5057   ) all_functions;
5058
5059   (* Check proc_nrs. *)
5060   List.iter (
5061     fun (name, _, proc_nr, _, _, _, _) ->
5062       if proc_nr <= 0 then
5063         failwithf "daemon function %s should have proc_nr > 0" name
5064   ) daemon_functions;
5065
5066   List.iter (
5067     fun (name, _, proc_nr, _, _, _, _) ->
5068       if proc_nr <> -1 then
5069         failwithf "non-daemon function %s should have proc_nr -1" name
5070   ) non_daemon_functions;
5071
5072   let proc_nrs =
5073     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5074       daemon_functions in
5075   let proc_nrs =
5076     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5077   let rec loop = function
5078     | [] -> ()
5079     | [_] -> ()
5080     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5081         loop rest
5082     | (name1,nr1) :: (name2,nr2) :: _ ->
5083         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5084           name1 name2 nr1 nr2
5085   in
5086   loop proc_nrs;
5087
5088   (* Check tests. *)
5089   List.iter (
5090     function
5091       (* Ignore functions that have no tests.  We generate a
5092        * warning when the user does 'make check' instead.
5093        *)
5094     | name, _, _, _, [], _, _ -> ()
5095     | name, _, _, _, tests, _, _ ->
5096         let funcs =
5097           List.map (
5098             fun (_, _, test) ->
5099               match seq_of_test test with
5100               | [] ->
5101                   failwithf "%s has a test containing an empty sequence" name
5102               | cmds -> List.map List.hd cmds
5103           ) tests in
5104         let funcs = List.flatten funcs in
5105
5106         let tested = List.mem name funcs in
5107
5108         if not tested then
5109           failwithf "function %s has tests but does not test itself" name
5110   ) all_functions
5111
5112 (* 'pr' prints to the current output file. *)
5113 let chan = ref Pervasives.stdout
5114 let lines = ref 0
5115 let pr fs =
5116   ksprintf
5117     (fun str ->
5118        let i = count_chars '\n' str in
5119        lines := !lines + i;
5120        output_string !chan str
5121     ) fs
5122
5123 let copyright_years =
5124   let this_year = 1900 + (localtime (time ())).tm_year in
5125   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5126
5127 (* Generate a header block in a number of standard styles. *)
5128 type comment_style =
5129     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5130 type license = GPLv2plus | LGPLv2plus
5131
5132 let generate_header ?(extra_inputs = []) comment license =
5133   let inputs = "src/generator.ml" :: extra_inputs in
5134   let c = match comment with
5135     | CStyle ->         pr "/* "; " *"
5136     | CPlusPlusStyle -> pr "// "; "//"
5137     | HashStyle ->      pr "# ";  "#"
5138     | OCamlStyle ->     pr "(* "; " *"
5139     | HaskellStyle ->   pr "{- "; "  " in
5140   pr "libguestfs generated file\n";
5141   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5142   List.iter (pr "%s   %s\n" c) inputs;
5143   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5144   pr "%s\n" c;
5145   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5146   pr "%s\n" c;
5147   (match license with
5148    | GPLv2plus ->
5149        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5150        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5151        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5152        pr "%s (at your option) any later version.\n" c;
5153        pr "%s\n" c;
5154        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5155        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5156        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5157        pr "%s GNU General Public License for more details.\n" c;
5158        pr "%s\n" c;
5159        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5160        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5161        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5162
5163    | LGPLv2plus ->
5164        pr "%s This library is free software; you can redistribute it and/or\n" c;
5165        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5166        pr "%s License as published by the Free Software Foundation; either\n" c;
5167        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5168        pr "%s\n" c;
5169        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5170        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5171        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5172        pr "%s Lesser General Public License for more details.\n" c;
5173        pr "%s\n" c;
5174        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5175        pr "%s License along with this library; if not, write to the Free Software\n" c;
5176        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5177   );
5178   (match comment with
5179    | CStyle -> pr " */\n"
5180    | CPlusPlusStyle
5181    | HashStyle -> ()
5182    | OCamlStyle -> pr " *)\n"
5183    | HaskellStyle -> pr "-}\n"
5184   );
5185   pr "\n"
5186
5187 (* Start of main code generation functions below this line. *)
5188
5189 (* Generate the pod documentation for the C API. *)
5190 let rec generate_actions_pod () =
5191   List.iter (
5192     fun (shortname, style, _, flags, _, _, longdesc) ->
5193       if not (List.mem NotInDocs flags) then (
5194         let name = "guestfs_" ^ shortname in
5195         pr "=head2 %s\n\n" name;
5196         pr " ";
5197         generate_prototype ~extern:false ~handle:"g" name style;
5198         pr "\n\n";
5199         pr "%s\n\n" longdesc;
5200         (match fst style with
5201          | RErr ->
5202              pr "This function returns 0 on success or -1 on error.\n\n"
5203          | RInt _ ->
5204              pr "On error this function returns -1.\n\n"
5205          | RInt64 _ ->
5206              pr "On error this function returns -1.\n\n"
5207          | RBool _ ->
5208              pr "This function returns a C truth value on success or -1 on error.\n\n"
5209          | RConstString _ ->
5210              pr "This function returns a string, or NULL on error.
5211 The string is owned by the guest handle and must I<not> be freed.\n\n"
5212          | RConstOptString _ ->
5213              pr "This function returns a string which may be NULL.
5214 There is way to return an error from this function.
5215 The string is owned by the guest handle and must I<not> be freed.\n\n"
5216          | RString _ ->
5217              pr "This function returns a string, or NULL on error.
5218 I<The caller must free the returned string after use>.\n\n"
5219          | RStringList _ ->
5220              pr "This function returns a NULL-terminated array of strings
5221 (like L<environ(3)>), or NULL if there was an error.
5222 I<The caller must free the strings and the array after use>.\n\n"
5223          | RStruct (_, typ) ->
5224              pr "This function returns a C<struct guestfs_%s *>,
5225 or NULL if there was an error.
5226 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5227          | RStructList (_, typ) ->
5228              pr "This function returns a C<struct guestfs_%s_list *>
5229 (see E<lt>guestfs-structs.hE<gt>),
5230 or NULL if there was an error.
5231 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5232          | RHashtable _ ->
5233              pr "This function returns a NULL-terminated array of
5234 strings, or NULL if there was an error.
5235 The array of strings will always have length C<2n+1>, where
5236 C<n> keys and values alternate, followed by the trailing NULL entry.
5237 I<The caller must free the strings and the array after use>.\n\n"
5238          | RBufferOut _ ->
5239              pr "This function returns a buffer, or NULL on error.
5240 The size of the returned buffer is written to C<*size_r>.
5241 I<The caller must free the returned buffer after use>.\n\n"
5242         );
5243         if List.mem ProtocolLimitWarning flags then
5244           pr "%s\n\n" protocol_limit_warning;
5245         if List.mem DangerWillRobinson flags then
5246           pr "%s\n\n" danger_will_robinson;
5247         match deprecation_notice flags with
5248         | None -> ()
5249         | Some txt -> pr "%s\n\n" txt
5250       )
5251   ) all_functions_sorted
5252
5253 and generate_structs_pod () =
5254   (* Structs documentation. *)
5255   List.iter (
5256     fun (typ, cols) ->
5257       pr "=head2 guestfs_%s\n" typ;
5258       pr "\n";
5259       pr " struct guestfs_%s {\n" typ;
5260       List.iter (
5261         function
5262         | name, FChar -> pr "   char %s;\n" name
5263         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5264         | name, FInt32 -> pr "   int32_t %s;\n" name
5265         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5266         | name, FInt64 -> pr "   int64_t %s;\n" name
5267         | name, FString -> pr "   char *%s;\n" name
5268         | name, FBuffer ->
5269             pr "   /* The next two fields describe a byte array. */\n";
5270             pr "   uint32_t %s_len;\n" name;
5271             pr "   char *%s;\n" name
5272         | name, FUUID ->
5273             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5274             pr "   char %s[32];\n" name
5275         | name, FOptPercent ->
5276             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5277             pr "   float %s;\n" name
5278       ) cols;
5279       pr " };\n";
5280       pr " \n";
5281       pr " struct guestfs_%s_list {\n" typ;
5282       pr "   uint32_t len; /* Number of elements in list. */\n";
5283       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5284       pr " };\n";
5285       pr " \n";
5286       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5287       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5288         typ typ;
5289       pr "\n"
5290   ) structs
5291
5292 and generate_availability_pod () =
5293   (* Availability documentation. *)
5294   pr "=over 4\n";
5295   pr "\n";
5296   List.iter (
5297     fun (group, functions) ->
5298       pr "=item B<%s>\n" group;
5299       pr "\n";
5300       pr "The following functions:\n";
5301       List.iter (pr "L</guestfs_%s>\n") functions;
5302       pr "\n"
5303   ) optgroups;
5304   pr "=back\n";
5305   pr "\n"
5306
5307 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5308  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5309  *
5310  * We have to use an underscore instead of a dash because otherwise
5311  * rpcgen generates incorrect code.
5312  *
5313  * This header is NOT exported to clients, but see also generate_structs_h.
5314  *)
5315 and generate_xdr () =
5316   generate_header CStyle LGPLv2plus;
5317
5318   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5319   pr "typedef string str<>;\n";
5320   pr "\n";
5321
5322   (* Internal structures. *)
5323   List.iter (
5324     function
5325     | typ, cols ->
5326         pr "struct guestfs_int_%s {\n" typ;
5327         List.iter (function
5328                    | name, FChar -> pr "  char %s;\n" name
5329                    | name, FString -> pr "  string %s<>;\n" name
5330                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5331                    | name, FUUID -> pr "  opaque %s[32];\n" name
5332                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5333                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5334                    | name, FOptPercent -> pr "  float %s;\n" name
5335                   ) cols;
5336         pr "};\n";
5337         pr "\n";
5338         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5339         pr "\n";
5340   ) structs;
5341
5342   List.iter (
5343     fun (shortname, style, _, _, _, _, _) ->
5344       let name = "guestfs_" ^ shortname in
5345
5346       (match snd style with
5347        | [] -> ()
5348        | args ->
5349            pr "struct %s_args {\n" name;
5350            List.iter (
5351              function
5352              | Pathname n | Device n | Dev_or_Path n | String n ->
5353                  pr "  string %s<>;\n" n
5354              | OptString n -> pr "  str *%s;\n" n
5355              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5356              | Bool n -> pr "  bool %s;\n" n
5357              | Int n -> pr "  int %s;\n" n
5358              | Int64 n -> pr "  hyper %s;\n" n
5359              | FileIn _ | FileOut _ -> ()
5360            ) args;
5361            pr "};\n\n"
5362       );
5363       (match fst style with
5364        | RErr -> ()
5365        | RInt n ->
5366            pr "struct %s_ret {\n" name;
5367            pr "  int %s;\n" n;
5368            pr "};\n\n"
5369        | RInt64 n ->
5370            pr "struct %s_ret {\n" name;
5371            pr "  hyper %s;\n" n;
5372            pr "};\n\n"
5373        | RBool n ->
5374            pr "struct %s_ret {\n" name;
5375            pr "  bool %s;\n" n;
5376            pr "};\n\n"
5377        | RConstString _ | RConstOptString _ ->
5378            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5379        | RString n ->
5380            pr "struct %s_ret {\n" name;
5381            pr "  string %s<>;\n" n;
5382            pr "};\n\n"
5383        | RStringList n ->
5384            pr "struct %s_ret {\n" name;
5385            pr "  str %s<>;\n" n;
5386            pr "};\n\n"
5387        | RStruct (n, typ) ->
5388            pr "struct %s_ret {\n" name;
5389            pr "  guestfs_int_%s %s;\n" typ n;
5390            pr "};\n\n"
5391        | RStructList (n, typ) ->
5392            pr "struct %s_ret {\n" name;
5393            pr "  guestfs_int_%s_list %s;\n" typ n;
5394            pr "};\n\n"
5395        | RHashtable n ->
5396            pr "struct %s_ret {\n" name;
5397            pr "  str %s<>;\n" n;
5398            pr "};\n\n"
5399        | RBufferOut n ->
5400            pr "struct %s_ret {\n" name;
5401            pr "  opaque %s<>;\n" n;
5402            pr "};\n\n"
5403       );
5404   ) daemon_functions;
5405
5406   (* Table of procedure numbers. *)
5407   pr "enum guestfs_procedure {\n";
5408   List.iter (
5409     fun (shortname, _, proc_nr, _, _, _, _) ->
5410       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5411   ) daemon_functions;
5412   pr "  GUESTFS_PROC_NR_PROCS\n";
5413   pr "};\n";
5414   pr "\n";
5415
5416   (* Having to choose a maximum message size is annoying for several
5417    * reasons (it limits what we can do in the API), but it (a) makes
5418    * the protocol a lot simpler, and (b) provides a bound on the size
5419    * of the daemon which operates in limited memory space.
5420    *)
5421   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5422   pr "\n";
5423
5424   (* Message header, etc. *)
5425   pr "\
5426 /* The communication protocol is now documented in the guestfs(3)
5427  * manpage.
5428  */
5429
5430 const GUESTFS_PROGRAM = 0x2000F5F5;
5431 const GUESTFS_PROTOCOL_VERSION = 1;
5432
5433 /* These constants must be larger than any possible message length. */
5434 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5435 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5436
5437 enum guestfs_message_direction {
5438   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5439   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5440 };
5441
5442 enum guestfs_message_status {
5443   GUESTFS_STATUS_OK = 0,
5444   GUESTFS_STATUS_ERROR = 1
5445 };
5446
5447 const GUESTFS_ERROR_LEN = 256;
5448
5449 struct guestfs_message_error {
5450   string error_message<GUESTFS_ERROR_LEN>;
5451 };
5452
5453 struct guestfs_message_header {
5454   unsigned prog;                     /* GUESTFS_PROGRAM */
5455   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5456   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5457   guestfs_message_direction direction;
5458   unsigned serial;                   /* message serial number */
5459   guestfs_message_status status;
5460 };
5461
5462 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5463
5464 struct guestfs_chunk {
5465   int cancel;                        /* if non-zero, transfer is cancelled */
5466   /* data size is 0 bytes if the transfer has finished successfully */
5467   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5468 };
5469 "
5470
5471 (* Generate the guestfs-structs.h file. *)
5472 and generate_structs_h () =
5473   generate_header CStyle LGPLv2plus;
5474
5475   (* This is a public exported header file containing various
5476    * structures.  The structures are carefully written to have
5477    * exactly the same in-memory format as the XDR structures that
5478    * we use on the wire to the daemon.  The reason for creating
5479    * copies of these structures here is just so we don't have to
5480    * export the whole of guestfs_protocol.h (which includes much
5481    * unrelated and XDR-dependent stuff that we don't want to be
5482    * public, or required by clients).
5483    *
5484    * To reiterate, we will pass these structures to and from the
5485    * client with a simple assignment or memcpy, so the format
5486    * must be identical to what rpcgen / the RFC defines.
5487    *)
5488
5489   (* Public structures. *)
5490   List.iter (
5491     fun (typ, cols) ->
5492       pr "struct guestfs_%s {\n" typ;
5493       List.iter (
5494         function
5495         | name, FChar -> pr "  char %s;\n" name
5496         | name, FString -> pr "  char *%s;\n" name
5497         | name, FBuffer ->
5498             pr "  uint32_t %s_len;\n" name;
5499             pr "  char *%s;\n" name
5500         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5501         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5502         | name, FInt32 -> pr "  int32_t %s;\n" name
5503         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5504         | name, FInt64 -> pr "  int64_t %s;\n" name
5505         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5506       ) cols;
5507       pr "};\n";
5508       pr "\n";
5509       pr "struct guestfs_%s_list {\n" typ;
5510       pr "  uint32_t len;\n";
5511       pr "  struct guestfs_%s *val;\n" typ;
5512       pr "};\n";
5513       pr "\n";
5514       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5515       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5516       pr "\n"
5517   ) structs
5518
5519 (* Generate the guestfs-actions.h file. *)
5520 and generate_actions_h () =
5521   generate_header CStyle LGPLv2plus;
5522   List.iter (
5523     fun (shortname, style, _, _, _, _, _) ->
5524       let name = "guestfs_" ^ shortname in
5525       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5526         name style
5527   ) all_functions
5528
5529 (* Generate the guestfs-internal-actions.h file. *)
5530 and generate_internal_actions_h () =
5531   generate_header CStyle LGPLv2plus;
5532   List.iter (
5533     fun (shortname, style, _, _, _, _, _) ->
5534       let name = "guestfs__" ^ shortname in
5535       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5536         name style
5537   ) non_daemon_functions
5538
5539 (* Generate the client-side dispatch stubs. *)
5540 and generate_client_actions () =
5541   generate_header CStyle LGPLv2plus;
5542
5543   pr "\
5544 #include <stdio.h>
5545 #include <stdlib.h>
5546 #include <stdint.h>
5547 #include <string.h>
5548 #include <inttypes.h>
5549
5550 #include \"guestfs.h\"
5551 #include \"guestfs-internal.h\"
5552 #include \"guestfs-internal-actions.h\"
5553 #include \"guestfs_protocol.h\"
5554
5555 #define error guestfs_error
5556 //#define perrorf guestfs_perrorf
5557 #define safe_malloc guestfs_safe_malloc
5558 #define safe_realloc guestfs_safe_realloc
5559 //#define safe_strdup guestfs_safe_strdup
5560 #define safe_memdup guestfs_safe_memdup
5561
5562 /* Check the return message from a call for validity. */
5563 static int
5564 check_reply_header (guestfs_h *g,
5565                     const struct guestfs_message_header *hdr,
5566                     unsigned int proc_nr, unsigned int serial)
5567 {
5568   if (hdr->prog != GUESTFS_PROGRAM) {
5569     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5570     return -1;
5571   }
5572   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5573     error (g, \"wrong protocol version (%%d/%%d)\",
5574            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5575     return -1;
5576   }
5577   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5578     error (g, \"unexpected message direction (%%d/%%d)\",
5579            hdr->direction, GUESTFS_DIRECTION_REPLY);
5580     return -1;
5581   }
5582   if (hdr->proc != proc_nr) {
5583     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5584     return -1;
5585   }
5586   if (hdr->serial != serial) {
5587     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5588     return -1;
5589   }
5590
5591   return 0;
5592 }
5593
5594 /* Check we are in the right state to run a high-level action. */
5595 static int
5596 check_state (guestfs_h *g, const char *caller)
5597 {
5598   if (!guestfs__is_ready (g)) {
5599     if (guestfs__is_config (g) || guestfs__is_launching (g))
5600       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5601         caller);
5602     else
5603       error (g, \"%%s called from the wrong state, %%d != READY\",
5604         caller, guestfs__get_state (g));
5605     return -1;
5606   }
5607   return 0;
5608 }
5609
5610 ";
5611
5612   (* Generate code to generate guestfish call traces. *)
5613   let trace_call shortname style =
5614     pr "  if (guestfs__get_trace (g)) {\n";
5615
5616     let needs_i =
5617       List.exists (function
5618                    | StringList _ | DeviceList _ -> true
5619                    | _ -> false) (snd style) in
5620     if needs_i then (
5621       pr "    int i;\n";
5622       pr "\n"
5623     );
5624
5625     pr "    printf (\"%s\");\n" shortname;
5626     List.iter (
5627       function
5628       | String n                        (* strings *)
5629       | Device n
5630       | Pathname n
5631       | Dev_or_Path n
5632       | FileIn n
5633       | FileOut n ->
5634           (* guestfish doesn't support string escaping, so neither do we *)
5635           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5636       | OptString n ->                  (* string option *)
5637           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5638           pr "    else printf (\" null\");\n"
5639       | StringList n
5640       | DeviceList n ->                 (* string list *)
5641           pr "    putchar (' ');\n";
5642           pr "    putchar ('\"');\n";
5643           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5644           pr "      if (i > 0) putchar (' ');\n";
5645           pr "      fputs (%s[i], stdout);\n" n;
5646           pr "    }\n";
5647           pr "    putchar ('\"');\n";
5648       | Bool n ->                       (* boolean *)
5649           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5650       | Int n ->                        (* int *)
5651           pr "    printf (\" %%d\", %s);\n" n
5652       | Int64 n ->
5653           pr "    printf (\" %%\" PRIi64, %s);\n" n
5654     ) (snd style);
5655     pr "    putchar ('\\n');\n";
5656     pr "  }\n";
5657     pr "\n";
5658   in
5659
5660   (* For non-daemon functions, generate a wrapper around each function. *)
5661   List.iter (
5662     fun (shortname, style, _, _, _, _, _) ->
5663       let name = "guestfs_" ^ shortname in
5664
5665       generate_prototype ~extern:false ~semicolon:false ~newline:true
5666         ~handle:"g" name style;
5667       pr "{\n";
5668       trace_call shortname style;
5669       pr "  return guestfs__%s " shortname;
5670       generate_c_call_args ~handle:"g" style;
5671       pr ";\n";
5672       pr "}\n";
5673       pr "\n"
5674   ) non_daemon_functions;
5675
5676   (* Client-side stubs for each function. *)
5677   List.iter (
5678     fun (shortname, style, _, _, _, _, _) ->
5679       let name = "guestfs_" ^ shortname in
5680
5681       (* Generate the action stub. *)
5682       generate_prototype ~extern:false ~semicolon:false ~newline:true
5683         ~handle:"g" name style;
5684
5685       let error_code =
5686         match fst style with
5687         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5688         | RConstString _ | RConstOptString _ ->
5689             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5690         | RString _ | RStringList _
5691         | RStruct _ | RStructList _
5692         | RHashtable _ | RBufferOut _ ->
5693             "NULL" in
5694
5695       pr "{\n";
5696
5697       (match snd style with
5698        | [] -> ()
5699        | _ -> pr "  struct %s_args args;\n" name
5700       );
5701
5702       pr "  guestfs_message_header hdr;\n";
5703       pr "  guestfs_message_error err;\n";
5704       let has_ret =
5705         match fst style with
5706         | RErr -> false
5707         | RConstString _ | RConstOptString _ ->
5708             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5709         | RInt _ | RInt64 _
5710         | RBool _ | RString _ | RStringList _
5711         | RStruct _ | RStructList _
5712         | RHashtable _ | RBufferOut _ ->
5713             pr "  struct %s_ret ret;\n" name;
5714             true in
5715
5716       pr "  int serial;\n";
5717       pr "  int r;\n";
5718       pr "\n";
5719       trace_call shortname style;
5720       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5721       pr "  guestfs___set_busy (g);\n";
5722       pr "\n";
5723
5724       (* Send the main header and arguments. *)
5725       (match snd style with
5726        | [] ->
5727            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5728              (String.uppercase shortname)
5729        | args ->
5730            List.iter (
5731              function
5732              | Pathname n | Device n | Dev_or_Path n | String n ->
5733                  pr "  args.%s = (char *) %s;\n" n n
5734              | OptString n ->
5735                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5736              | StringList n | DeviceList n ->
5737                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5738                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5739              | Bool n ->
5740                  pr "  args.%s = %s;\n" n n
5741              | Int n ->
5742                  pr "  args.%s = %s;\n" n n
5743              | Int64 n ->
5744                  pr "  args.%s = %s;\n" n n
5745              | FileIn _ | FileOut _ -> ()
5746            ) args;
5747            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5748              (String.uppercase shortname);
5749            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5750              name;
5751       );
5752       pr "  if (serial == -1) {\n";
5753       pr "    guestfs___end_busy (g);\n";
5754       pr "    return %s;\n" error_code;
5755       pr "  }\n";
5756       pr "\n";
5757
5758       (* Send any additional files (FileIn) requested. *)
5759       let need_read_reply_label = ref false in
5760       List.iter (
5761         function
5762         | FileIn n ->
5763             pr "  r = guestfs___send_file (g, %s);\n" n;
5764             pr "  if (r == -1) {\n";
5765             pr "    guestfs___end_busy (g);\n";
5766             pr "    return %s;\n" error_code;
5767             pr "  }\n";
5768             pr "  if (r == -2) /* daemon cancelled */\n";
5769             pr "    goto read_reply;\n";
5770             need_read_reply_label := true;
5771             pr "\n";
5772         | _ -> ()
5773       ) (snd style);
5774
5775       (* Wait for the reply from the remote end. *)
5776       if !need_read_reply_label then pr " read_reply:\n";
5777       pr "  memset (&hdr, 0, sizeof hdr);\n";
5778       pr "  memset (&err, 0, sizeof err);\n";
5779       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5780       pr "\n";
5781       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5782       if not has_ret then
5783         pr "NULL, NULL"
5784       else
5785         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5786       pr ");\n";
5787
5788       pr "  if (r == -1) {\n";
5789       pr "    guestfs___end_busy (g);\n";
5790       pr "    return %s;\n" error_code;
5791       pr "  }\n";
5792       pr "\n";
5793
5794       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5795         (String.uppercase shortname);
5796       pr "    guestfs___end_busy (g);\n";
5797       pr "    return %s;\n" error_code;
5798       pr "  }\n";
5799       pr "\n";
5800
5801       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5802       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5803       pr "    free (err.error_message);\n";
5804       pr "    guestfs___end_busy (g);\n";
5805       pr "    return %s;\n" error_code;
5806       pr "  }\n";
5807       pr "\n";
5808
5809       (* Expecting to receive further files (FileOut)? *)
5810       List.iter (
5811         function
5812         | FileOut n ->
5813             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5814             pr "    guestfs___end_busy (g);\n";
5815             pr "    return %s;\n" error_code;
5816             pr "  }\n";
5817             pr "\n";
5818         | _ -> ()
5819       ) (snd style);
5820
5821       pr "  guestfs___end_busy (g);\n";
5822
5823       (match fst style with
5824        | RErr -> pr "  return 0;\n"
5825        | RInt n | RInt64 n | RBool n ->
5826            pr "  return ret.%s;\n" n
5827        | RConstString _ | RConstOptString _ ->
5828            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5829        | RString n ->
5830            pr "  return ret.%s; /* caller will free */\n" n
5831        | RStringList n | RHashtable n ->
5832            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5833            pr "  ret.%s.%s_val =\n" n n;
5834            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5835            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5836              n n;
5837            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5838            pr "  return ret.%s.%s_val;\n" n n
5839        | RStruct (n, _) ->
5840            pr "  /* caller will free this */\n";
5841            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5842        | RStructList (n, _) ->
5843            pr "  /* caller will free this */\n";
5844            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5845        | RBufferOut n ->
5846            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5847            pr "   * _val might be NULL here.  To make the API saner for\n";
5848            pr "   * callers, we turn this case into a unique pointer (using\n";
5849            pr "   * malloc(1)).\n";
5850            pr "   */\n";
5851            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5852            pr "    *size_r = ret.%s.%s_len;\n" n n;
5853            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5854            pr "  } else {\n";
5855            pr "    free (ret.%s.%s_val);\n" n n;
5856            pr "    char *p = safe_malloc (g, 1);\n";
5857            pr "    *size_r = ret.%s.%s_len;\n" n n;
5858            pr "    return p;\n";
5859            pr "  }\n";
5860       );
5861
5862       pr "}\n\n"
5863   ) daemon_functions;
5864
5865   (* Functions to free structures. *)
5866   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5867   pr " * structure format is identical to the XDR format.  See note in\n";
5868   pr " * generator.ml.\n";
5869   pr " */\n";
5870   pr "\n";
5871
5872   List.iter (
5873     fun (typ, _) ->
5874       pr "void\n";
5875       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5876       pr "{\n";
5877       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5878       pr "  free (x);\n";
5879       pr "}\n";
5880       pr "\n";
5881
5882       pr "void\n";
5883       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5884       pr "{\n";
5885       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5886       pr "  free (x);\n";
5887       pr "}\n";
5888       pr "\n";
5889
5890   ) structs;
5891
5892 (* Generate daemon/actions.h. *)
5893 and generate_daemon_actions_h () =
5894   generate_header CStyle GPLv2plus;
5895
5896   pr "#include \"../src/guestfs_protocol.h\"\n";
5897   pr "\n";
5898
5899   List.iter (
5900     fun (name, style, _, _, _, _, _) ->
5901       generate_prototype
5902         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5903         name style;
5904   ) daemon_functions
5905
5906 (* Generate the linker script which controls the visibility of
5907  * symbols in the public ABI and ensures no other symbols get
5908  * exported accidentally.
5909  *)
5910 and generate_linker_script () =
5911   generate_header HashStyle GPLv2plus;
5912
5913   let globals = [
5914     "guestfs_create";
5915     "guestfs_close";
5916     "guestfs_get_error_handler";
5917     "guestfs_get_out_of_memory_handler";
5918     "guestfs_last_error";
5919     "guestfs_set_error_handler";
5920     "guestfs_set_launch_done_callback";
5921     "guestfs_set_log_message_callback";
5922     "guestfs_set_out_of_memory_handler";
5923     "guestfs_set_subprocess_quit_callback";
5924
5925     (* Unofficial parts of the API: the bindings code use these
5926      * functions, so it is useful to export them.
5927      *)
5928     "guestfs_safe_calloc";
5929     "guestfs_safe_malloc";
5930   ] in
5931   let functions =
5932     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5933       all_functions in
5934   let structs =
5935     List.concat (
5936       List.map (fun (typ, _) ->
5937                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5938         structs
5939     ) in
5940   let globals = List.sort compare (globals @ functions @ structs) in
5941
5942   pr "{\n";
5943   pr "    global:\n";
5944   List.iter (pr "        %s;\n") globals;
5945   pr "\n";
5946
5947   pr "    local:\n";
5948   pr "        *;\n";
5949   pr "};\n"
5950
5951 (* Generate the server-side stubs. *)
5952 and generate_daemon_actions () =
5953   generate_header CStyle GPLv2plus;
5954
5955   pr "#include <config.h>\n";
5956   pr "\n";
5957   pr "#include <stdio.h>\n";
5958   pr "#include <stdlib.h>\n";
5959   pr "#include <string.h>\n";
5960   pr "#include <inttypes.h>\n";
5961   pr "#include <rpc/types.h>\n";
5962   pr "#include <rpc/xdr.h>\n";
5963   pr "\n";
5964   pr "#include \"daemon.h\"\n";
5965   pr "#include \"c-ctype.h\"\n";
5966   pr "#include \"../src/guestfs_protocol.h\"\n";
5967   pr "#include \"actions.h\"\n";
5968   pr "\n";
5969
5970   List.iter (
5971     fun (name, style, _, _, _, _, _) ->
5972       (* Generate server-side stubs. *)
5973       pr "static void %s_stub (XDR *xdr_in)\n" name;
5974       pr "{\n";
5975       let error_code =
5976         match fst style with
5977         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5978         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5979         | RBool _ -> pr "  int r;\n"; "-1"
5980         | RConstString _ | RConstOptString _ ->
5981             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5982         | RString _ -> pr "  char *r;\n"; "NULL"
5983         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5984         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5985         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5986         | RBufferOut _ ->
5987             pr "  size_t size = 1;\n";
5988             pr "  char *r;\n";
5989             "NULL" in
5990
5991       (match snd style with
5992        | [] -> ()
5993        | args ->
5994            pr "  struct guestfs_%s_args args;\n" name;
5995            List.iter (
5996              function
5997              | Device n | Dev_or_Path n
5998              | Pathname n
5999              | String n -> ()
6000              | OptString n -> pr "  char *%s;\n" n
6001              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6002              | Bool n -> pr "  int %s;\n" n
6003              | Int n -> pr "  int %s;\n" n
6004              | Int64 n -> pr "  int64_t %s;\n" n
6005              | FileIn _ | FileOut _ -> ()
6006            ) args
6007       );
6008       pr "\n";
6009
6010       (match snd style with
6011        | [] -> ()
6012        | args ->
6013            pr "  memset (&args, 0, sizeof args);\n";
6014            pr "\n";
6015            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6016            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6017            pr "    return;\n";
6018            pr "  }\n";
6019            let pr_args n =
6020              pr "  char *%s = args.%s;\n" n n
6021            in
6022            let pr_list_handling_code n =
6023              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6024              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6025              pr "  if (%s == NULL) {\n" n;
6026              pr "    reply_with_perror (\"realloc\");\n";
6027              pr "    goto done;\n";
6028              pr "  }\n";
6029              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6030              pr "  args.%s.%s_val = %s;\n" n n n;
6031            in
6032            List.iter (
6033              function
6034              | Pathname n ->
6035                  pr_args n;
6036                  pr "  ABS_PATH (%s, goto done);\n" n;
6037              | Device n ->
6038                  pr_args n;
6039                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6040              | Dev_or_Path n ->
6041                  pr_args n;
6042                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6043              | String n -> pr_args n
6044              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6045              | StringList n ->
6046                  pr_list_handling_code n;
6047              | DeviceList n ->
6048                  pr_list_handling_code n;
6049                  pr "  /* Ensure that each is a device,\n";
6050                  pr "   * and perform device name translation. */\n";
6051                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6052                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6053                  pr "  }\n";
6054              | Bool n -> pr "  %s = args.%s;\n" n n
6055              | Int n -> pr "  %s = args.%s;\n" n n
6056              | Int64 n -> pr "  %s = args.%s;\n" n n
6057              | FileIn _ | FileOut _ -> ()
6058            ) args;
6059            pr "\n"
6060       );
6061
6062
6063       (* this is used at least for do_equal *)
6064       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6065         (* Emit NEED_ROOT just once, even when there are two or
6066            more Pathname args *)
6067         pr "  NEED_ROOT (goto done);\n";
6068       );
6069
6070       (* Don't want to call the impl with any FileIn or FileOut
6071        * parameters, since these go "outside" the RPC protocol.
6072        *)
6073       let args' =
6074         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6075           (snd style) in
6076       pr "  r = do_%s " name;
6077       generate_c_call_args (fst style, args');
6078       pr ";\n";
6079
6080       (match fst style with
6081        | RErr | RInt _ | RInt64 _ | RBool _
6082        | RConstString _ | RConstOptString _
6083        | RString _ | RStringList _ | RHashtable _
6084        | RStruct (_, _) | RStructList (_, _) ->
6085            pr "  if (r == %s)\n" error_code;
6086            pr "    /* do_%s has already called reply_with_error */\n" name;
6087            pr "    goto done;\n";
6088            pr "\n"
6089        | RBufferOut _ ->
6090            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6091            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6092            pr "   */\n";
6093            pr "  if (size == 1 && r == %s)\n" error_code;
6094            pr "    /* do_%s has already called reply_with_error */\n" name;
6095            pr "    goto done;\n";
6096            pr "\n"
6097       );
6098
6099       (* If there are any FileOut parameters, then the impl must
6100        * send its own reply.
6101        *)
6102       let no_reply =
6103         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6104       if no_reply then
6105         pr "  /* do_%s has already sent a reply */\n" name
6106       else (
6107         match fst style with
6108         | RErr -> pr "  reply (NULL, NULL);\n"
6109         | RInt n | RInt64 n | RBool n ->
6110             pr "  struct guestfs_%s_ret ret;\n" name;
6111             pr "  ret.%s = r;\n" n;
6112             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6113               name
6114         | RConstString _ | RConstOptString _ ->
6115             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6116         | RString n ->
6117             pr "  struct guestfs_%s_ret ret;\n" name;
6118             pr "  ret.%s = r;\n" n;
6119             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6120               name;
6121             pr "  free (r);\n"
6122         | RStringList n | RHashtable n ->
6123             pr "  struct guestfs_%s_ret ret;\n" name;
6124             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6125             pr "  ret.%s.%s_val = r;\n" n n;
6126             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6127               name;
6128             pr "  free_strings (r);\n"
6129         | RStruct (n, _) ->
6130             pr "  struct guestfs_%s_ret ret;\n" name;
6131             pr "  ret.%s = *r;\n" n;
6132             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6133               name;
6134             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6135               name
6136         | RStructList (n, _) ->
6137             pr "  struct guestfs_%s_ret ret;\n" name;
6138             pr "  ret.%s = *r;\n" n;
6139             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6140               name;
6141             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6142               name
6143         | RBufferOut n ->
6144             pr "  struct guestfs_%s_ret ret;\n" name;
6145             pr "  ret.%s.%s_val = r;\n" n n;
6146             pr "  ret.%s.%s_len = size;\n" n n;
6147             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6148               name;
6149             pr "  free (r);\n"
6150       );
6151
6152       (* Free the args. *)
6153       (match snd style with
6154        | [] ->
6155            pr "done: ;\n";
6156        | _ ->
6157            pr "done:\n";
6158            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6159              name
6160       );
6161
6162       pr "}\n\n";
6163   ) daemon_functions;
6164
6165   (* Dispatch function. *)
6166   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6167   pr "{\n";
6168   pr "  switch (proc_nr) {\n";
6169
6170   List.iter (
6171     fun (name, style, _, _, _, _, _) ->
6172       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6173       pr "      %s_stub (xdr_in);\n" name;
6174       pr "      break;\n"
6175   ) daemon_functions;
6176
6177   pr "    default:\n";
6178   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";
6179   pr "  }\n";
6180   pr "}\n";
6181   pr "\n";
6182
6183   (* LVM columns and tokenization functions. *)
6184   (* XXX This generates crap code.  We should rethink how we
6185    * do this parsing.
6186    *)
6187   List.iter (
6188     function
6189     | typ, cols ->
6190         pr "static const char *lvm_%s_cols = \"%s\";\n"
6191           typ (String.concat "," (List.map fst cols));
6192         pr "\n";
6193
6194         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6195         pr "{\n";
6196         pr "  char *tok, *p, *next;\n";
6197         pr "  int i, j;\n";
6198         pr "\n";
6199         (*
6200           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6201           pr "\n";
6202         *)
6203         pr "  if (!str) {\n";
6204         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6205         pr "    return -1;\n";
6206         pr "  }\n";
6207         pr "  if (!*str || c_isspace (*str)) {\n";
6208         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6209         pr "    return -1;\n";
6210         pr "  }\n";
6211         pr "  tok = str;\n";
6212         List.iter (
6213           fun (name, coltype) ->
6214             pr "  if (!tok) {\n";
6215             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6216             pr "    return -1;\n";
6217             pr "  }\n";
6218             pr "  p = strchrnul (tok, ',');\n";
6219             pr "  if (*p) next = p+1; else next = NULL;\n";
6220             pr "  *p = '\\0';\n";
6221             (match coltype with
6222              | FString ->
6223                  pr "  r->%s = strdup (tok);\n" name;
6224                  pr "  if (r->%s == NULL) {\n" name;
6225                  pr "    perror (\"strdup\");\n";
6226                  pr "    return -1;\n";
6227                  pr "  }\n"
6228              | FUUID ->
6229                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6230                  pr "    if (tok[j] == '\\0') {\n";
6231                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6232                  pr "      return -1;\n";
6233                  pr "    } else if (tok[j] != '-')\n";
6234                  pr "      r->%s[i++] = tok[j];\n" name;
6235                  pr "  }\n";
6236              | FBytes ->
6237                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6238                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6239                  pr "    return -1;\n";
6240                  pr "  }\n";
6241              | FInt64 ->
6242                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6243                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6244                  pr "    return -1;\n";
6245                  pr "  }\n";
6246              | FOptPercent ->
6247                  pr "  if (tok[0] == '\\0')\n";
6248                  pr "    r->%s = -1;\n" name;
6249                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6250                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6251                  pr "    return -1;\n";
6252                  pr "  }\n";
6253              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6254                  assert false (* can never be an LVM column *)
6255             );
6256             pr "  tok = next;\n";
6257         ) cols;
6258
6259         pr "  if (tok != NULL) {\n";
6260         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6261         pr "    return -1;\n";
6262         pr "  }\n";
6263         pr "  return 0;\n";
6264         pr "}\n";
6265         pr "\n";
6266
6267         pr "guestfs_int_lvm_%s_list *\n" typ;
6268         pr "parse_command_line_%ss (void)\n" typ;
6269         pr "{\n";
6270         pr "  char *out, *err;\n";
6271         pr "  char *p, *pend;\n";
6272         pr "  int r, i;\n";
6273         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6274         pr "  void *newp;\n";
6275         pr "\n";
6276         pr "  ret = malloc (sizeof *ret);\n";
6277         pr "  if (!ret) {\n";
6278         pr "    reply_with_perror (\"malloc\");\n";
6279         pr "    return NULL;\n";
6280         pr "  }\n";
6281         pr "\n";
6282         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6283         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6284         pr "\n";
6285         pr "  r = command (&out, &err,\n";
6286         pr "           \"lvm\", \"%ss\",\n" typ;
6287         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6288         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6289         pr "  if (r == -1) {\n";
6290         pr "    reply_with_error (\"%%s\", err);\n";
6291         pr "    free (out);\n";
6292         pr "    free (err);\n";
6293         pr "    free (ret);\n";
6294         pr "    return NULL;\n";
6295         pr "  }\n";
6296         pr "\n";
6297         pr "  free (err);\n";
6298         pr "\n";
6299         pr "  /* Tokenize each line of the output. */\n";
6300         pr "  p = out;\n";
6301         pr "  i = 0;\n";
6302         pr "  while (p) {\n";
6303         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6304         pr "    if (pend) {\n";
6305         pr "      *pend = '\\0';\n";
6306         pr "      pend++;\n";
6307         pr "    }\n";
6308         pr "\n";
6309         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6310         pr "      p++;\n";
6311         pr "\n";
6312         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6313         pr "      p = pend;\n";
6314         pr "      continue;\n";
6315         pr "    }\n";
6316         pr "\n";
6317         pr "    /* Allocate some space to store this next entry. */\n";
6318         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6319         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6320         pr "    if (newp == NULL) {\n";
6321         pr "      reply_with_perror (\"realloc\");\n";
6322         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6323         pr "      free (ret);\n";
6324         pr "      free (out);\n";
6325         pr "      return NULL;\n";
6326         pr "    }\n";
6327         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6328         pr "\n";
6329         pr "    /* Tokenize the next entry. */\n";
6330         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6331         pr "    if (r == -1) {\n";
6332         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6333         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6334         pr "      free (ret);\n";
6335         pr "      free (out);\n";
6336         pr "      return NULL;\n";
6337         pr "    }\n";
6338         pr "\n";
6339         pr "    ++i;\n";
6340         pr "    p = pend;\n";
6341         pr "  }\n";
6342         pr "\n";
6343         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6344         pr "\n";
6345         pr "  free (out);\n";
6346         pr "  return ret;\n";
6347         pr "}\n"
6348
6349   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6350
6351 (* Generate a list of function names, for debugging in the daemon.. *)
6352 and generate_daemon_names () =
6353   generate_header CStyle GPLv2plus;
6354
6355   pr "#include <config.h>\n";
6356   pr "\n";
6357   pr "#include \"daemon.h\"\n";
6358   pr "\n";
6359
6360   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6361   pr "const char *function_names[] = {\n";
6362   List.iter (
6363     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6364   ) daemon_functions;
6365   pr "};\n";
6366
6367 (* Generate the optional groups for the daemon to implement
6368  * guestfs_available.
6369  *)
6370 and generate_daemon_optgroups_c () =
6371   generate_header CStyle GPLv2plus;
6372
6373   pr "#include <config.h>\n";
6374   pr "\n";
6375   pr "#include \"daemon.h\"\n";
6376   pr "#include \"optgroups.h\"\n";
6377   pr "\n";
6378
6379   pr "struct optgroup optgroups[] = {\n";
6380   List.iter (
6381     fun (group, _) ->
6382       pr "  { \"%s\", optgroup_%s_available },\n" group group
6383   ) optgroups;
6384   pr "  { NULL, NULL }\n";
6385   pr "};\n"
6386
6387 and generate_daemon_optgroups_h () =
6388   generate_header CStyle GPLv2plus;
6389
6390   List.iter (
6391     fun (group, _) ->
6392       pr "extern int optgroup_%s_available (void);\n" group
6393   ) optgroups
6394
6395 (* Generate the tests. *)
6396 and generate_tests () =
6397   generate_header CStyle GPLv2plus;
6398
6399   pr "\
6400 #include <stdio.h>
6401 #include <stdlib.h>
6402 #include <string.h>
6403 #include <unistd.h>
6404 #include <sys/types.h>
6405 #include <fcntl.h>
6406
6407 #include \"guestfs.h\"
6408 #include \"guestfs-internal.h\"
6409
6410 static guestfs_h *g;
6411 static int suppress_error = 0;
6412
6413 static void print_error (guestfs_h *g, void *data, const char *msg)
6414 {
6415   if (!suppress_error)
6416     fprintf (stderr, \"%%s\\n\", msg);
6417 }
6418
6419 /* FIXME: nearly identical code appears in fish.c */
6420 static void print_strings (char *const *argv)
6421 {
6422   int argc;
6423
6424   for (argc = 0; argv[argc] != NULL; ++argc)
6425     printf (\"\\t%%s\\n\", argv[argc]);
6426 }
6427
6428 /*
6429 static void print_table (char const *const *argv)
6430 {
6431   int i;
6432
6433   for (i = 0; argv[i] != NULL; i += 2)
6434     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6435 }
6436 */
6437
6438 ";
6439
6440   (* Generate a list of commands which are not tested anywhere. *)
6441   pr "static void no_test_warnings (void)\n";
6442   pr "{\n";
6443
6444   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6445   List.iter (
6446     fun (_, _, _, _, tests, _, _) ->
6447       let tests = filter_map (
6448         function
6449         | (_, (Always|If _|Unless _), test) -> Some test
6450         | (_, Disabled, _) -> None
6451       ) tests in
6452       let seq = List.concat (List.map seq_of_test tests) in
6453       let cmds_tested = List.map List.hd seq in
6454       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6455   ) all_functions;
6456
6457   List.iter (
6458     fun (name, _, _, _, _, _, _) ->
6459       if not (Hashtbl.mem hash name) then
6460         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6461   ) all_functions;
6462
6463   pr "}\n";
6464   pr "\n";
6465
6466   (* Generate the actual tests.  Note that we generate the tests
6467    * in reverse order, deliberately, so that (in general) the
6468    * newest tests run first.  This makes it quicker and easier to
6469    * debug them.
6470    *)
6471   let test_names =
6472     List.map (
6473       fun (name, _, _, flags, tests, _, _) ->
6474         mapi (generate_one_test name flags) tests
6475     ) (List.rev all_functions) in
6476   let test_names = List.concat test_names in
6477   let nr_tests = List.length test_names in
6478
6479   pr "\
6480 int main (int argc, char *argv[])
6481 {
6482   char c = 0;
6483   unsigned long int n_failed = 0;
6484   const char *filename;
6485   int fd;
6486   int nr_tests, test_num = 0;
6487
6488   setbuf (stdout, NULL);
6489
6490   no_test_warnings ();
6491
6492   g = guestfs_create ();
6493   if (g == NULL) {
6494     printf (\"guestfs_create FAILED\\n\");
6495     exit (EXIT_FAILURE);
6496   }
6497
6498   guestfs_set_error_handler (g, print_error, NULL);
6499
6500   guestfs_set_path (g, \"../appliance\");
6501
6502   filename = \"test1.img\";
6503   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6504   if (fd == -1) {
6505     perror (filename);
6506     exit (EXIT_FAILURE);
6507   }
6508   if (lseek (fd, %d, SEEK_SET) == -1) {
6509     perror (\"lseek\");
6510     close (fd);
6511     unlink (filename);
6512     exit (EXIT_FAILURE);
6513   }
6514   if (write (fd, &c, 1) == -1) {
6515     perror (\"write\");
6516     close (fd);
6517     unlink (filename);
6518     exit (EXIT_FAILURE);
6519   }
6520   if (close (fd) == -1) {
6521     perror (filename);
6522     unlink (filename);
6523     exit (EXIT_FAILURE);
6524   }
6525   if (guestfs_add_drive (g, filename) == -1) {
6526     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6527     exit (EXIT_FAILURE);
6528   }
6529
6530   filename = \"test2.img\";
6531   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6532   if (fd == -1) {
6533     perror (filename);
6534     exit (EXIT_FAILURE);
6535   }
6536   if (lseek (fd, %d, SEEK_SET) == -1) {
6537     perror (\"lseek\");
6538     close (fd);
6539     unlink (filename);
6540     exit (EXIT_FAILURE);
6541   }
6542   if (write (fd, &c, 1) == -1) {
6543     perror (\"write\");
6544     close (fd);
6545     unlink (filename);
6546     exit (EXIT_FAILURE);
6547   }
6548   if (close (fd) == -1) {
6549     perror (filename);
6550     unlink (filename);
6551     exit (EXIT_FAILURE);
6552   }
6553   if (guestfs_add_drive (g, filename) == -1) {
6554     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6555     exit (EXIT_FAILURE);
6556   }
6557
6558   filename = \"test3.img\";
6559   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6560   if (fd == -1) {
6561     perror (filename);
6562     exit (EXIT_FAILURE);
6563   }
6564   if (lseek (fd, %d, SEEK_SET) == -1) {
6565     perror (\"lseek\");
6566     close (fd);
6567     unlink (filename);
6568     exit (EXIT_FAILURE);
6569   }
6570   if (write (fd, &c, 1) == -1) {
6571     perror (\"write\");
6572     close (fd);
6573     unlink (filename);
6574     exit (EXIT_FAILURE);
6575   }
6576   if (close (fd) == -1) {
6577     perror (filename);
6578     unlink (filename);
6579     exit (EXIT_FAILURE);
6580   }
6581   if (guestfs_add_drive (g, filename) == -1) {
6582     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6583     exit (EXIT_FAILURE);
6584   }
6585
6586   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6587     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6588     exit (EXIT_FAILURE);
6589   }
6590
6591   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6592   alarm (600);
6593
6594   if (guestfs_launch (g) == -1) {
6595     printf (\"guestfs_launch FAILED\\n\");
6596     exit (EXIT_FAILURE);
6597   }
6598
6599   /* Cancel previous alarm. */
6600   alarm (0);
6601
6602   nr_tests = %d;
6603
6604 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6605
6606   iteri (
6607     fun i test_name ->
6608       pr "  test_num++;\n";
6609       pr "  if (guestfs_get_verbose (g))\n";
6610       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6611       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6612       pr "  if (%s () == -1) {\n" test_name;
6613       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6614       pr "    n_failed++;\n";
6615       pr "  }\n";
6616   ) test_names;
6617   pr "\n";
6618
6619   pr "  guestfs_close (g);\n";
6620   pr "  unlink (\"test1.img\");\n";
6621   pr "  unlink (\"test2.img\");\n";
6622   pr "  unlink (\"test3.img\");\n";
6623   pr "\n";
6624
6625   pr "  if (n_failed > 0) {\n";
6626   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6627   pr "    exit (EXIT_FAILURE);\n";
6628   pr "  }\n";
6629   pr "\n";
6630
6631   pr "  exit (EXIT_SUCCESS);\n";
6632   pr "}\n"
6633
6634 and generate_one_test name flags i (init, prereq, test) =
6635   let test_name = sprintf "test_%s_%d" name i in
6636
6637   pr "\
6638 static int %s_skip (void)
6639 {
6640   const char *str;
6641
6642   str = getenv (\"TEST_ONLY\");
6643   if (str)
6644     return strstr (str, \"%s\") == NULL;
6645   str = getenv (\"SKIP_%s\");
6646   if (str && STREQ (str, \"1\")) return 1;
6647   str = getenv (\"SKIP_TEST_%s\");
6648   if (str && STREQ (str, \"1\")) return 1;
6649   return 0;
6650 }
6651
6652 " test_name name (String.uppercase test_name) (String.uppercase name);
6653
6654   (match prereq with
6655    | Disabled | Always -> ()
6656    | If code | Unless code ->
6657        pr "static int %s_prereq (void)\n" test_name;
6658        pr "{\n";
6659        pr "  %s\n" code;
6660        pr "}\n";
6661        pr "\n";
6662   );
6663
6664   pr "\
6665 static int %s (void)
6666 {
6667   if (%s_skip ()) {
6668     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6669     return 0;
6670   }
6671
6672 " test_name test_name test_name;
6673
6674   (* Optional functions should only be tested if the relevant
6675    * support is available in the daemon.
6676    *)
6677   List.iter (
6678     function
6679     | Optional group ->
6680         pr "  {\n";
6681         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6682         pr "    int r;\n";
6683         pr "    suppress_error = 1;\n";
6684         pr "    r = guestfs_available (g, (char **) groups);\n";
6685         pr "    suppress_error = 0;\n";
6686         pr "    if (r == -1) {\n";
6687         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6688         pr "      return 0;\n";
6689         pr "    }\n";
6690         pr "  }\n";
6691     | _ -> ()
6692   ) flags;
6693
6694   (match prereq with
6695    | Disabled ->
6696        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6697    | If _ ->
6698        pr "  if (! %s_prereq ()) {\n" test_name;
6699        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6700        pr "    return 0;\n";
6701        pr "  }\n";
6702        pr "\n";
6703        generate_one_test_body name i test_name init test;
6704    | Unless _ ->
6705        pr "  if (%s_prereq ()) {\n" test_name;
6706        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6707        pr "    return 0;\n";
6708        pr "  }\n";
6709        pr "\n";
6710        generate_one_test_body name i test_name init test;
6711    | Always ->
6712        generate_one_test_body name i test_name init test
6713   );
6714
6715   pr "  return 0;\n";
6716   pr "}\n";
6717   pr "\n";
6718   test_name
6719
6720 and generate_one_test_body name i test_name init test =
6721   (match init with
6722    | InitNone (* XXX at some point, InitNone and InitEmpty became
6723                * folded together as the same thing.  Really we should
6724                * make InitNone do nothing at all, but the tests may
6725                * need to be checked to make sure this is OK.
6726                *)
6727    | InitEmpty ->
6728        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6729        List.iter (generate_test_command_call test_name)
6730          [["blockdev_setrw"; "/dev/sda"];
6731           ["umount_all"];
6732           ["lvm_remove_all"]]
6733    | InitPartition ->
6734        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6735        List.iter (generate_test_command_call test_name)
6736          [["blockdev_setrw"; "/dev/sda"];
6737           ["umount_all"];
6738           ["lvm_remove_all"];
6739           ["part_disk"; "/dev/sda"; "mbr"]]
6740    | InitBasicFS ->
6741        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6742        List.iter (generate_test_command_call test_name)
6743          [["blockdev_setrw"; "/dev/sda"];
6744           ["umount_all"];
6745           ["lvm_remove_all"];
6746           ["part_disk"; "/dev/sda"; "mbr"];
6747           ["mkfs"; "ext2"; "/dev/sda1"];
6748           ["mount_options"; ""; "/dev/sda1"; "/"]]
6749    | InitBasicFSonLVM ->
6750        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6751          test_name;
6752        List.iter (generate_test_command_call test_name)
6753          [["blockdev_setrw"; "/dev/sda"];
6754           ["umount_all"];
6755           ["lvm_remove_all"];
6756           ["part_disk"; "/dev/sda"; "mbr"];
6757           ["pvcreate"; "/dev/sda1"];
6758           ["vgcreate"; "VG"; "/dev/sda1"];
6759           ["lvcreate"; "LV"; "VG"; "8"];
6760           ["mkfs"; "ext2"; "/dev/VG/LV"];
6761           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6762    | InitISOFS ->
6763        pr "  /* InitISOFS for %s */\n" test_name;
6764        List.iter (generate_test_command_call test_name)
6765          [["blockdev_setrw"; "/dev/sda"];
6766           ["umount_all"];
6767           ["lvm_remove_all"];
6768           ["mount_ro"; "/dev/sdd"; "/"]]
6769   );
6770
6771   let get_seq_last = function
6772     | [] ->
6773         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6774           test_name
6775     | seq ->
6776         let seq = List.rev seq in
6777         List.rev (List.tl seq), List.hd seq
6778   in
6779
6780   match test with
6781   | TestRun seq ->
6782       pr "  /* TestRun for %s (%d) */\n" name i;
6783       List.iter (generate_test_command_call test_name) seq
6784   | TestOutput (seq, expected) ->
6785       pr "  /* TestOutput for %s (%d) */\n" name i;
6786       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6787       let seq, last = get_seq_last seq in
6788       let test () =
6789         pr "    if (STRNEQ (r, expected)) {\n";
6790         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6791         pr "      return -1;\n";
6792         pr "    }\n"
6793       in
6794       List.iter (generate_test_command_call test_name) seq;
6795       generate_test_command_call ~test test_name last
6796   | TestOutputList (seq, expected) ->
6797       pr "  /* TestOutputList for %s (%d) */\n" name i;
6798       let seq, last = get_seq_last seq in
6799       let test () =
6800         iteri (
6801           fun i str ->
6802             pr "    if (!r[%d]) {\n" i;
6803             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6804             pr "      print_strings (r);\n";
6805             pr "      return -1;\n";
6806             pr "    }\n";
6807             pr "    {\n";
6808             pr "      const char *expected = \"%s\";\n" (c_quote str);
6809             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6810             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6811             pr "        return -1;\n";
6812             pr "      }\n";
6813             pr "    }\n"
6814         ) expected;
6815         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6816         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6817           test_name;
6818         pr "      print_strings (r);\n";
6819         pr "      return -1;\n";
6820         pr "    }\n"
6821       in
6822       List.iter (generate_test_command_call test_name) seq;
6823       generate_test_command_call ~test test_name last
6824   | TestOutputListOfDevices (seq, expected) ->
6825       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6826       let seq, last = get_seq_last seq in
6827       let test () =
6828         iteri (
6829           fun i str ->
6830             pr "    if (!r[%d]) {\n" i;
6831             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6832             pr "      print_strings (r);\n";
6833             pr "      return -1;\n";
6834             pr "    }\n";
6835             pr "    {\n";
6836             pr "      const char *expected = \"%s\";\n" (c_quote str);
6837             pr "      r[%d][5] = 's';\n" i;
6838             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6839             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6840             pr "        return -1;\n";
6841             pr "      }\n";
6842             pr "    }\n"
6843         ) expected;
6844         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6845         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6846           test_name;
6847         pr "      print_strings (r);\n";
6848         pr "      return -1;\n";
6849         pr "    }\n"
6850       in
6851       List.iter (generate_test_command_call test_name) seq;
6852       generate_test_command_call ~test test_name last
6853   | TestOutputInt (seq, expected) ->
6854       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6855       let seq, last = get_seq_last seq in
6856       let test () =
6857         pr "    if (r != %d) {\n" expected;
6858         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6859           test_name expected;
6860         pr "               (int) r);\n";
6861         pr "      return -1;\n";
6862         pr "    }\n"
6863       in
6864       List.iter (generate_test_command_call test_name) seq;
6865       generate_test_command_call ~test test_name last
6866   | TestOutputIntOp (seq, op, expected) ->
6867       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6868       let seq, last = get_seq_last seq in
6869       let test () =
6870         pr "    if (! (r %s %d)) {\n" op expected;
6871         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6872           test_name op expected;
6873         pr "               (int) r);\n";
6874         pr "      return -1;\n";
6875         pr "    }\n"
6876       in
6877       List.iter (generate_test_command_call test_name) seq;
6878       generate_test_command_call ~test test_name last
6879   | TestOutputTrue seq ->
6880       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6881       let seq, last = get_seq_last seq in
6882       let test () =
6883         pr "    if (!r) {\n";
6884         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6885           test_name;
6886         pr "      return -1;\n";
6887         pr "    }\n"
6888       in
6889       List.iter (generate_test_command_call test_name) seq;
6890       generate_test_command_call ~test test_name last
6891   | TestOutputFalse seq ->
6892       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6893       let seq, last = get_seq_last seq in
6894       let test () =
6895         pr "    if (r) {\n";
6896         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6897           test_name;
6898         pr "      return -1;\n";
6899         pr "    }\n"
6900       in
6901       List.iter (generate_test_command_call test_name) seq;
6902       generate_test_command_call ~test test_name last
6903   | TestOutputLength (seq, expected) ->
6904       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6905       let seq, last = get_seq_last seq in
6906       let test () =
6907         pr "    int j;\n";
6908         pr "    for (j = 0; j < %d; ++j)\n" expected;
6909         pr "      if (r[j] == NULL) {\n";
6910         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6911           test_name;
6912         pr "        print_strings (r);\n";
6913         pr "        return -1;\n";
6914         pr "      }\n";
6915         pr "    if (r[j] != NULL) {\n";
6916         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6917           test_name;
6918         pr "      print_strings (r);\n";
6919         pr "      return -1;\n";
6920         pr "    }\n"
6921       in
6922       List.iter (generate_test_command_call test_name) seq;
6923       generate_test_command_call ~test test_name last
6924   | TestOutputBuffer (seq, expected) ->
6925       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6926       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6927       let seq, last = get_seq_last seq in
6928       let len = String.length expected in
6929       let test () =
6930         pr "    if (size != %d) {\n" len;
6931         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6932         pr "      return -1;\n";
6933         pr "    }\n";
6934         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6935         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6936         pr "      return -1;\n";
6937         pr "    }\n"
6938       in
6939       List.iter (generate_test_command_call test_name) seq;
6940       generate_test_command_call ~test test_name last
6941   | TestOutputStruct (seq, checks) ->
6942       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6943       let seq, last = get_seq_last seq in
6944       let test () =
6945         List.iter (
6946           function
6947           | CompareWithInt (field, expected) ->
6948               pr "    if (r->%s != %d) {\n" field expected;
6949               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6950                 test_name field expected;
6951               pr "               (int) r->%s);\n" field;
6952               pr "      return -1;\n";
6953               pr "    }\n"
6954           | CompareWithIntOp (field, op, expected) ->
6955               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6956               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6957                 test_name field op expected;
6958               pr "               (int) r->%s);\n" field;
6959               pr "      return -1;\n";
6960               pr "    }\n"
6961           | CompareWithString (field, expected) ->
6962               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6963               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6964                 test_name field expected;
6965               pr "               r->%s);\n" field;
6966               pr "      return -1;\n";
6967               pr "    }\n"
6968           | CompareFieldsIntEq (field1, field2) ->
6969               pr "    if (r->%s != r->%s) {\n" field1 field2;
6970               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6971                 test_name field1 field2;
6972               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6973               pr "      return -1;\n";
6974               pr "    }\n"
6975           | CompareFieldsStrEq (field1, field2) ->
6976               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6977               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6978                 test_name field1 field2;
6979               pr "               r->%s, r->%s);\n" field1 field2;
6980               pr "      return -1;\n";
6981               pr "    }\n"
6982         ) checks
6983       in
6984       List.iter (generate_test_command_call test_name) seq;
6985       generate_test_command_call ~test test_name last
6986   | TestLastFail seq ->
6987       pr "  /* TestLastFail for %s (%d) */\n" name i;
6988       let seq, last = get_seq_last seq in
6989       List.iter (generate_test_command_call test_name) seq;
6990       generate_test_command_call test_name ~expect_error:true last
6991
6992 (* Generate the code to run a command, leaving the result in 'r'.
6993  * If you expect to get an error then you should set expect_error:true.
6994  *)
6995 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6996   match cmd with
6997   | [] -> assert false
6998   | name :: args ->
6999       (* Look up the command to find out what args/ret it has. *)
7000       let style =
7001         try
7002           let _, style, _, _, _, _, _ =
7003             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7004           style
7005         with Not_found ->
7006           failwithf "%s: in test, command %s was not found" test_name name in
7007
7008       if List.length (snd style) <> List.length args then
7009         failwithf "%s: in test, wrong number of args given to %s"
7010           test_name name;
7011
7012       pr "  {\n";
7013
7014       List.iter (
7015         function
7016         | OptString n, "NULL" -> ()
7017         | Pathname n, arg
7018         | Device n, arg
7019         | Dev_or_Path n, arg
7020         | String n, arg
7021         | OptString n, arg ->
7022             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7023         | Int _, _
7024         | Int64 _, _
7025         | Bool _, _
7026         | FileIn _, _ | FileOut _, _ -> ()
7027         | StringList n, "" | DeviceList n, "" ->
7028             pr "    const char *const %s[1] = { NULL };\n" n
7029         | StringList n, arg | DeviceList n, arg ->
7030             let strs = string_split " " arg in
7031             iteri (
7032               fun i str ->
7033                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7034             ) strs;
7035             pr "    const char *const %s[] = {\n" n;
7036             iteri (
7037               fun i _ -> pr "      %s_%d,\n" n i
7038             ) strs;
7039             pr "      NULL\n";
7040             pr "    };\n";
7041       ) (List.combine (snd style) args);
7042
7043       let error_code =
7044         match fst style with
7045         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7046         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7047         | RConstString _ | RConstOptString _ ->
7048             pr "    const char *r;\n"; "NULL"
7049         | RString _ -> pr "    char *r;\n"; "NULL"
7050         | RStringList _ | RHashtable _ ->
7051             pr "    char **r;\n";
7052             pr "    int i;\n";
7053             "NULL"
7054         | RStruct (_, typ) ->
7055             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7056         | RStructList (_, typ) ->
7057             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7058         | RBufferOut _ ->
7059             pr "    char *r;\n";
7060             pr "    size_t size;\n";
7061             "NULL" in
7062
7063       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7064       pr "    r = guestfs_%s (g" name;
7065
7066       (* Generate the parameters. *)
7067       List.iter (
7068         function
7069         | OptString _, "NULL" -> pr ", NULL"
7070         | Pathname n, _
7071         | Device n, _ | Dev_or_Path n, _
7072         | String n, _
7073         | OptString n, _ ->
7074             pr ", %s" n
7075         | FileIn _, arg | FileOut _, arg ->
7076             pr ", \"%s\"" (c_quote arg)
7077         | StringList n, _ | DeviceList n, _ ->
7078             pr ", (char **) %s" n
7079         | Int _, arg ->
7080             let i =
7081               try int_of_string arg
7082               with Failure "int_of_string" ->
7083                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7084             pr ", %d" i
7085         | Int64 _, arg ->
7086             let i =
7087               try Int64.of_string arg
7088               with Failure "int_of_string" ->
7089                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7090             pr ", %Ld" i
7091         | Bool _, arg ->
7092             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7093       ) (List.combine (snd style) args);
7094
7095       (match fst style with
7096        | RBufferOut _ -> pr ", &size"
7097        | _ -> ()
7098       );
7099
7100       pr ");\n";
7101
7102       if not expect_error then
7103         pr "    if (r == %s)\n" error_code
7104       else
7105         pr "    if (r != %s)\n" error_code;
7106       pr "      return -1;\n";
7107
7108       (* Insert the test code. *)
7109       (match test with
7110        | None -> ()
7111        | Some f -> f ()
7112       );
7113
7114       (match fst style with
7115        | RErr | RInt _ | RInt64 _ | RBool _
7116        | RConstString _ | RConstOptString _ -> ()
7117        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7118        | RStringList _ | RHashtable _ ->
7119            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7120            pr "      free (r[i]);\n";
7121            pr "    free (r);\n"
7122        | RStruct (_, typ) ->
7123            pr "    guestfs_free_%s (r);\n" typ
7124        | RStructList (_, typ) ->
7125            pr "    guestfs_free_%s_list (r);\n" typ
7126       );
7127
7128       pr "  }\n"
7129
7130 and c_quote str =
7131   let str = replace_str str "\r" "\\r" in
7132   let str = replace_str str "\n" "\\n" in
7133   let str = replace_str str "\t" "\\t" in
7134   let str = replace_str str "\000" "\\0" in
7135   str
7136
7137 (* Generate a lot of different functions for guestfish. *)
7138 and generate_fish_cmds () =
7139   generate_header CStyle GPLv2plus;
7140
7141   let all_functions =
7142     List.filter (
7143       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7144     ) all_functions in
7145   let all_functions_sorted =
7146     List.filter (
7147       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7148     ) all_functions_sorted in
7149
7150   pr "#include <config.h>\n";
7151   pr "\n";
7152   pr "#include <stdio.h>\n";
7153   pr "#include <stdlib.h>\n";
7154   pr "#include <string.h>\n";
7155   pr "#include <inttypes.h>\n";
7156   pr "\n";
7157   pr "#include <guestfs.h>\n";
7158   pr "#include \"c-ctype.h\"\n";
7159   pr "#include \"full-write.h\"\n";
7160   pr "#include \"xstrtol.h\"\n";
7161   pr "#include \"fish.h\"\n";
7162   pr "\n";
7163
7164   (* list_commands function, which implements guestfish -h *)
7165   pr "void list_commands (void)\n";
7166   pr "{\n";
7167   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7168   pr "  list_builtin_commands ();\n";
7169   List.iter (
7170     fun (name, _, _, flags, _, shortdesc, _) ->
7171       let name = replace_char name '_' '-' in
7172       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7173         name shortdesc
7174   ) all_functions_sorted;
7175   pr "  printf (\"    %%s\\n\",";
7176   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7177   pr "}\n";
7178   pr "\n";
7179
7180   (* display_command function, which implements guestfish -h cmd *)
7181   pr "void display_command (const char *cmd)\n";
7182   pr "{\n";
7183   List.iter (
7184     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7185       let name2 = replace_char name '_' '-' in
7186       let alias =
7187         try find_map (function FishAlias n -> Some n | _ -> None) flags
7188         with Not_found -> name in
7189       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7190       let synopsis =
7191         match snd style with
7192         | [] -> name2
7193         | args ->
7194             sprintf "%s %s"
7195               name2 (String.concat " " (List.map name_of_argt args)) in
7196
7197       let warnings =
7198         if List.mem ProtocolLimitWarning flags then
7199           ("\n\n" ^ protocol_limit_warning)
7200         else "" in
7201
7202       (* For DangerWillRobinson commands, we should probably have
7203        * guestfish prompt before allowing you to use them (especially
7204        * in interactive mode). XXX
7205        *)
7206       let warnings =
7207         warnings ^
7208           if List.mem DangerWillRobinson flags then
7209             ("\n\n" ^ danger_will_robinson)
7210           else "" in
7211
7212       let warnings =
7213         warnings ^
7214           match deprecation_notice flags with
7215           | None -> ""
7216           | Some txt -> "\n\n" ^ txt in
7217
7218       let describe_alias =
7219         if name <> alias then
7220           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7221         else "" in
7222
7223       pr "  if (";
7224       pr "STRCASEEQ (cmd, \"%s\")" name;
7225       if name <> name2 then
7226         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7227       if name <> alias then
7228         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7229       pr ")\n";
7230       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7231         name2 shortdesc
7232         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7233          "=head1 DESCRIPTION\n\n" ^
7234          longdesc ^ warnings ^ describe_alias);
7235       pr "  else\n"
7236   ) all_functions;
7237   pr "    display_builtin_command (cmd);\n";
7238   pr "}\n";
7239   pr "\n";
7240
7241   let emit_print_list_function typ =
7242     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7243       typ typ typ;
7244     pr "{\n";
7245     pr "  unsigned int i;\n";
7246     pr "\n";
7247     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7248     pr "    printf (\"[%%d] = {\\n\", i);\n";
7249     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7250     pr "    printf (\"}\\n\");\n";
7251     pr "  }\n";
7252     pr "}\n";
7253     pr "\n";
7254   in
7255
7256   (* print_* functions *)
7257   List.iter (
7258     fun (typ, cols) ->
7259       let needs_i =
7260         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7261
7262       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7263       pr "{\n";
7264       if needs_i then (
7265         pr "  unsigned int i;\n";
7266         pr "\n"
7267       );
7268       List.iter (
7269         function
7270         | name, FString ->
7271             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7272         | name, FUUID ->
7273             pr "  printf (\"%%s%s: \", indent);\n" name;
7274             pr "  for (i = 0; i < 32; ++i)\n";
7275             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7276             pr "  printf (\"\\n\");\n"
7277         | name, FBuffer ->
7278             pr "  printf (\"%%s%s: \", indent);\n" name;
7279             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7280             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7281             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7282             pr "    else\n";
7283             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7284             pr "  printf (\"\\n\");\n"
7285         | name, (FUInt64|FBytes) ->
7286             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7287               name typ name
7288         | name, FInt64 ->
7289             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7290               name typ name
7291         | name, FUInt32 ->
7292             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7293               name typ name
7294         | name, FInt32 ->
7295             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7296               name typ name
7297         | name, FChar ->
7298             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7299               name typ name
7300         | name, FOptPercent ->
7301             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7302               typ name name typ name;
7303             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7304       ) cols;
7305       pr "}\n";
7306       pr "\n";
7307   ) structs;
7308
7309   (* Emit a print_TYPE_list function definition only if that function is used. *)
7310   List.iter (
7311     function
7312     | typ, (RStructListOnly | RStructAndList) ->
7313         (* generate the function for typ *)
7314         emit_print_list_function typ
7315     | typ, _ -> () (* empty *)
7316   ) (rstructs_used_by all_functions);
7317
7318   (* Emit a print_TYPE function definition only if that function is used. *)
7319   List.iter (
7320     function
7321     | typ, (RStructOnly | RStructAndList) ->
7322         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7323         pr "{\n";
7324         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7325         pr "}\n";
7326         pr "\n";
7327     | typ, _ -> () (* empty *)
7328   ) (rstructs_used_by all_functions);
7329
7330   (* run_<action> actions *)
7331   List.iter (
7332     fun (name, style, _, flags, _, _, _) ->
7333       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7334       pr "{\n";
7335       (match fst style with
7336        | RErr
7337        | RInt _
7338        | RBool _ -> pr "  int r;\n"
7339        | RInt64 _ -> pr "  int64_t r;\n"
7340        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7341        | RString _ -> pr "  char *r;\n"
7342        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7343        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7344        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7345        | RBufferOut _ ->
7346            pr "  char *r;\n";
7347            pr "  size_t size;\n";
7348       );
7349       List.iter (
7350         function
7351         | Device n
7352         | String n
7353         | OptString n
7354         | FileIn n
7355         | FileOut n -> pr "  const char *%s;\n" n
7356         | Pathname n
7357         | Dev_or_Path n -> pr "  char *%s;\n" n
7358         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7359         | Bool n -> pr "  int %s;\n" n
7360         | Int n -> pr "  int %s;\n" n
7361         | Int64 n -> pr "  int64_t %s;\n" n
7362       ) (snd style);
7363
7364       (* Check and convert parameters. *)
7365       let argc_expected = List.length (snd style) in
7366       pr "  if (argc != %d) {\n" argc_expected;
7367       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7368         argc_expected;
7369       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7370       pr "    return -1;\n";
7371       pr "  }\n";
7372
7373       let parse_integer fn fntyp rtyp range name i =
7374         pr "  {\n";
7375         pr "    strtol_error xerr;\n";
7376         pr "    %s r;\n" fntyp;
7377         pr "\n";
7378         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7379         pr "    if (xerr != LONGINT_OK) {\n";
7380         pr "      fprintf (stderr,\n";
7381         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7382         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7383         pr "      return -1;\n";
7384         pr "    }\n";
7385         (match range with
7386          | None -> ()
7387          | Some (min, max, comment) ->
7388              pr "    /* %s */\n" comment;
7389              pr "    if (r < %s || r > %s) {\n" min max;
7390              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7391                name;
7392              pr "      return -1;\n";
7393              pr "    }\n";
7394              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7395         );
7396         pr "    %s = r;\n" name;
7397         pr "  }\n";
7398       in
7399
7400       iteri (
7401         fun i ->
7402           function
7403           | Device name
7404           | String name ->
7405               pr "  %s = argv[%d];\n" name i
7406           | Pathname name
7407           | Dev_or_Path name ->
7408               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7409               pr "  if (%s == NULL) return -1;\n" name
7410           | OptString name ->
7411               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7412                 name i i
7413           | FileIn name ->
7414               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7415                 name i i
7416           | FileOut name ->
7417               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7418                 name i i
7419           | StringList name | DeviceList name ->
7420               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7421               pr "  if (%s == NULL) return -1;\n" name;
7422           | Bool name ->
7423               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7424           | Int name ->
7425               let range =
7426                 let min = "(-(2LL<<30))"
7427                 and max = "((2LL<<30)-1)"
7428                 and comment =
7429                   "The Int type in the generator is a signed 31 bit int." in
7430                 Some (min, max, comment) in
7431               parse_integer "xstrtoll" "long long" "int" range name i
7432           | Int64 name ->
7433               parse_integer "xstrtoll" "long long" "int64_t" None name i
7434       ) (snd style);
7435
7436       (* Call C API function. *)
7437       let fn =
7438         try find_map (function FishAction n -> Some n | _ -> None) flags
7439         with Not_found -> sprintf "guestfs_%s" name in
7440       pr "  r = %s " fn;
7441       generate_c_call_args ~handle:"g" style;
7442       pr ";\n";
7443
7444       List.iter (
7445         function
7446         | Device name | String name
7447         | OptString name | FileIn name | FileOut name | Bool name
7448         | Int name | Int64 name -> ()
7449         | Pathname name | Dev_or_Path name ->
7450             pr "  free (%s);\n" name
7451         | StringList name | DeviceList name ->
7452             pr "  free_strings (%s);\n" name
7453       ) (snd style);
7454
7455       (* Check return value for errors and display command results. *)
7456       (match fst style with
7457        | RErr -> pr "  return r;\n"
7458        | RInt _ ->
7459            pr "  if (r == -1) return -1;\n";
7460            pr "  printf (\"%%d\\n\", r);\n";
7461            pr "  return 0;\n"
7462        | RInt64 _ ->
7463            pr "  if (r == -1) return -1;\n";
7464            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7465            pr "  return 0;\n"
7466        | RBool _ ->
7467            pr "  if (r == -1) return -1;\n";
7468            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7469            pr "  return 0;\n"
7470        | RConstString _ ->
7471            pr "  if (r == NULL) return -1;\n";
7472            pr "  printf (\"%%s\\n\", r);\n";
7473            pr "  return 0;\n"
7474        | RConstOptString _ ->
7475            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7476            pr "  return 0;\n"
7477        | RString _ ->
7478            pr "  if (r == NULL) return -1;\n";
7479            pr "  printf (\"%%s\\n\", r);\n";
7480            pr "  free (r);\n";
7481            pr "  return 0;\n"
7482        | RStringList _ ->
7483            pr "  if (r == NULL) return -1;\n";
7484            pr "  print_strings (r);\n";
7485            pr "  free_strings (r);\n";
7486            pr "  return 0;\n"
7487        | RStruct (_, typ) ->
7488            pr "  if (r == NULL) return -1;\n";
7489            pr "  print_%s (r);\n" typ;
7490            pr "  guestfs_free_%s (r);\n" typ;
7491            pr "  return 0;\n"
7492        | RStructList (_, typ) ->
7493            pr "  if (r == NULL) return -1;\n";
7494            pr "  print_%s_list (r);\n" typ;
7495            pr "  guestfs_free_%s_list (r);\n" typ;
7496            pr "  return 0;\n"
7497        | RHashtable _ ->
7498            pr "  if (r == NULL) return -1;\n";
7499            pr "  print_table (r);\n";
7500            pr "  free_strings (r);\n";
7501            pr "  return 0;\n"
7502        | RBufferOut _ ->
7503            pr "  if (r == NULL) return -1;\n";
7504            pr "  if (full_write (1, r, size) != size) {\n";
7505            pr "    perror (\"write\");\n";
7506            pr "    free (r);\n";
7507            pr "    return -1;\n";
7508            pr "  }\n";
7509            pr "  free (r);\n";
7510            pr "  return 0;\n"
7511       );
7512       pr "}\n";
7513       pr "\n"
7514   ) all_functions;
7515
7516   (* run_action function *)
7517   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7518   pr "{\n";
7519   List.iter (
7520     fun (name, _, _, flags, _, _, _) ->
7521       let name2 = replace_char name '_' '-' in
7522       let alias =
7523         try find_map (function FishAlias n -> Some n | _ -> None) flags
7524         with Not_found -> name in
7525       pr "  if (";
7526       pr "STRCASEEQ (cmd, \"%s\")" name;
7527       if name <> name2 then
7528         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7529       if name <> alias then
7530         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7531       pr ")\n";
7532       pr "    return run_%s (cmd, argc, argv);\n" name;
7533       pr "  else\n";
7534   ) all_functions;
7535   pr "    {\n";
7536   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7537   pr "      if (command_num == 1)\n";
7538   pr "        extended_help_message ();\n";
7539   pr "      return -1;\n";
7540   pr "    }\n";
7541   pr "  return 0;\n";
7542   pr "}\n";
7543   pr "\n"
7544
7545 (* Readline completion for guestfish. *)
7546 and generate_fish_completion () =
7547   generate_header CStyle GPLv2plus;
7548
7549   let all_functions =
7550     List.filter (
7551       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7552     ) all_functions in
7553
7554   pr "\
7555 #include <config.h>
7556
7557 #include <stdio.h>
7558 #include <stdlib.h>
7559 #include <string.h>
7560
7561 #ifdef HAVE_LIBREADLINE
7562 #include <readline/readline.h>
7563 #endif
7564
7565 #include \"fish.h\"
7566
7567 #ifdef HAVE_LIBREADLINE
7568
7569 static const char *const commands[] = {
7570   BUILTIN_COMMANDS_FOR_COMPLETION,
7571 ";
7572
7573   (* Get the commands, including the aliases.  They don't need to be
7574    * sorted - the generator() function just does a dumb linear search.
7575    *)
7576   let commands =
7577     List.map (
7578       fun (name, _, _, flags, _, _, _) ->
7579         let name2 = replace_char name '_' '-' in
7580         let alias =
7581           try find_map (function FishAlias n -> Some n | _ -> None) flags
7582           with Not_found -> name in
7583
7584         if name <> alias then [name2; alias] else [name2]
7585     ) all_functions in
7586   let commands = List.flatten commands in
7587
7588   List.iter (pr "  \"%s\",\n") commands;
7589
7590   pr "  NULL
7591 };
7592
7593 static char *
7594 generator (const char *text, int state)
7595 {
7596   static int index, len;
7597   const char *name;
7598
7599   if (!state) {
7600     index = 0;
7601     len = strlen (text);
7602   }
7603
7604   rl_attempted_completion_over = 1;
7605
7606   while ((name = commands[index]) != NULL) {
7607     index++;
7608     if (STRCASEEQLEN (name, text, len))
7609       return strdup (name);
7610   }
7611
7612   return NULL;
7613 }
7614
7615 #endif /* HAVE_LIBREADLINE */
7616
7617 #ifdef HAVE_RL_COMPLETION_MATCHES
7618 #define RL_COMPLETION_MATCHES rl_completion_matches
7619 #else
7620 #ifdef HAVE_COMPLETION_MATCHES
7621 #define RL_COMPLETION_MATCHES completion_matches
7622 #endif
7623 #endif /* else just fail if we don't have either symbol */
7624
7625 char **
7626 do_completion (const char *text, int start, int end)
7627 {
7628   char **matches = NULL;
7629
7630 #ifdef HAVE_LIBREADLINE
7631   rl_completion_append_character = ' ';
7632
7633   if (start == 0)
7634     matches = RL_COMPLETION_MATCHES (text, generator);
7635   else if (complete_dest_paths)
7636     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7637 #endif
7638
7639   return matches;
7640 }
7641 ";
7642
7643 (* Generate the POD documentation for guestfish. *)
7644 and generate_fish_actions_pod () =
7645   let all_functions_sorted =
7646     List.filter (
7647       fun (_, _, _, flags, _, _, _) ->
7648         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7649     ) all_functions_sorted in
7650
7651   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7652
7653   List.iter (
7654     fun (name, style, _, flags, _, _, longdesc) ->
7655       let longdesc =
7656         Str.global_substitute rex (
7657           fun s ->
7658             let sub =
7659               try Str.matched_group 1 s
7660               with Not_found ->
7661                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7662             "C<" ^ replace_char sub '_' '-' ^ ">"
7663         ) longdesc in
7664       let name = replace_char name '_' '-' in
7665       let alias =
7666         try find_map (function FishAlias n -> Some n | _ -> None) flags
7667         with Not_found -> name in
7668
7669       pr "=head2 %s" name;
7670       if name <> alias then
7671         pr " | %s" alias;
7672       pr "\n";
7673       pr "\n";
7674       pr " %s" name;
7675       List.iter (
7676         function
7677         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7678         | OptString n -> pr " %s" n
7679         | StringList n | DeviceList n -> pr " '%s ...'" n
7680         | Bool _ -> pr " true|false"
7681         | Int n -> pr " %s" n
7682         | Int64 n -> pr " %s" n
7683         | FileIn n | FileOut n -> pr " (%s|-)" n
7684       ) (snd style);
7685       pr "\n";
7686       pr "\n";
7687       pr "%s\n\n" longdesc;
7688
7689       if List.exists (function FileIn _ | FileOut _ -> true
7690                       | _ -> false) (snd style) then
7691         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7692
7693       if List.mem ProtocolLimitWarning flags then
7694         pr "%s\n\n" protocol_limit_warning;
7695
7696       if List.mem DangerWillRobinson flags then
7697         pr "%s\n\n" danger_will_robinson;
7698
7699       match deprecation_notice flags with
7700       | None -> ()
7701       | Some txt -> pr "%s\n\n" txt
7702   ) all_functions_sorted
7703
7704 (* Generate a C function prototype. *)
7705 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7706     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7707     ?(prefix = "")
7708     ?handle name style =
7709   if extern then pr "extern ";
7710   if static then pr "static ";
7711   (match fst style with
7712    | RErr -> pr "int "
7713    | RInt _ -> pr "int "
7714    | RInt64 _ -> pr "int64_t "
7715    | RBool _ -> pr "int "
7716    | RConstString _ | RConstOptString _ -> pr "const char *"
7717    | RString _ | RBufferOut _ -> pr "char *"
7718    | RStringList _ | RHashtable _ -> pr "char **"
7719    | RStruct (_, typ) ->
7720        if not in_daemon then pr "struct guestfs_%s *" typ
7721        else pr "guestfs_int_%s *" typ
7722    | RStructList (_, typ) ->
7723        if not in_daemon then pr "struct guestfs_%s_list *" typ
7724        else pr "guestfs_int_%s_list *" typ
7725   );
7726   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7727   pr "%s%s (" prefix name;
7728   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7729     pr "void"
7730   else (
7731     let comma = ref false in
7732     (match handle with
7733      | None -> ()
7734      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7735     );
7736     let next () =
7737       if !comma then (
7738         if single_line then pr ", " else pr ",\n\t\t"
7739       );
7740       comma := true
7741     in
7742     List.iter (
7743       function
7744       | Pathname n
7745       | Device n | Dev_or_Path n
7746       | String n
7747       | OptString n ->
7748           next ();
7749           pr "const char *%s" n
7750       | StringList n | DeviceList n ->
7751           next ();
7752           pr "char *const *%s" n
7753       | Bool n -> next (); pr "int %s" n
7754       | Int n -> next (); pr "int %s" n
7755       | Int64 n -> next (); pr "int64_t %s" n
7756       | FileIn n
7757       | FileOut n ->
7758           if not in_daemon then (next (); pr "const char *%s" n)
7759     ) (snd style);
7760     if is_RBufferOut then (next (); pr "size_t *size_r");
7761   );
7762   pr ")";
7763   if semicolon then pr ";";
7764   if newline then pr "\n"
7765
7766 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7767 and generate_c_call_args ?handle ?(decl = false) style =
7768   pr "(";
7769   let comma = ref false in
7770   let next () =
7771     if !comma then pr ", ";
7772     comma := true
7773   in
7774   (match handle with
7775    | None -> ()
7776    | Some handle -> pr "%s" handle; comma := true
7777   );
7778   List.iter (
7779     fun arg ->
7780       next ();
7781       pr "%s" (name_of_argt arg)
7782   ) (snd style);
7783   (* For RBufferOut calls, add implicit &size parameter. *)
7784   if not decl then (
7785     match fst style with
7786     | RBufferOut _ ->
7787         next ();
7788         pr "&size"
7789     | _ -> ()
7790   );
7791   pr ")"
7792
7793 (* Generate the OCaml bindings interface. *)
7794 and generate_ocaml_mli () =
7795   generate_header OCamlStyle LGPLv2plus;
7796
7797   pr "\
7798 (** For API documentation you should refer to the C API
7799     in the guestfs(3) manual page.  The OCaml API uses almost
7800     exactly the same calls. *)
7801
7802 type t
7803 (** A [guestfs_h] handle. *)
7804
7805 exception Error of string
7806 (** This exception is raised when there is an error. *)
7807
7808 exception Handle_closed of string
7809 (** This exception is raised if you use a {!Guestfs.t} handle
7810     after calling {!close} on it.  The string is the name of
7811     the function. *)
7812
7813 val create : unit -> t
7814 (** Create a {!Guestfs.t} handle. *)
7815
7816 val close : t -> unit
7817 (** Close the {!Guestfs.t} handle and free up all resources used
7818     by it immediately.
7819
7820     Handles are closed by the garbage collector when they become
7821     unreferenced, but callers can call this in order to provide
7822     predictable cleanup. *)
7823
7824 ";
7825   generate_ocaml_structure_decls ();
7826
7827   (* The actions. *)
7828   List.iter (
7829     fun (name, style, _, _, _, shortdesc, _) ->
7830       generate_ocaml_prototype name style;
7831       pr "(** %s *)\n" shortdesc;
7832       pr "\n"
7833   ) all_functions_sorted
7834
7835 (* Generate the OCaml bindings implementation. *)
7836 and generate_ocaml_ml () =
7837   generate_header OCamlStyle LGPLv2plus;
7838
7839   pr "\
7840 type t
7841
7842 exception Error of string
7843 exception Handle_closed of string
7844
7845 external create : unit -> t = \"ocaml_guestfs_create\"
7846 external close : t -> unit = \"ocaml_guestfs_close\"
7847
7848 (* Give the exceptions names, so they can be raised from the C code. *)
7849 let () =
7850   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7851   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7852
7853 ";
7854
7855   generate_ocaml_structure_decls ();
7856
7857   (* The actions. *)
7858   List.iter (
7859     fun (name, style, _, _, _, shortdesc, _) ->
7860       generate_ocaml_prototype ~is_external:true name style;
7861   ) all_functions_sorted
7862
7863 (* Generate the OCaml bindings C implementation. *)
7864 and generate_ocaml_c () =
7865   generate_header CStyle LGPLv2plus;
7866
7867   pr "\
7868 #include <stdio.h>
7869 #include <stdlib.h>
7870 #include <string.h>
7871
7872 #include <caml/config.h>
7873 #include <caml/alloc.h>
7874 #include <caml/callback.h>
7875 #include <caml/fail.h>
7876 #include <caml/memory.h>
7877 #include <caml/mlvalues.h>
7878 #include <caml/signals.h>
7879
7880 #include <guestfs.h>
7881
7882 #include \"guestfs_c.h\"
7883
7884 /* Copy a hashtable of string pairs into an assoc-list.  We return
7885  * the list in reverse order, but hashtables aren't supposed to be
7886  * ordered anyway.
7887  */
7888 static CAMLprim value
7889 copy_table (char * const * argv)
7890 {
7891   CAMLparam0 ();
7892   CAMLlocal5 (rv, pairv, kv, vv, cons);
7893   int i;
7894
7895   rv = Val_int (0);
7896   for (i = 0; argv[i] != NULL; i += 2) {
7897     kv = caml_copy_string (argv[i]);
7898     vv = caml_copy_string (argv[i+1]);
7899     pairv = caml_alloc (2, 0);
7900     Store_field (pairv, 0, kv);
7901     Store_field (pairv, 1, vv);
7902     cons = caml_alloc (2, 0);
7903     Store_field (cons, 1, rv);
7904     rv = cons;
7905     Store_field (cons, 0, pairv);
7906   }
7907
7908   CAMLreturn (rv);
7909 }
7910
7911 ";
7912
7913   (* Struct copy functions. *)
7914
7915   let emit_ocaml_copy_list_function typ =
7916     pr "static CAMLprim value\n";
7917     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7918     pr "{\n";
7919     pr "  CAMLparam0 ();\n";
7920     pr "  CAMLlocal2 (rv, v);\n";
7921     pr "  unsigned int i;\n";
7922     pr "\n";
7923     pr "  if (%ss->len == 0)\n" typ;
7924     pr "    CAMLreturn (Atom (0));\n";
7925     pr "  else {\n";
7926     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7927     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7928     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7929     pr "      caml_modify (&Field (rv, i), v);\n";
7930     pr "    }\n";
7931     pr "    CAMLreturn (rv);\n";
7932     pr "  }\n";
7933     pr "}\n";
7934     pr "\n";
7935   in
7936
7937   List.iter (
7938     fun (typ, cols) ->
7939       let has_optpercent_col =
7940         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7941
7942       pr "static CAMLprim value\n";
7943       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7944       pr "{\n";
7945       pr "  CAMLparam0 ();\n";
7946       if has_optpercent_col then
7947         pr "  CAMLlocal3 (rv, v, v2);\n"
7948       else
7949         pr "  CAMLlocal2 (rv, v);\n";
7950       pr "\n";
7951       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7952       iteri (
7953         fun i col ->
7954           (match col with
7955            | name, FString ->
7956                pr "  v = caml_copy_string (%s->%s);\n" typ name
7957            | name, FBuffer ->
7958                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7959                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7960                  typ name typ name
7961            | name, FUUID ->
7962                pr "  v = caml_alloc_string (32);\n";
7963                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7964            | name, (FBytes|FInt64|FUInt64) ->
7965                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7966            | name, (FInt32|FUInt32) ->
7967                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7968            | name, FOptPercent ->
7969                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7970                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7971                pr "    v = caml_alloc (1, 0);\n";
7972                pr "    Store_field (v, 0, v2);\n";
7973                pr "  } else /* None */\n";
7974                pr "    v = Val_int (0);\n";
7975            | name, FChar ->
7976                pr "  v = Val_int (%s->%s);\n" typ name
7977           );
7978           pr "  Store_field (rv, %d, v);\n" i
7979       ) cols;
7980       pr "  CAMLreturn (rv);\n";
7981       pr "}\n";
7982       pr "\n";
7983   ) structs;
7984
7985   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7986   List.iter (
7987     function
7988     | typ, (RStructListOnly | RStructAndList) ->
7989         (* generate the function for typ *)
7990         emit_ocaml_copy_list_function typ
7991     | typ, _ -> () (* empty *)
7992   ) (rstructs_used_by all_functions);
7993
7994   (* The wrappers. *)
7995   List.iter (
7996     fun (name, style, _, _, _, _, _) ->
7997       pr "/* Automatically generated wrapper for function\n";
7998       pr " * ";
7999       generate_ocaml_prototype name style;
8000       pr " */\n";
8001       pr "\n";
8002
8003       let params =
8004         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8005
8006       let needs_extra_vs =
8007         match fst style with RConstOptString _ -> true | _ -> false in
8008
8009       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8010       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8011       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8012       pr "\n";
8013
8014       pr "CAMLprim value\n";
8015       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8016       List.iter (pr ", value %s") (List.tl params);
8017       pr ")\n";
8018       pr "{\n";
8019
8020       (match params with
8021        | [p1; p2; p3; p4; p5] ->
8022            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8023        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8024            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8025            pr "  CAMLxparam%d (%s);\n"
8026              (List.length rest) (String.concat ", " rest)
8027        | ps ->
8028            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8029       );
8030       if not needs_extra_vs then
8031         pr "  CAMLlocal1 (rv);\n"
8032       else
8033         pr "  CAMLlocal3 (rv, v, v2);\n";
8034       pr "\n";
8035
8036       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8037       pr "  if (g == NULL)\n";
8038       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8039       pr "\n";
8040
8041       List.iter (
8042         function
8043         | Pathname n
8044         | Device n | Dev_or_Path n
8045         | String n
8046         | FileIn n
8047         | FileOut n ->
8048             pr "  const char *%s = String_val (%sv);\n" n n
8049         | OptString n ->
8050             pr "  const char *%s =\n" n;
8051             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8052               n n
8053         | StringList n | DeviceList n ->
8054             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8055         | Bool n ->
8056             pr "  int %s = Bool_val (%sv);\n" n n
8057         | Int n ->
8058             pr "  int %s = Int_val (%sv);\n" n n
8059         | Int64 n ->
8060             pr "  int64_t %s = Int64_val (%sv);\n" n n
8061       ) (snd style);
8062       let error_code =
8063         match fst style with
8064         | RErr -> pr "  int r;\n"; "-1"
8065         | RInt _ -> pr "  int r;\n"; "-1"
8066         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8067         | RBool _ -> pr "  int r;\n"; "-1"
8068         | RConstString _ | RConstOptString _ ->
8069             pr "  const char *r;\n"; "NULL"
8070         | RString _ -> pr "  char *r;\n"; "NULL"
8071         | RStringList _ ->
8072             pr "  int i;\n";
8073             pr "  char **r;\n";
8074             "NULL"
8075         | RStruct (_, typ) ->
8076             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8077         | RStructList (_, typ) ->
8078             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8079         | RHashtable _ ->
8080             pr "  int i;\n";
8081             pr "  char **r;\n";
8082             "NULL"
8083         | RBufferOut _ ->
8084             pr "  char *r;\n";
8085             pr "  size_t size;\n";
8086             "NULL" in
8087       pr "\n";
8088
8089       pr "  caml_enter_blocking_section ();\n";
8090       pr "  r = guestfs_%s " name;
8091       generate_c_call_args ~handle:"g" style;
8092       pr ";\n";
8093       pr "  caml_leave_blocking_section ();\n";
8094
8095       List.iter (
8096         function
8097         | StringList n | DeviceList n ->
8098             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8099         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8100         | Bool _ | Int _ | Int64 _
8101         | FileIn _ | FileOut _ -> ()
8102       ) (snd style);
8103
8104       pr "  if (r == %s)\n" error_code;
8105       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8106       pr "\n";
8107
8108       (match fst style with
8109        | RErr -> pr "  rv = Val_unit;\n"
8110        | RInt _ -> pr "  rv = Val_int (r);\n"
8111        | RInt64 _ ->
8112            pr "  rv = caml_copy_int64 (r);\n"
8113        | RBool _ -> pr "  rv = Val_bool (r);\n"
8114        | RConstString _ ->
8115            pr "  rv = caml_copy_string (r);\n"
8116        | RConstOptString _ ->
8117            pr "  if (r) { /* Some string */\n";
8118            pr "    v = caml_alloc (1, 0);\n";
8119            pr "    v2 = caml_copy_string (r);\n";
8120            pr "    Store_field (v, 0, v2);\n";
8121            pr "  } else /* None */\n";
8122            pr "    v = Val_int (0);\n";
8123        | RString _ ->
8124            pr "  rv = caml_copy_string (r);\n";
8125            pr "  free (r);\n"
8126        | RStringList _ ->
8127            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8128            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8129            pr "  free (r);\n"
8130        | RStruct (_, typ) ->
8131            pr "  rv = copy_%s (r);\n" typ;
8132            pr "  guestfs_free_%s (r);\n" typ;
8133        | RStructList (_, typ) ->
8134            pr "  rv = copy_%s_list (r);\n" typ;
8135            pr "  guestfs_free_%s_list (r);\n" typ;
8136        | RHashtable _ ->
8137            pr "  rv = copy_table (r);\n";
8138            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8139            pr "  free (r);\n";
8140        | RBufferOut _ ->
8141            pr "  rv = caml_alloc_string (size);\n";
8142            pr "  memcpy (String_val (rv), r, size);\n";
8143       );
8144
8145       pr "  CAMLreturn (rv);\n";
8146       pr "}\n";
8147       pr "\n";
8148
8149       if List.length params > 5 then (
8150         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8151         pr "CAMLprim value ";
8152         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8153         pr "CAMLprim value\n";
8154         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8155         pr "{\n";
8156         pr "  return ocaml_guestfs_%s (argv[0]" name;
8157         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8158         pr ");\n";
8159         pr "}\n";
8160         pr "\n"
8161       )
8162   ) all_functions_sorted
8163
8164 and generate_ocaml_structure_decls () =
8165   List.iter (
8166     fun (typ, cols) ->
8167       pr "type %s = {\n" typ;
8168       List.iter (
8169         function
8170         | name, FString -> pr "  %s : string;\n" name
8171         | name, FBuffer -> pr "  %s : string;\n" name
8172         | name, FUUID -> pr "  %s : string;\n" name
8173         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8174         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8175         | name, FChar -> pr "  %s : char;\n" name
8176         | name, FOptPercent -> pr "  %s : float option;\n" name
8177       ) cols;
8178       pr "}\n";
8179       pr "\n"
8180   ) structs
8181
8182 and generate_ocaml_prototype ?(is_external = false) name style =
8183   if is_external then pr "external " else pr "val ";
8184   pr "%s : t -> " name;
8185   List.iter (
8186     function
8187     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8188     | OptString _ -> pr "string option -> "
8189     | StringList _ | DeviceList _ -> pr "string array -> "
8190     | Bool _ -> pr "bool -> "
8191     | Int _ -> pr "int -> "
8192     | Int64 _ -> pr "int64 -> "
8193   ) (snd style);
8194   (match fst style with
8195    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8196    | RInt _ -> pr "int"
8197    | RInt64 _ -> pr "int64"
8198    | RBool _ -> pr "bool"
8199    | RConstString _ -> pr "string"
8200    | RConstOptString _ -> pr "string option"
8201    | RString _ | RBufferOut _ -> pr "string"
8202    | RStringList _ -> pr "string array"
8203    | RStruct (_, typ) -> pr "%s" typ
8204    | RStructList (_, typ) -> pr "%s array" typ
8205    | RHashtable _ -> pr "(string * string) list"
8206   );
8207   if is_external then (
8208     pr " = ";
8209     if List.length (snd style) + 1 > 5 then
8210       pr "\"ocaml_guestfs_%s_byte\" " name;
8211     pr "\"ocaml_guestfs_%s\"" name
8212   );
8213   pr "\n"
8214
8215 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8216 and generate_perl_xs () =
8217   generate_header CStyle LGPLv2plus;
8218
8219   pr "\
8220 #include \"EXTERN.h\"
8221 #include \"perl.h\"
8222 #include \"XSUB.h\"
8223
8224 #include <guestfs.h>
8225
8226 #ifndef PRId64
8227 #define PRId64 \"lld\"
8228 #endif
8229
8230 static SV *
8231 my_newSVll(long long val) {
8232 #ifdef USE_64_BIT_ALL
8233   return newSViv(val);
8234 #else
8235   char buf[100];
8236   int len;
8237   len = snprintf(buf, 100, \"%%\" PRId64, val);
8238   return newSVpv(buf, len);
8239 #endif
8240 }
8241
8242 #ifndef PRIu64
8243 #define PRIu64 \"llu\"
8244 #endif
8245
8246 static SV *
8247 my_newSVull(unsigned long long val) {
8248 #ifdef USE_64_BIT_ALL
8249   return newSVuv(val);
8250 #else
8251   char buf[100];
8252   int len;
8253   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8254   return newSVpv(buf, len);
8255 #endif
8256 }
8257
8258 /* http://www.perlmonks.org/?node_id=680842 */
8259 static char **
8260 XS_unpack_charPtrPtr (SV *arg) {
8261   char **ret;
8262   AV *av;
8263   I32 i;
8264
8265   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8266     croak (\"array reference expected\");
8267
8268   av = (AV *)SvRV (arg);
8269   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8270   if (!ret)
8271     croak (\"malloc failed\");
8272
8273   for (i = 0; i <= av_len (av); i++) {
8274     SV **elem = av_fetch (av, i, 0);
8275
8276     if (!elem || !*elem)
8277       croak (\"missing element in list\");
8278
8279     ret[i] = SvPV_nolen (*elem);
8280   }
8281
8282   ret[i] = NULL;
8283
8284   return ret;
8285 }
8286
8287 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8288
8289 PROTOTYPES: ENABLE
8290
8291 guestfs_h *
8292 _create ()
8293    CODE:
8294       RETVAL = guestfs_create ();
8295       if (!RETVAL)
8296         croak (\"could not create guestfs handle\");
8297       guestfs_set_error_handler (RETVAL, NULL, NULL);
8298  OUTPUT:
8299       RETVAL
8300
8301 void
8302 DESTROY (g)
8303       guestfs_h *g;
8304  PPCODE:
8305       guestfs_close (g);
8306
8307 ";
8308
8309   List.iter (
8310     fun (name, style, _, _, _, _, _) ->
8311       (match fst style with
8312        | RErr -> pr "void\n"
8313        | RInt _ -> pr "SV *\n"
8314        | RInt64 _ -> pr "SV *\n"
8315        | RBool _ -> pr "SV *\n"
8316        | RConstString _ -> pr "SV *\n"
8317        | RConstOptString _ -> pr "SV *\n"
8318        | RString _ -> pr "SV *\n"
8319        | RBufferOut _ -> pr "SV *\n"
8320        | RStringList _
8321        | RStruct _ | RStructList _
8322        | RHashtable _ ->
8323            pr "void\n" (* all lists returned implictly on the stack *)
8324       );
8325       (* Call and arguments. *)
8326       pr "%s " name;
8327       generate_c_call_args ~handle:"g" ~decl:true style;
8328       pr "\n";
8329       pr "      guestfs_h *g;\n";
8330       iteri (
8331         fun i ->
8332           function
8333           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8334               pr "      char *%s;\n" n
8335           | OptString n ->
8336               (* http://www.perlmonks.org/?node_id=554277
8337                * Note that the implicit handle argument means we have
8338                * to add 1 to the ST(x) operator.
8339                *)
8340               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8341           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8342           | Bool n -> pr "      int %s;\n" n
8343           | Int n -> pr "      int %s;\n" n
8344           | Int64 n -> pr "      int64_t %s;\n" n
8345       ) (snd style);
8346
8347       let do_cleanups () =
8348         List.iter (
8349           function
8350           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8351           | Bool _ | Int _ | Int64 _
8352           | FileIn _ | FileOut _ -> ()
8353           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8354         ) (snd style)
8355       in
8356
8357       (* Code. *)
8358       (match fst style with
8359        | RErr ->
8360            pr "PREINIT:\n";
8361            pr "      int r;\n";
8362            pr " PPCODE:\n";
8363            pr "      r = guestfs_%s " name;
8364            generate_c_call_args ~handle:"g" style;
8365            pr ";\n";
8366            do_cleanups ();
8367            pr "      if (r == -1)\n";
8368            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8369        | RInt n
8370        | RBool n ->
8371            pr "PREINIT:\n";
8372            pr "      int %s;\n" n;
8373            pr "   CODE:\n";
8374            pr "      %s = guestfs_%s " n name;
8375            generate_c_call_args ~handle:"g" style;
8376            pr ";\n";
8377            do_cleanups ();
8378            pr "      if (%s == -1)\n" n;
8379            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8380            pr "      RETVAL = newSViv (%s);\n" n;
8381            pr " OUTPUT:\n";
8382            pr "      RETVAL\n"
8383        | RInt64 n ->
8384            pr "PREINIT:\n";
8385            pr "      int64_t %s;\n" n;
8386            pr "   CODE:\n";
8387            pr "      %s = guestfs_%s " n name;
8388            generate_c_call_args ~handle:"g" style;
8389            pr ";\n";
8390            do_cleanups ();
8391            pr "      if (%s == -1)\n" n;
8392            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8393            pr "      RETVAL = my_newSVll (%s);\n" n;
8394            pr " OUTPUT:\n";
8395            pr "      RETVAL\n"
8396        | RConstString n ->
8397            pr "PREINIT:\n";
8398            pr "      const char *%s;\n" n;
8399            pr "   CODE:\n";
8400            pr "      %s = guestfs_%s " n name;
8401            generate_c_call_args ~handle:"g" style;
8402            pr ";\n";
8403            do_cleanups ();
8404            pr "      if (%s == NULL)\n" n;
8405            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8406            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8407            pr " OUTPUT:\n";
8408            pr "      RETVAL\n"
8409        | RConstOptString n ->
8410            pr "PREINIT:\n";
8411            pr "      const char *%s;\n" n;
8412            pr "   CODE:\n";
8413            pr "      %s = guestfs_%s " n name;
8414            generate_c_call_args ~handle:"g" style;
8415            pr ";\n";
8416            do_cleanups ();
8417            pr "      if (%s == NULL)\n" n;
8418            pr "        RETVAL = &PL_sv_undef;\n";
8419            pr "      else\n";
8420            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8421            pr " OUTPUT:\n";
8422            pr "      RETVAL\n"
8423        | RString n ->
8424            pr "PREINIT:\n";
8425            pr "      char *%s;\n" n;
8426            pr "   CODE:\n";
8427            pr "      %s = guestfs_%s " n name;
8428            generate_c_call_args ~handle:"g" style;
8429            pr ";\n";
8430            do_cleanups ();
8431            pr "      if (%s == NULL)\n" n;
8432            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8433            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8434            pr "      free (%s);\n" n;
8435            pr " OUTPUT:\n";
8436            pr "      RETVAL\n"
8437        | RStringList n | RHashtable n ->
8438            pr "PREINIT:\n";
8439            pr "      char **%s;\n" n;
8440            pr "      int i, n;\n";
8441            pr " PPCODE:\n";
8442            pr "      %s = guestfs_%s " n name;
8443            generate_c_call_args ~handle:"g" style;
8444            pr ";\n";
8445            do_cleanups ();
8446            pr "      if (%s == NULL)\n" n;
8447            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8448            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8449            pr "      EXTEND (SP, n);\n";
8450            pr "      for (i = 0; i < n; ++i) {\n";
8451            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8452            pr "        free (%s[i]);\n" n;
8453            pr "      }\n";
8454            pr "      free (%s);\n" n;
8455        | RStruct (n, typ) ->
8456            let cols = cols_of_struct typ in
8457            generate_perl_struct_code typ cols name style n do_cleanups
8458        | RStructList (n, typ) ->
8459            let cols = cols_of_struct typ in
8460            generate_perl_struct_list_code typ cols name style n do_cleanups
8461        | RBufferOut n ->
8462            pr "PREINIT:\n";
8463            pr "      char *%s;\n" n;
8464            pr "      size_t size;\n";
8465            pr "   CODE:\n";
8466            pr "      %s = guestfs_%s " n name;
8467            generate_c_call_args ~handle:"g" style;
8468            pr ";\n";
8469            do_cleanups ();
8470            pr "      if (%s == NULL)\n" n;
8471            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8472            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8473            pr "      free (%s);\n" n;
8474            pr " OUTPUT:\n";
8475            pr "      RETVAL\n"
8476       );
8477
8478       pr "\n"
8479   ) all_functions
8480
8481 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8482   pr "PREINIT:\n";
8483   pr "      struct guestfs_%s_list *%s;\n" typ n;
8484   pr "      int i;\n";
8485   pr "      HV *hv;\n";
8486   pr " PPCODE:\n";
8487   pr "      %s = guestfs_%s " n name;
8488   generate_c_call_args ~handle:"g" style;
8489   pr ";\n";
8490   do_cleanups ();
8491   pr "      if (%s == NULL)\n" n;
8492   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8493   pr "      EXTEND (SP, %s->len);\n" n;
8494   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8495   pr "        hv = newHV ();\n";
8496   List.iter (
8497     function
8498     | name, FString ->
8499         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8500           name (String.length name) n name
8501     | name, FUUID ->
8502         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8503           name (String.length name) n name
8504     | name, FBuffer ->
8505         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8506           name (String.length name) n name n name
8507     | name, (FBytes|FUInt64) ->
8508         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8509           name (String.length name) n name
8510     | name, FInt64 ->
8511         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8512           name (String.length name) n name
8513     | name, (FInt32|FUInt32) ->
8514         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8515           name (String.length name) n name
8516     | name, FChar ->
8517         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8518           name (String.length name) n name
8519     | name, FOptPercent ->
8520         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8521           name (String.length name) n name
8522   ) cols;
8523   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8524   pr "      }\n";
8525   pr "      guestfs_free_%s_list (%s);\n" typ n
8526
8527 and generate_perl_struct_code typ cols name style n do_cleanups =
8528   pr "PREINIT:\n";
8529   pr "      struct guestfs_%s *%s;\n" typ n;
8530   pr " PPCODE:\n";
8531   pr "      %s = guestfs_%s " n name;
8532   generate_c_call_args ~handle:"g" style;
8533   pr ";\n";
8534   do_cleanups ();
8535   pr "      if (%s == NULL)\n" n;
8536   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8537   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8538   List.iter (
8539     fun ((name, _) as col) ->
8540       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8541
8542       match col with
8543       | name, FString ->
8544           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8545             n name
8546       | name, FBuffer ->
8547           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8548             n name n name
8549       | name, FUUID ->
8550           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8551             n name
8552       | name, (FBytes|FUInt64) ->
8553           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8554             n name
8555       | name, FInt64 ->
8556           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8557             n name
8558       | name, (FInt32|FUInt32) ->
8559           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8560             n name
8561       | name, FChar ->
8562           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8563             n name
8564       | name, FOptPercent ->
8565           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8566             n name
8567   ) cols;
8568   pr "      free (%s);\n" n
8569
8570 (* Generate Sys/Guestfs.pm. *)
8571 and generate_perl_pm () =
8572   generate_header HashStyle LGPLv2plus;
8573
8574   pr "\
8575 =pod
8576
8577 =head1 NAME
8578
8579 Sys::Guestfs - Perl bindings for libguestfs
8580
8581 =head1 SYNOPSIS
8582
8583  use Sys::Guestfs;
8584
8585  my $h = Sys::Guestfs->new ();
8586  $h->add_drive ('guest.img');
8587  $h->launch ();
8588  $h->mount ('/dev/sda1', '/');
8589  $h->touch ('/hello');
8590  $h->sync ();
8591
8592 =head1 DESCRIPTION
8593
8594 The C<Sys::Guestfs> module provides a Perl XS binding to the
8595 libguestfs API for examining and modifying virtual machine
8596 disk images.
8597
8598 Amongst the things this is good for: making batch configuration
8599 changes to guests, getting disk used/free statistics (see also:
8600 virt-df), migrating between virtualization systems (see also:
8601 virt-p2v), performing partial backups, performing partial guest
8602 clones, cloning guests and changing registry/UUID/hostname info, and
8603 much else besides.
8604
8605 Libguestfs uses Linux kernel and qemu code, and can access any type of
8606 guest filesystem that Linux and qemu can, including but not limited
8607 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8608 schemes, qcow, qcow2, vmdk.
8609
8610 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8611 LVs, what filesystem is in each LV, etc.).  It can also run commands
8612 in the context of the guest.  Also you can access filesystems over
8613 FUSE.
8614
8615 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8616 functions for using libguestfs from Perl, including integration
8617 with libvirt.
8618
8619 =head1 ERRORS
8620
8621 All errors turn into calls to C<croak> (see L<Carp(3)>).
8622
8623 =head1 METHODS
8624
8625 =over 4
8626
8627 =cut
8628
8629 package Sys::Guestfs;
8630
8631 use strict;
8632 use warnings;
8633
8634 require XSLoader;
8635 XSLoader::load ('Sys::Guestfs');
8636
8637 =item $h = Sys::Guestfs->new ();
8638
8639 Create a new guestfs handle.
8640
8641 =cut
8642
8643 sub new {
8644   my $proto = shift;
8645   my $class = ref ($proto) || $proto;
8646
8647   my $self = Sys::Guestfs::_create ();
8648   bless $self, $class;
8649   return $self;
8650 }
8651
8652 ";
8653
8654   (* Actions.  We only need to print documentation for these as
8655    * they are pulled in from the XS code automatically.
8656    *)
8657   List.iter (
8658     fun (name, style, _, flags, _, _, longdesc) ->
8659       if not (List.mem NotInDocs flags) then (
8660         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8661         pr "=item ";
8662         generate_perl_prototype name style;
8663         pr "\n\n";
8664         pr "%s\n\n" longdesc;
8665         if List.mem ProtocolLimitWarning flags then
8666           pr "%s\n\n" protocol_limit_warning;
8667         if List.mem DangerWillRobinson flags then
8668           pr "%s\n\n" danger_will_robinson;
8669         match deprecation_notice flags with
8670         | None -> ()
8671         | Some txt -> pr "%s\n\n" txt
8672       )
8673   ) all_functions_sorted;
8674
8675   (* End of file. *)
8676   pr "\
8677 =cut
8678
8679 1;
8680
8681 =back
8682
8683 =head1 COPYRIGHT
8684
8685 Copyright (C) %s Red Hat Inc.
8686
8687 =head1 LICENSE
8688
8689 Please see the file COPYING.LIB for the full license.
8690
8691 =head1 SEE ALSO
8692
8693 L<guestfs(3)>,
8694 L<guestfish(1)>,
8695 L<http://libguestfs.org>,
8696 L<Sys::Guestfs::Lib(3)>.
8697
8698 =cut
8699 " copyright_years
8700
8701 and generate_perl_prototype name style =
8702   (match fst style with
8703    | RErr -> ()
8704    | RBool n
8705    | RInt n
8706    | RInt64 n
8707    | RConstString n
8708    | RConstOptString n
8709    | RString n
8710    | RBufferOut n -> pr "$%s = " n
8711    | RStruct (n,_)
8712    | RHashtable n -> pr "%%%s = " n
8713    | RStringList n
8714    | RStructList (n,_) -> pr "@%s = " n
8715   );
8716   pr "$h->%s (" name;
8717   let comma = ref false in
8718   List.iter (
8719     fun arg ->
8720       if !comma then pr ", ";
8721       comma := true;
8722       match arg with
8723       | Pathname n | Device n | Dev_or_Path n | String n
8724       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8725           pr "$%s" n
8726       | StringList n | DeviceList n ->
8727           pr "\\@%s" n
8728   ) (snd style);
8729   pr ");"
8730
8731 (* Generate Python C module. *)
8732 and generate_python_c () =
8733   generate_header CStyle LGPLv2plus;
8734
8735   pr "\
8736 #include <Python.h>
8737
8738 #include <stdio.h>
8739 #include <stdlib.h>
8740 #include <assert.h>
8741
8742 #include \"guestfs.h\"
8743
8744 typedef struct {
8745   PyObject_HEAD
8746   guestfs_h *g;
8747 } Pyguestfs_Object;
8748
8749 static guestfs_h *
8750 get_handle (PyObject *obj)
8751 {
8752   assert (obj);
8753   assert (obj != Py_None);
8754   return ((Pyguestfs_Object *) obj)->g;
8755 }
8756
8757 static PyObject *
8758 put_handle (guestfs_h *g)
8759 {
8760   assert (g);
8761   return
8762     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8763 }
8764
8765 /* This list should be freed (but not the strings) after use. */
8766 static char **
8767 get_string_list (PyObject *obj)
8768 {
8769   int i, len;
8770   char **r;
8771
8772   assert (obj);
8773
8774   if (!PyList_Check (obj)) {
8775     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8776     return NULL;
8777   }
8778
8779   len = PyList_Size (obj);
8780   r = malloc (sizeof (char *) * (len+1));
8781   if (r == NULL) {
8782     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8783     return NULL;
8784   }
8785
8786   for (i = 0; i < len; ++i)
8787     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8788   r[len] = NULL;
8789
8790   return r;
8791 }
8792
8793 static PyObject *
8794 put_string_list (char * const * const argv)
8795 {
8796   PyObject *list;
8797   int argc, i;
8798
8799   for (argc = 0; argv[argc] != NULL; ++argc)
8800     ;
8801
8802   list = PyList_New (argc);
8803   for (i = 0; i < argc; ++i)
8804     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8805
8806   return list;
8807 }
8808
8809 static PyObject *
8810 put_table (char * const * const argv)
8811 {
8812   PyObject *list, *item;
8813   int argc, i;
8814
8815   for (argc = 0; argv[argc] != NULL; ++argc)
8816     ;
8817
8818   list = PyList_New (argc >> 1);
8819   for (i = 0; i < argc; i += 2) {
8820     item = PyTuple_New (2);
8821     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8822     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8823     PyList_SetItem (list, i >> 1, item);
8824   }
8825
8826   return list;
8827 }
8828
8829 static void
8830 free_strings (char **argv)
8831 {
8832   int argc;
8833
8834   for (argc = 0; argv[argc] != NULL; ++argc)
8835     free (argv[argc]);
8836   free (argv);
8837 }
8838
8839 static PyObject *
8840 py_guestfs_create (PyObject *self, PyObject *args)
8841 {
8842   guestfs_h *g;
8843
8844   g = guestfs_create ();
8845   if (g == NULL) {
8846     PyErr_SetString (PyExc_RuntimeError,
8847                      \"guestfs.create: failed to allocate handle\");
8848     return NULL;
8849   }
8850   guestfs_set_error_handler (g, NULL, NULL);
8851   return put_handle (g);
8852 }
8853
8854 static PyObject *
8855 py_guestfs_close (PyObject *self, PyObject *args)
8856 {
8857   PyObject *py_g;
8858   guestfs_h *g;
8859
8860   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8861     return NULL;
8862   g = get_handle (py_g);
8863
8864   guestfs_close (g);
8865
8866   Py_INCREF (Py_None);
8867   return Py_None;
8868 }
8869
8870 ";
8871
8872   let emit_put_list_function typ =
8873     pr "static PyObject *\n";
8874     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8875     pr "{\n";
8876     pr "  PyObject *list;\n";
8877     pr "  int i;\n";
8878     pr "\n";
8879     pr "  list = PyList_New (%ss->len);\n" typ;
8880     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8881     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8882     pr "  return list;\n";
8883     pr "};\n";
8884     pr "\n"
8885   in
8886
8887   (* Structures, turned into Python dictionaries. *)
8888   List.iter (
8889     fun (typ, cols) ->
8890       pr "static PyObject *\n";
8891       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8892       pr "{\n";
8893       pr "  PyObject *dict;\n";
8894       pr "\n";
8895       pr "  dict = PyDict_New ();\n";
8896       List.iter (
8897         function
8898         | name, FString ->
8899             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8900             pr "                        PyString_FromString (%s->%s));\n"
8901               typ name
8902         | name, FBuffer ->
8903             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8904             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8905               typ name typ name
8906         | name, FUUID ->
8907             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8908             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8909               typ name
8910         | name, (FBytes|FUInt64) ->
8911             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8912             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8913               typ name
8914         | name, FInt64 ->
8915             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8916             pr "                        PyLong_FromLongLong (%s->%s));\n"
8917               typ name
8918         | name, FUInt32 ->
8919             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8920             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8921               typ name
8922         | name, FInt32 ->
8923             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8924             pr "                        PyLong_FromLong (%s->%s));\n"
8925               typ name
8926         | name, FOptPercent ->
8927             pr "  if (%s->%s >= 0)\n" typ name;
8928             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8929             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8930               typ name;
8931             pr "  else {\n";
8932             pr "    Py_INCREF (Py_None);\n";
8933             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8934             pr "  }\n"
8935         | name, FChar ->
8936             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8937             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8938       ) cols;
8939       pr "  return dict;\n";
8940       pr "};\n";
8941       pr "\n";
8942
8943   ) structs;
8944
8945   (* Emit a put_TYPE_list function definition only if that function is used. *)
8946   List.iter (
8947     function
8948     | typ, (RStructListOnly | RStructAndList) ->
8949         (* generate the function for typ *)
8950         emit_put_list_function typ
8951     | typ, _ -> () (* empty *)
8952   ) (rstructs_used_by all_functions);
8953
8954   (* Python wrapper functions. *)
8955   List.iter (
8956     fun (name, style, _, _, _, _, _) ->
8957       pr "static PyObject *\n";
8958       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8959       pr "{\n";
8960
8961       pr "  PyObject *py_g;\n";
8962       pr "  guestfs_h *g;\n";
8963       pr "  PyObject *py_r;\n";
8964
8965       let error_code =
8966         match fst style with
8967         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8968         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8969         | RConstString _ | RConstOptString _ ->
8970             pr "  const char *r;\n"; "NULL"
8971         | RString _ -> pr "  char *r;\n"; "NULL"
8972         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8973         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8974         | RStructList (_, typ) ->
8975             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8976         | RBufferOut _ ->
8977             pr "  char *r;\n";
8978             pr "  size_t size;\n";
8979             "NULL" in
8980
8981       List.iter (
8982         function
8983         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8984             pr "  const char *%s;\n" n
8985         | OptString n -> pr "  const char *%s;\n" n
8986         | StringList n | DeviceList n ->
8987             pr "  PyObject *py_%s;\n" n;
8988             pr "  char **%s;\n" n
8989         | Bool n -> pr "  int %s;\n" n
8990         | Int n -> pr "  int %s;\n" n
8991         | Int64 n -> pr "  long long %s;\n" n
8992       ) (snd style);
8993
8994       pr "\n";
8995
8996       (* Convert the parameters. *)
8997       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8998       List.iter (
8999         function
9000         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9001         | OptString _ -> pr "z"
9002         | StringList _ | DeviceList _ -> pr "O"
9003         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9004         | Int _ -> pr "i"
9005         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9006                              * emulate C's int/long/long long in Python?
9007                              *)
9008       ) (snd style);
9009       pr ":guestfs_%s\",\n" name;
9010       pr "                         &py_g";
9011       List.iter (
9012         function
9013         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9014         | OptString n -> pr ", &%s" n
9015         | StringList n | DeviceList n -> pr ", &py_%s" n
9016         | Bool n -> pr ", &%s" n
9017         | Int n -> pr ", &%s" n
9018         | Int64 n -> pr ", &%s" n
9019       ) (snd style);
9020
9021       pr "))\n";
9022       pr "    return NULL;\n";
9023
9024       pr "  g = get_handle (py_g);\n";
9025       List.iter (
9026         function
9027         | Pathname _ | Device _ | Dev_or_Path _ | String _
9028         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9029         | StringList n | DeviceList n ->
9030             pr "  %s = get_string_list (py_%s);\n" n n;
9031             pr "  if (!%s) return NULL;\n" n
9032       ) (snd style);
9033
9034       pr "\n";
9035
9036       pr "  r = guestfs_%s " name;
9037       generate_c_call_args ~handle:"g" style;
9038       pr ";\n";
9039
9040       List.iter (
9041         function
9042         | Pathname _ | Device _ | Dev_or_Path _ | String _
9043         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9044         | StringList n | DeviceList n ->
9045             pr "  free (%s);\n" n
9046       ) (snd style);
9047
9048       pr "  if (r == %s) {\n" error_code;
9049       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9050       pr "    return NULL;\n";
9051       pr "  }\n";
9052       pr "\n";
9053
9054       (match fst style with
9055        | RErr ->
9056            pr "  Py_INCREF (Py_None);\n";
9057            pr "  py_r = Py_None;\n"
9058        | RInt _
9059        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9060        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9061        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9062        | RConstOptString _ ->
9063            pr "  if (r)\n";
9064            pr "    py_r = PyString_FromString (r);\n";
9065            pr "  else {\n";
9066            pr "    Py_INCREF (Py_None);\n";
9067            pr "    py_r = Py_None;\n";
9068            pr "  }\n"
9069        | RString _ ->
9070            pr "  py_r = PyString_FromString (r);\n";
9071            pr "  free (r);\n"
9072        | RStringList _ ->
9073            pr "  py_r = put_string_list (r);\n";
9074            pr "  free_strings (r);\n"
9075        | RStruct (_, typ) ->
9076            pr "  py_r = put_%s (r);\n" typ;
9077            pr "  guestfs_free_%s (r);\n" typ
9078        | RStructList (_, typ) ->
9079            pr "  py_r = put_%s_list (r);\n" typ;
9080            pr "  guestfs_free_%s_list (r);\n" typ
9081        | RHashtable n ->
9082            pr "  py_r = put_table (r);\n";
9083            pr "  free_strings (r);\n"
9084        | RBufferOut _ ->
9085            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9086            pr "  free (r);\n"
9087       );
9088
9089       pr "  return py_r;\n";
9090       pr "}\n";
9091       pr "\n"
9092   ) all_functions;
9093
9094   (* Table of functions. *)
9095   pr "static PyMethodDef methods[] = {\n";
9096   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9097   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9098   List.iter (
9099     fun (name, _, _, _, _, _, _) ->
9100       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9101         name name
9102   ) all_functions;
9103   pr "  { NULL, NULL, 0, NULL }\n";
9104   pr "};\n";
9105   pr "\n";
9106
9107   (* Init function. *)
9108   pr "\
9109 void
9110 initlibguestfsmod (void)
9111 {
9112   static int initialized = 0;
9113
9114   if (initialized) return;
9115   Py_InitModule ((char *) \"libguestfsmod\", methods);
9116   initialized = 1;
9117 }
9118 "
9119
9120 (* Generate Python module. *)
9121 and generate_python_py () =
9122   generate_header HashStyle LGPLv2plus;
9123
9124   pr "\
9125 u\"\"\"Python bindings for libguestfs
9126
9127 import guestfs
9128 g = guestfs.GuestFS ()
9129 g.add_drive (\"guest.img\")
9130 g.launch ()
9131 parts = g.list_partitions ()
9132
9133 The guestfs module provides a Python binding to the libguestfs API
9134 for examining and modifying virtual machine disk images.
9135
9136 Amongst the things this is good for: making batch configuration
9137 changes to guests, getting disk used/free statistics (see also:
9138 virt-df), migrating between virtualization systems (see also:
9139 virt-p2v), performing partial backups, performing partial guest
9140 clones, cloning guests and changing registry/UUID/hostname info, and
9141 much else besides.
9142
9143 Libguestfs uses Linux kernel and qemu code, and can access any type of
9144 guest filesystem that Linux and qemu can, including but not limited
9145 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9146 schemes, qcow, qcow2, vmdk.
9147
9148 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9149 LVs, what filesystem is in each LV, etc.).  It can also run commands
9150 in the context of the guest.  Also you can access filesystems over
9151 FUSE.
9152
9153 Errors which happen while using the API are turned into Python
9154 RuntimeError exceptions.
9155
9156 To create a guestfs handle you usually have to perform the following
9157 sequence of calls:
9158
9159 # Create the handle, call add_drive at least once, and possibly
9160 # several times if the guest has multiple block devices:
9161 g = guestfs.GuestFS ()
9162 g.add_drive (\"guest.img\")
9163
9164 # Launch the qemu subprocess and wait for it to become ready:
9165 g.launch ()
9166
9167 # Now you can issue commands, for example:
9168 logvols = g.lvs ()
9169
9170 \"\"\"
9171
9172 import libguestfsmod
9173
9174 class GuestFS:
9175     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9176
9177     def __init__ (self):
9178         \"\"\"Create a new libguestfs handle.\"\"\"
9179         self._o = libguestfsmod.create ()
9180
9181     def __del__ (self):
9182         libguestfsmod.close (self._o)
9183
9184 ";
9185
9186   List.iter (
9187     fun (name, style, _, flags, _, _, longdesc) ->
9188       pr "    def %s " name;
9189       generate_py_call_args ~handle:"self" (snd style);
9190       pr ":\n";
9191
9192       if not (List.mem NotInDocs flags) then (
9193         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9194         let doc =
9195           match fst style with
9196           | RErr | RInt _ | RInt64 _ | RBool _
9197           | RConstOptString _ | RConstString _
9198           | RString _ | RBufferOut _ -> doc
9199           | RStringList _ ->
9200               doc ^ "\n\nThis function returns a list of strings."
9201           | RStruct (_, typ) ->
9202               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9203           | RStructList (_, typ) ->
9204               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9205           | RHashtable _ ->
9206               doc ^ "\n\nThis function returns a dictionary." in
9207         let doc =
9208           if List.mem ProtocolLimitWarning flags then
9209             doc ^ "\n\n" ^ protocol_limit_warning
9210           else doc in
9211         let doc =
9212           if List.mem DangerWillRobinson flags then
9213             doc ^ "\n\n" ^ danger_will_robinson
9214           else doc in
9215         let doc =
9216           match deprecation_notice flags with
9217           | None -> doc
9218           | Some txt -> doc ^ "\n\n" ^ txt in
9219         let doc = pod2text ~width:60 name doc in
9220         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9221         let doc = String.concat "\n        " doc in
9222         pr "        u\"\"\"%s\"\"\"\n" doc;
9223       );
9224       pr "        return libguestfsmod.%s " name;
9225       generate_py_call_args ~handle:"self._o" (snd style);
9226       pr "\n";
9227       pr "\n";
9228   ) all_functions
9229
9230 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9231 and generate_py_call_args ~handle args =
9232   pr "(%s" handle;
9233   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9234   pr ")"
9235
9236 (* Useful if you need the longdesc POD text as plain text.  Returns a
9237  * list of lines.
9238  *
9239  * Because this is very slow (the slowest part of autogeneration),
9240  * we memoize the results.
9241  *)
9242 and pod2text ~width name longdesc =
9243   let key = width, name, longdesc in
9244   try Hashtbl.find pod2text_memo key
9245   with Not_found ->
9246     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9247     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9248     close_out chan;
9249     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9250     let chan = open_process_in cmd in
9251     let lines = ref [] in
9252     let rec loop i =
9253       let line = input_line chan in
9254       if i = 1 then             (* discard the first line of output *)
9255         loop (i+1)
9256       else (
9257         let line = triml line in
9258         lines := line :: !lines;
9259         loop (i+1)
9260       ) in
9261     let lines = try loop 1 with End_of_file -> List.rev !lines in
9262     unlink filename;
9263     (match close_process_in chan with
9264      | WEXITED 0 -> ()
9265      | WEXITED i ->
9266          failwithf "pod2text: process exited with non-zero status (%d)" i
9267      | WSIGNALED i | WSTOPPED i ->
9268          failwithf "pod2text: process signalled or stopped by signal %d" i
9269     );
9270     Hashtbl.add pod2text_memo key lines;
9271     pod2text_memo_updated ();
9272     lines
9273
9274 (* Generate ruby bindings. *)
9275 and generate_ruby_c () =
9276   generate_header CStyle LGPLv2plus;
9277
9278   pr "\
9279 #include <stdio.h>
9280 #include <stdlib.h>
9281
9282 #include <ruby.h>
9283
9284 #include \"guestfs.h\"
9285
9286 #include \"extconf.h\"
9287
9288 /* For Ruby < 1.9 */
9289 #ifndef RARRAY_LEN
9290 #define RARRAY_LEN(r) (RARRAY((r))->len)
9291 #endif
9292
9293 static VALUE m_guestfs;                 /* guestfs module */
9294 static VALUE c_guestfs;                 /* guestfs_h handle */
9295 static VALUE e_Error;                   /* used for all errors */
9296
9297 static void ruby_guestfs_free (void *p)
9298 {
9299   if (!p) return;
9300   guestfs_close ((guestfs_h *) p);
9301 }
9302
9303 static VALUE ruby_guestfs_create (VALUE m)
9304 {
9305   guestfs_h *g;
9306
9307   g = guestfs_create ();
9308   if (!g)
9309     rb_raise (e_Error, \"failed to create guestfs handle\");
9310
9311   /* Don't print error messages to stderr by default. */
9312   guestfs_set_error_handler (g, NULL, NULL);
9313
9314   /* Wrap it, and make sure the close function is called when the
9315    * handle goes away.
9316    */
9317   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9318 }
9319
9320 static VALUE ruby_guestfs_close (VALUE gv)
9321 {
9322   guestfs_h *g;
9323   Data_Get_Struct (gv, guestfs_h, g);
9324
9325   ruby_guestfs_free (g);
9326   DATA_PTR (gv) = NULL;
9327
9328   return Qnil;
9329 }
9330
9331 ";
9332
9333   List.iter (
9334     fun (name, style, _, _, _, _, _) ->
9335       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9336       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9337       pr ")\n";
9338       pr "{\n";
9339       pr "  guestfs_h *g;\n";
9340       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9341       pr "  if (!g)\n";
9342       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9343         name;
9344       pr "\n";
9345
9346       List.iter (
9347         function
9348         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9349             pr "  Check_Type (%sv, T_STRING);\n" n;
9350             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9351             pr "  if (!%s)\n" n;
9352             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9353             pr "              \"%s\", \"%s\");\n" n name
9354         | OptString n ->
9355             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9356         | StringList n | DeviceList n ->
9357             pr "  char **%s;\n" n;
9358             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9359             pr "  {\n";
9360             pr "    int i, len;\n";
9361             pr "    len = RARRAY_LEN (%sv);\n" n;
9362             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9363               n;
9364             pr "    for (i = 0; i < len; ++i) {\n";
9365             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9366             pr "      %s[i] = StringValueCStr (v);\n" n;
9367             pr "    }\n";
9368             pr "    %s[len] = NULL;\n" n;
9369             pr "  }\n";
9370         | Bool n ->
9371             pr "  int %s = RTEST (%sv);\n" n n
9372         | Int n ->
9373             pr "  int %s = NUM2INT (%sv);\n" n n
9374         | Int64 n ->
9375             pr "  long long %s = NUM2LL (%sv);\n" n n
9376       ) (snd style);
9377       pr "\n";
9378
9379       let error_code =
9380         match fst style with
9381         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9382         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9383         | RConstString _ | RConstOptString _ ->
9384             pr "  const char *r;\n"; "NULL"
9385         | RString _ -> pr "  char *r;\n"; "NULL"
9386         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9387         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9388         | RStructList (_, typ) ->
9389             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9390         | RBufferOut _ ->
9391             pr "  char *r;\n";
9392             pr "  size_t size;\n";
9393             "NULL" in
9394       pr "\n";
9395
9396       pr "  r = guestfs_%s " name;
9397       generate_c_call_args ~handle:"g" style;
9398       pr ";\n";
9399
9400       List.iter (
9401         function
9402         | Pathname _ | Device _ | Dev_or_Path _ | String _
9403         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9404         | StringList n | DeviceList n ->
9405             pr "  free (%s);\n" n
9406       ) (snd style);
9407
9408       pr "  if (r == %s)\n" error_code;
9409       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9410       pr "\n";
9411
9412       (match fst style with
9413        | RErr ->
9414            pr "  return Qnil;\n"
9415        | RInt _ | RBool _ ->
9416            pr "  return INT2NUM (r);\n"
9417        | RInt64 _ ->
9418            pr "  return ULL2NUM (r);\n"
9419        | RConstString _ ->
9420            pr "  return rb_str_new2 (r);\n";
9421        | RConstOptString _ ->
9422            pr "  if (r)\n";
9423            pr "    return rb_str_new2 (r);\n";
9424            pr "  else\n";
9425            pr "    return Qnil;\n";
9426        | RString _ ->
9427            pr "  VALUE rv = rb_str_new2 (r);\n";
9428            pr "  free (r);\n";
9429            pr "  return rv;\n";
9430        | RStringList _ ->
9431            pr "  int i, len = 0;\n";
9432            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9433            pr "  VALUE rv = rb_ary_new2 (len);\n";
9434            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9435            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9436            pr "    free (r[i]);\n";
9437            pr "  }\n";
9438            pr "  free (r);\n";
9439            pr "  return rv;\n"
9440        | RStruct (_, typ) ->
9441            let cols = cols_of_struct typ in
9442            generate_ruby_struct_code typ cols
9443        | RStructList (_, typ) ->
9444            let cols = cols_of_struct typ in
9445            generate_ruby_struct_list_code typ cols
9446        | RHashtable _ ->
9447            pr "  VALUE rv = rb_hash_new ();\n";
9448            pr "  int i;\n";
9449            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9450            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9451            pr "    free (r[i]);\n";
9452            pr "    free (r[i+1]);\n";
9453            pr "  }\n";
9454            pr "  free (r);\n";
9455            pr "  return rv;\n"
9456        | RBufferOut _ ->
9457            pr "  VALUE rv = rb_str_new (r, size);\n";
9458            pr "  free (r);\n";
9459            pr "  return rv;\n";
9460       );
9461
9462       pr "}\n";
9463       pr "\n"
9464   ) all_functions;
9465
9466   pr "\
9467 /* Initialize the module. */
9468 void Init__guestfs ()
9469 {
9470   m_guestfs = rb_define_module (\"Guestfs\");
9471   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9472   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9473
9474   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9475   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9476
9477 ";
9478   (* Define the rest of the methods. *)
9479   List.iter (
9480     fun (name, style, _, _, _, _, _) ->
9481       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9482       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9483   ) all_functions;
9484
9485   pr "}\n"
9486
9487 (* Ruby code to return a struct. *)
9488 and generate_ruby_struct_code typ cols =
9489   pr "  VALUE rv = rb_hash_new ();\n";
9490   List.iter (
9491     function
9492     | name, FString ->
9493         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9494     | name, FBuffer ->
9495         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9496     | name, FUUID ->
9497         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9498     | name, (FBytes|FUInt64) ->
9499         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9500     | name, FInt64 ->
9501         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9502     | name, FUInt32 ->
9503         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9504     | name, FInt32 ->
9505         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9506     | name, FOptPercent ->
9507         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9508     | name, FChar -> (* XXX wrong? *)
9509         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9510   ) cols;
9511   pr "  guestfs_free_%s (r);\n" typ;
9512   pr "  return rv;\n"
9513
9514 (* Ruby code to return a struct list. *)
9515 and generate_ruby_struct_list_code typ cols =
9516   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9517   pr "  int i;\n";
9518   pr "  for (i = 0; i < r->len; ++i) {\n";
9519   pr "    VALUE hv = rb_hash_new ();\n";
9520   List.iter (
9521     function
9522     | name, FString ->
9523         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9524     | name, FBuffer ->
9525         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
9526     | name, FUUID ->
9527         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9528     | name, (FBytes|FUInt64) ->
9529         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9530     | name, FInt64 ->
9531         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9532     | name, FUInt32 ->
9533         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9534     | name, FInt32 ->
9535         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9536     | name, FOptPercent ->
9537         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9538     | name, FChar -> (* XXX wrong? *)
9539         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9540   ) cols;
9541   pr "    rb_ary_push (rv, hv);\n";
9542   pr "  }\n";
9543   pr "  guestfs_free_%s_list (r);\n" typ;
9544   pr "  return rv;\n"
9545
9546 (* Generate Java bindings GuestFS.java file. *)
9547 and generate_java_java () =
9548   generate_header CStyle LGPLv2plus;
9549
9550   pr "\
9551 package com.redhat.et.libguestfs;
9552
9553 import java.util.HashMap;
9554 import com.redhat.et.libguestfs.LibGuestFSException;
9555 import com.redhat.et.libguestfs.PV;
9556 import com.redhat.et.libguestfs.VG;
9557 import com.redhat.et.libguestfs.LV;
9558 import com.redhat.et.libguestfs.Stat;
9559 import com.redhat.et.libguestfs.StatVFS;
9560 import com.redhat.et.libguestfs.IntBool;
9561 import com.redhat.et.libguestfs.Dirent;
9562
9563 /**
9564  * The GuestFS object is a libguestfs handle.
9565  *
9566  * @author rjones
9567  */
9568 public class GuestFS {
9569   // Load the native code.
9570   static {
9571     System.loadLibrary (\"guestfs_jni\");
9572   }
9573
9574   /**
9575    * The native guestfs_h pointer.
9576    */
9577   long g;
9578
9579   /**
9580    * Create a libguestfs handle.
9581    *
9582    * @throws LibGuestFSException
9583    */
9584   public GuestFS () throws LibGuestFSException
9585   {
9586     g = _create ();
9587   }
9588   private native long _create () throws LibGuestFSException;
9589
9590   /**
9591    * Close a libguestfs handle.
9592    *
9593    * You can also leave handles to be collected by the garbage
9594    * collector, but this method ensures that the resources used
9595    * by the handle are freed up immediately.  If you call any
9596    * other methods after closing the handle, you will get an
9597    * exception.
9598    *
9599    * @throws LibGuestFSException
9600    */
9601   public void close () throws LibGuestFSException
9602   {
9603     if (g != 0)
9604       _close (g);
9605     g = 0;
9606   }
9607   private native void _close (long g) throws LibGuestFSException;
9608
9609   public void finalize () throws LibGuestFSException
9610   {
9611     close ();
9612   }
9613
9614 ";
9615
9616   List.iter (
9617     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9618       if not (List.mem NotInDocs flags); then (
9619         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9620         let doc =
9621           if List.mem ProtocolLimitWarning flags then
9622             doc ^ "\n\n" ^ protocol_limit_warning
9623           else doc in
9624         let doc =
9625           if List.mem DangerWillRobinson flags then
9626             doc ^ "\n\n" ^ danger_will_robinson
9627           else doc in
9628         let doc =
9629           match deprecation_notice flags with
9630           | None -> doc
9631           | Some txt -> doc ^ "\n\n" ^ txt in
9632         let doc = pod2text ~width:60 name doc in
9633         let doc = List.map (            (* RHBZ#501883 *)
9634           function
9635           | "" -> "<p>"
9636           | nonempty -> nonempty
9637         ) doc in
9638         let doc = String.concat "\n   * " doc in
9639
9640         pr "  /**\n";
9641         pr "   * %s\n" shortdesc;
9642         pr "   * <p>\n";
9643         pr "   * %s\n" doc;
9644         pr "   * @throws LibGuestFSException\n";
9645         pr "   */\n";
9646         pr "  ";
9647       );
9648       generate_java_prototype ~public:true ~semicolon:false name style;
9649       pr "\n";
9650       pr "  {\n";
9651       pr "    if (g == 0)\n";
9652       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9653         name;
9654       pr "    ";
9655       if fst style <> RErr then pr "return ";
9656       pr "_%s " name;
9657       generate_java_call_args ~handle:"g" (snd style);
9658       pr ";\n";
9659       pr "  }\n";
9660       pr "  ";
9661       generate_java_prototype ~privat:true ~native:true name style;
9662       pr "\n";
9663       pr "\n";
9664   ) all_functions;
9665
9666   pr "}\n"
9667
9668 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9669 and generate_java_call_args ~handle args =
9670   pr "(%s" handle;
9671   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9672   pr ")"
9673
9674 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9675     ?(semicolon=true) name style =
9676   if privat then pr "private ";
9677   if public then pr "public ";
9678   if native then pr "native ";
9679
9680   (* return type *)
9681   (match fst style with
9682    | RErr -> pr "void ";
9683    | RInt _ -> pr "int ";
9684    | RInt64 _ -> pr "long ";
9685    | RBool _ -> pr "boolean ";
9686    | RConstString _ | RConstOptString _ | RString _
9687    | RBufferOut _ -> pr "String ";
9688    | RStringList _ -> pr "String[] ";
9689    | RStruct (_, typ) ->
9690        let name = java_name_of_struct typ in
9691        pr "%s " name;
9692    | RStructList (_, typ) ->
9693        let name = java_name_of_struct typ in
9694        pr "%s[] " name;
9695    | RHashtable _ -> pr "HashMap<String,String> ";
9696   );
9697
9698   if native then pr "_%s " name else pr "%s " name;
9699   pr "(";
9700   let needs_comma = ref false in
9701   if native then (
9702     pr "long g";
9703     needs_comma := true
9704   );
9705
9706   (* args *)
9707   List.iter (
9708     fun arg ->
9709       if !needs_comma then pr ", ";
9710       needs_comma := true;
9711
9712       match arg with
9713       | Pathname n
9714       | Device n | Dev_or_Path n
9715       | String n
9716       | OptString n
9717       | FileIn n
9718       | FileOut n ->
9719           pr "String %s" n
9720       | StringList n | DeviceList n ->
9721           pr "String[] %s" n
9722       | Bool n ->
9723           pr "boolean %s" n
9724       | Int n ->
9725           pr "int %s" n
9726       | Int64 n ->
9727           pr "long %s" n
9728   ) (snd style);
9729
9730   pr ")\n";
9731   pr "    throws LibGuestFSException";
9732   if semicolon then pr ";"
9733
9734 and generate_java_struct jtyp cols () =
9735   generate_header CStyle LGPLv2plus;
9736
9737   pr "\
9738 package com.redhat.et.libguestfs;
9739
9740 /**
9741  * Libguestfs %s structure.
9742  *
9743  * @author rjones
9744  * @see GuestFS
9745  */
9746 public class %s {
9747 " jtyp jtyp;
9748
9749   List.iter (
9750     function
9751     | name, FString
9752     | name, FUUID
9753     | name, FBuffer -> pr "  public String %s;\n" name
9754     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9755     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9756     | name, FChar -> pr "  public char %s;\n" name
9757     | name, FOptPercent ->
9758         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9759         pr "  public float %s;\n" name
9760   ) cols;
9761
9762   pr "}\n"
9763
9764 and generate_java_c () =
9765   generate_header CStyle LGPLv2plus;
9766
9767   pr "\
9768 #include <stdio.h>
9769 #include <stdlib.h>
9770 #include <string.h>
9771
9772 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9773 #include \"guestfs.h\"
9774
9775 /* Note that this function returns.  The exception is not thrown
9776  * until after the wrapper function returns.
9777  */
9778 static void
9779 throw_exception (JNIEnv *env, const char *msg)
9780 {
9781   jclass cl;
9782   cl = (*env)->FindClass (env,
9783                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9784   (*env)->ThrowNew (env, cl, msg);
9785 }
9786
9787 JNIEXPORT jlong JNICALL
9788 Java_com_redhat_et_libguestfs_GuestFS__1create
9789   (JNIEnv *env, jobject obj)
9790 {
9791   guestfs_h *g;
9792
9793   g = guestfs_create ();
9794   if (g == NULL) {
9795     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9796     return 0;
9797   }
9798   guestfs_set_error_handler (g, NULL, NULL);
9799   return (jlong) (long) g;
9800 }
9801
9802 JNIEXPORT void JNICALL
9803 Java_com_redhat_et_libguestfs_GuestFS__1close
9804   (JNIEnv *env, jobject obj, jlong jg)
9805 {
9806   guestfs_h *g = (guestfs_h *) (long) jg;
9807   guestfs_close (g);
9808 }
9809
9810 ";
9811
9812   List.iter (
9813     fun (name, style, _, _, _, _, _) ->
9814       pr "JNIEXPORT ";
9815       (match fst style with
9816        | RErr -> pr "void ";
9817        | RInt _ -> pr "jint ";
9818        | RInt64 _ -> pr "jlong ";
9819        | RBool _ -> pr "jboolean ";
9820        | RConstString _ | RConstOptString _ | RString _
9821        | RBufferOut _ -> pr "jstring ";
9822        | RStruct _ | RHashtable _ ->
9823            pr "jobject ";
9824        | RStringList _ | RStructList _ ->
9825            pr "jobjectArray ";
9826       );
9827       pr "JNICALL\n";
9828       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9829       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9830       pr "\n";
9831       pr "  (JNIEnv *env, jobject obj, jlong jg";
9832       List.iter (
9833         function
9834         | Pathname n
9835         | Device n | Dev_or_Path n
9836         | String n
9837         | OptString n
9838         | FileIn n
9839         | FileOut n ->
9840             pr ", jstring j%s" n
9841         | StringList n | DeviceList n ->
9842             pr ", jobjectArray j%s" n
9843         | Bool n ->
9844             pr ", jboolean j%s" n
9845         | Int n ->
9846             pr ", jint j%s" n
9847         | Int64 n ->
9848             pr ", jlong j%s" n
9849       ) (snd style);
9850       pr ")\n";
9851       pr "{\n";
9852       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9853       let error_code, no_ret =
9854         match fst style with
9855         | RErr -> pr "  int r;\n"; "-1", ""
9856         | RBool _
9857         | RInt _ -> pr "  int r;\n"; "-1", "0"
9858         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9859         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9860         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9861         | RString _ ->
9862             pr "  jstring jr;\n";
9863             pr "  char *r;\n"; "NULL", "NULL"
9864         | RStringList _ ->
9865             pr "  jobjectArray jr;\n";
9866             pr "  int r_len;\n";
9867             pr "  jclass cl;\n";
9868             pr "  jstring jstr;\n";
9869             pr "  char **r;\n"; "NULL", "NULL"
9870         | RStruct (_, typ) ->
9871             pr "  jobject jr;\n";
9872             pr "  jclass cl;\n";
9873             pr "  jfieldID fl;\n";
9874             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9875         | RStructList (_, typ) ->
9876             pr "  jobjectArray jr;\n";
9877             pr "  jclass cl;\n";
9878             pr "  jfieldID fl;\n";
9879             pr "  jobject jfl;\n";
9880             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9881         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9882         | RBufferOut _ ->
9883             pr "  jstring jr;\n";
9884             pr "  char *r;\n";
9885             pr "  size_t size;\n";
9886             "NULL", "NULL" in
9887       List.iter (
9888         function
9889         | Pathname n
9890         | Device n | Dev_or_Path n
9891         | String n
9892         | OptString n
9893         | FileIn n
9894         | FileOut n ->
9895             pr "  const char *%s;\n" n
9896         | StringList n | DeviceList n ->
9897             pr "  int %s_len;\n" n;
9898             pr "  const char **%s;\n" n
9899         | Bool n
9900         | Int n ->
9901             pr "  int %s;\n" n
9902         | Int64 n ->
9903             pr "  int64_t %s;\n" n
9904       ) (snd style);
9905
9906       let needs_i =
9907         (match fst style with
9908          | RStringList _ | RStructList _ -> true
9909          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9910          | RConstOptString _
9911          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9912           List.exists (function
9913                        | StringList _ -> true
9914                        | DeviceList _ -> true
9915                        | _ -> false) (snd style) in
9916       if needs_i then
9917         pr "  int i;\n";
9918
9919       pr "\n";
9920
9921       (* Get the parameters. *)
9922       List.iter (
9923         function
9924         | Pathname n
9925         | Device n | Dev_or_Path n
9926         | String n
9927         | FileIn n
9928         | FileOut n ->
9929             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9930         | OptString n ->
9931             (* This is completely undocumented, but Java null becomes
9932              * a NULL parameter.
9933              *)
9934             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9935         | StringList n | DeviceList n ->
9936             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9937             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9938             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9939             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9940               n;
9941             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9942             pr "  }\n";
9943             pr "  %s[%s_len] = NULL;\n" n n;
9944         | Bool n
9945         | Int n
9946         | Int64 n ->
9947             pr "  %s = j%s;\n" n n
9948       ) (snd style);
9949
9950       (* Make the call. *)
9951       pr "  r = guestfs_%s " name;
9952       generate_c_call_args ~handle:"g" style;
9953       pr ";\n";
9954
9955       (* Release the parameters. *)
9956       List.iter (
9957         function
9958         | Pathname n
9959         | Device n | Dev_or_Path n
9960         | String n
9961         | FileIn n
9962         | FileOut n ->
9963             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9964         | OptString n ->
9965             pr "  if (j%s)\n" n;
9966             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9967         | StringList n | DeviceList n ->
9968             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9969             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9970               n;
9971             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9972             pr "  }\n";
9973             pr "  free (%s);\n" n
9974         | Bool n
9975         | Int n
9976         | Int64 n -> ()
9977       ) (snd style);
9978
9979       (* Check for errors. *)
9980       pr "  if (r == %s) {\n" error_code;
9981       pr "    throw_exception (env, guestfs_last_error (g));\n";
9982       pr "    return %s;\n" no_ret;
9983       pr "  }\n";
9984
9985       (* Return value. *)
9986       (match fst style with
9987        | RErr -> ()
9988        | RInt _ -> pr "  return (jint) r;\n"
9989        | RBool _ -> pr "  return (jboolean) r;\n"
9990        | RInt64 _ -> pr "  return (jlong) r;\n"
9991        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9992        | RConstOptString _ ->
9993            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9994        | RString _ ->
9995            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9996            pr "  free (r);\n";
9997            pr "  return jr;\n"
9998        | RStringList _ ->
9999            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10000            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10001            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10002            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10003            pr "  for (i = 0; i < r_len; ++i) {\n";
10004            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10005            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10006            pr "    free (r[i]);\n";
10007            pr "  }\n";
10008            pr "  free (r);\n";
10009            pr "  return jr;\n"
10010        | RStruct (_, typ) ->
10011            let jtyp = java_name_of_struct typ in
10012            let cols = cols_of_struct typ in
10013            generate_java_struct_return typ jtyp cols
10014        | RStructList (_, typ) ->
10015            let jtyp = java_name_of_struct typ in
10016            let cols = cols_of_struct typ in
10017            generate_java_struct_list_return typ jtyp cols
10018        | RHashtable _ ->
10019            (* XXX *)
10020            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10021            pr "  return NULL;\n"
10022        | RBufferOut _ ->
10023            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10024            pr "  free (r);\n";
10025            pr "  return jr;\n"
10026       );
10027
10028       pr "}\n";
10029       pr "\n"
10030   ) all_functions
10031
10032 and generate_java_struct_return typ jtyp cols =
10033   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10034   pr "  jr = (*env)->AllocObject (env, cl);\n";
10035   List.iter (
10036     function
10037     | name, FString ->
10038         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10039         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10040     | name, FUUID ->
10041         pr "  {\n";
10042         pr "    char s[33];\n";
10043         pr "    memcpy (s, r->%s, 32);\n" name;
10044         pr "    s[32] = 0;\n";
10045         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10046         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10047         pr "  }\n";
10048     | name, FBuffer ->
10049         pr "  {\n";
10050         pr "    int len = r->%s_len;\n" name;
10051         pr "    char s[len+1];\n";
10052         pr "    memcpy (s, r->%s, len);\n" name;
10053         pr "    s[len] = 0;\n";
10054         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10055         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10056         pr "  }\n";
10057     | name, (FBytes|FUInt64|FInt64) ->
10058         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10059         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10060     | name, (FUInt32|FInt32) ->
10061         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10062         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10063     | name, FOptPercent ->
10064         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10065         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10066     | name, FChar ->
10067         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10068         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10069   ) cols;
10070   pr "  free (r);\n";
10071   pr "  return jr;\n"
10072
10073 and generate_java_struct_list_return typ jtyp cols =
10074   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10075   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10076   pr "  for (i = 0; i < r->len; ++i) {\n";
10077   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10078   List.iter (
10079     function
10080     | name, FString ->
10081         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10082         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10083     | name, FUUID ->
10084         pr "    {\n";
10085         pr "      char s[33];\n";
10086         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10087         pr "      s[32] = 0;\n";
10088         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10089         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10090         pr "    }\n";
10091     | name, FBuffer ->
10092         pr "    {\n";
10093         pr "      int len = r->val[i].%s_len;\n" name;
10094         pr "      char s[len+1];\n";
10095         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10096         pr "      s[len] = 0;\n";
10097         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10098         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10099         pr "    }\n";
10100     | name, (FBytes|FUInt64|FInt64) ->
10101         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10102         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10103     | name, (FUInt32|FInt32) ->
10104         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10105         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10106     | name, FOptPercent ->
10107         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10108         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10109     | name, FChar ->
10110         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10111         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10112   ) cols;
10113   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10114   pr "  }\n";
10115   pr "  guestfs_free_%s_list (r);\n" typ;
10116   pr "  return jr;\n"
10117
10118 and generate_java_makefile_inc () =
10119   generate_header HashStyle GPLv2plus;
10120
10121   pr "java_built_sources = \\\n";
10122   List.iter (
10123     fun (typ, jtyp) ->
10124         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10125   ) java_structs;
10126   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10127
10128 and generate_haskell_hs () =
10129   generate_header HaskellStyle LGPLv2plus;
10130
10131   (* XXX We only know how to generate partial FFI for Haskell
10132    * at the moment.  Please help out!
10133    *)
10134   let can_generate style =
10135     match style with
10136     | RErr, _
10137     | RInt _, _
10138     | RInt64 _, _ -> true
10139     | RBool _, _
10140     | RConstString _, _
10141     | RConstOptString _, _
10142     | RString _, _
10143     | RStringList _, _
10144     | RStruct _, _
10145     | RStructList _, _
10146     | RHashtable _, _
10147     | RBufferOut _, _ -> false in
10148
10149   pr "\
10150 {-# INCLUDE <guestfs.h> #-}
10151 {-# LANGUAGE ForeignFunctionInterface #-}
10152
10153 module Guestfs (
10154   create";
10155
10156   (* List out the names of the actions we want to export. *)
10157   List.iter (
10158     fun (name, style, _, _, _, _, _) ->
10159       if can_generate style then pr ",\n  %s" name
10160   ) all_functions;
10161
10162   pr "
10163   ) where
10164
10165 -- Unfortunately some symbols duplicate ones already present
10166 -- in Prelude.  We don't know which, so we hard-code a list
10167 -- here.
10168 import Prelude hiding (truncate)
10169
10170 import Foreign
10171 import Foreign.C
10172 import Foreign.C.Types
10173 import IO
10174 import Control.Exception
10175 import Data.Typeable
10176
10177 data GuestfsS = GuestfsS            -- represents the opaque C struct
10178 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10179 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10180
10181 -- XXX define properly later XXX
10182 data PV = PV
10183 data VG = VG
10184 data LV = LV
10185 data IntBool = IntBool
10186 data Stat = Stat
10187 data StatVFS = StatVFS
10188 data Hashtable = Hashtable
10189
10190 foreign import ccall unsafe \"guestfs_create\" c_create
10191   :: IO GuestfsP
10192 foreign import ccall unsafe \"&guestfs_close\" c_close
10193   :: FunPtr (GuestfsP -> IO ())
10194 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10195   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10196
10197 create :: IO GuestfsH
10198 create = do
10199   p <- c_create
10200   c_set_error_handler p nullPtr nullPtr
10201   h <- newForeignPtr c_close p
10202   return h
10203
10204 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10205   :: GuestfsP -> IO CString
10206
10207 -- last_error :: GuestfsH -> IO (Maybe String)
10208 -- last_error h = do
10209 --   str <- withForeignPtr h (\\p -> c_last_error p)
10210 --   maybePeek peekCString str
10211
10212 last_error :: GuestfsH -> IO (String)
10213 last_error h = do
10214   str <- withForeignPtr h (\\p -> c_last_error p)
10215   if (str == nullPtr)
10216     then return \"no error\"
10217     else peekCString str
10218
10219 ";
10220
10221   (* Generate wrappers for each foreign function. *)
10222   List.iter (
10223     fun (name, style, _, _, _, _, _) ->
10224       if can_generate style then (
10225         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10226         pr "  :: ";
10227         generate_haskell_prototype ~handle:"GuestfsP" style;
10228         pr "\n";
10229         pr "\n";
10230         pr "%s :: " name;
10231         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10232         pr "\n";
10233         pr "%s %s = do\n" name
10234           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10235         pr "  r <- ";
10236         (* Convert pointer arguments using with* functions. *)
10237         List.iter (
10238           function
10239           | FileIn n
10240           | FileOut n
10241           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10242           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10243           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10244           | Bool _ | Int _ | Int64 _ -> ()
10245         ) (snd style);
10246         (* Convert integer arguments. *)
10247         let args =
10248           List.map (
10249             function
10250             | Bool n -> sprintf "(fromBool %s)" n
10251             | Int n -> sprintf "(fromIntegral %s)" n
10252             | Int64 n -> sprintf "(fromIntegral %s)" n
10253             | FileIn n | FileOut n
10254             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10255           ) (snd style) in
10256         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10257           (String.concat " " ("p" :: args));
10258         (match fst style with
10259          | RErr | RInt _ | RInt64 _ | RBool _ ->
10260              pr "  if (r == -1)\n";
10261              pr "    then do\n";
10262              pr "      err <- last_error h\n";
10263              pr "      fail err\n";
10264          | RConstString _ | RConstOptString _ | RString _
10265          | RStringList _ | RStruct _
10266          | RStructList _ | RHashtable _ | RBufferOut _ ->
10267              pr "  if (r == nullPtr)\n";
10268              pr "    then do\n";
10269              pr "      err <- last_error h\n";
10270              pr "      fail err\n";
10271         );
10272         (match fst style with
10273          | RErr ->
10274              pr "    else return ()\n"
10275          | RInt _ ->
10276              pr "    else return (fromIntegral r)\n"
10277          | RInt64 _ ->
10278              pr "    else return (fromIntegral r)\n"
10279          | RBool _ ->
10280              pr "    else return (toBool r)\n"
10281          | RConstString _
10282          | RConstOptString _
10283          | RString _
10284          | RStringList _
10285          | RStruct _
10286          | RStructList _
10287          | RHashtable _
10288          | RBufferOut _ ->
10289              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10290         );
10291         pr "\n";
10292       )
10293   ) all_functions
10294
10295 and generate_haskell_prototype ~handle ?(hs = false) style =
10296   pr "%s -> " handle;
10297   let string = if hs then "String" else "CString" in
10298   let int = if hs then "Int" else "CInt" in
10299   let bool = if hs then "Bool" else "CInt" in
10300   let int64 = if hs then "Integer" else "Int64" in
10301   List.iter (
10302     fun arg ->
10303       (match arg with
10304        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10305        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10306        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10307        | Bool _ -> pr "%s" bool
10308        | Int _ -> pr "%s" int
10309        | Int64 _ -> pr "%s" int
10310        | FileIn _ -> pr "%s" string
10311        | FileOut _ -> pr "%s" string
10312       );
10313       pr " -> ";
10314   ) (snd style);
10315   pr "IO (";
10316   (match fst style with
10317    | RErr -> if not hs then pr "CInt"
10318    | RInt _ -> pr "%s" int
10319    | RInt64 _ -> pr "%s" int64
10320    | RBool _ -> pr "%s" bool
10321    | RConstString _ -> pr "%s" string
10322    | RConstOptString _ -> pr "Maybe %s" string
10323    | RString _ -> pr "%s" string
10324    | RStringList _ -> pr "[%s]" string
10325    | RStruct (_, typ) ->
10326        let name = java_name_of_struct typ in
10327        pr "%s" name
10328    | RStructList (_, typ) ->
10329        let name = java_name_of_struct typ in
10330        pr "[%s]" name
10331    | RHashtable _ -> pr "Hashtable"
10332    | RBufferOut _ -> pr "%s" string
10333   );
10334   pr ")"
10335
10336 and generate_csharp () =
10337   generate_header CPlusPlusStyle LGPLv2plus;
10338
10339   (* XXX Make this configurable by the C# assembly users. *)
10340   let library = "libguestfs.so.0" in
10341
10342   pr "\
10343 // These C# bindings are highly experimental at present.
10344 //
10345 // Firstly they only work on Linux (ie. Mono).  In order to get them
10346 // to work on Windows (ie. .Net) you would need to port the library
10347 // itself to Windows first.
10348 //
10349 // The second issue is that some calls are known to be incorrect and
10350 // can cause Mono to segfault.  Particularly: calls which pass or
10351 // return string[], or return any structure value.  This is because
10352 // we haven't worked out the correct way to do this from C#.
10353 //
10354 // The third issue is that when compiling you get a lot of warnings.
10355 // We are not sure whether the warnings are important or not.
10356 //
10357 // Fourthly we do not routinely build or test these bindings as part
10358 // of the make && make check cycle, which means that regressions might
10359 // go unnoticed.
10360 //
10361 // Suggestions and patches are welcome.
10362
10363 // To compile:
10364 //
10365 // gmcs Libguestfs.cs
10366 // mono Libguestfs.exe
10367 //
10368 // (You'll probably want to add a Test class / static main function
10369 // otherwise this won't do anything useful).
10370
10371 using System;
10372 using System.IO;
10373 using System.Runtime.InteropServices;
10374 using System.Runtime.Serialization;
10375 using System.Collections;
10376
10377 namespace Guestfs
10378 {
10379   class Error : System.ApplicationException
10380   {
10381     public Error (string message) : base (message) {}
10382     protected Error (SerializationInfo info, StreamingContext context) {}
10383   }
10384
10385   class Guestfs
10386   {
10387     IntPtr _handle;
10388
10389     [DllImport (\"%s\")]
10390     static extern IntPtr guestfs_create ();
10391
10392     public Guestfs ()
10393     {
10394       _handle = guestfs_create ();
10395       if (_handle == IntPtr.Zero)
10396         throw new Error (\"could not create guestfs handle\");
10397     }
10398
10399     [DllImport (\"%s\")]
10400     static extern void guestfs_close (IntPtr h);
10401
10402     ~Guestfs ()
10403     {
10404       guestfs_close (_handle);
10405     }
10406
10407     [DllImport (\"%s\")]
10408     static extern string guestfs_last_error (IntPtr h);
10409
10410 " library library library;
10411
10412   (* Generate C# structure bindings.  We prefix struct names with
10413    * underscore because C# cannot have conflicting struct names and
10414    * method names (eg. "class stat" and "stat").
10415    *)
10416   List.iter (
10417     fun (typ, cols) ->
10418       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10419       pr "    public class _%s {\n" typ;
10420       List.iter (
10421         function
10422         | name, FChar -> pr "      char %s;\n" name
10423         | name, FString -> pr "      string %s;\n" name
10424         | name, FBuffer ->
10425             pr "      uint %s_len;\n" name;
10426             pr "      string %s;\n" name
10427         | name, FUUID ->
10428             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10429             pr "      string %s;\n" name
10430         | name, FUInt32 -> pr "      uint %s;\n" name
10431         | name, FInt32 -> pr "      int %s;\n" name
10432         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10433         | name, FInt64 -> pr "      long %s;\n" name
10434         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10435       ) cols;
10436       pr "    }\n";
10437       pr "\n"
10438   ) structs;
10439
10440   (* Generate C# function bindings. *)
10441   List.iter (
10442     fun (name, style, _, _, _, shortdesc, _) ->
10443       let rec csharp_return_type () =
10444         match fst style with
10445         | RErr -> "void"
10446         | RBool n -> "bool"
10447         | RInt n -> "int"
10448         | RInt64 n -> "long"
10449         | RConstString n
10450         | RConstOptString n
10451         | RString n
10452         | RBufferOut n -> "string"
10453         | RStruct (_,n) -> "_" ^ n
10454         | RHashtable n -> "Hashtable"
10455         | RStringList n -> "string[]"
10456         | RStructList (_,n) -> sprintf "_%s[]" n
10457
10458       and c_return_type () =
10459         match fst style with
10460         | RErr
10461         | RBool _
10462         | RInt _ -> "int"
10463         | RInt64 _ -> "long"
10464         | RConstString _
10465         | RConstOptString _
10466         | RString _
10467         | RBufferOut _ -> "string"
10468         | RStruct (_,n) -> "_" ^ n
10469         | RHashtable _
10470         | RStringList _ -> "string[]"
10471         | RStructList (_,n) -> sprintf "_%s[]" n
10472
10473       and c_error_comparison () =
10474         match fst style with
10475         | RErr
10476         | RBool _
10477         | RInt _
10478         | RInt64 _ -> "== -1"
10479         | RConstString _
10480         | RConstOptString _
10481         | RString _
10482         | RBufferOut _
10483         | RStruct (_,_)
10484         | RHashtable _
10485         | RStringList _
10486         | RStructList (_,_) -> "== null"
10487
10488       and generate_extern_prototype () =
10489         pr "    static extern %s guestfs_%s (IntPtr h"
10490           (c_return_type ()) name;
10491         List.iter (
10492           function
10493           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10494           | FileIn n | FileOut n ->
10495               pr ", [In] string %s" n
10496           | StringList n | DeviceList n ->
10497               pr ", [In] string[] %s" n
10498           | Bool n ->
10499               pr ", bool %s" n
10500           | Int n ->
10501               pr ", int %s" n
10502           | Int64 n ->
10503               pr ", long %s" n
10504         ) (snd style);
10505         pr ");\n"
10506
10507       and generate_public_prototype () =
10508         pr "    public %s %s (" (csharp_return_type ()) name;
10509         let comma = ref false in
10510         let next () =
10511           if !comma then pr ", ";
10512           comma := true
10513         in
10514         List.iter (
10515           function
10516           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10517           | FileIn n | FileOut n ->
10518               next (); pr "string %s" n
10519           | StringList n | DeviceList n ->
10520               next (); pr "string[] %s" n
10521           | Bool n ->
10522               next (); pr "bool %s" n
10523           | Int n ->
10524               next (); pr "int %s" n
10525           | Int64 n ->
10526               next (); pr "long %s" n
10527         ) (snd style);
10528         pr ")\n"
10529
10530       and generate_call () =
10531         pr "guestfs_%s (_handle" name;
10532         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10533         pr ");\n";
10534       in
10535
10536       pr "    [DllImport (\"%s\")]\n" library;
10537       generate_extern_prototype ();
10538       pr "\n";
10539       pr "    /// <summary>\n";
10540       pr "    /// %s\n" shortdesc;
10541       pr "    /// </summary>\n";
10542       generate_public_prototype ();
10543       pr "    {\n";
10544       pr "      %s r;\n" (c_return_type ());
10545       pr "      r = ";
10546       generate_call ();
10547       pr "      if (r %s)\n" (c_error_comparison ());
10548       pr "        throw new Error (guestfs_last_error (_handle));\n";
10549       (match fst style with
10550        | RErr -> ()
10551        | RBool _ ->
10552            pr "      return r != 0 ? true : false;\n"
10553        | RHashtable _ ->
10554            pr "      Hashtable rr = new Hashtable ();\n";
10555            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10556            pr "        rr.Add (r[i], r[i+1]);\n";
10557            pr "      return rr;\n"
10558        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10559        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10560        | RStructList _ ->
10561            pr "      return r;\n"
10562       );
10563       pr "    }\n";
10564       pr "\n";
10565   ) all_functions_sorted;
10566
10567   pr "  }
10568 }
10569 "
10570
10571 and generate_bindtests () =
10572   generate_header CStyle LGPLv2plus;
10573
10574   pr "\
10575 #include <stdio.h>
10576 #include <stdlib.h>
10577 #include <inttypes.h>
10578 #include <string.h>
10579
10580 #include \"guestfs.h\"
10581 #include \"guestfs-internal.h\"
10582 #include \"guestfs-internal-actions.h\"
10583 #include \"guestfs_protocol.h\"
10584
10585 #define error guestfs_error
10586 #define safe_calloc guestfs_safe_calloc
10587 #define safe_malloc guestfs_safe_malloc
10588
10589 static void
10590 print_strings (char *const *argv)
10591 {
10592   int argc;
10593
10594   printf (\"[\");
10595   for (argc = 0; argv[argc] != NULL; ++argc) {
10596     if (argc > 0) printf (\", \");
10597     printf (\"\\\"%%s\\\"\", argv[argc]);
10598   }
10599   printf (\"]\\n\");
10600 }
10601
10602 /* The test0 function prints its parameters to stdout. */
10603 ";
10604
10605   let test0, tests =
10606     match test_functions with
10607     | [] -> assert false
10608     | test0 :: tests -> test0, tests in
10609
10610   let () =
10611     let (name, style, _, _, _, _, _) = test0 in
10612     generate_prototype ~extern:false ~semicolon:false ~newline:true
10613       ~handle:"g" ~prefix:"guestfs__" name style;
10614     pr "{\n";
10615     List.iter (
10616       function
10617       | Pathname n
10618       | Device n | Dev_or_Path n
10619       | String n
10620       | FileIn n
10621       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10622       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10623       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10624       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10625       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10626       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10627     ) (snd style);
10628     pr "  /* Java changes stdout line buffering so we need this: */\n";
10629     pr "  fflush (stdout);\n";
10630     pr "  return 0;\n";
10631     pr "}\n";
10632     pr "\n" in
10633
10634   List.iter (
10635     fun (name, style, _, _, _, _, _) ->
10636       if String.sub name (String.length name - 3) 3 <> "err" then (
10637         pr "/* Test normal return. */\n";
10638         generate_prototype ~extern:false ~semicolon:false ~newline:true
10639           ~handle:"g" ~prefix:"guestfs__" name style;
10640         pr "{\n";
10641         (match fst style with
10642          | RErr ->
10643              pr "  return 0;\n"
10644          | RInt _ ->
10645              pr "  int r;\n";
10646              pr "  sscanf (val, \"%%d\", &r);\n";
10647              pr "  return r;\n"
10648          | RInt64 _ ->
10649              pr "  int64_t r;\n";
10650              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10651              pr "  return r;\n"
10652          | RBool _ ->
10653              pr "  return STREQ (val, \"true\");\n"
10654          | RConstString _
10655          | RConstOptString _ ->
10656              (* Can't return the input string here.  Return a static
10657               * string so we ensure we get a segfault if the caller
10658               * tries to free it.
10659               *)
10660              pr "  return \"static string\";\n"
10661          | RString _ ->
10662              pr "  return strdup (val);\n"
10663          | RStringList _ ->
10664              pr "  char **strs;\n";
10665              pr "  int n, i;\n";
10666              pr "  sscanf (val, \"%%d\", &n);\n";
10667              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10668              pr "  for (i = 0; i < n; ++i) {\n";
10669              pr "    strs[i] = safe_malloc (g, 16);\n";
10670              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10671              pr "  }\n";
10672              pr "  strs[n] = NULL;\n";
10673              pr "  return strs;\n"
10674          | RStruct (_, typ) ->
10675              pr "  struct guestfs_%s *r;\n" typ;
10676              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10677              pr "  return r;\n"
10678          | RStructList (_, typ) ->
10679              pr "  struct guestfs_%s_list *r;\n" typ;
10680              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10681              pr "  sscanf (val, \"%%d\", &r->len);\n";
10682              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10683              pr "  return r;\n"
10684          | RHashtable _ ->
10685              pr "  char **strs;\n";
10686              pr "  int n, i;\n";
10687              pr "  sscanf (val, \"%%d\", &n);\n";
10688              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10689              pr "  for (i = 0; i < n; ++i) {\n";
10690              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10691              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10692              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10693              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10694              pr "  }\n";
10695              pr "  strs[n*2] = NULL;\n";
10696              pr "  return strs;\n"
10697          | RBufferOut _ ->
10698              pr "  return strdup (val);\n"
10699         );
10700         pr "}\n";
10701         pr "\n"
10702       ) else (
10703         pr "/* Test error return. */\n";
10704         generate_prototype ~extern:false ~semicolon:false ~newline:true
10705           ~handle:"g" ~prefix:"guestfs__" name style;
10706         pr "{\n";
10707         pr "  error (g, \"error\");\n";
10708         (match fst style with
10709          | RErr | RInt _ | RInt64 _ | RBool _ ->
10710              pr "  return -1;\n"
10711          | RConstString _ | RConstOptString _
10712          | RString _ | RStringList _ | RStruct _
10713          | RStructList _
10714          | RHashtable _
10715          | RBufferOut _ ->
10716              pr "  return NULL;\n"
10717         );
10718         pr "}\n";
10719         pr "\n"
10720       )
10721   ) tests
10722
10723 and generate_ocaml_bindtests () =
10724   generate_header OCamlStyle GPLv2plus;
10725
10726   pr "\
10727 let () =
10728   let g = Guestfs.create () in
10729 ";
10730
10731   let mkargs args =
10732     String.concat " " (
10733       List.map (
10734         function
10735         | CallString s -> "\"" ^ s ^ "\""
10736         | CallOptString None -> "None"
10737         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10738         | CallStringList xs ->
10739             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10740         | CallInt i when i >= 0 -> string_of_int i
10741         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10742         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10743         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10744         | CallBool b -> string_of_bool b
10745       ) args
10746     )
10747   in
10748
10749   generate_lang_bindtests (
10750     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10751   );
10752
10753   pr "print_endline \"EOF\"\n"
10754
10755 and generate_perl_bindtests () =
10756   pr "#!/usr/bin/perl -w\n";
10757   generate_header HashStyle GPLv2plus;
10758
10759   pr "\
10760 use strict;
10761
10762 use Sys::Guestfs;
10763
10764 my $g = Sys::Guestfs->new ();
10765 ";
10766
10767   let mkargs args =
10768     String.concat ", " (
10769       List.map (
10770         function
10771         | CallString s -> "\"" ^ s ^ "\""
10772         | CallOptString None -> "undef"
10773         | CallOptString (Some s) -> sprintf "\"%s\"" s
10774         | CallStringList xs ->
10775             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10776         | CallInt i -> string_of_int i
10777         | CallInt64 i -> Int64.to_string i
10778         | CallBool b -> if b then "1" else "0"
10779       ) args
10780     )
10781   in
10782
10783   generate_lang_bindtests (
10784     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10785   );
10786
10787   pr "print \"EOF\\n\"\n"
10788
10789 and generate_python_bindtests () =
10790   generate_header HashStyle GPLv2plus;
10791
10792   pr "\
10793 import guestfs
10794
10795 g = guestfs.GuestFS ()
10796 ";
10797
10798   let mkargs args =
10799     String.concat ", " (
10800       List.map (
10801         function
10802         | CallString s -> "\"" ^ s ^ "\""
10803         | CallOptString None -> "None"
10804         | CallOptString (Some s) -> sprintf "\"%s\"" s
10805         | CallStringList xs ->
10806             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10807         | CallInt i -> string_of_int i
10808         | CallInt64 i -> Int64.to_string i
10809         | CallBool b -> if b then "1" else "0"
10810       ) args
10811     )
10812   in
10813
10814   generate_lang_bindtests (
10815     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10816   );
10817
10818   pr "print \"EOF\"\n"
10819
10820 and generate_ruby_bindtests () =
10821   generate_header HashStyle GPLv2plus;
10822
10823   pr "\
10824 require 'guestfs'
10825
10826 g = Guestfs::create()
10827 ";
10828
10829   let mkargs args =
10830     String.concat ", " (
10831       List.map (
10832         function
10833         | CallString s -> "\"" ^ s ^ "\""
10834         | CallOptString None -> "nil"
10835         | CallOptString (Some s) -> sprintf "\"%s\"" s
10836         | CallStringList xs ->
10837             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10838         | CallInt i -> string_of_int i
10839         | CallInt64 i -> Int64.to_string i
10840         | CallBool b -> string_of_bool b
10841       ) args
10842     )
10843   in
10844
10845   generate_lang_bindtests (
10846     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10847   );
10848
10849   pr "print \"EOF\\n\"\n"
10850
10851 and generate_java_bindtests () =
10852   generate_header CStyle GPLv2plus;
10853
10854   pr "\
10855 import com.redhat.et.libguestfs.*;
10856
10857 public class Bindtests {
10858     public static void main (String[] argv)
10859     {
10860         try {
10861             GuestFS g = new GuestFS ();
10862 ";
10863
10864   let mkargs args =
10865     String.concat ", " (
10866       List.map (
10867         function
10868         | CallString s -> "\"" ^ s ^ "\""
10869         | CallOptString None -> "null"
10870         | CallOptString (Some s) -> sprintf "\"%s\"" s
10871         | CallStringList xs ->
10872             "new String[]{" ^
10873               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10874         | CallInt i -> string_of_int i
10875         | CallInt64 i -> Int64.to_string i
10876         | CallBool b -> string_of_bool b
10877       ) args
10878     )
10879   in
10880
10881   generate_lang_bindtests (
10882     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10883   );
10884
10885   pr "
10886             System.out.println (\"EOF\");
10887         }
10888         catch (Exception exn) {
10889             System.err.println (exn);
10890             System.exit (1);
10891         }
10892     }
10893 }
10894 "
10895
10896 and generate_haskell_bindtests () =
10897   generate_header HaskellStyle GPLv2plus;
10898
10899   pr "\
10900 module Bindtests where
10901 import qualified Guestfs
10902
10903 main = do
10904   g <- Guestfs.create
10905 ";
10906
10907   let mkargs args =
10908     String.concat " " (
10909       List.map (
10910         function
10911         | CallString s -> "\"" ^ s ^ "\""
10912         | CallOptString None -> "Nothing"
10913         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10914         | CallStringList xs ->
10915             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10916         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10917         | CallInt i -> string_of_int i
10918         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10919         | CallInt64 i -> Int64.to_string i
10920         | CallBool true -> "True"
10921         | CallBool false -> "False"
10922       ) args
10923     )
10924   in
10925
10926   generate_lang_bindtests (
10927     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10928   );
10929
10930   pr "  putStrLn \"EOF\"\n"
10931
10932 (* Language-independent bindings tests - we do it this way to
10933  * ensure there is parity in testing bindings across all languages.
10934  *)
10935 and generate_lang_bindtests call =
10936   call "test0" [CallString "abc"; CallOptString (Some "def");
10937                 CallStringList []; CallBool false;
10938                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10939   call "test0" [CallString "abc"; CallOptString None;
10940                 CallStringList []; CallBool false;
10941                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10942   call "test0" [CallString ""; CallOptString (Some "def");
10943                 CallStringList []; CallBool false;
10944                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10945   call "test0" [CallString ""; CallOptString (Some "");
10946                 CallStringList []; CallBool false;
10947                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10948   call "test0" [CallString "abc"; CallOptString (Some "def");
10949                 CallStringList ["1"]; CallBool false;
10950                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10951   call "test0" [CallString "abc"; CallOptString (Some "def");
10952                 CallStringList ["1"; "2"]; CallBool false;
10953                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10954   call "test0" [CallString "abc"; CallOptString (Some "def");
10955                 CallStringList ["1"]; CallBool true;
10956                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10957   call "test0" [CallString "abc"; CallOptString (Some "def");
10958                 CallStringList ["1"]; CallBool false;
10959                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10960   call "test0" [CallString "abc"; CallOptString (Some "def");
10961                 CallStringList ["1"]; CallBool false;
10962                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10963   call "test0" [CallString "abc"; CallOptString (Some "def");
10964                 CallStringList ["1"]; CallBool false;
10965                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10966   call "test0" [CallString "abc"; CallOptString (Some "def");
10967                 CallStringList ["1"]; CallBool false;
10968                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10969   call "test0" [CallString "abc"; CallOptString (Some "def");
10970                 CallStringList ["1"]; CallBool false;
10971                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10972   call "test0" [CallString "abc"; CallOptString (Some "def");
10973                 CallStringList ["1"]; CallBool false;
10974                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10975
10976 (* XXX Add here tests of the return and error functions. *)
10977
10978 (* Code to generator bindings for virt-inspector.  Currently only
10979  * implemented for OCaml code (for virt-p2v 2.0).
10980  *)
10981 let rng_input = "inspector/virt-inspector.rng"
10982
10983 (* Read the input file and parse it into internal structures.  This is
10984  * by no means a complete RELAX NG parser, but is just enough to be
10985  * able to parse the specific input file.
10986  *)
10987 type rng =
10988   | Element of string * rng list        (* <element name=name/> *)
10989   | Attribute of string * rng list        (* <attribute name=name/> *)
10990   | Interleave of rng list                (* <interleave/> *)
10991   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10992   | OneOrMore of rng                        (* <oneOrMore/> *)
10993   | Optional of rng                        (* <optional/> *)
10994   | Choice of string list                (* <choice><value/>*</choice> *)
10995   | Value of string                        (* <value>str</value> *)
10996   | Text                                (* <text/> *)
10997
10998 let rec string_of_rng = function
10999   | Element (name, xs) ->
11000       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11001   | Attribute (name, xs) ->
11002       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11003   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11004   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11005   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11006   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11007   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11008   | Value value -> "Value \"" ^ value ^ "\""
11009   | Text -> "Text"
11010
11011 and string_of_rng_list xs =
11012   String.concat ", " (List.map string_of_rng xs)
11013
11014 let rec parse_rng ?defines context = function
11015   | [] -> []
11016   | Xml.Element ("element", ["name", name], children) :: rest ->
11017       Element (name, parse_rng ?defines context children)
11018       :: parse_rng ?defines context rest
11019   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11020       Attribute (name, parse_rng ?defines context children)
11021       :: parse_rng ?defines context rest
11022   | Xml.Element ("interleave", [], children) :: rest ->
11023       Interleave (parse_rng ?defines context children)
11024       :: parse_rng ?defines context rest
11025   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11026       let rng = parse_rng ?defines context [child] in
11027       (match rng with
11028        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11029        | _ ->
11030            failwithf "%s: <zeroOrMore> contains more than one child element"
11031              context
11032       )
11033   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11034       let rng = parse_rng ?defines context [child] in
11035       (match rng with
11036        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11037        | _ ->
11038            failwithf "%s: <oneOrMore> contains more than one child element"
11039              context
11040       )
11041   | Xml.Element ("optional", [], [child]) :: rest ->
11042       let rng = parse_rng ?defines context [child] in
11043       (match rng with
11044        | [child] -> Optional child :: parse_rng ?defines context rest
11045        | _ ->
11046            failwithf "%s: <optional> contains more than one child element"
11047              context
11048       )
11049   | Xml.Element ("choice", [], children) :: rest ->
11050       let values = List.map (
11051         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11052         | _ ->
11053             failwithf "%s: can't handle anything except <value> in <choice>"
11054               context
11055       ) children in
11056       Choice values
11057       :: parse_rng ?defines context rest
11058   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11059       Value value :: parse_rng ?defines context rest
11060   | Xml.Element ("text", [], []) :: rest ->
11061       Text :: parse_rng ?defines context rest
11062   | Xml.Element ("ref", ["name", name], []) :: rest ->
11063       (* Look up the reference.  Because of limitations in this parser,
11064        * we can't handle arbitrarily nested <ref> yet.  You can only
11065        * use <ref> from inside <start>.
11066        *)
11067       (match defines with
11068        | None ->
11069            failwithf "%s: contains <ref>, but no refs are defined yet" context
11070        | Some map ->
11071            let rng = StringMap.find name map in
11072            rng @ parse_rng ?defines context rest
11073       )
11074   | x :: _ ->
11075       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11076
11077 let grammar =
11078   let xml = Xml.parse_file rng_input in
11079   match xml with
11080   | Xml.Element ("grammar", _,
11081                  Xml.Element ("start", _, gram) :: defines) ->
11082       (* The <define/> elements are referenced in the <start> section,
11083        * so build a map of those first.
11084        *)
11085       let defines = List.fold_left (
11086         fun map ->
11087           function Xml.Element ("define", ["name", name], defn) ->
11088             StringMap.add name defn map
11089           | _ ->
11090               failwithf "%s: expected <define name=name/>" rng_input
11091       ) StringMap.empty defines in
11092       let defines = StringMap.mapi parse_rng defines in
11093
11094       (* Parse the <start> clause, passing the defines. *)
11095       parse_rng ~defines "<start>" gram
11096   | _ ->
11097       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11098         rng_input
11099
11100 let name_of_field = function
11101   | Element (name, _) | Attribute (name, _)
11102   | ZeroOrMore (Element (name, _))
11103   | OneOrMore (Element (name, _))
11104   | Optional (Element (name, _)) -> name
11105   | Optional (Attribute (name, _)) -> name
11106   | Text -> (* an unnamed field in an element *)
11107       "data"
11108   | rng ->
11109       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11110
11111 (* At the moment this function only generates OCaml types.  However we
11112  * should parameterize it later so it can generate types/structs in a
11113  * variety of languages.
11114  *)
11115 let generate_types xs =
11116   (* A simple type is one that can be printed out directly, eg.
11117    * "string option".  A complex type is one which has a name and has
11118    * to be defined via another toplevel definition, eg. a struct.
11119    *
11120    * generate_type generates code for either simple or complex types.
11121    * In the simple case, it returns the string ("string option").  In
11122    * the complex case, it returns the name ("mountpoint").  In the
11123    * complex case it has to print out the definition before returning,
11124    * so it should only be called when we are at the beginning of a
11125    * new line (BOL context).
11126    *)
11127   let rec generate_type = function
11128     | Text ->                                (* string *)
11129         "string", true
11130     | Choice values ->                        (* [`val1|`val2|...] *)
11131         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11132     | ZeroOrMore rng ->                        (* <rng> list *)
11133         let t, is_simple = generate_type rng in
11134         t ^ " list (* 0 or more *)", is_simple
11135     | OneOrMore rng ->                        (* <rng> list *)
11136         let t, is_simple = generate_type rng in
11137         t ^ " list (* 1 or more *)", is_simple
11138                                         (* virt-inspector hack: bool *)
11139     | Optional (Attribute (name, [Value "1"])) ->
11140         "bool", true
11141     | Optional rng ->                        (* <rng> list *)
11142         let t, is_simple = generate_type rng in
11143         t ^ " option", is_simple
11144                                         (* type name = { fields ... } *)
11145     | Element (name, fields) when is_attrs_interleave fields ->
11146         generate_type_struct name (get_attrs_interleave fields)
11147     | Element (name, [field])                (* type name = field *)
11148     | Attribute (name, [field]) ->
11149         let t, is_simple = generate_type field in
11150         if is_simple then (t, true)
11151         else (
11152           pr "type %s = %s\n" name t;
11153           name, false
11154         )
11155     | Element (name, fields) ->              (* type name = { fields ... } *)
11156         generate_type_struct name fields
11157     | rng ->
11158         failwithf "generate_type failed at: %s" (string_of_rng rng)
11159
11160   and is_attrs_interleave = function
11161     | [Interleave _] -> true
11162     | Attribute _ :: fields -> is_attrs_interleave fields
11163     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11164     | _ -> false
11165
11166   and get_attrs_interleave = function
11167     | [Interleave fields] -> fields
11168     | ((Attribute _) as field) :: fields
11169     | ((Optional (Attribute _)) as field) :: fields ->
11170         field :: get_attrs_interleave fields
11171     | _ -> assert false
11172
11173   and generate_types xs =
11174     List.iter (fun x -> ignore (generate_type x)) xs
11175
11176   and generate_type_struct name fields =
11177     (* Calculate the types of the fields first.  We have to do this
11178      * before printing anything so we are still in BOL context.
11179      *)
11180     let types = List.map fst (List.map generate_type fields) in
11181
11182     (* Special case of a struct containing just a string and another
11183      * field.  Turn it into an assoc list.
11184      *)
11185     match types with
11186     | ["string"; other] ->
11187         let fname1, fname2 =
11188           match fields with
11189           | [f1; f2] -> name_of_field f1, name_of_field f2
11190           | _ -> assert false in
11191         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11192         name, false
11193
11194     | types ->
11195         pr "type %s = {\n" name;
11196         List.iter (
11197           fun (field, ftype) ->
11198             let fname = name_of_field field in
11199             pr "  %s_%s : %s;\n" name fname ftype
11200         ) (List.combine fields types);
11201         pr "}\n";
11202         (* Return the name of this type, and
11203          * false because it's not a simple type.
11204          *)
11205         name, false
11206   in
11207
11208   generate_types xs
11209
11210 let generate_parsers xs =
11211   (* As for generate_type above, generate_parser makes a parser for
11212    * some type, and returns the name of the parser it has generated.
11213    * Because it (may) need to print something, it should always be
11214    * called in BOL context.
11215    *)
11216   let rec generate_parser = function
11217     | Text ->                                (* string *)
11218         "string_child_or_empty"
11219     | Choice values ->                        (* [`val1|`val2|...] *)
11220         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11221           (String.concat "|"
11222              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11223     | ZeroOrMore rng ->                        (* <rng> list *)
11224         let pa = generate_parser rng in
11225         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11226     | OneOrMore rng ->                        (* <rng> list *)
11227         let pa = generate_parser rng in
11228         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11229                                         (* virt-inspector hack: bool *)
11230     | Optional (Attribute (name, [Value "1"])) ->
11231         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11232     | Optional rng ->                        (* <rng> list *)
11233         let pa = generate_parser rng in
11234         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11235                                         (* type name = { fields ... } *)
11236     | Element (name, fields) when is_attrs_interleave fields ->
11237         generate_parser_struct name (get_attrs_interleave fields)
11238     | Element (name, [field]) ->        (* type name = field *)
11239         let pa = generate_parser field in
11240         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11241         pr "let %s =\n" parser_name;
11242         pr "  %s\n" pa;
11243         pr "let parse_%s = %s\n" name parser_name;
11244         parser_name
11245     | Attribute (name, [field]) ->
11246         let pa = generate_parser field in
11247         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11248         pr "let %s =\n" parser_name;
11249         pr "  %s\n" pa;
11250         pr "let parse_%s = %s\n" name parser_name;
11251         parser_name
11252     | Element (name, fields) ->              (* type name = { fields ... } *)
11253         generate_parser_struct name ([], fields)
11254     | rng ->
11255         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11256
11257   and is_attrs_interleave = function
11258     | [Interleave _] -> true
11259     | Attribute _ :: fields -> is_attrs_interleave fields
11260     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11261     | _ -> false
11262
11263   and get_attrs_interleave = function
11264     | [Interleave fields] -> [], fields
11265     | ((Attribute _) as field) :: fields
11266     | ((Optional (Attribute _)) as field) :: fields ->
11267         let attrs, interleaves = get_attrs_interleave fields in
11268         (field :: attrs), interleaves
11269     | _ -> assert false
11270
11271   and generate_parsers xs =
11272     List.iter (fun x -> ignore (generate_parser x)) xs
11273
11274   and generate_parser_struct name (attrs, interleaves) =
11275     (* Generate parsers for the fields first.  We have to do this
11276      * before printing anything so we are still in BOL context.
11277      *)
11278     let fields = attrs @ interleaves in
11279     let pas = List.map generate_parser fields in
11280
11281     (* Generate an intermediate tuple from all the fields first.
11282      * If the type is just a string + another field, then we will
11283      * return this directly, otherwise it is turned into a record.
11284      *
11285      * RELAX NG note: This code treats <interleave> and plain lists of
11286      * fields the same.  In other words, it doesn't bother enforcing
11287      * any ordering of fields in the XML.
11288      *)
11289     pr "let parse_%s x =\n" name;
11290     pr "  let t = (\n    ";
11291     let comma = ref false in
11292     List.iter (
11293       fun x ->
11294         if !comma then pr ",\n    ";
11295         comma := true;
11296         match x with
11297         | Optional (Attribute (fname, [field])), pa ->
11298             pr "%s x" pa
11299         | Optional (Element (fname, [field])), pa ->
11300             pr "%s (optional_child %S x)" pa fname
11301         | Attribute (fname, [Text]), _ ->
11302             pr "attribute %S x" fname
11303         | (ZeroOrMore _ | OneOrMore _), pa ->
11304             pr "%s x" pa
11305         | Text, pa ->
11306             pr "%s x" pa
11307         | (field, pa) ->
11308             let fname = name_of_field field in
11309             pr "%s (child %S x)" pa fname
11310     ) (List.combine fields pas);
11311     pr "\n  ) in\n";
11312
11313     (match fields with
11314      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11315          pr "  t\n"
11316
11317      | _ ->
11318          pr "  (Obj.magic t : %s)\n" name
11319 (*
11320          List.iter (
11321            function
11322            | (Optional (Attribute (fname, [field])), pa) ->
11323                pr "  %s_%s =\n" name fname;
11324                pr "    %s x;\n" pa
11325            | (Optional (Element (fname, [field])), pa) ->
11326                pr "  %s_%s =\n" name fname;
11327                pr "    (let x = optional_child %S x in\n" fname;
11328                pr "     %s x);\n" pa
11329            | (field, pa) ->
11330                let fname = name_of_field field in
11331                pr "  %s_%s =\n" name fname;
11332                pr "    (let x = child %S x in\n" fname;
11333                pr "     %s x);\n" pa
11334          ) (List.combine fields pas);
11335          pr "}\n"
11336 *)
11337     );
11338     sprintf "parse_%s" name
11339   in
11340
11341   generate_parsers xs
11342
11343 (* Generate ocaml/guestfs_inspector.mli. *)
11344 let generate_ocaml_inspector_mli () =
11345   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11346
11347   pr "\
11348 (** This is an OCaml language binding to the external [virt-inspector]
11349     program.
11350
11351     For more information, please read the man page [virt-inspector(1)].
11352 *)
11353
11354 ";
11355
11356   generate_types grammar;
11357   pr "(** The nested information returned from the {!inspect} function. *)\n";
11358   pr "\n";
11359
11360   pr "\
11361 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11362 (** To inspect a libvirt domain called [name], pass a singleton
11363     list: [inspect [name]].  When using libvirt only, you may
11364     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11365
11366     To inspect a disk image or images, pass a list of the filenames
11367     of the disk images: [inspect filenames]
11368
11369     This function inspects the given guest or disk images and
11370     returns a list of operating system(s) found and a large amount
11371     of information about them.  In the vast majority of cases,
11372     a virtual machine only contains a single operating system.
11373
11374     If the optional [~xml] parameter is given, then this function
11375     skips running the external virt-inspector program and just
11376     parses the given XML directly (which is expected to be XML
11377     produced from a previous run of virt-inspector).  The list of
11378     names and connect URI are ignored in this case.
11379
11380     This function can throw a wide variety of exceptions, for example
11381     if the external virt-inspector program cannot be found, or if
11382     it doesn't generate valid XML.
11383 *)
11384 "
11385
11386 (* Generate ocaml/guestfs_inspector.ml. *)
11387 let generate_ocaml_inspector_ml () =
11388   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11389
11390   pr "open Unix\n";
11391   pr "\n";
11392
11393   generate_types grammar;
11394   pr "\n";
11395
11396   pr "\
11397 (* Misc functions which are used by the parser code below. *)
11398 let first_child = function
11399   | Xml.Element (_, _, c::_) -> c
11400   | Xml.Element (name, _, []) ->
11401       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11402   | Xml.PCData str ->
11403       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11404
11405 let string_child_or_empty = function
11406   | Xml.Element (_, _, [Xml.PCData s]) -> s
11407   | Xml.Element (_, _, []) -> \"\"
11408   | Xml.Element (x, _, _) ->
11409       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11410                 x ^ \" instead\")
11411   | Xml.PCData str ->
11412       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11413
11414 let optional_child name xml =
11415   let children = Xml.children xml in
11416   try
11417     Some (List.find (function
11418                      | Xml.Element (n, _, _) when n = name -> true
11419                      | _ -> false) children)
11420   with
11421     Not_found -> None
11422
11423 let child name xml =
11424   match optional_child name xml with
11425   | Some c -> c
11426   | None ->
11427       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11428
11429 let attribute name xml =
11430   try Xml.attrib xml name
11431   with Xml.No_attribute _ ->
11432     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11433
11434 ";
11435
11436   generate_parsers grammar;
11437   pr "\n";
11438
11439   pr "\
11440 (* Run external virt-inspector, then use parser to parse the XML. *)
11441 let inspect ?connect ?xml names =
11442   let xml =
11443     match xml with
11444     | None ->
11445         if names = [] then invalid_arg \"inspect: no names given\";
11446         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11447           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11448           names in
11449         let cmd = List.map Filename.quote cmd in
11450         let cmd = String.concat \" \" cmd in
11451         let chan = open_process_in cmd in
11452         let xml = Xml.parse_in chan in
11453         (match close_process_in chan with
11454          | WEXITED 0 -> ()
11455          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11456          | WSIGNALED i | WSTOPPED i ->
11457              failwith (\"external virt-inspector command died or stopped on sig \" ^
11458                        string_of_int i)
11459         );
11460         xml
11461     | Some doc ->
11462         Xml.parse_string doc in
11463   parse_operatingsystems xml
11464 "
11465
11466 (* This is used to generate the src/MAX_PROC_NR file which
11467  * contains the maximum procedure number, a surrogate for the
11468  * ABI version number.  See src/Makefile.am for the details.
11469  *)
11470 and generate_max_proc_nr () =
11471   let proc_nrs = List.map (
11472     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11473   ) daemon_functions in
11474
11475   let max_proc_nr = List.fold_left max 0 proc_nrs in
11476
11477   pr "%d\n" max_proc_nr
11478
11479 let output_to filename k =
11480   let filename_new = filename ^ ".new" in
11481   chan := open_out filename_new;
11482   k ();
11483   close_out !chan;
11484   chan := Pervasives.stdout;
11485
11486   (* Is the new file different from the current file? *)
11487   if Sys.file_exists filename && files_equal filename filename_new then
11488     unlink filename_new                 (* same, so skip it *)
11489   else (
11490     (* different, overwrite old one *)
11491     (try chmod filename 0o644 with Unix_error _ -> ());
11492     rename filename_new filename;
11493     chmod filename 0o444;
11494     printf "written %s\n%!" filename;
11495   )
11496
11497 let perror msg = function
11498   | Unix_error (err, _, _) ->
11499       eprintf "%s: %s\n" msg (error_message err)
11500   | exn ->
11501       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11502
11503 (* Main program. *)
11504 let () =
11505   let lock_fd =
11506     try openfile "HACKING" [O_RDWR] 0
11507     with
11508     | Unix_error (ENOENT, _, _) ->
11509         eprintf "\
11510 You are probably running this from the wrong directory.
11511 Run it from the top source directory using the command
11512   src/generator.ml
11513 ";
11514         exit 1
11515     | exn ->
11516         perror "open: HACKING" exn;
11517         exit 1 in
11518
11519   (* Acquire a lock so parallel builds won't try to run the generator
11520    * twice at the same time.  Subsequent builds will wait for the first
11521    * one to finish.  Note the lock is released implicitly when the
11522    * program exits.
11523    *)
11524   (try lockf lock_fd F_LOCK 1
11525    with exn ->
11526      perror "lock: HACKING" exn;
11527      exit 1);
11528
11529   check_functions ();
11530
11531   output_to "src/guestfs_protocol.x" generate_xdr;
11532   output_to "src/guestfs-structs.h" generate_structs_h;
11533   output_to "src/guestfs-actions.h" generate_actions_h;
11534   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11535   output_to "src/guestfs-actions.c" generate_client_actions;
11536   output_to "src/guestfs-bindtests.c" generate_bindtests;
11537   output_to "src/guestfs-structs.pod" generate_structs_pod;
11538   output_to "src/guestfs-actions.pod" generate_actions_pod;
11539   output_to "src/guestfs-availability.pod" generate_availability_pod;
11540   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11541   output_to "src/libguestfs.syms" generate_linker_script;
11542   output_to "daemon/actions.h" generate_daemon_actions_h;
11543   output_to "daemon/stubs.c" generate_daemon_actions;
11544   output_to "daemon/names.c" generate_daemon_names;
11545   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11546   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11547   output_to "capitests/tests.c" generate_tests;
11548   output_to "fish/cmds.c" generate_fish_cmds;
11549   output_to "fish/completion.c" generate_fish_completion;
11550   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11551   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11552   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11553   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11554   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11555   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11556   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11557   output_to "perl/Guestfs.xs" generate_perl_xs;
11558   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11559   output_to "perl/bindtests.pl" generate_perl_bindtests;
11560   output_to "python/guestfs-py.c" generate_python_c;
11561   output_to "python/guestfs.py" generate_python_py;
11562   output_to "python/bindtests.py" generate_python_bindtests;
11563   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11564   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11565   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11566
11567   List.iter (
11568     fun (typ, jtyp) ->
11569       let cols = cols_of_struct typ in
11570       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11571       output_to filename (generate_java_struct jtyp cols);
11572   ) java_structs;
11573
11574   output_to "java/Makefile.inc" generate_java_makefile_inc;
11575   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11576   output_to "java/Bindtests.java" generate_java_bindtests;
11577   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11578   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11579   output_to "csharp/Libguestfs.cs" generate_csharp;
11580
11581   (* Always generate this file last, and unconditionally.  It's used
11582    * by the Makefile to know when we must re-run the generator.
11583    *)
11584   let chan = open_out "src/stamp-generator" in
11585   fprintf chan "1\n";
11586   close_out chan;
11587
11588   printf "generated %d lines of code\n" !lines