bab4bc031da44312740afeeccc4297a320c14faf
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use dynamic linker functions
795 to find out if this symbol exists (if it doesn't, then
796 it's an earlier version).
797
798 The call returns a structure with four elements.  The first
799 three (C<major>, C<minor> and C<release>) are numbers and
800 correspond to the usual version triplet.  The fourth element
801 (C<extra>) is a string and is normally empty, but may be
802 used for distro-specific information.
803
804 To construct the original version string:
805 C<$major.$minor.$release$extra>
806
807 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
808
809 I<Note:> Don't use this call to test for availability
810 of features.  In enterprise distributions we backport
811 features from later versions into earlier versions,
812 making this an unreliable way to test for features.
813 Use C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 B<Important note:>
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly.  This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability.  Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
970
971   ("sync", (RErr, []), 2, [],
972    [ InitEmpty, Always, TestRun [["sync"]]],
973    "sync disks, writes are flushed through to the disk image",
974    "\
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
977
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
980
981   ("touch", (RErr, [Pathname "path"]), 3, [],
982    [InitBasicFS, Always, TestOutputTrue (
983       [["touch"; "/new"];
984        ["exists"; "/new"]])],
985    "update file timestamps or create a new file",
986    "\
987 Touch acts like the L<touch(1)> command.  It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
990
991   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992    [InitISOFS, Always, TestOutput (
993       [["cat"; "/known-2"]], "abcdef\n")],
994    "list the contents of a file",
995    "\
996 Return the contents of the file named C<path>.
997
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string).  For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1002
1003   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004    [], (* XXX Tricky to test because it depends on the exact format
1005         * of the 'ls -l' command, which changes between F10 and F11.
1006         *)
1007    "list the files in a directory (long format)",
1008    "\
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1011
1012 This command is mostly useful for interactive sessions.  It
1013 is I<not> intended that you try to parse the output string.");
1014
1015   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016    [InitBasicFS, Always, TestOutputList (
1017       [["touch"; "/new"];
1018        ["touch"; "/newer"];
1019        ["touch"; "/newest"];
1020        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021    "list the files in a directory",
1022    "\
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd).  The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1026
1027 This command is mostly useful for interactive sessions.  Programs
1028 should probably use C<guestfs_readdir> instead.");
1029
1030   ("list_devices", (RStringList "devices", []), 7, [],
1031    [InitEmpty, Always, TestOutputListOfDevices (
1032       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033    "list the block devices",
1034    "\
1035 List all the block devices.
1036
1037 The full block device names are returned, eg. C</dev/sda>");
1038
1039   ("list_partitions", (RStringList "partitions", []), 8, [],
1040    [InitBasicFS, Always, TestOutputListOfDevices (
1041       [["list_partitions"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045    "list the partitions",
1046    "\
1047 List all the partitions detected on all block devices.
1048
1049 The full partition device names are returned, eg. C</dev/sda1>
1050
1051 This does not return logical volumes.  For that you will need to
1052 call C<guestfs_lvs>.");
1053
1054   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056       [["pvs"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["pvcreate"; "/dev/sda1"];
1060        ["pvcreate"; "/dev/sda2"];
1061        ["pvcreate"; "/dev/sda3"];
1062        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063    "list the LVM physical volumes (PVs)",
1064    "\
1065 List all the physical volumes detected.  This is the equivalent
1066 of the L<pvs(8)> command.
1067
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1070
1071 See also C<guestfs_pvs_full>.");
1072
1073   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074    [InitBasicFSonLVM, Always, TestOutputList (
1075       [["vgs"]], ["VG"]);
1076     InitEmpty, Always, TestOutputList (
1077       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078        ["pvcreate"; "/dev/sda1"];
1079        ["pvcreate"; "/dev/sda2"];
1080        ["pvcreate"; "/dev/sda3"];
1081        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082        ["vgcreate"; "VG2"; "/dev/sda3"];
1083        ["vgs"]], ["VG1"; "VG2"])],
1084    "list the LVM volume groups (VGs)",
1085    "\
1086 List all the volumes groups detected.  This is the equivalent
1087 of the L<vgs(8)> command.
1088
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1091
1092 See also C<guestfs_vgs_full>.");
1093
1094   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095    [InitBasicFSonLVM, Always, TestOutputList (
1096       [["lvs"]], ["/dev/VG/LV"]);
1097     InitEmpty, Always, TestOutputList (
1098       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099        ["pvcreate"; "/dev/sda1"];
1100        ["pvcreate"; "/dev/sda2"];
1101        ["pvcreate"; "/dev/sda3"];
1102        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103        ["vgcreate"; "VG2"; "/dev/sda3"];
1104        ["lvcreate"; "LV1"; "VG1"; "50"];
1105        ["lvcreate"; "LV2"; "VG1"; "50"];
1106        ["lvcreate"; "LV3"; "VG2"; "50"];
1107        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108    "list the LVM logical volumes (LVs)",
1109    "\
1110 List all the logical volumes detected.  This is the equivalent
1111 of the L<lvs(8)> command.
1112
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1115
1116 See also C<guestfs_lvs_full>.");
1117
1118   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM physical volumes (PVs)",
1121    "\
1122 List all the physical volumes detected.  This is the equivalent
1123 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM volume groups (VGs)",
1128    "\
1129 List all the volumes groups detected.  This is the equivalent
1130 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM logical volumes (LVs)",
1135    "\
1136 List all the logical volumes detected.  This is the equivalent
1137 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140    [InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142     InitISOFS, Always, TestOutputList (
1143       [["read_lines"; "/empty"]], [])],
1144    "read file as lines",
1145    "\
1146 Return the contents of the file named C<path>.
1147
1148 The file contents are returned as a list of lines.  Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1150
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line).  For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1155
1156   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "create a new Augeas handle",
1159    "\
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1163
1164 You must call this before using any other C<guestfs_aug_*>
1165 commands.
1166
1167 C<root> is the filesystem root.  C<root> must not be NULL,
1168 use C</> instead.
1169
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 integers:
1173
1174 =over 4
1175
1176 =item C<AUG_SAVE_BACKUP> = 1
1177
1178 Keep the original file with a C<.augsave> extension.
1179
1180 =item C<AUG_SAVE_NEWFILE> = 2
1181
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1184
1185 =item C<AUG_TYPE_CHECK> = 4
1186
1187 Typecheck lenses (can be expensive).
1188
1189 =item C<AUG_NO_STDINC> = 8
1190
1191 Do not use standard load path for modules.
1192
1193 =item C<AUG_SAVE_NOOP> = 16
1194
1195 Make save a no-op, just record what would have been changed.
1196
1197 =item C<AUG_NO_LOAD> = 32
1198
1199 Do not load the tree in C<guestfs_aug_init>.
1200
1201 =back
1202
1203 To close the handle, you can call C<guestfs_aug_close>.
1204
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1206
1207   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "close the current Augeas handle",
1210    "\
1211 Close the current Augeas handle and free up any resources
1212 used by it.  After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1215
1216   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "define an Augeas variable",
1219    "\
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1222 undefined.
1223
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226
1227   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "define an Augeas node",
1230    "\
1231 Defines a variable C<name> whose value is the result of
1232 evaluating C<expr>.
1233
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1237
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1241
1242   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "look up the value of an Augeas path",
1245    "\
1246 Look up the value associated with C<path>.  If C<path>
1247 matches exactly one node, the C<value> is returned.");
1248
1249   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "set Augeas path to value",
1252    "\
1253 Set the value associated with C<path> to C<value>.");
1254
1255   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "insert a sibling Augeas node",
1258    "\
1259 Create a new sibling C<label> for C<path>, inserting it into
1260 the tree before or after C<path> (depending on the boolean
1261 flag C<before>).
1262
1263 C<path> must match exactly one existing node in the tree, and
1264 C<label> must be a label, ie. not contain C</>, C<*> or end
1265 with a bracketed index C<[N]>.");
1266
1267   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1268    [], (* XXX Augeas code needs tests. *)
1269    "remove an Augeas path",
1270    "\
1271 Remove C<path> and all of its children.
1272
1273 On success this returns the number of entries which were removed.");
1274
1275   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "move Augeas node",
1278    "\
1279 Move the node C<src> to C<dest>.  C<src> must match exactly
1280 one node.  C<dest> is overwritten if it exists.");
1281
1282   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1283    [], (* XXX Augeas code needs tests. *)
1284    "return Augeas nodes which match augpath",
1285    "\
1286 Returns a list of paths which match the path expression C<path>.
1287 The returned paths are sufficiently qualified so that they match
1288 exactly one node in the current tree.");
1289
1290   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1291    [], (* XXX Augeas code needs tests. *)
1292    "write all pending Augeas changes to disk",
1293    "\
1294 This writes all pending changes to disk.
1295
1296 The flags which were passed to C<guestfs_aug_init> affect exactly
1297 how files are saved.");
1298
1299   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1300    [], (* XXX Augeas code needs tests. *)
1301    "load files into the tree",
1302    "\
1303 Load files into the tree.
1304
1305 See C<aug_load> in the Augeas documentation for the full gory
1306 details.");
1307
1308   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1309    [], (* XXX Augeas code needs tests. *)
1310    "list Augeas nodes under augpath",
1311    "\
1312 This is just a shortcut for listing C<guestfs_aug_match>
1313 C<path/*> and sorting the resulting nodes into alphabetical order.");
1314
1315   ("rm", (RErr, [Pathname "path"]), 29, [],
1316    [InitBasicFS, Always, TestRun
1317       [["touch"; "/new"];
1318        ["rm"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["rm"; "/new"]];
1321     InitBasicFS, Always, TestLastFail
1322       [["mkdir"; "/new"];
1323        ["rm"; "/new"]]],
1324    "remove a file",
1325    "\
1326 Remove the single file C<path>.");
1327
1328   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1329    [InitBasicFS, Always, TestRun
1330       [["mkdir"; "/new"];
1331        ["rmdir"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["rmdir"; "/new"]];
1334     InitBasicFS, Always, TestLastFail
1335       [["touch"; "/new"];
1336        ["rmdir"; "/new"]]],
1337    "remove a directory",
1338    "\
1339 Remove the single directory C<path>.");
1340
1341   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1342    [InitBasicFS, Always, TestOutputFalse
1343       [["mkdir"; "/new"];
1344        ["mkdir"; "/new/foo"];
1345        ["touch"; "/new/foo/bar"];
1346        ["rm_rf"; "/new"];
1347        ["exists"; "/new"]]],
1348    "remove a file or directory recursively",
1349    "\
1350 Remove the file or directory C<path>, recursively removing the
1351 contents if its a directory.  This is like the C<rm -rf> shell
1352 command.");
1353
1354   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1355    [InitBasicFS, Always, TestOutputTrue
1356       [["mkdir"; "/new"];
1357        ["is_dir"; "/new"]];
1358     InitBasicFS, Always, TestLastFail
1359       [["mkdir"; "/new/foo/bar"]]],
1360    "create a directory",
1361    "\
1362 Create a directory named C<path>.");
1363
1364   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1365    [InitBasicFS, Always, TestOutputTrue
1366       [["mkdir_p"; "/new/foo/bar"];
1367        ["is_dir"; "/new/foo/bar"]];
1368     InitBasicFS, Always, TestOutputTrue
1369       [["mkdir_p"; "/new/foo/bar"];
1370        ["is_dir"; "/new/foo"]];
1371     InitBasicFS, Always, TestOutputTrue
1372       [["mkdir_p"; "/new/foo/bar"];
1373        ["is_dir"; "/new"]];
1374     (* Regression tests for RHBZ#503133: *)
1375     InitBasicFS, Always, TestRun
1376       [["mkdir"; "/new"];
1377        ["mkdir_p"; "/new"]];
1378     InitBasicFS, Always, TestLastFail
1379       [["touch"; "/new"];
1380        ["mkdir_p"; "/new"]]],
1381    "create a directory and parents",
1382    "\
1383 Create a directory named C<path>, creating any parent directories
1384 as necessary.  This is like the C<mkdir -p> shell command.");
1385
1386   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1387    [], (* XXX Need stat command to test *)
1388    "change file mode",
1389    "\
1390 Change the mode (permissions) of C<path> to C<mode>.  Only
1391 numeric modes are supported.
1392
1393 I<Note>: When using this command from guestfish, C<mode>
1394 by default would be decimal, unless you prefix it with
1395 C<0> to get octal, ie. use C<0700> not C<700>.
1396
1397 The mode actually set is affected by the umask.");
1398
1399   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1400    [], (* XXX Need stat command to test *)
1401    "change file owner and group",
1402    "\
1403 Change the file owner to C<owner> and group to C<group>.
1404
1405 Only numeric uid and gid are supported.  If you want to use
1406 names, you will need to locate and parse the password file
1407 yourself (Augeas support makes this relatively easy).");
1408
1409   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1410    [InitISOFS, Always, TestOutputTrue (
1411       [["exists"; "/empty"]]);
1412     InitISOFS, Always, TestOutputTrue (
1413       [["exists"; "/directory"]])],
1414    "test if file or directory exists",
1415    "\
1416 This returns C<true> if and only if there is a file, directory
1417 (or anything) with the given C<path> name.
1418
1419 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1420
1421   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1422    [InitISOFS, Always, TestOutputTrue (
1423       [["is_file"; "/known-1"]]);
1424     InitISOFS, Always, TestOutputFalse (
1425       [["is_file"; "/directory"]])],
1426    "test if file exists",
1427    "\
1428 This returns C<true> if and only if there is a file
1429 with the given C<path> name.  Note that it returns false for
1430 other objects like directories.
1431
1432 See also C<guestfs_stat>.");
1433
1434   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1435    [InitISOFS, Always, TestOutputFalse (
1436       [["is_dir"; "/known-3"]]);
1437     InitISOFS, Always, TestOutputTrue (
1438       [["is_dir"; "/directory"]])],
1439    "test if file exists",
1440    "\
1441 This returns C<true> if and only if there is a directory
1442 with the given C<path> name.  Note that it returns false for
1443 other objects like files.
1444
1445 See also C<guestfs_stat>.");
1446
1447   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1448    [InitEmpty, Always, TestOutputListOfDevices (
1449       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1450        ["pvcreate"; "/dev/sda1"];
1451        ["pvcreate"; "/dev/sda2"];
1452        ["pvcreate"; "/dev/sda3"];
1453        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1454    "create an LVM physical volume",
1455    "\
1456 This creates an LVM physical volume on the named C<device>,
1457 where C<device> should usually be a partition name such
1458 as C</dev/sda1>.");
1459
1460   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["vgs"]], ["VG1"; "VG2"])],
1469    "create an LVM volume group",
1470    "\
1471 This creates an LVM volume group called C<volgroup>
1472 from the non-empty list of physical volumes C<physvols>.");
1473
1474   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1475    [InitEmpty, Always, TestOutputList (
1476       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1477        ["pvcreate"; "/dev/sda1"];
1478        ["pvcreate"; "/dev/sda2"];
1479        ["pvcreate"; "/dev/sda3"];
1480        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1481        ["vgcreate"; "VG2"; "/dev/sda3"];
1482        ["lvcreate"; "LV1"; "VG1"; "50"];
1483        ["lvcreate"; "LV2"; "VG1"; "50"];
1484        ["lvcreate"; "LV3"; "VG2"; "50"];
1485        ["lvcreate"; "LV4"; "VG2"; "50"];
1486        ["lvcreate"; "LV5"; "VG2"; "50"];
1487        ["lvs"]],
1488       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1489        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1490    "create an LVM logical volume",
1491    "\
1492 This creates an LVM logical volume called C<logvol>
1493 on the volume group C<volgroup>, with C<size> megabytes.");
1494
1495   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1496    [InitEmpty, Always, TestOutput (
1497       [["part_disk"; "/dev/sda"; "mbr"];
1498        ["mkfs"; "ext2"; "/dev/sda1"];
1499        ["mount_options"; ""; "/dev/sda1"; "/"];
1500        ["write_file"; "/new"; "new file contents"; "0"];
1501        ["cat"; "/new"]], "new file contents")],
1502    "make a filesystem",
1503    "\
1504 This creates a filesystem on C<device> (usually a partition
1505 or LVM logical volume).  The filesystem type is C<fstype>, for
1506 example C<ext3>.");
1507
1508   ("sfdisk", (RErr, [Device "device";
1509                      Int "cyls"; Int "heads"; Int "sectors";
1510                      StringList "lines"]), 43, [DangerWillRobinson],
1511    [],
1512    "create partitions on a block device",
1513    "\
1514 This is a direct interface to the L<sfdisk(8)> program for creating
1515 partitions on block devices.
1516
1517 C<device> should be a block device, for example C</dev/sda>.
1518
1519 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1520 and sectors on the device, which are passed directly to sfdisk as
1521 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1522 of these, then the corresponding parameter is omitted.  Usually for
1523 'large' disks, you can just pass C<0> for these, but for small
1524 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1525 out the right geometry and you will need to tell it.
1526
1527 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1528 information refer to the L<sfdisk(8)> manpage.
1529
1530 To create a single partition occupying the whole disk, you would
1531 pass C<lines> as a single element list, when the single element being
1532 the string C<,> (comma).
1533
1534 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1535 C<guestfs_part_init>");
1536
1537   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1538    [InitBasicFS, Always, TestOutput (
1539       [["write_file"; "/new"; "new file contents"; "0"];
1540        ["cat"; "/new"]], "new file contents");
1541     InitBasicFS, Always, TestOutput (
1542       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1543        ["cat"; "/new"]], "\nnew file contents\n");
1544     InitBasicFS, Always, TestOutput (
1545       [["write_file"; "/new"; "\n\n"; "0"];
1546        ["cat"; "/new"]], "\n\n");
1547     InitBasicFS, Always, TestOutput (
1548       [["write_file"; "/new"; ""; "0"];
1549        ["cat"; "/new"]], "");
1550     InitBasicFS, Always, TestOutput (
1551       [["write_file"; "/new"; "\n\n\n"; "0"];
1552        ["cat"; "/new"]], "\n\n\n");
1553     InitBasicFS, Always, TestOutput (
1554       [["write_file"; "/new"; "\n"; "0"];
1555        ["cat"; "/new"]], "\n")],
1556    "create a file",
1557    "\
1558 This call creates a file called C<path>.  The contents of the
1559 file is the string C<content> (which can contain any 8 bit data),
1560 with length C<size>.
1561
1562 As a special case, if C<size> is C<0>
1563 then the length is calculated using C<strlen> (so in this case
1564 the content cannot contain embedded ASCII NULs).
1565
1566 I<NB.> Owing to a bug, writing content containing ASCII NUL
1567 characters does I<not> work, even if the length is specified.
1568 We hope to resolve this bug in a future version.  In the meantime
1569 use C<guestfs_upload>.");
1570
1571   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1572    [InitEmpty, Always, TestOutputListOfDevices (
1573       [["part_disk"; "/dev/sda"; "mbr"];
1574        ["mkfs"; "ext2"; "/dev/sda1"];
1575        ["mount_options"; ""; "/dev/sda1"; "/"];
1576        ["mounts"]], ["/dev/sda1"]);
1577     InitEmpty, Always, TestOutputList (
1578       [["part_disk"; "/dev/sda"; "mbr"];
1579        ["mkfs"; "ext2"; "/dev/sda1"];
1580        ["mount_options"; ""; "/dev/sda1"; "/"];
1581        ["umount"; "/"];
1582        ["mounts"]], [])],
1583    "unmount a filesystem",
1584    "\
1585 This unmounts the given filesystem.  The filesystem may be
1586 specified either by its mountpoint (path) or the device which
1587 contains the filesystem.");
1588
1589   ("mounts", (RStringList "devices", []), 46, [],
1590    [InitBasicFS, Always, TestOutputListOfDevices (
1591       [["mounts"]], ["/dev/sda1"])],
1592    "show mounted filesystems",
1593    "\
1594 This returns the list of currently mounted filesystems.  It returns
1595 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1596
1597 Some internal mounts are not shown.
1598
1599 See also: C<guestfs_mountpoints>");
1600
1601   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1602    [InitBasicFS, Always, TestOutputList (
1603       [["umount_all"];
1604        ["mounts"]], []);
1605     (* check that umount_all can unmount nested mounts correctly: *)
1606     InitEmpty, Always, TestOutputList (
1607       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1608        ["mkfs"; "ext2"; "/dev/sda1"];
1609        ["mkfs"; "ext2"; "/dev/sda2"];
1610        ["mkfs"; "ext2"; "/dev/sda3"];
1611        ["mount_options"; ""; "/dev/sda1"; "/"];
1612        ["mkdir"; "/mp1"];
1613        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1614        ["mkdir"; "/mp1/mp2"];
1615        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1616        ["mkdir"; "/mp1/mp2/mp3"];
1617        ["umount_all"];
1618        ["mounts"]], [])],
1619    "unmount all filesystems",
1620    "\
1621 This unmounts all mounted filesystems.
1622
1623 Some internal mounts are not unmounted by this call.");
1624
1625   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1626    [],
1627    "remove all LVM LVs, VGs and PVs",
1628    "\
1629 This command removes all LVM logical volumes, volume groups
1630 and physical volumes.");
1631
1632   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1633    [InitISOFS, Always, TestOutput (
1634       [["file"; "/empty"]], "empty");
1635     InitISOFS, Always, TestOutput (
1636       [["file"; "/known-1"]], "ASCII text");
1637     InitISOFS, Always, TestLastFail (
1638       [["file"; "/notexists"]])],
1639    "determine file type",
1640    "\
1641 This call uses the standard L<file(1)> command to determine
1642 the type or contents of the file.  This also works on devices,
1643 for example to find out whether a partition contains a filesystem.
1644
1645 This call will also transparently look inside various types
1646 of compressed file.
1647
1648 The exact command which runs is C<file -zbsL path>.  Note in
1649 particular that the filename is not prepended to the output
1650 (the C<-b> option).");
1651
1652   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1653    [InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 1"]], "Result1");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 2"]], "Result2\n");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 3"]], "\nResult3");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 4"]], "\nResult4\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 5"]], "\nResult5\n\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 7"]], "");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 8"]], "\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 9"]], "\n\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1693     InitBasicFS, Always, TestOutput (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1697     InitBasicFS, Always, TestLastFail (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command"; "/test-command"]])],
1701    "run a command from the guest filesystem",
1702    "\
1703 This call runs a command from the guest filesystem.  The
1704 filesystem must be mounted, and must contain a compatible
1705 operating system (ie. something Linux, with the same
1706 or compatible processor architecture).
1707
1708 The single parameter is an argv-style list of arguments.
1709 The first element is the name of the program to run.
1710 Subsequent elements are parameters.  The list must be
1711 non-empty (ie. must contain a program name).  Note that
1712 the command runs directly, and is I<not> invoked via
1713 the shell (see C<guestfs_sh>).
1714
1715 The return value is anything printed to I<stdout> by
1716 the command.
1717
1718 If the command returns a non-zero exit status, then
1719 this function returns an error message.  The error message
1720 string is the content of I<stderr> from the command.
1721
1722 The C<$PATH> environment variable will contain at least
1723 C</usr/bin> and C</bin>.  If you require a program from
1724 another location, you should provide the full path in the
1725 first parameter.
1726
1727 Shared libraries and data files required by the program
1728 must be available on filesystems which are mounted in the
1729 correct places.  It is the caller's responsibility to ensure
1730 all filesystems that are needed are mounted at the right
1731 locations.");
1732
1733   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1734    [InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 1"]], ["Result1"]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 2"]], ["Result2"]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 7"]], []);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 8"]], [""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 9"]], ["";""]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1774     InitBasicFS, Always, TestOutputList (
1775       [["upload"; "test-command"; "/test-command"];
1776        ["chmod"; "0o755"; "/test-command"];
1777        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1778    "run a command, returning lines",
1779    "\
1780 This is the same as C<guestfs_command>, but splits the
1781 result into a list of lines.
1782
1783 See also: C<guestfs_sh_lines>");
1784
1785   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1786    [InitISOFS, Always, TestOutputStruct (
1787       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1788    "get file information",
1789    "\
1790 Returns file information for the given C<path>.
1791
1792 This is the same as the C<stat(2)> system call.");
1793
1794   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1795    [InitISOFS, Always, TestOutputStruct (
1796       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1797    "get file information for a symbolic link",
1798    "\
1799 Returns file information for the given C<path>.
1800
1801 This is the same as C<guestfs_stat> except that if C<path>
1802 is a symbolic link, then the link is stat-ed, not the file it
1803 refers to.
1804
1805 This is the same as the C<lstat(2)> system call.");
1806
1807   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1808    [InitISOFS, Always, TestOutputStruct (
1809       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1810    "get file system statistics",
1811    "\
1812 Returns file system statistics for any mounted file system.
1813 C<path> should be a file or directory in the mounted file system
1814 (typically it is the mount point itself, but it doesn't need to be).
1815
1816 This is the same as the C<statvfs(2)> system call.");
1817
1818   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1819    [], (* XXX test *)
1820    "get ext2/ext3/ext4 superblock details",
1821    "\
1822 This returns the contents of the ext2, ext3 or ext4 filesystem
1823 superblock on C<device>.
1824
1825 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1826 manpage for more details.  The list of fields returned isn't
1827 clearly defined, and depends on both the version of C<tune2fs>
1828 that libguestfs was built against, and the filesystem itself.");
1829
1830   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1831    [InitEmpty, Always, TestOutputTrue (
1832       [["blockdev_setro"; "/dev/sda"];
1833        ["blockdev_getro"; "/dev/sda"]])],
1834    "set block device to read-only",
1835    "\
1836 Sets the block device named C<device> to read-only.
1837
1838 This uses the L<blockdev(8)> command.");
1839
1840   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1841    [InitEmpty, Always, TestOutputFalse (
1842       [["blockdev_setrw"; "/dev/sda"];
1843        ["blockdev_getro"; "/dev/sda"]])],
1844    "set block device to read-write",
1845    "\
1846 Sets the block device named C<device> to read-write.
1847
1848 This uses the L<blockdev(8)> command.");
1849
1850   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1851    [InitEmpty, Always, TestOutputTrue (
1852       [["blockdev_setro"; "/dev/sda"];
1853        ["blockdev_getro"; "/dev/sda"]])],
1854    "is block device set to read-only",
1855    "\
1856 Returns a boolean indicating if the block device is read-only
1857 (true if read-only, false if not).
1858
1859 This uses the L<blockdev(8)> command.");
1860
1861   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1862    [InitEmpty, Always, TestOutputInt (
1863       [["blockdev_getss"; "/dev/sda"]], 512)],
1864    "get sectorsize of block device",
1865    "\
1866 This returns the size of sectors on a block device.
1867 Usually 512, but can be larger for modern devices.
1868
1869 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1870 for that).
1871
1872 This uses the L<blockdev(8)> command.");
1873
1874   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1875    [InitEmpty, Always, TestOutputInt (
1876       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1877    "get blocksize of block device",
1878    "\
1879 This returns the block size of a device.
1880
1881 (Note this is different from both I<size in blocks> and
1882 I<filesystem block size>).
1883
1884 This uses the L<blockdev(8)> command.");
1885
1886   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1887    [], (* XXX test *)
1888    "set blocksize of block device",
1889    "\
1890 This sets the block size of a device.
1891
1892 (Note this is different from both I<size in blocks> and
1893 I<filesystem block size>).
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1900    "get total size of device in 512-byte sectors",
1901    "\
1902 This returns the size of the device in units of 512-byte sectors
1903 (even if the sectorsize isn't 512 bytes ... weird).
1904
1905 See also C<guestfs_blockdev_getss> for the real sector size of
1906 the device, and C<guestfs_blockdev_getsize64> for the more
1907 useful I<size in bytes>.
1908
1909 This uses the L<blockdev(8)> command.");
1910
1911   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1912    [InitEmpty, Always, TestOutputInt (
1913       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1914    "get total size of device in bytes",
1915    "\
1916 This returns the size of the device in bytes.
1917
1918 See also C<guestfs_blockdev_getsz>.
1919
1920 This uses the L<blockdev(8)> command.");
1921
1922   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1923    [InitEmpty, Always, TestRun
1924       [["blockdev_flushbufs"; "/dev/sda"]]],
1925    "flush device buffers",
1926    "\
1927 This tells the kernel to flush internal buffers associated
1928 with C<device>.
1929
1930 This uses the L<blockdev(8)> command.");
1931
1932   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1933    [InitEmpty, Always, TestRun
1934       [["blockdev_rereadpt"; "/dev/sda"]]],
1935    "reread partition table",
1936    "\
1937 Reread the partition table on C<device>.
1938
1939 This uses the L<blockdev(8)> command.");
1940
1941   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1942    [InitBasicFS, Always, TestOutput (
1943       (* Pick a file from cwd which isn't likely to change. *)
1944       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945        ["checksum"; "md5"; "/COPYING.LIB"]],
1946       Digest.to_hex (Digest.file "COPYING.LIB"))],
1947    "upload a file from the local machine",
1948    "\
1949 Upload local file C<filename> to C<remotefilename> on the
1950 filesystem.
1951
1952 C<filename> can also be a named pipe.
1953
1954 See also C<guestfs_download>.");
1955
1956   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1957    [InitBasicFS, Always, TestOutput (
1958       (* Pick a file from cwd which isn't likely to change. *)
1959       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1960        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1961        ["upload"; "testdownload.tmp"; "/upload"];
1962        ["checksum"; "md5"; "/upload"]],
1963       Digest.to_hex (Digest.file "COPYING.LIB"))],
1964    "download a file to the local machine",
1965    "\
1966 Download file C<remotefilename> and save it as C<filename>
1967 on the local machine.
1968
1969 C<filename> can also be a named pipe.
1970
1971 See also C<guestfs_upload>, C<guestfs_cat>.");
1972
1973   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1974    [InitISOFS, Always, TestOutput (
1975       [["checksum"; "crc"; "/known-3"]], "2891671662");
1976     InitISOFS, Always, TestLastFail (
1977       [["checksum"; "crc"; "/notexists"]]);
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1990    "compute MD5, SHAx or CRC checksum of file",
1991    "\
1992 This call computes the MD5, SHAx or CRC checksum of the
1993 file named C<path>.
1994
1995 The type of checksum to compute is given by the C<csumtype>
1996 parameter which must have one of the following values:
1997
1998 =over 4
1999
2000 =item C<crc>
2001
2002 Compute the cyclic redundancy check (CRC) specified by POSIX
2003 for the C<cksum> command.
2004
2005 =item C<md5>
2006
2007 Compute the MD5 hash (using the C<md5sum> program).
2008
2009 =item C<sha1>
2010
2011 Compute the SHA1 hash (using the C<sha1sum> program).
2012
2013 =item C<sha224>
2014
2015 Compute the SHA224 hash (using the C<sha224sum> program).
2016
2017 =item C<sha256>
2018
2019 Compute the SHA256 hash (using the C<sha256sum> program).
2020
2021 =item C<sha384>
2022
2023 Compute the SHA384 hash (using the C<sha384sum> program).
2024
2025 =item C<sha512>
2026
2027 Compute the SHA512 hash (using the C<sha512sum> program).
2028
2029 =back
2030
2031 The checksum is returned as a printable string.");
2032
2033   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2034    [InitBasicFS, Always, TestOutput (
2035       [["tar_in"; "../images/helloworld.tar"; "/"];
2036        ["cat"; "/hello"]], "hello\n")],
2037    "unpack tarfile to directory",
2038    "\
2039 This command uploads and unpacks local file C<tarfile> (an
2040 I<uncompressed> tar file) into C<directory>.
2041
2042 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2043
2044   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2045    [],
2046    "pack directory into tarfile",
2047    "\
2048 This command packs the contents of C<directory> and downloads
2049 it to local file C<tarfile>.
2050
2051 To download a compressed tarball, use C<guestfs_tgz_out>.");
2052
2053   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2054    [InitBasicFS, Always, TestOutput (
2055       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2056        ["cat"; "/hello"]], "hello\n")],
2057    "unpack compressed tarball to directory",
2058    "\
2059 This command uploads and unpacks local file C<tarball> (a
2060 I<gzip compressed> tar file) into C<directory>.
2061
2062 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2063
2064   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2065    [],
2066    "pack directory into compressed tarball",
2067    "\
2068 This command packs the contents of C<directory> and downloads
2069 it to local file C<tarball>.
2070
2071 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2072
2073   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2074    [InitBasicFS, Always, TestLastFail (
2075       [["umount"; "/"];
2076        ["mount_ro"; "/dev/sda1"; "/"];
2077        ["touch"; "/new"]]);
2078     InitBasicFS, Always, TestOutput (
2079       [["write_file"; "/new"; "data"; "0"];
2080        ["umount"; "/"];
2081        ["mount_ro"; "/dev/sda1"; "/"];
2082        ["cat"; "/new"]], "data")],
2083    "mount a guest disk, read-only",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 mounts the filesystem with the read-only (I<-o ro>) flag.");
2087
2088   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2089    [],
2090    "mount a guest disk with mount options",
2091    "\
2092 This is the same as the C<guestfs_mount> command, but it
2093 allows you to set the mount options as for the
2094 L<mount(8)> I<-o> flag.
2095
2096 If the C<options> parameter is an empty string, then
2097 no options are passed (all options default to whatever
2098 the filesystem uses).");
2099
2100   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2101    [],
2102    "mount a guest disk with mount options and vfstype",
2103    "\
2104 This is the same as the C<guestfs_mount> command, but it
2105 allows you to set both the mount options and the vfstype
2106 as for the L<mount(8)> I<-o> and I<-t> flags.");
2107
2108   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2109    [],
2110    "debugging and internals",
2111    "\
2112 The C<guestfs_debug> command exposes some internals of
2113 C<guestfsd> (the guestfs daemon) that runs inside the
2114 qemu subprocess.
2115
2116 There is no comprehensive help for this command.  You have
2117 to look at the file C<daemon/debug.c> in the libguestfs source
2118 to find out what you can do.");
2119
2120   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2121    [InitEmpty, Always, TestOutputList (
2122       [["part_disk"; "/dev/sda"; "mbr"];
2123        ["pvcreate"; "/dev/sda1"];
2124        ["vgcreate"; "VG"; "/dev/sda1"];
2125        ["lvcreate"; "LV1"; "VG"; "50"];
2126        ["lvcreate"; "LV2"; "VG"; "50"];
2127        ["lvremove"; "/dev/VG/LV1"];
2128        ["lvs"]], ["/dev/VG/LV2"]);
2129     InitEmpty, Always, TestOutputList (
2130       [["part_disk"; "/dev/sda"; "mbr"];
2131        ["pvcreate"; "/dev/sda1"];
2132        ["vgcreate"; "VG"; "/dev/sda1"];
2133        ["lvcreate"; "LV1"; "VG"; "50"];
2134        ["lvcreate"; "LV2"; "VG"; "50"];
2135        ["lvremove"; "/dev/VG"];
2136        ["lvs"]], []);
2137     InitEmpty, Always, TestOutputList (
2138       [["part_disk"; "/dev/sda"; "mbr"];
2139        ["pvcreate"; "/dev/sda1"];
2140        ["vgcreate"; "VG"; "/dev/sda1"];
2141        ["lvcreate"; "LV1"; "VG"; "50"];
2142        ["lvcreate"; "LV2"; "VG"; "50"];
2143        ["lvremove"; "/dev/VG"];
2144        ["vgs"]], ["VG"])],
2145    "remove an LVM logical volume",
2146    "\
2147 Remove an LVM logical volume C<device>, where C<device> is
2148 the path to the LV, such as C</dev/VG/LV>.
2149
2150 You can also remove all LVs in a volume group by specifying
2151 the VG name, C</dev/VG>.");
2152
2153   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2154    [InitEmpty, Always, TestOutputList (
2155       [["part_disk"; "/dev/sda"; "mbr"];
2156        ["pvcreate"; "/dev/sda1"];
2157        ["vgcreate"; "VG"; "/dev/sda1"];
2158        ["lvcreate"; "LV1"; "VG"; "50"];
2159        ["lvcreate"; "LV2"; "VG"; "50"];
2160        ["vgremove"; "VG"];
2161        ["lvs"]], []);
2162     InitEmpty, Always, TestOutputList (
2163       [["part_disk"; "/dev/sda"; "mbr"];
2164        ["pvcreate"; "/dev/sda1"];
2165        ["vgcreate"; "VG"; "/dev/sda1"];
2166        ["lvcreate"; "LV1"; "VG"; "50"];
2167        ["lvcreate"; "LV2"; "VG"; "50"];
2168        ["vgremove"; "VG"];
2169        ["vgs"]], [])],
2170    "remove an LVM volume group",
2171    "\
2172 Remove an LVM volume group C<vgname>, (for example C<VG>).
2173
2174 This also forcibly removes all logical volumes in the volume
2175 group (if any).");
2176
2177   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2178    [InitEmpty, Always, TestOutputListOfDevices (
2179       [["part_disk"; "/dev/sda"; "mbr"];
2180        ["pvcreate"; "/dev/sda1"];
2181        ["vgcreate"; "VG"; "/dev/sda1"];
2182        ["lvcreate"; "LV1"; "VG"; "50"];
2183        ["lvcreate"; "LV2"; "VG"; "50"];
2184        ["vgremove"; "VG"];
2185        ["pvremove"; "/dev/sda1"];
2186        ["lvs"]], []);
2187     InitEmpty, Always, TestOutputListOfDevices (
2188       [["part_disk"; "/dev/sda"; "mbr"];
2189        ["pvcreate"; "/dev/sda1"];
2190        ["vgcreate"; "VG"; "/dev/sda1"];
2191        ["lvcreate"; "LV1"; "VG"; "50"];
2192        ["lvcreate"; "LV2"; "VG"; "50"];
2193        ["vgremove"; "VG"];
2194        ["pvremove"; "/dev/sda1"];
2195        ["vgs"]], []);
2196     InitEmpty, Always, TestOutputListOfDevices (
2197       [["part_disk"; "/dev/sda"; "mbr"];
2198        ["pvcreate"; "/dev/sda1"];
2199        ["vgcreate"; "VG"; "/dev/sda1"];
2200        ["lvcreate"; "LV1"; "VG"; "50"];
2201        ["lvcreate"; "LV2"; "VG"; "50"];
2202        ["vgremove"; "VG"];
2203        ["pvremove"; "/dev/sda1"];
2204        ["pvs"]], [])],
2205    "remove an LVM physical volume",
2206    "\
2207 This wipes a physical volume C<device> so that LVM will no longer
2208 recognise it.
2209
2210 The implementation uses the C<pvremove> command which refuses to
2211 wipe physical volumes that contain any volume groups, so you have
2212 to remove those first.");
2213
2214   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2215    [InitBasicFS, Always, TestOutput (
2216       [["set_e2label"; "/dev/sda1"; "testlabel"];
2217        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2218    "set the ext2/3/4 filesystem label",
2219    "\
2220 This sets the ext2/3/4 filesystem label of the filesystem on
2221 C<device> to C<label>.  Filesystem labels are limited to
2222 16 characters.
2223
2224 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2225 to return the existing label on a filesystem.");
2226
2227   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2228    [],
2229    "get the ext2/3/4 filesystem label",
2230    "\
2231 This returns the ext2/3/4 filesystem label of the filesystem on
2232 C<device>.");
2233
2234   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2235    (let uuid = uuidgen () in
2236     [InitBasicFS, Always, TestOutput (
2237        [["set_e2uuid"; "/dev/sda1"; uuid];
2238         ["get_e2uuid"; "/dev/sda1"]], uuid);
2239      InitBasicFS, Always, TestOutput (
2240        [["set_e2uuid"; "/dev/sda1"; "clear"];
2241         ["get_e2uuid"; "/dev/sda1"]], "");
2242      (* We can't predict what UUIDs will be, so just check the commands run. *)
2243      InitBasicFS, Always, TestRun (
2244        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2245      InitBasicFS, Always, TestRun (
2246        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2247    "set the ext2/3/4 filesystem UUID",
2248    "\
2249 This sets the ext2/3/4 filesystem UUID of the filesystem on
2250 C<device> to C<uuid>.  The format of the UUID and alternatives
2251 such as C<clear>, C<random> and C<time> are described in the
2252 L<tune2fs(8)> manpage.
2253
2254 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2255 to return the existing UUID of a filesystem.");
2256
2257   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2258    [],
2259    "get the ext2/3/4 filesystem UUID",
2260    "\
2261 This returns the ext2/3/4 filesystem UUID of the filesystem on
2262 C<device>.");
2263
2264   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2265    [InitBasicFS, Always, TestOutputInt (
2266       [["umount"; "/dev/sda1"];
2267        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2268     InitBasicFS, Always, TestOutputInt (
2269       [["umount"; "/dev/sda1"];
2270        ["zero"; "/dev/sda1"];
2271        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2272    "run the filesystem checker",
2273    "\
2274 This runs the filesystem checker (fsck) on C<device> which
2275 should have filesystem type C<fstype>.
2276
2277 The returned integer is the status.  See L<fsck(8)> for the
2278 list of status codes from C<fsck>.
2279
2280 Notes:
2281
2282 =over 4
2283
2284 =item *
2285
2286 Multiple status codes can be summed together.
2287
2288 =item *
2289
2290 A non-zero return code can mean \"success\", for example if
2291 errors have been corrected on the filesystem.
2292
2293 =item *
2294
2295 Checking or repairing NTFS volumes is not supported
2296 (by linux-ntfs).
2297
2298 =back
2299
2300 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2301
2302   ("zero", (RErr, [Device "device"]), 85, [],
2303    [InitBasicFS, Always, TestOutput (
2304       [["umount"; "/dev/sda1"];
2305        ["zero"; "/dev/sda1"];
2306        ["file"; "/dev/sda1"]], "data")],
2307    "write zeroes to the device",
2308    "\
2309 This command writes zeroes over the first few blocks of C<device>.
2310
2311 How many blocks are zeroed isn't specified (but it's I<not> enough
2312 to securely wipe the device).  It should be sufficient to remove
2313 any partition tables, filesystem superblocks and so on.
2314
2315 See also: C<guestfs_scrub_device>.");
2316
2317   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2318    (* Test disabled because grub-install incompatible with virtio-blk driver.
2319     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2320     *)
2321    [InitBasicFS, Disabled, TestOutputTrue (
2322       [["grub_install"; "/"; "/dev/sda1"];
2323        ["is_dir"; "/boot"]])],
2324    "install GRUB",
2325    "\
2326 This command installs GRUB (the Grand Unified Bootloader) on
2327 C<device>, with the root directory being C<root>.");
2328
2329   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2330    [InitBasicFS, Always, TestOutput (
2331       [["write_file"; "/old"; "file content"; "0"];
2332        ["cp"; "/old"; "/new"];
2333        ["cat"; "/new"]], "file content");
2334     InitBasicFS, Always, TestOutputTrue (
2335       [["write_file"; "/old"; "file content"; "0"];
2336        ["cp"; "/old"; "/new"];
2337        ["is_file"; "/old"]]);
2338     InitBasicFS, Always, TestOutput (
2339       [["write_file"; "/old"; "file content"; "0"];
2340        ["mkdir"; "/dir"];
2341        ["cp"; "/old"; "/dir/new"];
2342        ["cat"; "/dir/new"]], "file content")],
2343    "copy a file",
2344    "\
2345 This copies a file from C<src> to C<dest> where C<dest> is
2346 either a destination filename or destination directory.");
2347
2348   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2349    [InitBasicFS, Always, TestOutput (
2350       [["mkdir"; "/olddir"];
2351        ["mkdir"; "/newdir"];
2352        ["write_file"; "/olddir/file"; "file content"; "0"];
2353        ["cp_a"; "/olddir"; "/newdir"];
2354        ["cat"; "/newdir/olddir/file"]], "file content")],
2355    "copy a file or directory recursively",
2356    "\
2357 This copies a file or directory from C<src> to C<dest>
2358 recursively using the C<cp -a> command.");
2359
2360   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2361    [InitBasicFS, Always, TestOutput (
2362       [["write_file"; "/old"; "file content"; "0"];
2363        ["mv"; "/old"; "/new"];
2364        ["cat"; "/new"]], "file content");
2365     InitBasicFS, Always, TestOutputFalse (
2366       [["write_file"; "/old"; "file content"; "0"];
2367        ["mv"; "/old"; "/new"];
2368        ["is_file"; "/old"]])],
2369    "move a file",
2370    "\
2371 This moves a file from C<src> to C<dest> where C<dest> is
2372 either a destination filename or destination directory.");
2373
2374   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2375    [InitEmpty, Always, TestRun (
2376       [["drop_caches"; "3"]])],
2377    "drop kernel page cache, dentries and inodes",
2378    "\
2379 This instructs the guest kernel to drop its page cache,
2380 and/or dentries and inode caches.  The parameter C<whattodrop>
2381 tells the kernel what precisely to drop, see
2382 L<http://linux-mm.org/Drop_Caches>
2383
2384 Setting C<whattodrop> to 3 should drop everything.
2385
2386 This automatically calls L<sync(2)> before the operation,
2387 so that the maximum guest memory is freed.");
2388
2389   ("dmesg", (RString "kmsgs", []), 91, [],
2390    [InitEmpty, Always, TestRun (
2391       [["dmesg"]])],
2392    "return kernel messages",
2393    "\
2394 This returns the kernel messages (C<dmesg> output) from
2395 the guest kernel.  This is sometimes useful for extended
2396 debugging of problems.
2397
2398 Another way to get the same information is to enable
2399 verbose messages with C<guestfs_set_verbose> or by setting
2400 the environment variable C<LIBGUESTFS_DEBUG=1> before
2401 running the program.");
2402
2403   ("ping_daemon", (RErr, []), 92, [],
2404    [InitEmpty, Always, TestRun (
2405       [["ping_daemon"]])],
2406    "ping the guest daemon",
2407    "\
2408 This is a test probe into the guestfs daemon running inside
2409 the qemu subprocess.  Calling this function checks that the
2410 daemon responds to the ping message, without affecting the daemon
2411 or attached block device(s) in any other way.");
2412
2413   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2414    [InitBasicFS, Always, TestOutputTrue (
2415       [["write_file"; "/file1"; "contents of a file"; "0"];
2416        ["cp"; "/file1"; "/file2"];
2417        ["equal"; "/file1"; "/file2"]]);
2418     InitBasicFS, Always, TestOutputFalse (
2419       [["write_file"; "/file1"; "contents of a file"; "0"];
2420        ["write_file"; "/file2"; "contents of another file"; "0"];
2421        ["equal"; "/file1"; "/file2"]]);
2422     InitBasicFS, Always, TestLastFail (
2423       [["equal"; "/file1"; "/file2"]])],
2424    "test if two files have equal contents",
2425    "\
2426 This compares the two files C<file1> and C<file2> and returns
2427 true if their content is exactly equal, or false otherwise.
2428
2429 The external L<cmp(1)> program is used for the comparison.");
2430
2431   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2432    [InitISOFS, Always, TestOutputList (
2433       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2434     InitISOFS, Always, TestOutputList (
2435       [["strings"; "/empty"]], [])],
2436    "print the printable strings in a file",
2437    "\
2438 This runs the L<strings(1)> command on a file and returns
2439 the list of printable strings found.");
2440
2441   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2442    [InitISOFS, Always, TestOutputList (
2443       [["strings_e"; "b"; "/known-5"]], []);
2444     InitBasicFS, Disabled, TestOutputList (
2445       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2446        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2447    "print the printable strings in a file",
2448    "\
2449 This is like the C<guestfs_strings> command, but allows you to
2450 specify the encoding of strings that are looked for in
2451 the source file C<path>.
2452
2453 Allowed encodings are:
2454
2455 =over 4
2456
2457 =item s
2458
2459 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2460 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2461
2462 =item S
2463
2464 Single 8-bit-byte characters.
2465
2466 =item b
2467
2468 16-bit big endian strings such as those encoded in
2469 UTF-16BE or UCS-2BE.
2470
2471 =item l (lower case letter L)
2472
2473 16-bit little endian such as UTF-16LE and UCS-2LE.
2474 This is useful for examining binaries in Windows guests.
2475
2476 =item B
2477
2478 32-bit big endian such as UCS-4BE.
2479
2480 =item L
2481
2482 32-bit little endian such as UCS-4LE.
2483
2484 =back
2485
2486 The returned strings are transcoded to UTF-8.");
2487
2488   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2489    [InitISOFS, Always, TestOutput (
2490       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2491     (* Test for RHBZ#501888c2 regression which caused large hexdump
2492      * commands to segfault.
2493      *)
2494     InitISOFS, Always, TestRun (
2495       [["hexdump"; "/100krandom"]])],
2496    "dump a file in hexadecimal",
2497    "\
2498 This runs C<hexdump -C> on the given C<path>.  The result is
2499 the human-readable, canonical hex dump of the file.");
2500
2501   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2502    [InitNone, Always, TestOutput (
2503       [["part_disk"; "/dev/sda"; "mbr"];
2504        ["mkfs"; "ext3"; "/dev/sda1"];
2505        ["mount_options"; ""; "/dev/sda1"; "/"];
2506        ["write_file"; "/new"; "test file"; "0"];
2507        ["umount"; "/dev/sda1"];
2508        ["zerofree"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["cat"; "/new"]], "test file")],
2511    "zero unused inodes and disk blocks on ext2/3 filesystem",
2512    "\
2513 This runs the I<zerofree> program on C<device>.  This program
2514 claims to zero unused inodes and disk blocks on an ext2/3
2515 filesystem, thus making it possible to compress the filesystem
2516 more effectively.
2517
2518 You should B<not> run this program if the filesystem is
2519 mounted.
2520
2521 It is possible that using this program can damage the filesystem
2522 or data on the filesystem.");
2523
2524   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2525    [],
2526    "resize an LVM physical volume",
2527    "\
2528 This resizes (expands or shrinks) an existing LVM physical
2529 volume to match the new size of the underlying device.");
2530
2531   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2532                        Int "cyls"; Int "heads"; Int "sectors";
2533                        String "line"]), 99, [DangerWillRobinson],
2534    [],
2535    "modify a single partition on a block device",
2536    "\
2537 This runs L<sfdisk(8)> option to modify just the single
2538 partition C<n> (note: C<n> counts from 1).
2539
2540 For other parameters, see C<guestfs_sfdisk>.  You should usually
2541 pass C<0> for the cyls/heads/sectors parameters.
2542
2543 See also: C<guestfs_part_add>");
2544
2545   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2546    [],
2547    "display the partition table",
2548    "\
2549 This displays the partition table on C<device>, in the
2550 human-readable output of the L<sfdisk(8)> command.  It is
2551 not intended to be parsed.
2552
2553 See also: C<guestfs_part_list>");
2554
2555   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2556    [],
2557    "display the kernel geometry",
2558    "\
2559 This displays the kernel's idea of the geometry of C<device>.
2560
2561 The result is in human-readable format, and not designed to
2562 be parsed.");
2563
2564   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2565    [],
2566    "display the disk geometry from the partition table",
2567    "\
2568 This displays the disk geometry of C<device> read from the
2569 partition table.  Especially in the case where the underlying
2570 block device has been resized, this can be different from the
2571 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2572
2573 The result is in human-readable format, and not designed to
2574 be parsed.");
2575
2576   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2577    [],
2578    "activate or deactivate all volume groups",
2579    "\
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in all volume groups.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2584 then those devices disappear.
2585
2586 This command is the same as running C<vgchange -a y|n>");
2587
2588   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2589    [],
2590    "activate or deactivate some volume groups",
2591    "\
2592 This command activates or (if C<activate> is false) deactivates
2593 all logical volumes in the listed volume groups C<volgroups>.
2594 If activated, then they are made known to the
2595 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2596 then those devices disappear.
2597
2598 This command is the same as running C<vgchange -a y|n volgroups...>
2599
2600 Note that if C<volgroups> is an empty list then B<all> volume groups
2601 are activated or deactivated.");
2602
2603   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2604    [InitNone, Always, TestOutput (
2605       [["part_disk"; "/dev/sda"; "mbr"];
2606        ["pvcreate"; "/dev/sda1"];
2607        ["vgcreate"; "VG"; "/dev/sda1"];
2608        ["lvcreate"; "LV"; "VG"; "10"];
2609        ["mkfs"; "ext2"; "/dev/VG/LV"];
2610        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2611        ["write_file"; "/new"; "test content"; "0"];
2612        ["umount"; "/"];
2613        ["lvresize"; "/dev/VG/LV"; "20"];
2614        ["e2fsck_f"; "/dev/VG/LV"];
2615        ["resize2fs"; "/dev/VG/LV"];
2616        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2617        ["cat"; "/new"]], "test content");
2618     InitNone, Always, TestRun (
2619       (* Make an LV smaller to test RHBZ#587484. *)
2620       [["part_disk"; "/dev/sda"; "mbr"];
2621        ["pvcreate"; "/dev/sda1"];
2622        ["vgcreate"; "VG"; "/dev/sda1"];
2623        ["lvcreate"; "LV"; "VG"; "20"];
2624        ["lvresize"; "/dev/VG/LV"; "10"]])],
2625    "resize an LVM logical volume",
2626    "\
2627 This resizes (expands or shrinks) an existing LVM logical
2628 volume to C<mbytes>.  When reducing, data in the reduced part
2629 is lost.");
2630
2631   ("resize2fs", (RErr, [Device "device"]), 106, [],
2632    [], (* lvresize tests this *)
2633    "resize an ext2/ext3 filesystem",
2634    "\
2635 This resizes an ext2 or ext3 filesystem to match the size of
2636 the underlying device.
2637
2638 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2639 on the C<device> before calling this command.  For unknown reasons
2640 C<resize2fs> sometimes gives an error about this and sometimes not.
2641 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2642 calling this function.");
2643
2644   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2645    [InitBasicFS, Always, TestOutputList (
2646       [["find"; "/"]], ["lost+found"]);
2647     InitBasicFS, Always, TestOutputList (
2648       [["touch"; "/a"];
2649        ["mkdir"; "/b"];
2650        ["touch"; "/b/c"];
2651        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2652     InitBasicFS, Always, TestOutputList (
2653       [["mkdir_p"; "/a/b/c"];
2654        ["touch"; "/a/b/c/d"];
2655        ["find"; "/a/b/"]], ["c"; "c/d"])],
2656    "find all files and directories",
2657    "\
2658 This command lists out all files and directories, recursively,
2659 starting at C<directory>.  It is essentially equivalent to
2660 running the shell command C<find directory -print> but some
2661 post-processing happens on the output, described below.
2662
2663 This returns a list of strings I<without any prefix>.  Thus
2664 if the directory structure was:
2665
2666  /tmp/a
2667  /tmp/b
2668  /tmp/c/d
2669
2670 then the returned list from C<guestfs_find> C</tmp> would be
2671 4 elements:
2672
2673  a
2674  b
2675  c
2676  c/d
2677
2678 If C<directory> is not a directory, then this command returns
2679 an error.
2680
2681 The returned list is sorted.
2682
2683 See also C<guestfs_find0>.");
2684
2685   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2686    [], (* lvresize tests this *)
2687    "check an ext2/ext3 filesystem",
2688    "\
2689 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2690 filesystem checker on C<device>, noninteractively (C<-p>),
2691 even if the filesystem appears to be clean (C<-f>).
2692
2693 This command is only needed because of C<guestfs_resize2fs>
2694 (q.v.).  Normally you should use C<guestfs_fsck>.");
2695
2696   ("sleep", (RErr, [Int "secs"]), 109, [],
2697    [InitNone, Always, TestRun (
2698       [["sleep"; "1"]])],
2699    "sleep for some seconds",
2700    "\
2701 Sleep for C<secs> seconds.");
2702
2703   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2704    [InitNone, Always, TestOutputInt (
2705       [["part_disk"; "/dev/sda"; "mbr"];
2706        ["mkfs"; "ntfs"; "/dev/sda1"];
2707        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2708     InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ext2"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2712    "probe NTFS volume",
2713    "\
2714 This command runs the L<ntfs-3g.probe(8)> command which probes
2715 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2716 be mounted read-write, and some cannot be mounted at all).
2717
2718 C<rw> is a boolean flag.  Set it to true if you want to test
2719 if the volume can be mounted read-write.  Set it to false if
2720 you want to test if the volume can be mounted read-only.
2721
2722 The return value is an integer which C<0> if the operation
2723 would succeed, or some non-zero value documented in the
2724 L<ntfs-3g.probe(8)> manual page.");
2725
2726   ("sh", (RString "output", [String "command"]), 111, [],
2727    [], (* XXX needs tests *)
2728    "run a command via the shell",
2729    "\
2730 This call runs a command from the guest filesystem via the
2731 guest's C</bin/sh>.
2732
2733 This is like C<guestfs_command>, but passes the command to:
2734
2735  /bin/sh -c \"command\"
2736
2737 Depending on the guest's shell, this usually results in
2738 wildcards being expanded, shell expressions being interpolated
2739 and so on.
2740
2741 All the provisos about C<guestfs_command> apply to this call.");
2742
2743   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2744    [], (* XXX needs tests *)
2745    "run a command via the shell returning lines",
2746    "\
2747 This is the same as C<guestfs_sh>, but splits the result
2748 into a list of lines.
2749
2750 See also: C<guestfs_command_lines>");
2751
2752   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2753    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2754     * code in stubs.c, since all valid glob patterns must start with "/".
2755     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2756     *)
2757    [InitBasicFS, Always, TestOutputList (
2758       [["mkdir_p"; "/a/b/c"];
2759        ["touch"; "/a/b/c/d"];
2760        ["touch"; "/a/b/c/e"];
2761        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2762     InitBasicFS, Always, TestOutputList (
2763       [["mkdir_p"; "/a/b/c"];
2764        ["touch"; "/a/b/c/d"];
2765        ["touch"; "/a/b/c/e"];
2766        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2767     InitBasicFS, Always, TestOutputList (
2768       [["mkdir_p"; "/a/b/c"];
2769        ["touch"; "/a/b/c/d"];
2770        ["touch"; "/a/b/c/e"];
2771        ["glob_expand"; "/a/*/x/*"]], [])],
2772    "expand a wildcard path",
2773    "\
2774 This command searches for all the pathnames matching
2775 C<pattern> according to the wildcard expansion rules
2776 used by the shell.
2777
2778 If no paths match, then this returns an empty list
2779 (note: not an error).
2780
2781 It is just a wrapper around the C L<glob(3)> function
2782 with flags C<GLOB_MARK|GLOB_BRACE>.
2783 See that manual page for more details.");
2784
2785   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2786    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2787       [["scrub_device"; "/dev/sdc"]])],
2788    "scrub (securely wipe) a device",
2789    "\
2790 This command writes patterns over C<device> to make data retrieval
2791 more difficult.
2792
2793 It is an interface to the L<scrub(1)> program.  See that
2794 manual page for more details.");
2795
2796   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2797    [InitBasicFS, Always, TestRun (
2798       [["write_file"; "/file"; "content"; "0"];
2799        ["scrub_file"; "/file"]])],
2800    "scrub (securely wipe) a file",
2801    "\
2802 This command writes patterns over a file to make data retrieval
2803 more difficult.
2804
2805 The file is I<removed> after scrubbing.
2806
2807 It is an interface to the L<scrub(1)> program.  See that
2808 manual page for more details.");
2809
2810   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2811    [], (* XXX needs testing *)
2812    "scrub (securely wipe) free space",
2813    "\
2814 This command creates the directory C<dir> and then fills it
2815 with files until the filesystem is full, and scrubs the files
2816 as for C<guestfs_scrub_file>, and deletes them.
2817 The intention is to scrub any free space on the partition
2818 containing C<dir>.
2819
2820 It is an interface to the L<scrub(1)> program.  See that
2821 manual page for more details.");
2822
2823   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2824    [InitBasicFS, Always, TestRun (
2825       [["mkdir"; "/tmp"];
2826        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2827    "create a temporary directory",
2828    "\
2829 This command creates a temporary directory.  The
2830 C<template> parameter should be a full pathname for the
2831 temporary directory name with the final six characters being
2832 \"XXXXXX\".
2833
2834 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2835 the second one being suitable for Windows filesystems.
2836
2837 The name of the temporary directory that was created
2838 is returned.
2839
2840 The temporary directory is created with mode 0700
2841 and is owned by root.
2842
2843 The caller is responsible for deleting the temporary
2844 directory and its contents after use.
2845
2846 See also: L<mkdtemp(3)>");
2847
2848   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2849    [InitISOFS, Always, TestOutputInt (
2850       [["wc_l"; "/10klines"]], 10000)],
2851    "count lines in a file",
2852    "\
2853 This command counts the lines in a file, using the
2854 C<wc -l> external command.");
2855
2856   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2857    [InitISOFS, Always, TestOutputInt (
2858       [["wc_w"; "/10klines"]], 10000)],
2859    "count words in a file",
2860    "\
2861 This command counts the words in a file, using the
2862 C<wc -w> external command.");
2863
2864   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2865    [InitISOFS, Always, TestOutputInt (
2866       [["wc_c"; "/100kallspaces"]], 102400)],
2867    "count characters in a file",
2868    "\
2869 This command counts the characters in a file, using the
2870 C<wc -c> external command.");
2871
2872   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2873    [InitISOFS, Always, TestOutputList (
2874       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2875    "return first 10 lines of a file",
2876    "\
2877 This command returns up to the first 10 lines of a file as
2878 a list of strings.");
2879
2880   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2881    [InitISOFS, Always, TestOutputList (
2882       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2883     InitISOFS, Always, TestOutputList (
2884       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2885     InitISOFS, Always, TestOutputList (
2886       [["head_n"; "0"; "/10klines"]], [])],
2887    "return first N lines of a file",
2888    "\
2889 If the parameter C<nrlines> is a positive number, this returns the first
2890 C<nrlines> lines of the file C<path>.
2891
2892 If the parameter C<nrlines> is a negative number, this returns lines
2893 from the file C<path>, excluding the last C<nrlines> lines.
2894
2895 If the parameter C<nrlines> is zero, this returns an empty list.");
2896
2897   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2898    [InitISOFS, Always, TestOutputList (
2899       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2900    "return last 10 lines of a file",
2901    "\
2902 This command returns up to the last 10 lines of a file as
2903 a list of strings.");
2904
2905   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2906    [InitISOFS, Always, TestOutputList (
2907       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2908     InitISOFS, Always, TestOutputList (
2909       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2910     InitISOFS, Always, TestOutputList (
2911       [["tail_n"; "0"; "/10klines"]], [])],
2912    "return last N lines of a file",
2913    "\
2914 If the parameter C<nrlines> is a positive number, this returns the last
2915 C<nrlines> lines of the file C<path>.
2916
2917 If the parameter C<nrlines> is a negative number, this returns lines
2918 from the file C<path>, starting with the C<-nrlines>th line.
2919
2920 If the parameter C<nrlines> is zero, this returns an empty list.");
2921
2922   ("df", (RString "output", []), 125, [],
2923    [], (* XXX Tricky to test because it depends on the exact format
2924         * of the 'df' command and other imponderables.
2925         *)
2926    "report file system disk space usage",
2927    "\
2928 This command runs the C<df> command to report disk space used.
2929
2930 This command is mostly useful for interactive sessions.  It
2931 is I<not> intended that you try to parse the output string.
2932 Use C<statvfs> from programs.");
2933
2934   ("df_h", (RString "output", []), 126, [],
2935    [], (* XXX Tricky to test because it depends on the exact format
2936         * of the 'df' command and other imponderables.
2937         *)
2938    "report file system disk space usage (human readable)",
2939    "\
2940 This command runs the C<df -h> command to report disk space used
2941 in human-readable format.
2942
2943 This command is mostly useful for interactive sessions.  It
2944 is I<not> intended that you try to parse the output string.
2945 Use C<statvfs> from programs.");
2946
2947   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2948    [InitISOFS, Always, TestOutputInt (
2949       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2950    "estimate file space usage",
2951    "\
2952 This command runs the C<du -s> command to estimate file space
2953 usage for C<path>.
2954
2955 C<path> can be a file or a directory.  If C<path> is a directory
2956 then the estimate includes the contents of the directory and all
2957 subdirectories (recursively).
2958
2959 The result is the estimated size in I<kilobytes>
2960 (ie. units of 1024 bytes).");
2961
2962   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2963    [InitISOFS, Always, TestOutputList (
2964       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2965    "list files in an initrd",
2966    "\
2967 This command lists out files contained in an initrd.
2968
2969 The files are listed without any initial C</> character.  The
2970 files are listed in the order they appear (not necessarily
2971 alphabetical).  Directory names are listed as separate items.
2972
2973 Old Linux kernels (2.4 and earlier) used a compressed ext2
2974 filesystem as initrd.  We I<only> support the newer initramfs
2975 format (compressed cpio files).");
2976
2977   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2978    [],
2979    "mount a file using the loop device",
2980    "\
2981 This command lets you mount C<file> (a filesystem image
2982 in a file) on a mount point.  It is entirely equivalent to
2983 the command C<mount -o loop file mountpoint>.");
2984
2985   ("mkswap", (RErr, [Device "device"]), 130, [],
2986    [InitEmpty, Always, TestRun (
2987       [["part_disk"; "/dev/sda"; "mbr"];
2988        ["mkswap"; "/dev/sda1"]])],
2989    "create a swap partition",
2990    "\
2991 Create a swap partition on C<device>.");
2992
2993   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2994    [InitEmpty, Always, TestRun (
2995       [["part_disk"; "/dev/sda"; "mbr"];
2996        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2997    "create a swap partition with a label",
2998    "\
2999 Create a swap partition on C<device> with label C<label>.
3000
3001 Note that you cannot attach a swap label to a block device
3002 (eg. C</dev/sda>), just to a partition.  This appears to be
3003 a limitation of the kernel or swap tools.");
3004
3005   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3006    (let uuid = uuidgen () in
3007     [InitEmpty, Always, TestRun (
3008        [["part_disk"; "/dev/sda"; "mbr"];
3009         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3010    "create a swap partition with an explicit UUID",
3011    "\
3012 Create a swap partition on C<device> with UUID C<uuid>.");
3013
3014   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3015    [InitBasicFS, Always, TestOutputStruct (
3016       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3017        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3018        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3019     InitBasicFS, Always, TestOutputStruct (
3020       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3021        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3022    "make block, character or FIFO devices",
3023    "\
3024 This call creates block or character special devices, or
3025 named pipes (FIFOs).
3026
3027 The C<mode> parameter should be the mode, using the standard
3028 constants.  C<devmajor> and C<devminor> are the
3029 device major and minor numbers, only used when creating block
3030 and character special devices.
3031
3032 Note that, just like L<mknod(2)>, the mode must be bitwise
3033 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3034 just creates a regular file).  These constants are
3035 available in the standard Linux header files, or you can use
3036 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3037 which are wrappers around this command which bitwise OR
3038 in the appropriate constant for you.
3039
3040 The mode actually set is affected by the umask.");
3041
3042   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3043    [InitBasicFS, Always, TestOutputStruct (
3044       [["mkfifo"; "0o777"; "/node"];
3045        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3046    "make FIFO (named pipe)",
3047    "\
3048 This call creates a FIFO (named pipe) called C<path> with
3049 mode C<mode>.  It is just a convenient wrapper around
3050 C<guestfs_mknod>.
3051
3052 The mode actually set is affected by the umask.");
3053
3054   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3055    [InitBasicFS, Always, TestOutputStruct (
3056       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3057        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3058    "make block device node",
3059    "\
3060 This call creates a block device node called C<path> with
3061 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3062 It is just a convenient wrapper around C<guestfs_mknod>.
3063
3064 The mode actually set is affected by the umask.");
3065
3066   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3067    [InitBasicFS, Always, TestOutputStruct (
3068       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3069        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3070    "make char device node",
3071    "\
3072 This call creates a char device node called C<path> with
3073 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3074 It is just a convenient wrapper around C<guestfs_mknod>.
3075
3076 The mode actually set is affected by the umask.");
3077
3078   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3079    [InitEmpty, Always, TestOutputInt (
3080       [["umask"; "0o22"]], 0o22)],
3081    "set file mode creation mask (umask)",
3082    "\
3083 This function sets the mask used for creating new files and
3084 device nodes to C<mask & 0777>.
3085
3086 Typical umask values would be C<022> which creates new files
3087 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3088 C<002> which creates new files with permissions like
3089 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3090
3091 The default umask is C<022>.  This is important because it
3092 means that directories and device nodes will be created with
3093 C<0644> or C<0755> mode even if you specify C<0777>.
3094
3095 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3096
3097 This call returns the previous umask.");
3098
3099   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3100    [],
3101    "read directories entries",
3102    "\
3103 This returns the list of directory entries in directory C<dir>.
3104
3105 All entries in the directory are returned, including C<.> and
3106 C<..>.  The entries are I<not> sorted, but returned in the same
3107 order as the underlying filesystem.
3108
3109 Also this call returns basic file type information about each
3110 file.  The C<ftyp> field will contain one of the following characters:
3111
3112 =over 4
3113
3114 =item 'b'
3115
3116 Block special
3117
3118 =item 'c'
3119
3120 Char special
3121
3122 =item 'd'
3123
3124 Directory
3125
3126 =item 'f'
3127
3128 FIFO (named pipe)
3129
3130 =item 'l'
3131
3132 Symbolic link
3133
3134 =item 'r'
3135
3136 Regular file
3137
3138 =item 's'
3139
3140 Socket
3141
3142 =item 'u'
3143
3144 Unknown file type
3145
3146 =item '?'
3147
3148 The L<readdir(3)> call returned a C<d_type> field with an
3149 unexpected value
3150
3151 =back
3152
3153 This function is primarily intended for use by programs.  To
3154 get a simple list of names, use C<guestfs_ls>.  To get a printable
3155 directory for human consumption, use C<guestfs_ll>.");
3156
3157   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3158    [],
3159    "create partitions on a block device",
3160    "\
3161 This is a simplified interface to the C<guestfs_sfdisk>
3162 command, where partition sizes are specified in megabytes
3163 only (rounded to the nearest cylinder) and you don't need
3164 to specify the cyls, heads and sectors parameters which
3165 were rarely if ever used anyway.
3166
3167 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3168 and C<guestfs_part_disk>");
3169
3170   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3171    [],
3172    "determine file type inside a compressed file",
3173    "\
3174 This command runs C<file> after first decompressing C<path>
3175 using C<method>.
3176
3177 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3178
3179 Since 1.0.63, use C<guestfs_file> instead which can now
3180 process compressed files.");
3181
3182   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3183    [],
3184    "list extended attributes of a file or directory",
3185    "\
3186 This call lists the extended attributes of the file or directory
3187 C<path>.
3188
3189 At the system call level, this is a combination of the
3190 L<listxattr(2)> and L<getxattr(2)> calls.
3191
3192 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3193
3194   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3195    [],
3196    "list extended attributes of a file or directory",
3197    "\
3198 This is the same as C<guestfs_getxattrs>, but if C<path>
3199 is a symbolic link, then it returns the extended attributes
3200 of the link itself.");
3201
3202   ("setxattr", (RErr, [String "xattr";
3203                        String "val"; Int "vallen"; (* will be BufferIn *)
3204                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3205    [],
3206    "set extended attribute of a file or directory",
3207    "\
3208 This call sets the extended attribute named C<xattr>
3209 of the file C<path> to the value C<val> (of length C<vallen>).
3210 The value is arbitrary 8 bit data.
3211
3212 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3213
3214   ("lsetxattr", (RErr, [String "xattr";
3215                         String "val"; Int "vallen"; (* will be BufferIn *)
3216                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3217    [],
3218    "set extended attribute of a file or directory",
3219    "\
3220 This is the same as C<guestfs_setxattr>, but if C<path>
3221 is a symbolic link, then it sets an extended attribute
3222 of the link itself.");
3223
3224   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3225    [],
3226    "remove extended attribute of a file or directory",
3227    "\
3228 This call removes the extended attribute named C<xattr>
3229 of the file C<path>.
3230
3231 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3232
3233   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3234    [],
3235    "remove extended attribute of a file or directory",
3236    "\
3237 This is the same as C<guestfs_removexattr>, but if C<path>
3238 is a symbolic link, then it removes an extended attribute
3239 of the link itself.");
3240
3241   ("mountpoints", (RHashtable "mps", []), 147, [],
3242    [],
3243    "show mountpoints",
3244    "\
3245 This call is similar to C<guestfs_mounts>.  That call returns
3246 a list of devices.  This one returns a hash table (map) of
3247 device name to directory where the device is mounted.");
3248
3249   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3250    (* This is a special case: while you would expect a parameter
3251     * of type "Pathname", that doesn't work, because it implies
3252     * NEED_ROOT in the generated calling code in stubs.c, and
3253     * this function cannot use NEED_ROOT.
3254     *)
3255    [],
3256    "create a mountpoint",
3257    "\
3258 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3259 specialized calls that can be used to create extra mountpoints
3260 before mounting the first filesystem.
3261
3262 These calls are I<only> necessary in some very limited circumstances,
3263 mainly the case where you want to mount a mix of unrelated and/or
3264 read-only filesystems together.
3265
3266 For example, live CDs often contain a \"Russian doll\" nest of
3267 filesystems, an ISO outer layer, with a squashfs image inside, with
3268 an ext2/3 image inside that.  You can unpack this as follows
3269 in guestfish:
3270
3271  add-ro Fedora-11-i686-Live.iso
3272  run
3273  mkmountpoint /cd
3274  mkmountpoint /squash
3275  mkmountpoint /ext3
3276  mount /dev/sda /cd
3277  mount-loop /cd/LiveOS/squashfs.img /squash
3278  mount-loop /squash/LiveOS/ext3fs.img /ext3
3279
3280 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3281
3282   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3283    [],
3284    "remove a mountpoint",
3285    "\
3286 This calls removes a mountpoint that was previously created
3287 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3288 for full details.");
3289
3290   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3291    [InitISOFS, Always, TestOutputBuffer (
3292       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3293     (* Test various near large, large and too large files (RHBZ#589039). *)
3294     InitBasicFS, Always, TestLastFail (
3295       [["touch"; "/a"];
3296        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3297        ["read_file"; "/a"]]);
3298     InitBasicFS, Always, TestLastFail (
3299       [["touch"; "/a"];
3300        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3301        ["read_file"; "/a"]]);
3302     InitBasicFS, Always, TestLastFail (
3303       [["touch"; "/a"];
3304        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3305        ["read_file"; "/a"]])],
3306    "read a file",
3307    "\
3308 This calls returns the contents of the file C<path> as a
3309 buffer.
3310
3311 Unlike C<guestfs_cat>, this function can correctly
3312 handle files that contain embedded ASCII NUL characters.
3313 However unlike C<guestfs_download>, this function is limited
3314 in the total size of file that can be handled.");
3315
3316   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3317    [InitISOFS, Always, TestOutputList (
3318       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3319     InitISOFS, Always, TestOutputList (
3320       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3321    "return lines matching a pattern",
3322    "\
3323 This calls the external C<grep> program and returns the
3324 matching lines.");
3325
3326   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3327    [InitISOFS, Always, TestOutputList (
3328       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3329    "return lines matching a pattern",
3330    "\
3331 This calls the external C<egrep> program and returns the
3332 matching lines.");
3333
3334   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3335    [InitISOFS, Always, TestOutputList (
3336       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3337    "return lines matching a pattern",
3338    "\
3339 This calls the external C<fgrep> program and returns the
3340 matching lines.");
3341
3342   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3343    [InitISOFS, Always, TestOutputList (
3344       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3345    "return lines matching a pattern",
3346    "\
3347 This calls the external C<grep -i> program and returns the
3348 matching lines.");
3349
3350   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3351    [InitISOFS, Always, TestOutputList (
3352       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3353    "return lines matching a pattern",
3354    "\
3355 This calls the external C<egrep -i> program and returns the
3356 matching lines.");
3357
3358   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3359    [InitISOFS, Always, TestOutputList (
3360       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3361    "return lines matching a pattern",
3362    "\
3363 This calls the external C<fgrep -i> program and returns the
3364 matching lines.");
3365
3366   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3367    [InitISOFS, Always, TestOutputList (
3368       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3369    "return lines matching a pattern",
3370    "\
3371 This calls the external C<zgrep> program and returns the
3372 matching lines.");
3373
3374   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3375    [InitISOFS, Always, TestOutputList (
3376       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3377    "return lines matching a pattern",
3378    "\
3379 This calls the external C<zegrep> program and returns the
3380 matching lines.");
3381
3382   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3383    [InitISOFS, Always, TestOutputList (
3384       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3385    "return lines matching a pattern",
3386    "\
3387 This calls the external C<zfgrep> program and returns the
3388 matching lines.");
3389
3390   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3391    [InitISOFS, Always, TestOutputList (
3392       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3393    "return lines matching a pattern",
3394    "\
3395 This calls the external C<zgrep -i> program and returns the
3396 matching lines.");
3397
3398   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3399    [InitISOFS, Always, TestOutputList (
3400       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3401    "return lines matching a pattern",
3402    "\
3403 This calls the external C<zegrep -i> program and returns the
3404 matching lines.");
3405
3406   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3407    [InitISOFS, Always, TestOutputList (
3408       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3409    "return lines matching a pattern",
3410    "\
3411 This calls the external C<zfgrep -i> program and returns the
3412 matching lines.");
3413
3414   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3415    [InitISOFS, Always, TestOutput (
3416       [["realpath"; "/../directory"]], "/directory")],
3417    "canonicalized absolute pathname",
3418    "\
3419 Return the canonicalized absolute pathname of C<path>.  The
3420 returned path has no C<.>, C<..> or symbolic link path elements.");
3421
3422   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3423    [InitBasicFS, Always, TestOutputStruct (
3424       [["touch"; "/a"];
3425        ["ln"; "/a"; "/b"];
3426        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3427    "create a hard link",
3428    "\
3429 This command creates a hard link using the C<ln> command.");
3430
3431   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3432    [InitBasicFS, Always, TestOutputStruct (
3433       [["touch"; "/a"];
3434        ["touch"; "/b"];
3435        ["ln_f"; "/a"; "/b"];
3436        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3437    "create a hard link",
3438    "\
3439 This command creates a hard link using the C<ln -f> command.
3440 The C<-f> option removes the link (C<linkname>) if it exists already.");
3441
3442   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3443    [InitBasicFS, Always, TestOutputStruct (
3444       [["touch"; "/a"];
3445        ["ln_s"; "a"; "/b"];
3446        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3447    "create a symbolic link",
3448    "\
3449 This command creates a symbolic link using the C<ln -s> command.");
3450
3451   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3452    [InitBasicFS, Always, TestOutput (
3453       [["mkdir_p"; "/a/b"];
3454        ["touch"; "/a/b/c"];
3455        ["ln_sf"; "../d"; "/a/b/c"];
3456        ["readlink"; "/a/b/c"]], "../d")],
3457    "create a symbolic link",
3458    "\
3459 This command creates a symbolic link using the C<ln -sf> command,
3460 The C<-f> option removes the link (C<linkname>) if it exists already.");
3461
3462   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3463    [] (* XXX tested above *),
3464    "read the target of a symbolic link",
3465    "\
3466 This command reads the target of a symbolic link.");
3467
3468   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3469    [InitBasicFS, Always, TestOutputStruct (
3470       [["fallocate"; "/a"; "1000000"];
3471        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3472    "preallocate a file in the guest filesystem",
3473    "\
3474 This command preallocates a file (containing zero bytes) named
3475 C<path> of size C<len> bytes.  If the file exists already, it
3476 is overwritten.
3477
3478 Do not confuse this with the guestfish-specific
3479 C<alloc> command which allocates a file in the host and
3480 attaches it as a device.");
3481
3482   ("swapon_device", (RErr, [Device "device"]), 170, [],
3483    [InitPartition, Always, TestRun (
3484       [["mkswap"; "/dev/sda1"];
3485        ["swapon_device"; "/dev/sda1"];
3486        ["swapoff_device"; "/dev/sda1"]])],
3487    "enable swap on device",
3488    "\
3489 This command enables the libguestfs appliance to use the
3490 swap device or partition named C<device>.  The increased
3491 memory is made available for all commands, for example
3492 those run using C<guestfs_command> or C<guestfs_sh>.
3493
3494 Note that you should not swap to existing guest swap
3495 partitions unless you know what you are doing.  They may
3496 contain hibernation information, or other information that
3497 the guest doesn't want you to trash.  You also risk leaking
3498 information about the host to the guest this way.  Instead,
3499 attach a new host device to the guest and swap on that.");
3500
3501   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3502    [], (* XXX tested by swapon_device *)
3503    "disable swap on device",
3504    "\
3505 This command disables the libguestfs appliance swap
3506 device or partition named C<device>.
3507 See C<guestfs_swapon_device>.");
3508
3509   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3510    [InitBasicFS, Always, TestRun (
3511       [["fallocate"; "/swap"; "8388608"];
3512        ["mkswap_file"; "/swap"];
3513        ["swapon_file"; "/swap"];
3514        ["swapoff_file"; "/swap"]])],
3515    "enable swap on file",
3516    "\
3517 This command enables swap to a file.
3518 See C<guestfs_swapon_device> for other notes.");
3519
3520   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3521    [], (* XXX tested by swapon_file *)
3522    "disable swap on file",
3523    "\
3524 This command disables the libguestfs appliance swap on file.");
3525
3526   ("swapon_label", (RErr, [String "label"]), 174, [],
3527    [InitEmpty, Always, TestRun (
3528       [["part_disk"; "/dev/sdb"; "mbr"];
3529        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3530        ["swapon_label"; "swapit"];
3531        ["swapoff_label"; "swapit"];
3532        ["zero"; "/dev/sdb"];
3533        ["blockdev_rereadpt"; "/dev/sdb"]])],
3534    "enable swap on labeled swap partition",
3535    "\
3536 This command enables swap to a labeled swap partition.
3537 See C<guestfs_swapon_device> for other notes.");
3538
3539   ("swapoff_label", (RErr, [String "label"]), 175, [],
3540    [], (* XXX tested by swapon_label *)
3541    "disable swap on labeled swap partition",
3542    "\
3543 This command disables the libguestfs appliance swap on
3544 labeled swap partition.");
3545
3546   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3547    (let uuid = uuidgen () in
3548     [InitEmpty, Always, TestRun (
3549        [["mkswap_U"; uuid; "/dev/sdb"];
3550         ["swapon_uuid"; uuid];
3551         ["swapoff_uuid"; uuid]])]),
3552    "enable swap on swap partition by UUID",
3553    "\
3554 This command enables swap to a swap partition with the given UUID.
3555 See C<guestfs_swapon_device> for other notes.");
3556
3557   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3558    [], (* XXX tested by swapon_uuid *)
3559    "disable swap on swap partition by UUID",
3560    "\
3561 This command disables the libguestfs appliance swap partition
3562 with the given UUID.");
3563
3564   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3565    [InitBasicFS, Always, TestRun (
3566       [["fallocate"; "/swap"; "8388608"];
3567        ["mkswap_file"; "/swap"]])],
3568    "create a swap file",
3569    "\
3570 Create a swap file.
3571
3572 This command just writes a swap file signature to an existing
3573 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3574
3575   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3576    [InitISOFS, Always, TestRun (
3577       [["inotify_init"; "0"]])],
3578    "create an inotify handle",
3579    "\
3580 This command creates a new inotify handle.
3581 The inotify subsystem can be used to notify events which happen to
3582 objects in the guest filesystem.
3583
3584 C<maxevents> is the maximum number of events which will be
3585 queued up between calls to C<guestfs_inotify_read> or
3586 C<guestfs_inotify_files>.
3587 If this is passed as C<0>, then the kernel (or previously set)
3588 default is used.  For Linux 2.6.29 the default was 16384 events.
3589 Beyond this limit, the kernel throws away events, but records
3590 the fact that it threw them away by setting a flag
3591 C<IN_Q_OVERFLOW> in the returned structure list (see
3592 C<guestfs_inotify_read>).
3593
3594 Before any events are generated, you have to add some
3595 watches to the internal watch list.  See:
3596 C<guestfs_inotify_add_watch>,
3597 C<guestfs_inotify_rm_watch> and
3598 C<guestfs_inotify_watch_all>.
3599
3600 Queued up events should be read periodically by calling
3601 C<guestfs_inotify_read>
3602 (or C<guestfs_inotify_files> which is just a helpful
3603 wrapper around C<guestfs_inotify_read>).  If you don't
3604 read the events out often enough then you risk the internal
3605 queue overflowing.
3606
3607 The handle should be closed after use by calling
3608 C<guestfs_inotify_close>.  This also removes any
3609 watches automatically.
3610
3611 See also L<inotify(7)> for an overview of the inotify interface
3612 as exposed by the Linux kernel, which is roughly what we expose
3613 via libguestfs.  Note that there is one global inotify handle
3614 per libguestfs instance.");
3615
3616   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3617    [InitBasicFS, Always, TestOutputList (
3618       [["inotify_init"; "0"];
3619        ["inotify_add_watch"; "/"; "1073741823"];
3620        ["touch"; "/a"];
3621        ["touch"; "/b"];
3622        ["inotify_files"]], ["a"; "b"])],
3623    "add an inotify watch",
3624    "\
3625 Watch C<path> for the events listed in C<mask>.
3626
3627 Note that if C<path> is a directory then events within that
3628 directory are watched, but this does I<not> happen recursively
3629 (in subdirectories).
3630
3631 Note for non-C or non-Linux callers: the inotify events are
3632 defined by the Linux kernel ABI and are listed in
3633 C</usr/include/sys/inotify.h>.");
3634
3635   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3636    [],
3637    "remove an inotify watch",
3638    "\
3639 Remove a previously defined inotify watch.
3640 See C<guestfs_inotify_add_watch>.");
3641
3642   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3643    [],
3644    "return list of inotify events",
3645    "\
3646 Return the complete queue of events that have happened
3647 since the previous read call.
3648
3649 If no events have happened, this returns an empty list.
3650
3651 I<Note>: In order to make sure that all events have been
3652 read, you must call this function repeatedly until it
3653 returns an empty list.  The reason is that the call will
3654 read events up to the maximum appliance-to-host message
3655 size and leave remaining events in the queue.");
3656
3657   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3658    [],
3659    "return list of watched files that had events",
3660    "\
3661 This function is a helpful wrapper around C<guestfs_inotify_read>
3662 which just returns a list of pathnames of objects that were
3663 touched.  The returned pathnames are sorted and deduplicated.");
3664
3665   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3666    [],
3667    "close the inotify handle",
3668    "\
3669 This closes the inotify handle which was previously
3670 opened by inotify_init.  It removes all watches, throws
3671 away any pending events, and deallocates all resources.");
3672
3673   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3674    [],
3675    "set SELinux security context",
3676    "\
3677 This sets the SELinux security context of the daemon
3678 to the string C<context>.
3679
3680 See the documentation about SELINUX in L<guestfs(3)>.");
3681
3682   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3683    [],
3684    "get SELinux security context",
3685    "\
3686 This gets the SELinux security context of the daemon.
3687
3688 See the documentation about SELINUX in L<guestfs(3)>,
3689 and C<guestfs_setcon>");
3690
3691   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3692    [InitEmpty, Always, TestOutput (
3693       [["part_disk"; "/dev/sda"; "mbr"];
3694        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3695        ["mount_options"; ""; "/dev/sda1"; "/"];
3696        ["write_file"; "/new"; "new file contents"; "0"];
3697        ["cat"; "/new"]], "new file contents")],
3698    "make a filesystem with block size",
3699    "\
3700 This call is similar to C<guestfs_mkfs>, but it allows you to
3701 control the block size of the resulting filesystem.  Supported
3702 block sizes depend on the filesystem type, but typically they
3703 are C<1024>, C<2048> or C<4096> only.");
3704
3705   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3706    [InitEmpty, Always, TestOutput (
3707       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3708        ["mke2journal"; "4096"; "/dev/sda1"];
3709        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3710        ["mount_options"; ""; "/dev/sda2"; "/"];
3711        ["write_file"; "/new"; "new file contents"; "0"];
3712        ["cat"; "/new"]], "new file contents")],
3713    "make ext2/3/4 external journal",
3714    "\
3715 This creates an ext2 external journal on C<device>.  It is equivalent
3716 to the command:
3717
3718  mke2fs -O journal_dev -b blocksize device");
3719
3720   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3721    [InitEmpty, Always, TestOutput (
3722       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3723        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3724        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3725        ["mount_options"; ""; "/dev/sda2"; "/"];
3726        ["write_file"; "/new"; "new file contents"; "0"];
3727        ["cat"; "/new"]], "new file contents")],
3728    "make ext2/3/4 external journal with label",
3729    "\
3730 This creates an ext2 external journal on C<device> with label C<label>.");
3731
3732   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3733    (let uuid = uuidgen () in
3734     [InitEmpty, Always, TestOutput (
3735        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3736         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3737         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3738         ["mount_options"; ""; "/dev/sda2"; "/"];
3739         ["write_file"; "/new"; "new file contents"; "0"];
3740         ["cat"; "/new"]], "new file contents")]),
3741    "make ext2/3/4 external journal with UUID",
3742    "\
3743 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3744
3745   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3746    [],
3747    "make ext2/3/4 filesystem with external journal",
3748    "\
3749 This creates an ext2/3/4 filesystem on C<device> with
3750 an external journal on C<journal>.  It is equivalent
3751 to the command:
3752
3753  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3754
3755 See also C<guestfs_mke2journal>.");
3756
3757   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3758    [],
3759    "make ext2/3/4 filesystem with external journal",
3760    "\
3761 This creates an ext2/3/4 filesystem on C<device> with
3762 an external journal on the journal labeled C<label>.
3763
3764 See also C<guestfs_mke2journal_L>.");
3765
3766   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3767    [],
3768    "make ext2/3/4 filesystem with external journal",
3769    "\
3770 This creates an ext2/3/4 filesystem on C<device> with
3771 an external journal on the journal with UUID C<uuid>.
3772
3773 See also C<guestfs_mke2journal_U>.");
3774
3775   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3776    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3777    "load a kernel module",
3778    "\
3779 This loads a kernel module in the appliance.
3780
3781 The kernel module must have been whitelisted when libguestfs
3782 was built (see C<appliance/kmod.whitelist.in> in the source).");
3783
3784   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3785    [InitNone, Always, TestOutput (
3786       [["echo_daemon"; "This is a test"]], "This is a test"
3787     )],
3788    "echo arguments back to the client",
3789    "\
3790 This command concatenates the list of C<words> passed with single spaces
3791 between them and returns the resulting string.
3792
3793 You can use this command to test the connection through to the daemon.
3794
3795 See also C<guestfs_ping_daemon>.");
3796
3797   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3798    [], (* There is a regression test for this. *)
3799    "find all files and directories, returning NUL-separated list",
3800    "\
3801 This command lists out all files and directories, recursively,
3802 starting at C<directory>, placing the resulting list in the
3803 external file called C<files>.
3804
3805 This command works the same way as C<guestfs_find> with the
3806 following exceptions:
3807
3808 =over 4
3809
3810 =item *
3811
3812 The resulting list is written to an external file.
3813
3814 =item *
3815
3816 Items (filenames) in the result are separated
3817 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3818
3819 =item *
3820
3821 This command is not limited in the number of names that it
3822 can return.
3823
3824 =item *
3825
3826 The result list is not sorted.
3827
3828 =back");
3829
3830   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3831    [InitISOFS, Always, TestOutput (
3832       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3833     InitISOFS, Always, TestOutput (
3834       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3835     InitISOFS, Always, TestOutput (
3836       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3837     InitISOFS, Always, TestLastFail (
3838       [["case_sensitive_path"; "/Known-1/"]]);
3839     InitBasicFS, Always, TestOutput (
3840       [["mkdir"; "/a"];
3841        ["mkdir"; "/a/bbb"];
3842        ["touch"; "/a/bbb/c"];
3843        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3844     InitBasicFS, Always, TestOutput (
3845       [["mkdir"; "/a"];
3846        ["mkdir"; "/a/bbb"];
3847        ["touch"; "/a/bbb/c"];
3848        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3849     InitBasicFS, Always, TestLastFail (
3850       [["mkdir"; "/a"];
3851        ["mkdir"; "/a/bbb"];
3852        ["touch"; "/a/bbb/c"];
3853        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3854    "return true path on case-insensitive filesystem",
3855    "\
3856 This can be used to resolve case insensitive paths on
3857 a filesystem which is case sensitive.  The use case is
3858 to resolve paths which you have read from Windows configuration
3859 files or the Windows Registry, to the true path.
3860
3861 The command handles a peculiarity of the Linux ntfs-3g
3862 filesystem driver (and probably others), which is that although
3863 the underlying filesystem is case-insensitive, the driver
3864 exports the filesystem to Linux as case-sensitive.
3865
3866 One consequence of this is that special directories such
3867 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3868 (or other things) depending on the precise details of how
3869 they were created.  In Windows itself this would not be
3870 a problem.
3871
3872 Bug or feature?  You decide:
3873 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3874
3875 This function resolves the true case of each element in the
3876 path and returns the case-sensitive path.
3877
3878 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3879 might return C<\"/WINDOWS/system32\"> (the exact return value
3880 would depend on details of how the directories were originally
3881 created under Windows).
3882
3883 I<Note>:
3884 This function does not handle drive names, backslashes etc.
3885
3886 See also C<guestfs_realpath>.");
3887
3888   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3889    [InitBasicFS, Always, TestOutput (
3890       [["vfs_type"; "/dev/sda1"]], "ext2")],
3891    "get the Linux VFS type corresponding to a mounted device",
3892    "\
3893 This command gets the block device type corresponding to
3894 a mounted device called C<device>.
3895
3896 Usually the result is the name of the Linux VFS module that
3897 is used to mount this device (probably determined automatically
3898 if you used the C<guestfs_mount> call).");
3899
3900   ("truncate", (RErr, [Pathname "path"]), 199, [],
3901    [InitBasicFS, Always, TestOutputStruct (
3902       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3903        ["truncate"; "/test"];
3904        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3905    "truncate a file to zero size",
3906    "\
3907 This command truncates C<path> to a zero-length file.  The
3908 file must exist already.");
3909
3910   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3911    [InitBasicFS, Always, TestOutputStruct (
3912       [["touch"; "/test"];
3913        ["truncate_size"; "/test"; "1000"];
3914        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3915    "truncate a file to a particular size",
3916    "\
3917 This command truncates C<path> to size C<size> bytes.  The file
3918 must exist already.
3919
3920 If the current file size is less than C<size> then
3921 the file is extended to the required size with zero bytes.
3922 This creates a sparse file (ie. disk blocks are not allocated
3923 for the file until you write to it).  To create a non-sparse
3924 file of zeroes, use C<guestfs_fallocate64> instead.");
3925
3926   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3927    [InitBasicFS, Always, TestOutputStruct (
3928       [["touch"; "/test"];
3929        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3930        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3931    "set timestamp of a file with nanosecond precision",
3932    "\
3933 This command sets the timestamps of a file with nanosecond
3934 precision.
3935
3936 C<atsecs, atnsecs> are the last access time (atime) in secs and
3937 nanoseconds from the epoch.
3938
3939 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3940 secs and nanoseconds from the epoch.
3941
3942 If the C<*nsecs> field contains the special value C<-1> then
3943 the corresponding timestamp is set to the current time.  (The
3944 C<*secs> field is ignored in this case).
3945
3946 If the C<*nsecs> field contains the special value C<-2> then
3947 the corresponding timestamp is left unchanged.  (The
3948 C<*secs> field is ignored in this case).");
3949
3950   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3951    [InitBasicFS, Always, TestOutputStruct (
3952       [["mkdir_mode"; "/test"; "0o111"];
3953        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3954    "create a directory with a particular mode",
3955    "\
3956 This command creates a directory, setting the initial permissions
3957 of the directory to C<mode>.
3958
3959 For common Linux filesystems, the actual mode which is set will
3960 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3961 interpret the mode in other ways.
3962
3963 See also C<guestfs_mkdir>, C<guestfs_umask>");
3964
3965   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3966    [], (* XXX *)
3967    "change file owner and group",
3968    "\
3969 Change the file owner to C<owner> and group to C<group>.
3970 This is like C<guestfs_chown> but if C<path> is a symlink then
3971 the link itself is changed, not the target.
3972
3973 Only numeric uid and gid are supported.  If you want to use
3974 names, you will need to locate and parse the password file
3975 yourself (Augeas support makes this relatively easy).");
3976
3977   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3978    [], (* XXX *)
3979    "lstat on multiple files",
3980    "\
3981 This call allows you to perform the C<guestfs_lstat> operation
3982 on multiple files, where all files are in the directory C<path>.
3983 C<names> is the list of files from this directory.
3984
3985 On return you get a list of stat structs, with a one-to-one
3986 correspondence to the C<names> list.  If any name did not exist
3987 or could not be lstat'd, then the C<ino> field of that structure
3988 is set to C<-1>.
3989
3990 This call is intended for programs that want to efficiently
3991 list a directory contents without making many round-trips.
3992 See also C<guestfs_lxattrlist> for a similarly efficient call
3993 for getting extended attributes.  Very long directory listings
3994 might cause the protocol message size to be exceeded, causing
3995 this call to fail.  The caller must split up such requests
3996 into smaller groups of names.");
3997
3998   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3999    [], (* XXX *)
4000    "lgetxattr on multiple files",
4001    "\
4002 This call allows you to get the extended attributes
4003 of multiple files, where all files are in the directory C<path>.
4004 C<names> is the list of files from this directory.
4005
4006 On return you get a flat list of xattr structs which must be
4007 interpreted sequentially.  The first xattr struct always has a zero-length
4008 C<attrname>.  C<attrval> in this struct is zero-length
4009 to indicate there was an error doing C<lgetxattr> for this
4010 file, I<or> is a C string which is a decimal number
4011 (the number of following attributes for this file, which could
4012 be C<\"0\">).  Then after the first xattr struct are the
4013 zero or more attributes for the first named file.
4014 This repeats for the second and subsequent files.
4015
4016 This call is intended for programs that want to efficiently
4017 list a directory contents without making many round-trips.
4018 See also C<guestfs_lstatlist> for a similarly efficient call
4019 for getting standard stats.  Very long directory listings
4020 might cause the protocol message size to be exceeded, causing
4021 this call to fail.  The caller must split up such requests
4022 into smaller groups of names.");
4023
4024   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4025    [], (* XXX *)
4026    "readlink on multiple files",
4027    "\
4028 This call allows you to do a C<readlink> operation
4029 on multiple files, where all files are in the directory C<path>.
4030 C<names> is the list of files from this directory.
4031
4032 On return you get a list of strings, with a one-to-one
4033 correspondence to the C<names> list.  Each string is the
4034 value of the symbolic link.
4035
4036 If the C<readlink(2)> operation fails on any name, then
4037 the corresponding result string is the empty string C<\"\">.
4038 However the whole operation is completed even if there
4039 were C<readlink(2)> errors, and so you can call this
4040 function with names where you don't know if they are
4041 symbolic links already (albeit slightly less efficient).
4042
4043 This call is intended for programs that want to efficiently
4044 list a directory contents without making many round-trips.
4045 Very long directory listings might cause the protocol
4046 message size to be exceeded, causing
4047 this call to fail.  The caller must split up such requests
4048 into smaller groups of names.");
4049
4050   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4051    [InitISOFS, Always, TestOutputBuffer (
4052       [["pread"; "/known-4"; "1"; "3"]], "\n");
4053     InitISOFS, Always, TestOutputBuffer (
4054       [["pread"; "/empty"; "0"; "100"]], "")],
4055    "read part of a file",
4056    "\
4057 This command lets you read part of a file.  It reads C<count>
4058 bytes of the file, starting at C<offset>, from file C<path>.
4059
4060 This may read fewer bytes than requested.  For further details
4061 see the L<pread(2)> system call.");
4062
4063   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4064    [InitEmpty, Always, TestRun (
4065       [["part_init"; "/dev/sda"; "gpt"]])],
4066    "create an empty partition table",
4067    "\
4068 This creates an empty partition table on C<device> of one of the
4069 partition types listed below.  Usually C<parttype> should be
4070 either C<msdos> or C<gpt> (for large disks).
4071
4072 Initially there are no partitions.  Following this, you should
4073 call C<guestfs_part_add> for each partition required.
4074
4075 Possible values for C<parttype> are:
4076
4077 =over 4
4078
4079 =item B<efi> | B<gpt>
4080
4081 Intel EFI / GPT partition table.
4082
4083 This is recommended for >= 2 TB partitions that will be accessed
4084 from Linux and Intel-based Mac OS X.  It also has limited backwards
4085 compatibility with the C<mbr> format.
4086
4087 =item B<mbr> | B<msdos>
4088
4089 The standard PC \"Master Boot Record\" (MBR) format used
4090 by MS-DOS and Windows.  This partition type will B<only> work
4091 for device sizes up to 2 TB.  For large disks we recommend
4092 using C<gpt>.
4093
4094 =back
4095
4096 Other partition table types that may work but are not
4097 supported include:
4098
4099 =over 4
4100
4101 =item B<aix>
4102
4103 AIX disk labels.
4104
4105 =item B<amiga> | B<rdb>
4106
4107 Amiga \"Rigid Disk Block\" format.
4108
4109 =item B<bsd>
4110
4111 BSD disk labels.
4112
4113 =item B<dasd>
4114
4115 DASD, used on IBM mainframes.
4116
4117 =item B<dvh>
4118
4119 MIPS/SGI volumes.
4120
4121 =item B<mac>
4122
4123 Old Mac partition format.  Modern Macs use C<gpt>.
4124
4125 =item B<pc98>
4126
4127 NEC PC-98 format, common in Japan apparently.
4128
4129 =item B<sun>
4130
4131 Sun disk labels.
4132
4133 =back");
4134
4135   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4136    [InitEmpty, Always, TestRun (
4137       [["part_init"; "/dev/sda"; "mbr"];
4138        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4139     InitEmpty, Always, TestRun (
4140       [["part_init"; "/dev/sda"; "gpt"];
4141        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4142        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4143     InitEmpty, Always, TestRun (
4144       [["part_init"; "/dev/sda"; "mbr"];
4145        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4146        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4147        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4148        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4149    "add a partition to the device",
4150    "\
4151 This command adds a partition to C<device>.  If there is no partition
4152 table on the device, call C<guestfs_part_init> first.
4153
4154 The C<prlogex> parameter is the type of partition.  Normally you
4155 should pass C<p> or C<primary> here, but MBR partition tables also
4156 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4157 types.
4158
4159 C<startsect> and C<endsect> are the start and end of the partition
4160 in I<sectors>.  C<endsect> may be negative, which means it counts
4161 backwards from the end of the disk (C<-1> is the last sector).
4162
4163 Creating a partition which covers the whole disk is not so easy.
4164 Use C<guestfs_part_disk> to do that.");
4165
4166   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4167    [InitEmpty, Always, TestRun (
4168       [["part_disk"; "/dev/sda"; "mbr"]]);
4169     InitEmpty, Always, TestRun (
4170       [["part_disk"; "/dev/sda"; "gpt"]])],
4171    "partition whole disk with a single primary partition",
4172    "\
4173 This command is simply a combination of C<guestfs_part_init>
4174 followed by C<guestfs_part_add> to create a single primary partition
4175 covering the whole disk.
4176
4177 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4178 but other possible values are described in C<guestfs_part_init>.");
4179
4180   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4181    [InitEmpty, Always, TestRun (
4182       [["part_disk"; "/dev/sda"; "mbr"];
4183        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4184    "make a partition bootable",
4185    "\
4186 This sets the bootable flag on partition numbered C<partnum> on
4187 device C<device>.  Note that partitions are numbered from 1.
4188
4189 The bootable flag is used by some operating systems (notably
4190 Windows) to determine which partition to boot from.  It is by
4191 no means universally recognized.");
4192
4193   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4194    [InitEmpty, Always, TestRun (
4195       [["part_disk"; "/dev/sda"; "gpt"];
4196        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4197    "set partition name",
4198    "\
4199 This sets the partition name on partition numbered C<partnum> on
4200 device C<device>.  Note that partitions are numbered from 1.
4201
4202 The partition name can only be set on certain types of partition
4203 table.  This works on C<gpt> but not on C<mbr> partitions.");
4204
4205   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4206    [], (* XXX Add a regression test for this. *)
4207    "list partitions on a device",
4208    "\
4209 This command parses the partition table on C<device> and
4210 returns the list of partitions found.
4211
4212 The fields in the returned structure are:
4213
4214 =over 4
4215
4216 =item B<part_num>
4217
4218 Partition number, counting from 1.
4219
4220 =item B<part_start>
4221
4222 Start of the partition I<in bytes>.  To get sectors you have to
4223 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4224
4225 =item B<part_end>
4226
4227 End of the partition in bytes.
4228
4229 =item B<part_size>
4230
4231 Size of the partition in bytes.
4232
4233 =back");
4234
4235   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4236    [InitEmpty, Always, TestOutput (
4237       [["part_disk"; "/dev/sda"; "gpt"];
4238        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4239    "get the partition table type",
4240    "\
4241 This command examines the partition table on C<device> and
4242 returns the partition table type (format) being used.
4243
4244 Common return values include: C<msdos> (a DOS/Windows style MBR
4245 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4246 values are possible, although unusual.  See C<guestfs_part_init>
4247 for a full list.");
4248
4249   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4250    [InitBasicFS, Always, TestOutputBuffer (
4251       [["fill"; "0x63"; "10"; "/test"];
4252        ["read_file"; "/test"]], "cccccccccc")],
4253    "fill a file with octets",
4254    "\
4255 This command creates a new file called C<path>.  The initial
4256 content of the file is C<len> octets of C<c>, where C<c>
4257 must be a number in the range C<[0..255]>.
4258
4259 To fill a file with zero bytes (sparsely), it is
4260 much more efficient to use C<guestfs_truncate_size>.");
4261
4262   ("available", (RErr, [StringList "groups"]), 216, [],
4263    [InitNone, Always, TestRun [["available"; ""]]],
4264    "test availability of some parts of the API",
4265    "\
4266 This command is used to check the availability of some
4267 groups of functionality in the appliance, which not all builds of
4268 the libguestfs appliance will be able to provide.
4269
4270 The libguestfs groups, and the functions that those
4271 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4272
4273 The argument C<groups> is a list of group names, eg:
4274 C<[\"inotify\", \"augeas\"]> would check for the availability of
4275 the Linux inotify functions and Augeas (configuration file
4276 editing) functions.
4277
4278 The command returns no error if I<all> requested groups are available.
4279
4280 It fails with an error if one or more of the requested
4281 groups is unavailable in the appliance.
4282
4283 If an unknown group name is included in the
4284 list of groups then an error is always returned.
4285
4286 I<Notes:>
4287
4288 =over 4
4289
4290 =item *
4291
4292 You must call C<guestfs_launch> before calling this function.
4293
4294 The reason is because we don't know what groups are
4295 supported by the appliance/daemon until it is running and can
4296 be queried.
4297
4298 =item *
4299
4300 If a group of functions is available, this does not necessarily
4301 mean that they will work.  You still have to check for errors
4302 when calling individual API functions even if they are
4303 available.
4304
4305 =item *
4306
4307 It is usually the job of distro packagers to build
4308 complete functionality into the libguestfs appliance.
4309 Upstream libguestfs, if built from source with all
4310 requirements satisfied, will support everything.
4311
4312 =item *
4313
4314 This call was added in version C<1.0.80>.  In previous
4315 versions of libguestfs all you could do would be to speculatively
4316 execute a command to find out if the daemon implemented it.
4317 See also C<guestfs_version>.
4318
4319 =back");
4320
4321   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4322    [InitBasicFS, Always, TestOutputBuffer (
4323       [["write_file"; "/src"; "hello, world"; "0"];
4324        ["dd"; "/src"; "/dest"];
4325        ["read_file"; "/dest"]], "hello, world")],
4326    "copy from source to destination using dd",
4327    "\
4328 This command copies from one source device or file C<src>
4329 to another destination device or file C<dest>.  Normally you
4330 would use this to copy to or from a device or partition, for
4331 example to duplicate a filesystem.
4332
4333 If the destination is a device, it must be as large or larger
4334 than the source file or device, otherwise the copy will fail.
4335 This command cannot do partial copies (see C<guestfs_copy_size>).");
4336
4337   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4338    [InitBasicFS, Always, TestOutputInt (
4339       [["write_file"; "/file"; "hello, world"; "0"];
4340        ["filesize"; "/file"]], 12)],
4341    "return the size of the file in bytes",
4342    "\
4343 This command returns the size of C<file> in bytes.
4344
4345 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4346 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4347 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4348
4349   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4350    [InitBasicFSonLVM, Always, TestOutputList (
4351       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4352        ["lvs"]], ["/dev/VG/LV2"])],
4353    "rename an LVM logical volume",
4354    "\
4355 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4356
4357   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4358    [InitBasicFSonLVM, Always, TestOutputList (
4359       [["umount"; "/"];
4360        ["vg_activate"; "false"; "VG"];
4361        ["vgrename"; "VG"; "VG2"];
4362        ["vg_activate"; "true"; "VG2"];
4363        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4364        ["vgs"]], ["VG2"])],
4365    "rename an LVM volume group",
4366    "\
4367 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4368
4369   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4370    [InitISOFS, Always, TestOutputBuffer (
4371       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4372    "list the contents of a single file in an initrd",
4373    "\
4374 This command unpacks the file C<filename> from the initrd file
4375 called C<initrdpath>.  The filename must be given I<without> the
4376 initial C</> character.
4377
4378 For example, in guestfish you could use the following command
4379 to examine the boot script (usually called C</init>)
4380 contained in a Linux initrd or initramfs image:
4381
4382  initrd-cat /boot/initrd-<version>.img init
4383
4384 See also C<guestfs_initrd_list>.");
4385
4386   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4387    [],
4388    "get the UUID of a physical volume",
4389    "\
4390 This command returns the UUID of the LVM PV C<device>.");
4391
4392   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4393    [],
4394    "get the UUID of a volume group",
4395    "\
4396 This command returns the UUID of the LVM VG named C<vgname>.");
4397
4398   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4399    [],
4400    "get the UUID of a logical volume",
4401    "\
4402 This command returns the UUID of the LVM LV C<device>.");
4403
4404   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4405    [],
4406    "get the PV UUIDs containing the volume group",
4407    "\
4408 Given a VG called C<vgname>, this returns the UUIDs of all
4409 the physical volumes that this volume group resides on.
4410
4411 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4412 calls to associate physical volumes and volume groups.
4413
4414 See also C<guestfs_vglvuuids>.");
4415
4416   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4417    [],
4418    "get the LV UUIDs of all LVs in the volume group",
4419    "\
4420 Given a VG called C<vgname>, this returns the UUIDs of all
4421 the logical volumes created in this volume group.
4422
4423 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4424 calls to associate logical volumes and volume groups.
4425
4426 See also C<guestfs_vgpvuuids>.");
4427
4428   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4429    [InitBasicFS, Always, TestOutputBuffer (
4430       [["write_file"; "/src"; "hello, world"; "0"];
4431        ["copy_size"; "/src"; "/dest"; "5"];
4432        ["read_file"; "/dest"]], "hello")],
4433    "copy size bytes from source to destination using dd",
4434    "\
4435 This command copies exactly C<size> bytes from one source device
4436 or file C<src> to another destination device or file C<dest>.
4437
4438 Note this will fail if the source is too short or if the destination
4439 is not large enough.");
4440
4441   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4442    [InitEmpty, Always, TestRun (
4443       [["part_init"; "/dev/sda"; "mbr"];
4444        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4445        ["part_del"; "/dev/sda"; "1"]])],
4446    "delete a partition",
4447    "\
4448 This command deletes the partition numbered C<partnum> on C<device>.
4449
4450 Note that in the case of MBR partitioning, deleting an
4451 extended partition also deletes any logical partitions
4452 it contains.");
4453
4454   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4455    [InitEmpty, Always, TestOutputTrue (
4456       [["part_init"; "/dev/sda"; "mbr"];
4457        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4458        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4459        ["part_get_bootable"; "/dev/sda"; "1"]])],
4460    "return true if a partition is bootable",
4461    "\
4462 This command returns true if the partition C<partnum> on
4463 C<device> has the bootable flag set.
4464
4465 See also C<guestfs_part_set_bootable>.");
4466
4467   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [],
4468    [InitEmpty, Always, TestOutputInt (
4469       [["part_init"; "/dev/sda"; "mbr"];
4470        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4471        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4472        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4473    "get the MBR type byte (ID byte) from a partition",
4474    "\
4475 Returns the MBR type byte (also known as the ID byte) from
4476 the numbered partition C<partnum>.
4477
4478 Note that only MBR (old DOS-style) partitions have type bytes.
4479 You will get undefined results for other partition table
4480 types (see C<guestfs_part_get_parttype>).");
4481
4482   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4483    [], (* tested by part_get_mbr_id *)
4484    "set the MBR type byte (ID byte) of a partition",
4485    "\
4486 Sets the MBR type byte (also known as the ID byte) of
4487 the numbered partition C<partnum> to C<idbyte>.  Note
4488 that the type bytes quoted in most documentation are
4489 in fact hexadecimal numbers, but usually documented
4490 without any leading \"0x\" which might be confusing.
4491
4492 Note that only MBR (old DOS-style) partitions have type bytes.
4493 You will get undefined results for other partition table
4494 types (see C<guestfs_part_get_parttype>).");
4495
4496 ]
4497
4498 let all_functions = non_daemon_functions @ daemon_functions
4499
4500 (* In some places we want the functions to be displayed sorted
4501  * alphabetically, so this is useful:
4502  *)
4503 let all_functions_sorted =
4504   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4505                compare n1 n2) all_functions
4506
4507 (* Field types for structures. *)
4508 type field =
4509   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4510   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4511   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4512   | FUInt32
4513   | FInt32
4514   | FUInt64
4515   | FInt64
4516   | FBytes                      (* Any int measure that counts bytes. *)
4517   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4518   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4519
4520 (* Because we generate extra parsing code for LVM command line tools,
4521  * we have to pull out the LVM columns separately here.
4522  *)
4523 let lvm_pv_cols = [
4524   "pv_name", FString;
4525   "pv_uuid", FUUID;
4526   "pv_fmt", FString;
4527   "pv_size", FBytes;
4528   "dev_size", FBytes;
4529   "pv_free", FBytes;
4530   "pv_used", FBytes;
4531   "pv_attr", FString (* XXX *);
4532   "pv_pe_count", FInt64;
4533   "pv_pe_alloc_count", FInt64;
4534   "pv_tags", FString;
4535   "pe_start", FBytes;
4536   "pv_mda_count", FInt64;
4537   "pv_mda_free", FBytes;
4538   (* Not in Fedora 10:
4539      "pv_mda_size", FBytes;
4540   *)
4541 ]
4542 let lvm_vg_cols = [
4543   "vg_name", FString;
4544   "vg_uuid", FUUID;
4545   "vg_fmt", FString;
4546   "vg_attr", FString (* XXX *);
4547   "vg_size", FBytes;
4548   "vg_free", FBytes;
4549   "vg_sysid", FString;
4550   "vg_extent_size", FBytes;
4551   "vg_extent_count", FInt64;
4552   "vg_free_count", FInt64;
4553   "max_lv", FInt64;
4554   "max_pv", FInt64;
4555   "pv_count", FInt64;
4556   "lv_count", FInt64;
4557   "snap_count", FInt64;
4558   "vg_seqno", FInt64;
4559   "vg_tags", FString;
4560   "vg_mda_count", FInt64;
4561   "vg_mda_free", FBytes;
4562   (* Not in Fedora 10:
4563      "vg_mda_size", FBytes;
4564   *)
4565 ]
4566 let lvm_lv_cols = [
4567   "lv_name", FString;
4568   "lv_uuid", FUUID;
4569   "lv_attr", FString (* XXX *);
4570   "lv_major", FInt64;
4571   "lv_minor", FInt64;
4572   "lv_kernel_major", FInt64;
4573   "lv_kernel_minor", FInt64;
4574   "lv_size", FBytes;
4575   "seg_count", FInt64;
4576   "origin", FString;
4577   "snap_percent", FOptPercent;
4578   "copy_percent", FOptPercent;
4579   "move_pv", FString;
4580   "lv_tags", FString;
4581   "mirror_log", FString;
4582   "modules", FString;
4583 ]
4584
4585 (* Names and fields in all structures (in RStruct and RStructList)
4586  * that we support.
4587  *)
4588 let structs = [
4589   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4590    * not use this struct in any new code.
4591    *)
4592   "int_bool", [
4593     "i", FInt32;                (* for historical compatibility *)
4594     "b", FInt32;                (* for historical compatibility *)
4595   ];
4596
4597   (* LVM PVs, VGs, LVs. *)
4598   "lvm_pv", lvm_pv_cols;
4599   "lvm_vg", lvm_vg_cols;
4600   "lvm_lv", lvm_lv_cols;
4601
4602   (* Column names and types from stat structures.
4603    * NB. Can't use things like 'st_atime' because glibc header files
4604    * define some of these as macros.  Ugh.
4605    *)
4606   "stat", [
4607     "dev", FInt64;
4608     "ino", FInt64;
4609     "mode", FInt64;
4610     "nlink", FInt64;
4611     "uid", FInt64;
4612     "gid", FInt64;
4613     "rdev", FInt64;
4614     "size", FInt64;
4615     "blksize", FInt64;
4616     "blocks", FInt64;
4617     "atime", FInt64;
4618     "mtime", FInt64;
4619     "ctime", FInt64;
4620   ];
4621   "statvfs", [
4622     "bsize", FInt64;
4623     "frsize", FInt64;
4624     "blocks", FInt64;
4625     "bfree", FInt64;
4626     "bavail", FInt64;
4627     "files", FInt64;
4628     "ffree", FInt64;
4629     "favail", FInt64;
4630     "fsid", FInt64;
4631     "flag", FInt64;
4632     "namemax", FInt64;
4633   ];
4634
4635   (* Column names in dirent structure. *)
4636   "dirent", [
4637     "ino", FInt64;
4638     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4639     "ftyp", FChar;
4640     "name", FString;
4641   ];
4642
4643   (* Version numbers. *)
4644   "version", [
4645     "major", FInt64;
4646     "minor", FInt64;
4647     "release", FInt64;
4648     "extra", FString;
4649   ];
4650
4651   (* Extended attribute. *)
4652   "xattr", [
4653     "attrname", FString;
4654     "attrval", FBuffer;
4655   ];
4656
4657   (* Inotify events. *)
4658   "inotify_event", [
4659     "in_wd", FInt64;
4660     "in_mask", FUInt32;
4661     "in_cookie", FUInt32;
4662     "in_name", FString;
4663   ];
4664
4665   (* Partition table entry. *)
4666   "partition", [
4667     "part_num", FInt32;
4668     "part_start", FBytes;
4669     "part_end", FBytes;
4670     "part_size", FBytes;
4671   ];
4672 ] (* end of structs *)
4673
4674 (* Ugh, Java has to be different ..
4675  * These names are also used by the Haskell bindings.
4676  *)
4677 let java_structs = [
4678   "int_bool", "IntBool";
4679   "lvm_pv", "PV";
4680   "lvm_vg", "VG";
4681   "lvm_lv", "LV";
4682   "stat", "Stat";
4683   "statvfs", "StatVFS";
4684   "dirent", "Dirent";
4685   "version", "Version";
4686   "xattr", "XAttr";
4687   "inotify_event", "INotifyEvent";
4688   "partition", "Partition";
4689 ]
4690
4691 (* What structs are actually returned. *)
4692 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4693
4694 (* Returns a list of RStruct/RStructList structs that are returned
4695  * by any function.  Each element of returned list is a pair:
4696  *
4697  * (structname, RStructOnly)
4698  *    == there exists function which returns RStruct (_, structname)
4699  * (structname, RStructListOnly)
4700  *    == there exists function which returns RStructList (_, structname)
4701  * (structname, RStructAndList)
4702  *    == there are functions returning both RStruct (_, structname)
4703  *                                      and RStructList (_, structname)
4704  *)
4705 let rstructs_used_by functions =
4706   (* ||| is a "logical OR" for rstructs_used_t *)
4707   let (|||) a b =
4708     match a, b with
4709     | RStructAndList, _
4710     | _, RStructAndList -> RStructAndList
4711     | RStructOnly, RStructListOnly
4712     | RStructListOnly, RStructOnly -> RStructAndList
4713     | RStructOnly, RStructOnly -> RStructOnly
4714     | RStructListOnly, RStructListOnly -> RStructListOnly
4715   in
4716
4717   let h = Hashtbl.create 13 in
4718
4719   (* if elem->oldv exists, update entry using ||| operator,
4720    * else just add elem->newv to the hash
4721    *)
4722   let update elem newv =
4723     try  let oldv = Hashtbl.find h elem in
4724          Hashtbl.replace h elem (newv ||| oldv)
4725     with Not_found -> Hashtbl.add h elem newv
4726   in
4727
4728   List.iter (
4729     fun (_, style, _, _, _, _, _) ->
4730       match fst style with
4731       | RStruct (_, structname) -> update structname RStructOnly
4732       | RStructList (_, structname) -> update structname RStructListOnly
4733       | _ -> ()
4734   ) functions;
4735
4736   (* return key->values as a list of (key,value) *)
4737   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4738
4739 (* Used for testing language bindings. *)
4740 type callt =
4741   | CallString of string
4742   | CallOptString of string option
4743   | CallStringList of string list
4744   | CallInt of int
4745   | CallInt64 of int64
4746   | CallBool of bool
4747
4748 (* Used to memoize the result of pod2text. *)
4749 let pod2text_memo_filename = "src/.pod2text.data"
4750 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4751   try
4752     let chan = open_in pod2text_memo_filename in
4753     let v = input_value chan in
4754     close_in chan;
4755     v
4756   with
4757     _ -> Hashtbl.create 13
4758 let pod2text_memo_updated () =
4759   let chan = open_out pod2text_memo_filename in
4760   output_value chan pod2text_memo;
4761   close_out chan
4762
4763 (* Useful functions.
4764  * Note we don't want to use any external OCaml libraries which
4765  * makes this a bit harder than it should be.
4766  *)
4767 module StringMap = Map.Make (String)
4768
4769 let failwithf fs = ksprintf failwith fs
4770
4771 let unique = let i = ref 0 in fun () -> incr i; !i
4772
4773 let replace_char s c1 c2 =
4774   let s2 = String.copy s in
4775   let r = ref false in
4776   for i = 0 to String.length s2 - 1 do
4777     if String.unsafe_get s2 i = c1 then (
4778       String.unsafe_set s2 i c2;
4779       r := true
4780     )
4781   done;
4782   if not !r then s else s2
4783
4784 let isspace c =
4785   c = ' '
4786   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4787
4788 let triml ?(test = isspace) str =
4789   let i = ref 0 in
4790   let n = ref (String.length str) in
4791   while !n > 0 && test str.[!i]; do
4792     decr n;
4793     incr i
4794   done;
4795   if !i = 0 then str
4796   else String.sub str !i !n
4797
4798 let trimr ?(test = isspace) str =
4799   let n = ref (String.length str) in
4800   while !n > 0 && test str.[!n-1]; do
4801     decr n
4802   done;
4803   if !n = String.length str then str
4804   else String.sub str 0 !n
4805
4806 let trim ?(test = isspace) str =
4807   trimr ~test (triml ~test str)
4808
4809 let rec find s sub =
4810   let len = String.length s in
4811   let sublen = String.length sub in
4812   let rec loop i =
4813     if i <= len-sublen then (
4814       let rec loop2 j =
4815         if j < sublen then (
4816           if s.[i+j] = sub.[j] then loop2 (j+1)
4817           else -1
4818         ) else
4819           i (* found *)
4820       in
4821       let r = loop2 0 in
4822       if r = -1 then loop (i+1) else r
4823     ) else
4824       -1 (* not found *)
4825   in
4826   loop 0
4827
4828 let rec replace_str s s1 s2 =
4829   let len = String.length s in
4830   let sublen = String.length s1 in
4831   let i = find s s1 in
4832   if i = -1 then s
4833   else (
4834     let s' = String.sub s 0 i in
4835     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4836     s' ^ s2 ^ replace_str s'' s1 s2
4837   )
4838
4839 let rec string_split sep str =
4840   let len = String.length str in
4841   let seplen = String.length sep in
4842   let i = find str sep in
4843   if i = -1 then [str]
4844   else (
4845     let s' = String.sub str 0 i in
4846     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4847     s' :: string_split sep s''
4848   )
4849
4850 let files_equal n1 n2 =
4851   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4852   match Sys.command cmd with
4853   | 0 -> true
4854   | 1 -> false
4855   | i -> failwithf "%s: failed with error code %d" cmd i
4856
4857 let rec filter_map f = function
4858   | [] -> []
4859   | x :: xs ->
4860       match f x with
4861       | Some y -> y :: filter_map f xs
4862       | None -> filter_map f xs
4863
4864 let rec find_map f = function
4865   | [] -> raise Not_found
4866   | x :: xs ->
4867       match f x with
4868       | Some y -> y
4869       | None -> find_map f xs
4870
4871 let iteri f xs =
4872   let rec loop i = function
4873     | [] -> ()
4874     | x :: xs -> f i x; loop (i+1) xs
4875   in
4876   loop 0 xs
4877
4878 let mapi f xs =
4879   let rec loop i = function
4880     | [] -> []
4881     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4882   in
4883   loop 0 xs
4884
4885 let count_chars c str =
4886   let count = ref 0 in
4887   for i = 0 to String.length str - 1 do
4888     if c = String.unsafe_get str i then incr count
4889   done;
4890   !count
4891
4892 let name_of_argt = function
4893   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4894   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4895   | FileIn n | FileOut n -> n
4896
4897 let java_name_of_struct typ =
4898   try List.assoc typ java_structs
4899   with Not_found ->
4900     failwithf
4901       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4902
4903 let cols_of_struct typ =
4904   try List.assoc typ structs
4905   with Not_found ->
4906     failwithf "cols_of_struct: unknown struct %s" typ
4907
4908 let seq_of_test = function
4909   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4910   | TestOutputListOfDevices (s, _)
4911   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4912   | TestOutputTrue s | TestOutputFalse s
4913   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4914   | TestOutputStruct (s, _)
4915   | TestLastFail s -> s
4916
4917 (* Handling for function flags. *)
4918 let protocol_limit_warning =
4919   "Because of the message protocol, there is a transfer limit
4920 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4921
4922 let danger_will_robinson =
4923   "B<This command is dangerous.  Without careful use you
4924 can easily destroy all your data>."
4925
4926 let deprecation_notice flags =
4927   try
4928     let alt =
4929       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4930     let txt =
4931       sprintf "This function is deprecated.
4932 In new code, use the C<%s> call instead.
4933
4934 Deprecated functions will not be removed from the API, but the
4935 fact that they are deprecated indicates that there are problems
4936 with correct use of these functions." alt in
4937     Some txt
4938   with
4939     Not_found -> None
4940
4941 (* Create list of optional groups. *)
4942 let optgroups =
4943   let h = Hashtbl.create 13 in
4944   List.iter (
4945     fun (name, _, _, flags, _, _, _) ->
4946       List.iter (
4947         function
4948         | Optional group ->
4949             let names = try Hashtbl.find h group with Not_found -> [] in
4950             Hashtbl.replace h group (name :: names)
4951         | _ -> ()
4952       ) flags
4953   ) daemon_functions;
4954   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4955   let groups =
4956     List.map (
4957       fun group -> group, List.sort compare (Hashtbl.find h group)
4958     ) groups in
4959   List.sort (fun x y -> compare (fst x) (fst y)) groups
4960
4961 (* Check function names etc. for consistency. *)
4962 let check_functions () =
4963   let contains_uppercase str =
4964     let len = String.length str in
4965     let rec loop i =
4966       if i >= len then false
4967       else (
4968         let c = str.[i] in
4969         if c >= 'A' && c <= 'Z' then true
4970         else loop (i+1)
4971       )
4972     in
4973     loop 0
4974   in
4975
4976   (* Check function names. *)
4977   List.iter (
4978     fun (name, _, _, _, _, _, _) ->
4979       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4980         failwithf "function name %s does not need 'guestfs' prefix" name;
4981       if name = "" then
4982         failwithf "function name is empty";
4983       if name.[0] < 'a' || name.[0] > 'z' then
4984         failwithf "function name %s must start with lowercase a-z" name;
4985       if String.contains name '-' then
4986         failwithf "function name %s should not contain '-', use '_' instead."
4987           name
4988   ) all_functions;
4989
4990   (* Check function parameter/return names. *)
4991   List.iter (
4992     fun (name, style, _, _, _, _, _) ->
4993       let check_arg_ret_name n =
4994         if contains_uppercase n then
4995           failwithf "%s param/ret %s should not contain uppercase chars"
4996             name n;
4997         if String.contains n '-' || String.contains n '_' then
4998           failwithf "%s param/ret %s should not contain '-' or '_'"
4999             name n;
5000         if n = "value" then
5001           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;
5002         if n = "int" || n = "char" || n = "short" || n = "long" then
5003           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5004         if n = "i" || n = "n" then
5005           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5006         if n = "argv" || n = "args" then
5007           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5008
5009         (* List Haskell, OCaml and C keywords here.
5010          * http://www.haskell.org/haskellwiki/Keywords
5011          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5012          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5013          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5014          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5015          * Omitting _-containing words, since they're handled above.
5016          * Omitting the OCaml reserved word, "val", is ok,
5017          * and saves us from renaming several parameters.
5018          *)
5019         let reserved = [
5020           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5021           "char"; "class"; "const"; "constraint"; "continue"; "data";
5022           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5023           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5024           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5025           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5026           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5027           "interface";
5028           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5029           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5030           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5031           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5032           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5033           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5034           "volatile"; "when"; "where"; "while";
5035           ] in
5036         if List.mem n reserved then
5037           failwithf "%s has param/ret using reserved word %s" name n;
5038       in
5039
5040       (match fst style with
5041        | RErr -> ()
5042        | RInt n | RInt64 n | RBool n
5043        | RConstString n | RConstOptString n | RString n
5044        | RStringList n | RStruct (n, _) | RStructList (n, _)
5045        | RHashtable n | RBufferOut n ->
5046            check_arg_ret_name n
5047       );
5048       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5049   ) all_functions;
5050
5051   (* Check short descriptions. *)
5052   List.iter (
5053     fun (name, _, _, _, _, shortdesc, _) ->
5054       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5055         failwithf "short description of %s should begin with lowercase." name;
5056       let c = shortdesc.[String.length shortdesc-1] in
5057       if c = '\n' || c = '.' then
5058         failwithf "short description of %s should not end with . or \\n." name
5059   ) all_functions;
5060
5061   (* Check long descriptions. *)
5062   List.iter (
5063     fun (name, _, _, _, _, _, longdesc) ->
5064       if longdesc.[String.length longdesc-1] = '\n' then
5065         failwithf "long description of %s should not end with \\n." name
5066   ) all_functions;
5067
5068   (* Check proc_nrs. *)
5069   List.iter (
5070     fun (name, _, proc_nr, _, _, _, _) ->
5071       if proc_nr <= 0 then
5072         failwithf "daemon function %s should have proc_nr > 0" name
5073   ) daemon_functions;
5074
5075   List.iter (
5076     fun (name, _, proc_nr, _, _, _, _) ->
5077       if proc_nr <> -1 then
5078         failwithf "non-daemon function %s should have proc_nr -1" name
5079   ) non_daemon_functions;
5080
5081   let proc_nrs =
5082     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5083       daemon_functions in
5084   let proc_nrs =
5085     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5086   let rec loop = function
5087     | [] -> ()
5088     | [_] -> ()
5089     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5090         loop rest
5091     | (name1,nr1) :: (name2,nr2) :: _ ->
5092         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5093           name1 name2 nr1 nr2
5094   in
5095   loop proc_nrs;
5096
5097   (* Check tests. *)
5098   List.iter (
5099     function
5100       (* Ignore functions that have no tests.  We generate a
5101        * warning when the user does 'make check' instead.
5102        *)
5103     | name, _, _, _, [], _, _ -> ()
5104     | name, _, _, _, tests, _, _ ->
5105         let funcs =
5106           List.map (
5107             fun (_, _, test) ->
5108               match seq_of_test test with
5109               | [] ->
5110                   failwithf "%s has a test containing an empty sequence" name
5111               | cmds -> List.map List.hd cmds
5112           ) tests in
5113         let funcs = List.flatten funcs in
5114
5115         let tested = List.mem name funcs in
5116
5117         if not tested then
5118           failwithf "function %s has tests but does not test itself" name
5119   ) all_functions
5120
5121 (* 'pr' prints to the current output file. *)
5122 let chan = ref Pervasives.stdout
5123 let lines = ref 0
5124 let pr fs =
5125   ksprintf
5126     (fun str ->
5127        let i = count_chars '\n' str in
5128        lines := !lines + i;
5129        output_string !chan str
5130     ) fs
5131
5132 let copyright_years =
5133   let this_year = 1900 + (localtime (time ())).tm_year in
5134   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5135
5136 (* Generate a header block in a number of standard styles. *)
5137 type comment_style =
5138     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5139 type license = GPLv2plus | LGPLv2plus
5140
5141 let generate_header ?(extra_inputs = []) comment license =
5142   let inputs = "src/generator.ml" :: extra_inputs in
5143   let c = match comment with
5144     | CStyle ->         pr "/* "; " *"
5145     | CPlusPlusStyle -> pr "// "; "//"
5146     | HashStyle ->      pr "# ";  "#"
5147     | OCamlStyle ->     pr "(* "; " *"
5148     | HaskellStyle ->   pr "{- "; "  " in
5149   pr "libguestfs generated file\n";
5150   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5151   List.iter (pr "%s   %s\n" c) inputs;
5152   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5153   pr "%s\n" c;
5154   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5155   pr "%s\n" c;
5156   (match license with
5157    | GPLv2plus ->
5158        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5159        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5160        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5161        pr "%s (at your option) any later version.\n" c;
5162        pr "%s\n" c;
5163        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5164        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5165        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5166        pr "%s GNU General Public License for more details.\n" c;
5167        pr "%s\n" c;
5168        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5169        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5170        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5171
5172    | LGPLv2plus ->
5173        pr "%s This library is free software; you can redistribute it and/or\n" c;
5174        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5175        pr "%s License as published by the Free Software Foundation; either\n" c;
5176        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5177        pr "%s\n" c;
5178        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5179        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5180        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5181        pr "%s Lesser General Public License for more details.\n" c;
5182        pr "%s\n" c;
5183        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5184        pr "%s License along with this library; if not, write to the Free Software\n" c;
5185        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5186   );
5187   (match comment with
5188    | CStyle -> pr " */\n"
5189    | CPlusPlusStyle
5190    | HashStyle -> ()
5191    | OCamlStyle -> pr " *)\n"
5192    | HaskellStyle -> pr "-}\n"
5193   );
5194   pr "\n"
5195
5196 (* Start of main code generation functions below this line. *)
5197
5198 (* Generate the pod documentation for the C API. *)
5199 let rec generate_actions_pod () =
5200   List.iter (
5201     fun (shortname, style, _, flags, _, _, longdesc) ->
5202       if not (List.mem NotInDocs flags) then (
5203         let name = "guestfs_" ^ shortname in
5204         pr "=head2 %s\n\n" name;
5205         pr " ";
5206         generate_prototype ~extern:false ~handle:"g" name style;
5207         pr "\n\n";
5208         pr "%s\n\n" longdesc;
5209         (match fst style with
5210          | RErr ->
5211              pr "This function returns 0 on success or -1 on error.\n\n"
5212          | RInt _ ->
5213              pr "On error this function returns -1.\n\n"
5214          | RInt64 _ ->
5215              pr "On error this function returns -1.\n\n"
5216          | RBool _ ->
5217              pr "This function returns a C truth value on success or -1 on error.\n\n"
5218          | RConstString _ ->
5219              pr "This function returns a string, or NULL on error.
5220 The string is owned by the guest handle and must I<not> be freed.\n\n"
5221          | RConstOptString _ ->
5222              pr "This function returns a string which may be NULL.
5223 There is way to return an error from this function.
5224 The string is owned by the guest handle and must I<not> be freed.\n\n"
5225          | RString _ ->
5226              pr "This function returns a string, or NULL on error.
5227 I<The caller must free the returned string after use>.\n\n"
5228          | RStringList _ ->
5229              pr "This function returns a NULL-terminated array of strings
5230 (like L<environ(3)>), or NULL if there was an error.
5231 I<The caller must free the strings and the array after use>.\n\n"
5232          | RStruct (_, typ) ->
5233              pr "This function returns a C<struct guestfs_%s *>,
5234 or NULL if there was an error.
5235 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5236          | RStructList (_, typ) ->
5237              pr "This function returns a C<struct guestfs_%s_list *>
5238 (see E<lt>guestfs-structs.hE<gt>),
5239 or NULL if there was an error.
5240 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5241          | RHashtable _ ->
5242              pr "This function returns a NULL-terminated array of
5243 strings, or NULL if there was an error.
5244 The array of strings will always have length C<2n+1>, where
5245 C<n> keys and values alternate, followed by the trailing NULL entry.
5246 I<The caller must free the strings and the array after use>.\n\n"
5247          | RBufferOut _ ->
5248              pr "This function returns a buffer, or NULL on error.
5249 The size of the returned buffer is written to C<*size_r>.
5250 I<The caller must free the returned buffer after use>.\n\n"
5251         );
5252         if List.mem ProtocolLimitWarning flags then
5253           pr "%s\n\n" protocol_limit_warning;
5254         if List.mem DangerWillRobinson flags then
5255           pr "%s\n\n" danger_will_robinson;
5256         match deprecation_notice flags with
5257         | None -> ()
5258         | Some txt -> pr "%s\n\n" txt
5259       )
5260   ) all_functions_sorted
5261
5262 and generate_structs_pod () =
5263   (* Structs documentation. *)
5264   List.iter (
5265     fun (typ, cols) ->
5266       pr "=head2 guestfs_%s\n" typ;
5267       pr "\n";
5268       pr " struct guestfs_%s {\n" typ;
5269       List.iter (
5270         function
5271         | name, FChar -> pr "   char %s;\n" name
5272         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5273         | name, FInt32 -> pr "   int32_t %s;\n" name
5274         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5275         | name, FInt64 -> pr "   int64_t %s;\n" name
5276         | name, FString -> pr "   char *%s;\n" name
5277         | name, FBuffer ->
5278             pr "   /* The next two fields describe a byte array. */\n";
5279             pr "   uint32_t %s_len;\n" name;
5280             pr "   char *%s;\n" name
5281         | name, FUUID ->
5282             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5283             pr "   char %s[32];\n" name
5284         | name, FOptPercent ->
5285             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5286             pr "   float %s;\n" name
5287       ) cols;
5288       pr " };\n";
5289       pr " \n";
5290       pr " struct guestfs_%s_list {\n" typ;
5291       pr "   uint32_t len; /* Number of elements in list. */\n";
5292       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5293       pr " };\n";
5294       pr " \n";
5295       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5296       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5297         typ typ;
5298       pr "\n"
5299   ) structs
5300
5301 and generate_availability_pod () =
5302   (* Availability documentation. *)
5303   pr "=over 4\n";
5304   pr "\n";
5305   List.iter (
5306     fun (group, functions) ->
5307       pr "=item B<%s>\n" group;
5308       pr "\n";
5309       pr "The following functions:\n";
5310       List.iter (pr "L</guestfs_%s>\n") functions;
5311       pr "\n"
5312   ) optgroups;
5313   pr "=back\n";
5314   pr "\n"
5315
5316 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5317  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5318  *
5319  * We have to use an underscore instead of a dash because otherwise
5320  * rpcgen generates incorrect code.
5321  *
5322  * This header is NOT exported to clients, but see also generate_structs_h.
5323  *)
5324 and generate_xdr () =
5325   generate_header CStyle LGPLv2plus;
5326
5327   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5328   pr "typedef string str<>;\n";
5329   pr "\n";
5330
5331   (* Internal structures. *)
5332   List.iter (
5333     function
5334     | typ, cols ->
5335         pr "struct guestfs_int_%s {\n" typ;
5336         List.iter (function
5337                    | name, FChar -> pr "  char %s;\n" name
5338                    | name, FString -> pr "  string %s<>;\n" name
5339                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5340                    | name, FUUID -> pr "  opaque %s[32];\n" name
5341                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5342                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5343                    | name, FOptPercent -> pr "  float %s;\n" name
5344                   ) cols;
5345         pr "};\n";
5346         pr "\n";
5347         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5348         pr "\n";
5349   ) structs;
5350
5351   List.iter (
5352     fun (shortname, style, _, _, _, _, _) ->
5353       let name = "guestfs_" ^ shortname in
5354
5355       (match snd style with
5356        | [] -> ()
5357        | args ->
5358            pr "struct %s_args {\n" name;
5359            List.iter (
5360              function
5361              | Pathname n | Device n | Dev_or_Path n | String n ->
5362                  pr "  string %s<>;\n" n
5363              | OptString n -> pr "  str *%s;\n" n
5364              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5365              | Bool n -> pr "  bool %s;\n" n
5366              | Int n -> pr "  int %s;\n" n
5367              | Int64 n -> pr "  hyper %s;\n" n
5368              | FileIn _ | FileOut _ -> ()
5369            ) args;
5370            pr "};\n\n"
5371       );
5372       (match fst style with
5373        | RErr -> ()
5374        | RInt n ->
5375            pr "struct %s_ret {\n" name;
5376            pr "  int %s;\n" n;
5377            pr "};\n\n"
5378        | RInt64 n ->
5379            pr "struct %s_ret {\n" name;
5380            pr "  hyper %s;\n" n;
5381            pr "};\n\n"
5382        | RBool n ->
5383            pr "struct %s_ret {\n" name;
5384            pr "  bool %s;\n" n;
5385            pr "};\n\n"
5386        | RConstString _ | RConstOptString _ ->
5387            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5388        | RString n ->
5389            pr "struct %s_ret {\n" name;
5390            pr "  string %s<>;\n" n;
5391            pr "};\n\n"
5392        | RStringList n ->
5393            pr "struct %s_ret {\n" name;
5394            pr "  str %s<>;\n" n;
5395            pr "};\n\n"
5396        | RStruct (n, typ) ->
5397            pr "struct %s_ret {\n" name;
5398            pr "  guestfs_int_%s %s;\n" typ n;
5399            pr "};\n\n"
5400        | RStructList (n, typ) ->
5401            pr "struct %s_ret {\n" name;
5402            pr "  guestfs_int_%s_list %s;\n" typ n;
5403            pr "};\n\n"
5404        | RHashtable n ->
5405            pr "struct %s_ret {\n" name;
5406            pr "  str %s<>;\n" n;
5407            pr "};\n\n"
5408        | RBufferOut n ->
5409            pr "struct %s_ret {\n" name;
5410            pr "  opaque %s<>;\n" n;
5411            pr "};\n\n"
5412       );
5413   ) daemon_functions;
5414
5415   (* Table of procedure numbers. *)
5416   pr "enum guestfs_procedure {\n";
5417   List.iter (
5418     fun (shortname, _, proc_nr, _, _, _, _) ->
5419       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5420   ) daemon_functions;
5421   pr "  GUESTFS_PROC_NR_PROCS\n";
5422   pr "};\n";
5423   pr "\n";
5424
5425   (* Having to choose a maximum message size is annoying for several
5426    * reasons (it limits what we can do in the API), but it (a) makes
5427    * the protocol a lot simpler, and (b) provides a bound on the size
5428    * of the daemon which operates in limited memory space.
5429    *)
5430   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5431   pr "\n";
5432
5433   (* Message header, etc. *)
5434   pr "\
5435 /* The communication protocol is now documented in the guestfs(3)
5436  * manpage.
5437  */
5438
5439 const GUESTFS_PROGRAM = 0x2000F5F5;
5440 const GUESTFS_PROTOCOL_VERSION = 1;
5441
5442 /* These constants must be larger than any possible message length. */
5443 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5444 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5445
5446 enum guestfs_message_direction {
5447   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5448   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5449 };
5450
5451 enum guestfs_message_status {
5452   GUESTFS_STATUS_OK = 0,
5453   GUESTFS_STATUS_ERROR = 1
5454 };
5455
5456 const GUESTFS_ERROR_LEN = 256;
5457
5458 struct guestfs_message_error {
5459   string error_message<GUESTFS_ERROR_LEN>;
5460 };
5461
5462 struct guestfs_message_header {
5463   unsigned prog;                     /* GUESTFS_PROGRAM */
5464   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5465   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5466   guestfs_message_direction direction;
5467   unsigned serial;                   /* message serial number */
5468   guestfs_message_status status;
5469 };
5470
5471 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5472
5473 struct guestfs_chunk {
5474   int cancel;                        /* if non-zero, transfer is cancelled */
5475   /* data size is 0 bytes if the transfer has finished successfully */
5476   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5477 };
5478 "
5479
5480 (* Generate the guestfs-structs.h file. *)
5481 and generate_structs_h () =
5482   generate_header CStyle LGPLv2plus;
5483
5484   (* This is a public exported header file containing various
5485    * structures.  The structures are carefully written to have
5486    * exactly the same in-memory format as the XDR structures that
5487    * we use on the wire to the daemon.  The reason for creating
5488    * copies of these structures here is just so we don't have to
5489    * export the whole of guestfs_protocol.h (which includes much
5490    * unrelated and XDR-dependent stuff that we don't want to be
5491    * public, or required by clients).
5492    *
5493    * To reiterate, we will pass these structures to and from the
5494    * client with a simple assignment or memcpy, so the format
5495    * must be identical to what rpcgen / the RFC defines.
5496    *)
5497
5498   (* Public structures. *)
5499   List.iter (
5500     fun (typ, cols) ->
5501       pr "struct guestfs_%s {\n" typ;
5502       List.iter (
5503         function
5504         | name, FChar -> pr "  char %s;\n" name
5505         | name, FString -> pr "  char *%s;\n" name
5506         | name, FBuffer ->
5507             pr "  uint32_t %s_len;\n" name;
5508             pr "  char *%s;\n" name
5509         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5510         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5511         | name, FInt32 -> pr "  int32_t %s;\n" name
5512         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5513         | name, FInt64 -> pr "  int64_t %s;\n" name
5514         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5515       ) cols;
5516       pr "};\n";
5517       pr "\n";
5518       pr "struct guestfs_%s_list {\n" typ;
5519       pr "  uint32_t len;\n";
5520       pr "  struct guestfs_%s *val;\n" typ;
5521       pr "};\n";
5522       pr "\n";
5523       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5524       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5525       pr "\n"
5526   ) structs
5527
5528 (* Generate the guestfs-actions.h file. *)
5529 and generate_actions_h () =
5530   generate_header CStyle LGPLv2plus;
5531   List.iter (
5532     fun (shortname, style, _, _, _, _, _) ->
5533       let name = "guestfs_" ^ shortname in
5534       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5535         name style
5536   ) all_functions
5537
5538 (* Generate the guestfs-internal-actions.h file. *)
5539 and generate_internal_actions_h () =
5540   generate_header CStyle LGPLv2plus;
5541   List.iter (
5542     fun (shortname, style, _, _, _, _, _) ->
5543       let name = "guestfs__" ^ shortname in
5544       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5545         name style
5546   ) non_daemon_functions
5547
5548 (* Generate the client-side dispatch stubs. *)
5549 and generate_client_actions () =
5550   generate_header CStyle LGPLv2plus;
5551
5552   pr "\
5553 #include <stdio.h>
5554 #include <stdlib.h>
5555 #include <stdint.h>
5556 #include <string.h>
5557 #include <inttypes.h>
5558
5559 #include \"guestfs.h\"
5560 #include \"guestfs-internal.h\"
5561 #include \"guestfs-internal-actions.h\"
5562 #include \"guestfs_protocol.h\"
5563
5564 #define error guestfs_error
5565 //#define perrorf guestfs_perrorf
5566 #define safe_malloc guestfs_safe_malloc
5567 #define safe_realloc guestfs_safe_realloc
5568 //#define safe_strdup guestfs_safe_strdup
5569 #define safe_memdup guestfs_safe_memdup
5570
5571 /* Check the return message from a call for validity. */
5572 static int
5573 check_reply_header (guestfs_h *g,
5574                     const struct guestfs_message_header *hdr,
5575                     unsigned int proc_nr, unsigned int serial)
5576 {
5577   if (hdr->prog != GUESTFS_PROGRAM) {
5578     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5579     return -1;
5580   }
5581   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5582     error (g, \"wrong protocol version (%%d/%%d)\",
5583            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5584     return -1;
5585   }
5586   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5587     error (g, \"unexpected message direction (%%d/%%d)\",
5588            hdr->direction, GUESTFS_DIRECTION_REPLY);
5589     return -1;
5590   }
5591   if (hdr->proc != proc_nr) {
5592     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5593     return -1;
5594   }
5595   if (hdr->serial != serial) {
5596     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5597     return -1;
5598   }
5599
5600   return 0;
5601 }
5602
5603 /* Check we are in the right state to run a high-level action. */
5604 static int
5605 check_state (guestfs_h *g, const char *caller)
5606 {
5607   if (!guestfs__is_ready (g)) {
5608     if (guestfs__is_config (g) || guestfs__is_launching (g))
5609       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5610         caller);
5611     else
5612       error (g, \"%%s called from the wrong state, %%d != READY\",
5613         caller, guestfs__get_state (g));
5614     return -1;
5615   }
5616   return 0;
5617 }
5618
5619 ";
5620
5621   (* Generate code to generate guestfish call traces. *)
5622   let trace_call shortname style =
5623     pr "  if (guestfs__get_trace (g)) {\n";
5624
5625     let needs_i =
5626       List.exists (function
5627                    | StringList _ | DeviceList _ -> true
5628                    | _ -> false) (snd style) in
5629     if needs_i then (
5630       pr "    int i;\n";
5631       pr "\n"
5632     );
5633
5634     pr "    printf (\"%s\");\n" shortname;
5635     List.iter (
5636       function
5637       | String n                        (* strings *)
5638       | Device n
5639       | Pathname n
5640       | Dev_or_Path n
5641       | FileIn n
5642       | FileOut n ->
5643           (* guestfish doesn't support string escaping, so neither do we *)
5644           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5645       | OptString n ->                  (* string option *)
5646           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5647           pr "    else printf (\" null\");\n"
5648       | StringList n
5649       | DeviceList n ->                 (* string list *)
5650           pr "    putchar (' ');\n";
5651           pr "    putchar ('\"');\n";
5652           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5653           pr "      if (i > 0) putchar (' ');\n";
5654           pr "      fputs (%s[i], stdout);\n" n;
5655           pr "    }\n";
5656           pr "    putchar ('\"');\n";
5657       | Bool n ->                       (* boolean *)
5658           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5659       | Int n ->                        (* int *)
5660           pr "    printf (\" %%d\", %s);\n" n
5661       | Int64 n ->
5662           pr "    printf (\" %%\" PRIi64, %s);\n" n
5663     ) (snd style);
5664     pr "    putchar ('\\n');\n";
5665     pr "  }\n";
5666     pr "\n";
5667   in
5668
5669   (* For non-daemon functions, generate a wrapper around each function. *)
5670   List.iter (
5671     fun (shortname, style, _, _, _, _, _) ->
5672       let name = "guestfs_" ^ shortname in
5673
5674       generate_prototype ~extern:false ~semicolon:false ~newline:true
5675         ~handle:"g" name style;
5676       pr "{\n";
5677       trace_call shortname style;
5678       pr "  return guestfs__%s " shortname;
5679       generate_c_call_args ~handle:"g" style;
5680       pr ";\n";
5681       pr "}\n";
5682       pr "\n"
5683   ) non_daemon_functions;
5684
5685   (* Client-side stubs for each function. *)
5686   List.iter (
5687     fun (shortname, style, _, _, _, _, _) ->
5688       let name = "guestfs_" ^ shortname in
5689
5690       (* Generate the action stub. *)
5691       generate_prototype ~extern:false ~semicolon:false ~newline:true
5692         ~handle:"g" name style;
5693
5694       let error_code =
5695         match fst style with
5696         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5697         | RConstString _ | RConstOptString _ ->
5698             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5699         | RString _ | RStringList _
5700         | RStruct _ | RStructList _
5701         | RHashtable _ | RBufferOut _ ->
5702             "NULL" in
5703
5704       pr "{\n";
5705
5706       (match snd style with
5707        | [] -> ()
5708        | _ -> pr "  struct %s_args args;\n" name
5709       );
5710
5711       pr "  guestfs_message_header hdr;\n";
5712       pr "  guestfs_message_error err;\n";
5713       let has_ret =
5714         match fst style with
5715         | RErr -> false
5716         | RConstString _ | RConstOptString _ ->
5717             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5718         | RInt _ | RInt64 _
5719         | RBool _ | RString _ | RStringList _
5720         | RStruct _ | RStructList _
5721         | RHashtable _ | RBufferOut _ ->
5722             pr "  struct %s_ret ret;\n" name;
5723             true in
5724
5725       pr "  int serial;\n";
5726       pr "  int r;\n";
5727       pr "\n";
5728       trace_call shortname style;
5729       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5730       pr "  guestfs___set_busy (g);\n";
5731       pr "\n";
5732
5733       (* Send the main header and arguments. *)
5734       (match snd style with
5735        | [] ->
5736            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5737              (String.uppercase shortname)
5738        | args ->
5739            List.iter (
5740              function
5741              | Pathname n | Device n | Dev_or_Path n | String n ->
5742                  pr "  args.%s = (char *) %s;\n" n n
5743              | OptString n ->
5744                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5745              | StringList n | DeviceList n ->
5746                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5747                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5748              | Bool n ->
5749                  pr "  args.%s = %s;\n" n n
5750              | Int n ->
5751                  pr "  args.%s = %s;\n" n n
5752              | Int64 n ->
5753                  pr "  args.%s = %s;\n" n n
5754              | FileIn _ | FileOut _ -> ()
5755            ) args;
5756            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5757              (String.uppercase shortname);
5758            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5759              name;
5760       );
5761       pr "  if (serial == -1) {\n";
5762       pr "    guestfs___end_busy (g);\n";
5763       pr "    return %s;\n" error_code;
5764       pr "  }\n";
5765       pr "\n";
5766
5767       (* Send any additional files (FileIn) requested. *)
5768       let need_read_reply_label = ref false in
5769       List.iter (
5770         function
5771         | FileIn n ->
5772             pr "  r = guestfs___send_file (g, %s);\n" n;
5773             pr "  if (r == -1) {\n";
5774             pr "    guestfs___end_busy (g);\n";
5775             pr "    return %s;\n" error_code;
5776             pr "  }\n";
5777             pr "  if (r == -2) /* daemon cancelled */\n";
5778             pr "    goto read_reply;\n";
5779             need_read_reply_label := true;
5780             pr "\n";
5781         | _ -> ()
5782       ) (snd style);
5783
5784       (* Wait for the reply from the remote end. *)
5785       if !need_read_reply_label then pr " read_reply:\n";
5786       pr "  memset (&hdr, 0, sizeof hdr);\n";
5787       pr "  memset (&err, 0, sizeof err);\n";
5788       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5789       pr "\n";
5790       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5791       if not has_ret then
5792         pr "NULL, NULL"
5793       else
5794         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5795       pr ");\n";
5796
5797       pr "  if (r == -1) {\n";
5798       pr "    guestfs___end_busy (g);\n";
5799       pr "    return %s;\n" error_code;
5800       pr "  }\n";
5801       pr "\n";
5802
5803       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5804         (String.uppercase shortname);
5805       pr "    guestfs___end_busy (g);\n";
5806       pr "    return %s;\n" error_code;
5807       pr "  }\n";
5808       pr "\n";
5809
5810       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5811       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5812       pr "    free (err.error_message);\n";
5813       pr "    guestfs___end_busy (g);\n";
5814       pr "    return %s;\n" error_code;
5815       pr "  }\n";
5816       pr "\n";
5817
5818       (* Expecting to receive further files (FileOut)? *)
5819       List.iter (
5820         function
5821         | FileOut n ->
5822             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5823             pr "    guestfs___end_busy (g);\n";
5824             pr "    return %s;\n" error_code;
5825             pr "  }\n";
5826             pr "\n";
5827         | _ -> ()
5828       ) (snd style);
5829
5830       pr "  guestfs___end_busy (g);\n";
5831
5832       (match fst style with
5833        | RErr -> pr "  return 0;\n"
5834        | RInt n | RInt64 n | RBool n ->
5835            pr "  return ret.%s;\n" n
5836        | RConstString _ | RConstOptString _ ->
5837            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5838        | RString n ->
5839            pr "  return ret.%s; /* caller will free */\n" n
5840        | RStringList n | RHashtable n ->
5841            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5842            pr "  ret.%s.%s_val =\n" n n;
5843            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5844            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5845              n n;
5846            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5847            pr "  return ret.%s.%s_val;\n" n n
5848        | RStruct (n, _) ->
5849            pr "  /* caller will free this */\n";
5850            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5851        | RStructList (n, _) ->
5852            pr "  /* caller will free this */\n";
5853            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5854        | RBufferOut n ->
5855            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5856            pr "   * _val might be NULL here.  To make the API saner for\n";
5857            pr "   * callers, we turn this case into a unique pointer (using\n";
5858            pr "   * malloc(1)).\n";
5859            pr "   */\n";
5860            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5861            pr "    *size_r = ret.%s.%s_len;\n" n n;
5862            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5863            pr "  } else {\n";
5864            pr "    free (ret.%s.%s_val);\n" n n;
5865            pr "    char *p = safe_malloc (g, 1);\n";
5866            pr "    *size_r = ret.%s.%s_len;\n" n n;
5867            pr "    return p;\n";
5868            pr "  }\n";
5869       );
5870
5871       pr "}\n\n"
5872   ) daemon_functions;
5873
5874   (* Functions to free structures. *)
5875   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5876   pr " * structure format is identical to the XDR format.  See note in\n";
5877   pr " * generator.ml.\n";
5878   pr " */\n";
5879   pr "\n";
5880
5881   List.iter (
5882     fun (typ, _) ->
5883       pr "void\n";
5884       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5885       pr "{\n";
5886       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5887       pr "  free (x);\n";
5888       pr "}\n";
5889       pr "\n";
5890
5891       pr "void\n";
5892       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5893       pr "{\n";
5894       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5895       pr "  free (x);\n";
5896       pr "}\n";
5897       pr "\n";
5898
5899   ) structs;
5900
5901 (* Generate daemon/actions.h. *)
5902 and generate_daemon_actions_h () =
5903   generate_header CStyle GPLv2plus;
5904
5905   pr "#include \"../src/guestfs_protocol.h\"\n";
5906   pr "\n";
5907
5908   List.iter (
5909     fun (name, style, _, _, _, _, _) ->
5910       generate_prototype
5911         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5912         name style;
5913   ) daemon_functions
5914
5915 (* Generate the linker script which controls the visibility of
5916  * symbols in the public ABI and ensures no other symbols get
5917  * exported accidentally.
5918  *)
5919 and generate_linker_script () =
5920   generate_header HashStyle GPLv2plus;
5921
5922   let globals = [
5923     "guestfs_create";
5924     "guestfs_close";
5925     "guestfs_get_error_handler";
5926     "guestfs_get_out_of_memory_handler";
5927     "guestfs_last_error";
5928     "guestfs_set_error_handler";
5929     "guestfs_set_launch_done_callback";
5930     "guestfs_set_log_message_callback";
5931     "guestfs_set_out_of_memory_handler";
5932     "guestfs_set_subprocess_quit_callback";
5933
5934     (* Unofficial parts of the API: the bindings code use these
5935      * functions, so it is useful to export them.
5936      *)
5937     "guestfs_safe_calloc";
5938     "guestfs_safe_malloc";
5939   ] in
5940   let functions =
5941     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5942       all_functions in
5943   let structs =
5944     List.concat (
5945       List.map (fun (typ, _) ->
5946                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5947         structs
5948     ) in
5949   let globals = List.sort compare (globals @ functions @ structs) in
5950
5951   pr "{\n";
5952   pr "    global:\n";
5953   List.iter (pr "        %s;\n") globals;
5954   pr "\n";
5955
5956   pr "    local:\n";
5957   pr "        *;\n";
5958   pr "};\n"
5959
5960 (* Generate the server-side stubs. *)
5961 and generate_daemon_actions () =
5962   generate_header CStyle GPLv2plus;
5963
5964   pr "#include <config.h>\n";
5965   pr "\n";
5966   pr "#include <stdio.h>\n";
5967   pr "#include <stdlib.h>\n";
5968   pr "#include <string.h>\n";
5969   pr "#include <inttypes.h>\n";
5970   pr "#include <rpc/types.h>\n";
5971   pr "#include <rpc/xdr.h>\n";
5972   pr "\n";
5973   pr "#include \"daemon.h\"\n";
5974   pr "#include \"c-ctype.h\"\n";
5975   pr "#include \"../src/guestfs_protocol.h\"\n";
5976   pr "#include \"actions.h\"\n";
5977   pr "\n";
5978
5979   List.iter (
5980     fun (name, style, _, _, _, _, _) ->
5981       (* Generate server-side stubs. *)
5982       pr "static void %s_stub (XDR *xdr_in)\n" name;
5983       pr "{\n";
5984       let error_code =
5985         match fst style with
5986         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5987         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5988         | RBool _ -> pr "  int r;\n"; "-1"
5989         | RConstString _ | RConstOptString _ ->
5990             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5991         | RString _ -> pr "  char *r;\n"; "NULL"
5992         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5993         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5994         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5995         | RBufferOut _ ->
5996             pr "  size_t size = 1;\n";
5997             pr "  char *r;\n";
5998             "NULL" in
5999
6000       (match snd style with
6001        | [] -> ()
6002        | args ->
6003            pr "  struct guestfs_%s_args args;\n" name;
6004            List.iter (
6005              function
6006              | Device n | Dev_or_Path n
6007              | Pathname n
6008              | String n -> ()
6009              | OptString n -> pr "  char *%s;\n" n
6010              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6011              | Bool n -> pr "  int %s;\n" n
6012              | Int n -> pr "  int %s;\n" n
6013              | Int64 n -> pr "  int64_t %s;\n" n
6014              | FileIn _ | FileOut _ -> ()
6015            ) args
6016       );
6017       pr "\n";
6018
6019       (match snd style with
6020        | [] -> ()
6021        | args ->
6022            pr "  memset (&args, 0, sizeof args);\n";
6023            pr "\n";
6024            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6025            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6026            pr "    return;\n";
6027            pr "  }\n";
6028            let pr_args n =
6029              pr "  char *%s = args.%s;\n" n n
6030            in
6031            let pr_list_handling_code n =
6032              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6033              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6034              pr "  if (%s == NULL) {\n" n;
6035              pr "    reply_with_perror (\"realloc\");\n";
6036              pr "    goto done;\n";
6037              pr "  }\n";
6038              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6039              pr "  args.%s.%s_val = %s;\n" n n n;
6040            in
6041            List.iter (
6042              function
6043              | Pathname n ->
6044                  pr_args n;
6045                  pr "  ABS_PATH (%s, goto done);\n" n;
6046              | Device n ->
6047                  pr_args n;
6048                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6049              | Dev_or_Path n ->
6050                  pr_args n;
6051                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6052              | String n -> pr_args n
6053              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6054              | StringList n ->
6055                  pr_list_handling_code n;
6056              | DeviceList n ->
6057                  pr_list_handling_code n;
6058                  pr "  /* Ensure that each is a device,\n";
6059                  pr "   * and perform device name translation. */\n";
6060                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6061                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6062                  pr "  }\n";
6063              | Bool n -> pr "  %s = args.%s;\n" n n
6064              | Int n -> pr "  %s = args.%s;\n" n n
6065              | Int64 n -> pr "  %s = args.%s;\n" n n
6066              | FileIn _ | FileOut _ -> ()
6067            ) args;
6068            pr "\n"
6069       );
6070
6071
6072       (* this is used at least for do_equal *)
6073       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6074         (* Emit NEED_ROOT just once, even when there are two or
6075            more Pathname args *)
6076         pr "  NEED_ROOT (goto done);\n";
6077       );
6078
6079       (* Don't want to call the impl with any FileIn or FileOut
6080        * parameters, since these go "outside" the RPC protocol.
6081        *)
6082       let args' =
6083         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6084           (snd style) in
6085       pr "  r = do_%s " name;
6086       generate_c_call_args (fst style, args');
6087       pr ";\n";
6088
6089       (match fst style with
6090        | RErr | RInt _ | RInt64 _ | RBool _
6091        | RConstString _ | RConstOptString _
6092        | RString _ | RStringList _ | RHashtable _
6093        | RStruct (_, _) | RStructList (_, _) ->
6094            pr "  if (r == %s)\n" error_code;
6095            pr "    /* do_%s has already called reply_with_error */\n" name;
6096            pr "    goto done;\n";
6097            pr "\n"
6098        | RBufferOut _ ->
6099            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6100            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6101            pr "   */\n";
6102            pr "  if (size == 1 && r == %s)\n" error_code;
6103            pr "    /* do_%s has already called reply_with_error */\n" name;
6104            pr "    goto done;\n";
6105            pr "\n"
6106       );
6107
6108       (* If there are any FileOut parameters, then the impl must
6109        * send its own reply.
6110        *)
6111       let no_reply =
6112         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6113       if no_reply then
6114         pr "  /* do_%s has already sent a reply */\n" name
6115       else (
6116         match fst style with
6117         | RErr -> pr "  reply (NULL, NULL);\n"
6118         | RInt n | RInt64 n | RBool n ->
6119             pr "  struct guestfs_%s_ret ret;\n" name;
6120             pr "  ret.%s = r;\n" n;
6121             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6122               name
6123         | RConstString _ | RConstOptString _ ->
6124             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6125         | RString n ->
6126             pr "  struct guestfs_%s_ret ret;\n" name;
6127             pr "  ret.%s = r;\n" n;
6128             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6129               name;
6130             pr "  free (r);\n"
6131         | RStringList n | RHashtable n ->
6132             pr "  struct guestfs_%s_ret ret;\n" name;
6133             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6134             pr "  ret.%s.%s_val = r;\n" n n;
6135             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6136               name;
6137             pr "  free_strings (r);\n"
6138         | RStruct (n, _) ->
6139             pr "  struct guestfs_%s_ret ret;\n" name;
6140             pr "  ret.%s = *r;\n" n;
6141             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6142               name;
6143             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6144               name
6145         | RStructList (n, _) ->
6146             pr "  struct guestfs_%s_ret ret;\n" name;
6147             pr "  ret.%s = *r;\n" n;
6148             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6149               name;
6150             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6151               name
6152         | RBufferOut n ->
6153             pr "  struct guestfs_%s_ret ret;\n" name;
6154             pr "  ret.%s.%s_val = r;\n" n n;
6155             pr "  ret.%s.%s_len = size;\n" n n;
6156             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6157               name;
6158             pr "  free (r);\n"
6159       );
6160
6161       (* Free the args. *)
6162       (match snd style with
6163        | [] ->
6164            pr "done: ;\n";
6165        | _ ->
6166            pr "done:\n";
6167            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6168              name
6169       );
6170
6171       pr "}\n\n";
6172   ) daemon_functions;
6173
6174   (* Dispatch function. *)
6175   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6176   pr "{\n";
6177   pr "  switch (proc_nr) {\n";
6178
6179   List.iter (
6180     fun (name, style, _, _, _, _, _) ->
6181       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6182       pr "      %s_stub (xdr_in);\n" name;
6183       pr "      break;\n"
6184   ) daemon_functions;
6185
6186   pr "    default:\n";
6187   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";
6188   pr "  }\n";
6189   pr "}\n";
6190   pr "\n";
6191
6192   (* LVM columns and tokenization functions. *)
6193   (* XXX This generates crap code.  We should rethink how we
6194    * do this parsing.
6195    *)
6196   List.iter (
6197     function
6198     | typ, cols ->
6199         pr "static const char *lvm_%s_cols = \"%s\";\n"
6200           typ (String.concat "," (List.map fst cols));
6201         pr "\n";
6202
6203         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6204         pr "{\n";
6205         pr "  char *tok, *p, *next;\n";
6206         pr "  int i, j;\n";
6207         pr "\n";
6208         (*
6209           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6210           pr "\n";
6211         *)
6212         pr "  if (!str) {\n";
6213         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6214         pr "    return -1;\n";
6215         pr "  }\n";
6216         pr "  if (!*str || c_isspace (*str)) {\n";
6217         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6218         pr "    return -1;\n";
6219         pr "  }\n";
6220         pr "  tok = str;\n";
6221         List.iter (
6222           fun (name, coltype) ->
6223             pr "  if (!tok) {\n";
6224             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6225             pr "    return -1;\n";
6226             pr "  }\n";
6227             pr "  p = strchrnul (tok, ',');\n";
6228             pr "  if (*p) next = p+1; else next = NULL;\n";
6229             pr "  *p = '\\0';\n";
6230             (match coltype with
6231              | FString ->
6232                  pr "  r->%s = strdup (tok);\n" name;
6233                  pr "  if (r->%s == NULL) {\n" name;
6234                  pr "    perror (\"strdup\");\n";
6235                  pr "    return -1;\n";
6236                  pr "  }\n"
6237              | FUUID ->
6238                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6239                  pr "    if (tok[j] == '\\0') {\n";
6240                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6241                  pr "      return -1;\n";
6242                  pr "    } else if (tok[j] != '-')\n";
6243                  pr "      r->%s[i++] = tok[j];\n" name;
6244                  pr "  }\n";
6245              | FBytes ->
6246                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6247                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6248                  pr "    return -1;\n";
6249                  pr "  }\n";
6250              | FInt64 ->
6251                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6252                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6253                  pr "    return -1;\n";
6254                  pr "  }\n";
6255              | FOptPercent ->
6256                  pr "  if (tok[0] == '\\0')\n";
6257                  pr "    r->%s = -1;\n" name;
6258                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6259                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6260                  pr "    return -1;\n";
6261                  pr "  }\n";
6262              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6263                  assert false (* can never be an LVM column *)
6264             );
6265             pr "  tok = next;\n";
6266         ) cols;
6267
6268         pr "  if (tok != NULL) {\n";
6269         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6270         pr "    return -1;\n";
6271         pr "  }\n";
6272         pr "  return 0;\n";
6273         pr "}\n";
6274         pr "\n";
6275
6276         pr "guestfs_int_lvm_%s_list *\n" typ;
6277         pr "parse_command_line_%ss (void)\n" typ;
6278         pr "{\n";
6279         pr "  char *out, *err;\n";
6280         pr "  char *p, *pend;\n";
6281         pr "  int r, i;\n";
6282         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6283         pr "  void *newp;\n";
6284         pr "\n";
6285         pr "  ret = malloc (sizeof *ret);\n";
6286         pr "  if (!ret) {\n";
6287         pr "    reply_with_perror (\"malloc\");\n";
6288         pr "    return NULL;\n";
6289         pr "  }\n";
6290         pr "\n";
6291         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6292         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6293         pr "\n";
6294         pr "  r = command (&out, &err,\n";
6295         pr "           \"lvm\", \"%ss\",\n" typ;
6296         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6297         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6298         pr "  if (r == -1) {\n";
6299         pr "    reply_with_error (\"%%s\", err);\n";
6300         pr "    free (out);\n";
6301         pr "    free (err);\n";
6302         pr "    free (ret);\n";
6303         pr "    return NULL;\n";
6304         pr "  }\n";
6305         pr "\n";
6306         pr "  free (err);\n";
6307         pr "\n";
6308         pr "  /* Tokenize each line of the output. */\n";
6309         pr "  p = out;\n";
6310         pr "  i = 0;\n";
6311         pr "  while (p) {\n";
6312         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6313         pr "    if (pend) {\n";
6314         pr "      *pend = '\\0';\n";
6315         pr "      pend++;\n";
6316         pr "    }\n";
6317         pr "\n";
6318         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6319         pr "      p++;\n";
6320         pr "\n";
6321         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6322         pr "      p = pend;\n";
6323         pr "      continue;\n";
6324         pr "    }\n";
6325         pr "\n";
6326         pr "    /* Allocate some space to store this next entry. */\n";
6327         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6328         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6329         pr "    if (newp == NULL) {\n";
6330         pr "      reply_with_perror (\"realloc\");\n";
6331         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6332         pr "      free (ret);\n";
6333         pr "      free (out);\n";
6334         pr "      return NULL;\n";
6335         pr "    }\n";
6336         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6337         pr "\n";
6338         pr "    /* Tokenize the next entry. */\n";
6339         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6340         pr "    if (r == -1) {\n";
6341         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6342         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6343         pr "      free (ret);\n";
6344         pr "      free (out);\n";
6345         pr "      return NULL;\n";
6346         pr "    }\n";
6347         pr "\n";
6348         pr "    ++i;\n";
6349         pr "    p = pend;\n";
6350         pr "  }\n";
6351         pr "\n";
6352         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6353         pr "\n";
6354         pr "  free (out);\n";
6355         pr "  return ret;\n";
6356         pr "}\n"
6357
6358   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6359
6360 (* Generate a list of function names, for debugging in the daemon.. *)
6361 and generate_daemon_names () =
6362   generate_header CStyle GPLv2plus;
6363
6364   pr "#include <config.h>\n";
6365   pr "\n";
6366   pr "#include \"daemon.h\"\n";
6367   pr "\n";
6368
6369   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6370   pr "const char *function_names[] = {\n";
6371   List.iter (
6372     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6373   ) daemon_functions;
6374   pr "};\n";
6375
6376 (* Generate the optional groups for the daemon to implement
6377  * guestfs_available.
6378  *)
6379 and generate_daemon_optgroups_c () =
6380   generate_header CStyle GPLv2plus;
6381
6382   pr "#include <config.h>\n";
6383   pr "\n";
6384   pr "#include \"daemon.h\"\n";
6385   pr "#include \"optgroups.h\"\n";
6386   pr "\n";
6387
6388   pr "struct optgroup optgroups[] = {\n";
6389   List.iter (
6390     fun (group, _) ->
6391       pr "  { \"%s\", optgroup_%s_available },\n" group group
6392   ) optgroups;
6393   pr "  { NULL, NULL }\n";
6394   pr "};\n"
6395
6396 and generate_daemon_optgroups_h () =
6397   generate_header CStyle GPLv2plus;
6398
6399   List.iter (
6400     fun (group, _) ->
6401       pr "extern int optgroup_%s_available (void);\n" group
6402   ) optgroups
6403
6404 (* Generate the tests. *)
6405 and generate_tests () =
6406   generate_header CStyle GPLv2plus;
6407
6408   pr "\
6409 #include <stdio.h>
6410 #include <stdlib.h>
6411 #include <string.h>
6412 #include <unistd.h>
6413 #include <sys/types.h>
6414 #include <fcntl.h>
6415
6416 #include \"guestfs.h\"
6417 #include \"guestfs-internal.h\"
6418
6419 static guestfs_h *g;
6420 static int suppress_error = 0;
6421
6422 static void print_error (guestfs_h *g, void *data, const char *msg)
6423 {
6424   if (!suppress_error)
6425     fprintf (stderr, \"%%s\\n\", msg);
6426 }
6427
6428 /* FIXME: nearly identical code appears in fish.c */
6429 static void print_strings (char *const *argv)
6430 {
6431   int argc;
6432
6433   for (argc = 0; argv[argc] != NULL; ++argc)
6434     printf (\"\\t%%s\\n\", argv[argc]);
6435 }
6436
6437 /*
6438 static void print_table (char const *const *argv)
6439 {
6440   int i;
6441
6442   for (i = 0; argv[i] != NULL; i += 2)
6443     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6444 }
6445 */
6446
6447 ";
6448
6449   (* Generate a list of commands which are not tested anywhere. *)
6450   pr "static void no_test_warnings (void)\n";
6451   pr "{\n";
6452
6453   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6454   List.iter (
6455     fun (_, _, _, _, tests, _, _) ->
6456       let tests = filter_map (
6457         function
6458         | (_, (Always|If _|Unless _), test) -> Some test
6459         | (_, Disabled, _) -> None
6460       ) tests in
6461       let seq = List.concat (List.map seq_of_test tests) in
6462       let cmds_tested = List.map List.hd seq in
6463       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6464   ) all_functions;
6465
6466   List.iter (
6467     fun (name, _, _, _, _, _, _) ->
6468       if not (Hashtbl.mem hash name) then
6469         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6470   ) all_functions;
6471
6472   pr "}\n";
6473   pr "\n";
6474
6475   (* Generate the actual tests.  Note that we generate the tests
6476    * in reverse order, deliberately, so that (in general) the
6477    * newest tests run first.  This makes it quicker and easier to
6478    * debug them.
6479    *)
6480   let test_names =
6481     List.map (
6482       fun (name, _, _, flags, tests, _, _) ->
6483         mapi (generate_one_test name flags) tests
6484     ) (List.rev all_functions) in
6485   let test_names = List.concat test_names in
6486   let nr_tests = List.length test_names in
6487
6488   pr "\
6489 int main (int argc, char *argv[])
6490 {
6491   char c = 0;
6492   unsigned long int n_failed = 0;
6493   const char *filename;
6494   int fd;
6495   int nr_tests, test_num = 0;
6496
6497   setbuf (stdout, NULL);
6498
6499   no_test_warnings ();
6500
6501   g = guestfs_create ();
6502   if (g == NULL) {
6503     printf (\"guestfs_create FAILED\\n\");
6504     exit (EXIT_FAILURE);
6505   }
6506
6507   guestfs_set_error_handler (g, print_error, NULL);
6508
6509   guestfs_set_path (g, \"../appliance\");
6510
6511   filename = \"test1.img\";
6512   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6513   if (fd == -1) {
6514     perror (filename);
6515     exit (EXIT_FAILURE);
6516   }
6517   if (lseek (fd, %d, SEEK_SET) == -1) {
6518     perror (\"lseek\");
6519     close (fd);
6520     unlink (filename);
6521     exit (EXIT_FAILURE);
6522   }
6523   if (write (fd, &c, 1) == -1) {
6524     perror (\"write\");
6525     close (fd);
6526     unlink (filename);
6527     exit (EXIT_FAILURE);
6528   }
6529   if (close (fd) == -1) {
6530     perror (filename);
6531     unlink (filename);
6532     exit (EXIT_FAILURE);
6533   }
6534   if (guestfs_add_drive (g, filename) == -1) {
6535     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6536     exit (EXIT_FAILURE);
6537   }
6538
6539   filename = \"test2.img\";
6540   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6541   if (fd == -1) {
6542     perror (filename);
6543     exit (EXIT_FAILURE);
6544   }
6545   if (lseek (fd, %d, SEEK_SET) == -1) {
6546     perror (\"lseek\");
6547     close (fd);
6548     unlink (filename);
6549     exit (EXIT_FAILURE);
6550   }
6551   if (write (fd, &c, 1) == -1) {
6552     perror (\"write\");
6553     close (fd);
6554     unlink (filename);
6555     exit (EXIT_FAILURE);
6556   }
6557   if (close (fd) == -1) {
6558     perror (filename);
6559     unlink (filename);
6560     exit (EXIT_FAILURE);
6561   }
6562   if (guestfs_add_drive (g, filename) == -1) {
6563     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6564     exit (EXIT_FAILURE);
6565   }
6566
6567   filename = \"test3.img\";
6568   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6569   if (fd == -1) {
6570     perror (filename);
6571     exit (EXIT_FAILURE);
6572   }
6573   if (lseek (fd, %d, SEEK_SET) == -1) {
6574     perror (\"lseek\");
6575     close (fd);
6576     unlink (filename);
6577     exit (EXIT_FAILURE);
6578   }
6579   if (write (fd, &c, 1) == -1) {
6580     perror (\"write\");
6581     close (fd);
6582     unlink (filename);
6583     exit (EXIT_FAILURE);
6584   }
6585   if (close (fd) == -1) {
6586     perror (filename);
6587     unlink (filename);
6588     exit (EXIT_FAILURE);
6589   }
6590   if (guestfs_add_drive (g, filename) == -1) {
6591     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6592     exit (EXIT_FAILURE);
6593   }
6594
6595   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6596     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6597     exit (EXIT_FAILURE);
6598   }
6599
6600   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6601   alarm (600);
6602
6603   if (guestfs_launch (g) == -1) {
6604     printf (\"guestfs_launch FAILED\\n\");
6605     exit (EXIT_FAILURE);
6606   }
6607
6608   /* Cancel previous alarm. */
6609   alarm (0);
6610
6611   nr_tests = %d;
6612
6613 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6614
6615   iteri (
6616     fun i test_name ->
6617       pr "  test_num++;\n";
6618       pr "  if (guestfs_get_verbose (g))\n";
6619       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6620       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6621       pr "  if (%s () == -1) {\n" test_name;
6622       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6623       pr "    n_failed++;\n";
6624       pr "  }\n";
6625   ) test_names;
6626   pr "\n";
6627
6628   pr "  guestfs_close (g);\n";
6629   pr "  unlink (\"test1.img\");\n";
6630   pr "  unlink (\"test2.img\");\n";
6631   pr "  unlink (\"test3.img\");\n";
6632   pr "\n";
6633
6634   pr "  if (n_failed > 0) {\n";
6635   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6636   pr "    exit (EXIT_FAILURE);\n";
6637   pr "  }\n";
6638   pr "\n";
6639
6640   pr "  exit (EXIT_SUCCESS);\n";
6641   pr "}\n"
6642
6643 and generate_one_test name flags i (init, prereq, test) =
6644   let test_name = sprintf "test_%s_%d" name i in
6645
6646   pr "\
6647 static int %s_skip (void)
6648 {
6649   const char *str;
6650
6651   str = getenv (\"TEST_ONLY\");
6652   if (str)
6653     return strstr (str, \"%s\") == NULL;
6654   str = getenv (\"SKIP_%s\");
6655   if (str && STREQ (str, \"1\")) return 1;
6656   str = getenv (\"SKIP_TEST_%s\");
6657   if (str && STREQ (str, \"1\")) return 1;
6658   return 0;
6659 }
6660
6661 " test_name name (String.uppercase test_name) (String.uppercase name);
6662
6663   (match prereq with
6664    | Disabled | Always -> ()
6665    | If code | Unless code ->
6666        pr "static int %s_prereq (void)\n" test_name;
6667        pr "{\n";
6668        pr "  %s\n" code;
6669        pr "}\n";
6670        pr "\n";
6671   );
6672
6673   pr "\
6674 static int %s (void)
6675 {
6676   if (%s_skip ()) {
6677     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6678     return 0;
6679   }
6680
6681 " test_name test_name test_name;
6682
6683   (* Optional functions should only be tested if the relevant
6684    * support is available in the daemon.
6685    *)
6686   List.iter (
6687     function
6688     | Optional group ->
6689         pr "  {\n";
6690         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6691         pr "    int r;\n";
6692         pr "    suppress_error = 1;\n";
6693         pr "    r = guestfs_available (g, (char **) groups);\n";
6694         pr "    suppress_error = 0;\n";
6695         pr "    if (r == -1) {\n";
6696         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6697         pr "      return 0;\n";
6698         pr "    }\n";
6699         pr "  }\n";
6700     | _ -> ()
6701   ) flags;
6702
6703   (match prereq with
6704    | Disabled ->
6705        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6706    | If _ ->
6707        pr "  if (! %s_prereq ()) {\n" test_name;
6708        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6709        pr "    return 0;\n";
6710        pr "  }\n";
6711        pr "\n";
6712        generate_one_test_body name i test_name init test;
6713    | Unless _ ->
6714        pr "  if (%s_prereq ()) {\n" test_name;
6715        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6716        pr "    return 0;\n";
6717        pr "  }\n";
6718        pr "\n";
6719        generate_one_test_body name i test_name init test;
6720    | Always ->
6721        generate_one_test_body name i test_name init test
6722   );
6723
6724   pr "  return 0;\n";
6725   pr "}\n";
6726   pr "\n";
6727   test_name
6728
6729 and generate_one_test_body name i test_name init test =
6730   (match init with
6731    | InitNone (* XXX at some point, InitNone and InitEmpty became
6732                * folded together as the same thing.  Really we should
6733                * make InitNone do nothing at all, but the tests may
6734                * need to be checked to make sure this is OK.
6735                *)
6736    | InitEmpty ->
6737        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6738        List.iter (generate_test_command_call test_name)
6739          [["blockdev_setrw"; "/dev/sda"];
6740           ["umount_all"];
6741           ["lvm_remove_all"]]
6742    | InitPartition ->
6743        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6744        List.iter (generate_test_command_call test_name)
6745          [["blockdev_setrw"; "/dev/sda"];
6746           ["umount_all"];
6747           ["lvm_remove_all"];
6748           ["part_disk"; "/dev/sda"; "mbr"]]
6749    | InitBasicFS ->
6750        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6751        List.iter (generate_test_command_call test_name)
6752          [["blockdev_setrw"; "/dev/sda"];
6753           ["umount_all"];
6754           ["lvm_remove_all"];
6755           ["part_disk"; "/dev/sda"; "mbr"];
6756           ["mkfs"; "ext2"; "/dev/sda1"];
6757           ["mount_options"; ""; "/dev/sda1"; "/"]]
6758    | InitBasicFSonLVM ->
6759        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6760          test_name;
6761        List.iter (generate_test_command_call test_name)
6762          [["blockdev_setrw"; "/dev/sda"];
6763           ["umount_all"];
6764           ["lvm_remove_all"];
6765           ["part_disk"; "/dev/sda"; "mbr"];
6766           ["pvcreate"; "/dev/sda1"];
6767           ["vgcreate"; "VG"; "/dev/sda1"];
6768           ["lvcreate"; "LV"; "VG"; "8"];
6769           ["mkfs"; "ext2"; "/dev/VG/LV"];
6770           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6771    | InitISOFS ->
6772        pr "  /* InitISOFS for %s */\n" test_name;
6773        List.iter (generate_test_command_call test_name)
6774          [["blockdev_setrw"; "/dev/sda"];
6775           ["umount_all"];
6776           ["lvm_remove_all"];
6777           ["mount_ro"; "/dev/sdd"; "/"]]
6778   );
6779
6780   let get_seq_last = function
6781     | [] ->
6782         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6783           test_name
6784     | seq ->
6785         let seq = List.rev seq in
6786         List.rev (List.tl seq), List.hd seq
6787   in
6788
6789   match test with
6790   | TestRun seq ->
6791       pr "  /* TestRun for %s (%d) */\n" name i;
6792       List.iter (generate_test_command_call test_name) seq
6793   | TestOutput (seq, expected) ->
6794       pr "  /* TestOutput for %s (%d) */\n" name i;
6795       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6796       let seq, last = get_seq_last seq in
6797       let test () =
6798         pr "    if (STRNEQ (r, expected)) {\n";
6799         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6800         pr "      return -1;\n";
6801         pr "    }\n"
6802       in
6803       List.iter (generate_test_command_call test_name) seq;
6804       generate_test_command_call ~test test_name last
6805   | TestOutputList (seq, expected) ->
6806       pr "  /* TestOutputList for %s (%d) */\n" name i;
6807       let seq, last = get_seq_last seq in
6808       let test () =
6809         iteri (
6810           fun i str ->
6811             pr "    if (!r[%d]) {\n" i;
6812             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6813             pr "      print_strings (r);\n";
6814             pr "      return -1;\n";
6815             pr "    }\n";
6816             pr "    {\n";
6817             pr "      const char *expected = \"%s\";\n" (c_quote str);
6818             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6819             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6820             pr "        return -1;\n";
6821             pr "      }\n";
6822             pr "    }\n"
6823         ) expected;
6824         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6825         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6826           test_name;
6827         pr "      print_strings (r);\n";
6828         pr "      return -1;\n";
6829         pr "    }\n"
6830       in
6831       List.iter (generate_test_command_call test_name) seq;
6832       generate_test_command_call ~test test_name last
6833   | TestOutputListOfDevices (seq, expected) ->
6834       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6835       let seq, last = get_seq_last seq in
6836       let test () =
6837         iteri (
6838           fun i str ->
6839             pr "    if (!r[%d]) {\n" i;
6840             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6841             pr "      print_strings (r);\n";
6842             pr "      return -1;\n";
6843             pr "    }\n";
6844             pr "    {\n";
6845             pr "      const char *expected = \"%s\";\n" (c_quote str);
6846             pr "      r[%d][5] = 's';\n" i;
6847             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6848             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6849             pr "        return -1;\n";
6850             pr "      }\n";
6851             pr "    }\n"
6852         ) expected;
6853         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6854         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6855           test_name;
6856         pr "      print_strings (r);\n";
6857         pr "      return -1;\n";
6858         pr "    }\n"
6859       in
6860       List.iter (generate_test_command_call test_name) seq;
6861       generate_test_command_call ~test test_name last
6862   | TestOutputInt (seq, expected) ->
6863       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6864       let seq, last = get_seq_last seq in
6865       let test () =
6866         pr "    if (r != %d) {\n" expected;
6867         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6868           test_name expected;
6869         pr "               (int) r);\n";
6870         pr "      return -1;\n";
6871         pr "    }\n"
6872       in
6873       List.iter (generate_test_command_call test_name) seq;
6874       generate_test_command_call ~test test_name last
6875   | TestOutputIntOp (seq, op, expected) ->
6876       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6877       let seq, last = get_seq_last seq in
6878       let test () =
6879         pr "    if (! (r %s %d)) {\n" op expected;
6880         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6881           test_name op expected;
6882         pr "               (int) r);\n";
6883         pr "      return -1;\n";
6884         pr "    }\n"
6885       in
6886       List.iter (generate_test_command_call test_name) seq;
6887       generate_test_command_call ~test test_name last
6888   | TestOutputTrue seq ->
6889       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6890       let seq, last = get_seq_last seq in
6891       let test () =
6892         pr "    if (!r) {\n";
6893         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6894           test_name;
6895         pr "      return -1;\n";
6896         pr "    }\n"
6897       in
6898       List.iter (generate_test_command_call test_name) seq;
6899       generate_test_command_call ~test test_name last
6900   | TestOutputFalse seq ->
6901       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6902       let seq, last = get_seq_last seq in
6903       let test () =
6904         pr "    if (r) {\n";
6905         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6906           test_name;
6907         pr "      return -1;\n";
6908         pr "    }\n"
6909       in
6910       List.iter (generate_test_command_call test_name) seq;
6911       generate_test_command_call ~test test_name last
6912   | TestOutputLength (seq, expected) ->
6913       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6914       let seq, last = get_seq_last seq in
6915       let test () =
6916         pr "    int j;\n";
6917         pr "    for (j = 0; j < %d; ++j)\n" expected;
6918         pr "      if (r[j] == NULL) {\n";
6919         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6920           test_name;
6921         pr "        print_strings (r);\n";
6922         pr "        return -1;\n";
6923         pr "      }\n";
6924         pr "    if (r[j] != NULL) {\n";
6925         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6926           test_name;
6927         pr "      print_strings (r);\n";
6928         pr "      return -1;\n";
6929         pr "    }\n"
6930       in
6931       List.iter (generate_test_command_call test_name) seq;
6932       generate_test_command_call ~test test_name last
6933   | TestOutputBuffer (seq, expected) ->
6934       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6935       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6936       let seq, last = get_seq_last seq in
6937       let len = String.length expected in
6938       let test () =
6939         pr "    if (size != %d) {\n" len;
6940         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6941         pr "      return -1;\n";
6942         pr "    }\n";
6943         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6944         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6945         pr "      return -1;\n";
6946         pr "    }\n"
6947       in
6948       List.iter (generate_test_command_call test_name) seq;
6949       generate_test_command_call ~test test_name last
6950   | TestOutputStruct (seq, checks) ->
6951       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6952       let seq, last = get_seq_last seq in
6953       let test () =
6954         List.iter (
6955           function
6956           | CompareWithInt (field, expected) ->
6957               pr "    if (r->%s != %d) {\n" field expected;
6958               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6959                 test_name field expected;
6960               pr "               (int) r->%s);\n" field;
6961               pr "      return -1;\n";
6962               pr "    }\n"
6963           | CompareWithIntOp (field, op, expected) ->
6964               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6965               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6966                 test_name field op expected;
6967               pr "               (int) r->%s);\n" field;
6968               pr "      return -1;\n";
6969               pr "    }\n"
6970           | CompareWithString (field, expected) ->
6971               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6972               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6973                 test_name field expected;
6974               pr "               r->%s);\n" field;
6975               pr "      return -1;\n";
6976               pr "    }\n"
6977           | CompareFieldsIntEq (field1, field2) ->
6978               pr "    if (r->%s != r->%s) {\n" field1 field2;
6979               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6980                 test_name field1 field2;
6981               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6982               pr "      return -1;\n";
6983               pr "    }\n"
6984           | CompareFieldsStrEq (field1, field2) ->
6985               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6986               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6987                 test_name field1 field2;
6988               pr "               r->%s, r->%s);\n" field1 field2;
6989               pr "      return -1;\n";
6990               pr "    }\n"
6991         ) checks
6992       in
6993       List.iter (generate_test_command_call test_name) seq;
6994       generate_test_command_call ~test test_name last
6995   | TestLastFail seq ->
6996       pr "  /* TestLastFail for %s (%d) */\n" name i;
6997       let seq, last = get_seq_last seq in
6998       List.iter (generate_test_command_call test_name) seq;
6999       generate_test_command_call test_name ~expect_error:true last
7000
7001 (* Generate the code to run a command, leaving the result in 'r'.
7002  * If you expect to get an error then you should set expect_error:true.
7003  *)
7004 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7005   match cmd with
7006   | [] -> assert false
7007   | name :: args ->
7008       (* Look up the command to find out what args/ret it has. *)
7009       let style =
7010         try
7011           let _, style, _, _, _, _, _ =
7012             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7013           style
7014         with Not_found ->
7015           failwithf "%s: in test, command %s was not found" test_name name in
7016
7017       if List.length (snd style) <> List.length args then
7018         failwithf "%s: in test, wrong number of args given to %s"
7019           test_name name;
7020
7021       pr "  {\n";
7022
7023       List.iter (
7024         function
7025         | OptString n, "NULL" -> ()
7026         | Pathname n, arg
7027         | Device n, arg
7028         | Dev_or_Path n, arg
7029         | String n, arg
7030         | OptString n, arg ->
7031             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7032         | Int _, _
7033         | Int64 _, _
7034         | Bool _, _
7035         | FileIn _, _ | FileOut _, _ -> ()
7036         | StringList n, "" | DeviceList n, "" ->
7037             pr "    const char *const %s[1] = { NULL };\n" n
7038         | StringList n, arg | DeviceList n, arg ->
7039             let strs = string_split " " arg in
7040             iteri (
7041               fun i str ->
7042                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7043             ) strs;
7044             pr "    const char *const %s[] = {\n" n;
7045             iteri (
7046               fun i _ -> pr "      %s_%d,\n" n i
7047             ) strs;
7048             pr "      NULL\n";
7049             pr "    };\n";
7050       ) (List.combine (snd style) args);
7051
7052       let error_code =
7053         match fst style with
7054         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7055         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7056         | RConstString _ | RConstOptString _ ->
7057             pr "    const char *r;\n"; "NULL"
7058         | RString _ -> pr "    char *r;\n"; "NULL"
7059         | RStringList _ | RHashtable _ ->
7060             pr "    char **r;\n";
7061             pr "    int i;\n";
7062             "NULL"
7063         | RStruct (_, typ) ->
7064             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7065         | RStructList (_, typ) ->
7066             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7067         | RBufferOut _ ->
7068             pr "    char *r;\n";
7069             pr "    size_t size;\n";
7070             "NULL" in
7071
7072       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7073       pr "    r = guestfs_%s (g" name;
7074
7075       (* Generate the parameters. *)
7076       List.iter (
7077         function
7078         | OptString _, "NULL" -> pr ", NULL"
7079         | Pathname n, _
7080         | Device n, _ | Dev_or_Path n, _
7081         | String n, _
7082         | OptString n, _ ->
7083             pr ", %s" n
7084         | FileIn _, arg | FileOut _, arg ->
7085             pr ", \"%s\"" (c_quote arg)
7086         | StringList n, _ | DeviceList n, _ ->
7087             pr ", (char **) %s" n
7088         | Int _, arg ->
7089             let i =
7090               try int_of_string arg
7091               with Failure "int_of_string" ->
7092                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7093             pr ", %d" i
7094         | Int64 _, arg ->
7095             let i =
7096               try Int64.of_string arg
7097               with Failure "int_of_string" ->
7098                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7099             pr ", %Ld" i
7100         | Bool _, arg ->
7101             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7102       ) (List.combine (snd style) args);
7103
7104       (match fst style with
7105        | RBufferOut _ -> pr ", &size"
7106        | _ -> ()
7107       );
7108
7109       pr ");\n";
7110
7111       if not expect_error then
7112         pr "    if (r == %s)\n" error_code
7113       else
7114         pr "    if (r != %s)\n" error_code;
7115       pr "      return -1;\n";
7116
7117       (* Insert the test code. *)
7118       (match test with
7119        | None -> ()
7120        | Some f -> f ()
7121       );
7122
7123       (match fst style with
7124        | RErr | RInt _ | RInt64 _ | RBool _
7125        | RConstString _ | RConstOptString _ -> ()
7126        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7127        | RStringList _ | RHashtable _ ->
7128            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7129            pr "      free (r[i]);\n";
7130            pr "    free (r);\n"
7131        | RStruct (_, typ) ->
7132            pr "    guestfs_free_%s (r);\n" typ
7133        | RStructList (_, typ) ->
7134            pr "    guestfs_free_%s_list (r);\n" typ
7135       );
7136
7137       pr "  }\n"
7138
7139 and c_quote str =
7140   let str = replace_str str "\r" "\\r" in
7141   let str = replace_str str "\n" "\\n" in
7142   let str = replace_str str "\t" "\\t" in
7143   let str = replace_str str "\000" "\\0" in
7144   str
7145
7146 (* Generate a lot of different functions for guestfish. *)
7147 and generate_fish_cmds () =
7148   generate_header CStyle GPLv2plus;
7149
7150   let all_functions =
7151     List.filter (
7152       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7153     ) all_functions in
7154   let all_functions_sorted =
7155     List.filter (
7156       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7157     ) all_functions_sorted in
7158
7159   pr "#include <config.h>\n";
7160   pr "\n";
7161   pr "#include <stdio.h>\n";
7162   pr "#include <stdlib.h>\n";
7163   pr "#include <string.h>\n";
7164   pr "#include <inttypes.h>\n";
7165   pr "\n";
7166   pr "#include <guestfs.h>\n";
7167   pr "#include \"c-ctype.h\"\n";
7168   pr "#include \"full-write.h\"\n";
7169   pr "#include \"xstrtol.h\"\n";
7170   pr "#include \"fish.h\"\n";
7171   pr "\n";
7172
7173   (* list_commands function, which implements guestfish -h *)
7174   pr "void list_commands (void)\n";
7175   pr "{\n";
7176   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7177   pr "  list_builtin_commands ();\n";
7178   List.iter (
7179     fun (name, _, _, flags, _, shortdesc, _) ->
7180       let name = replace_char name '_' '-' in
7181       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7182         name shortdesc
7183   ) all_functions_sorted;
7184   pr "  printf (\"    %%s\\n\",";
7185   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7186   pr "}\n";
7187   pr "\n";
7188
7189   (* display_command function, which implements guestfish -h cmd *)
7190   pr "void display_command (const char *cmd)\n";
7191   pr "{\n";
7192   List.iter (
7193     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7194       let name2 = replace_char name '_' '-' in
7195       let alias =
7196         try find_map (function FishAlias n -> Some n | _ -> None) flags
7197         with Not_found -> name in
7198       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7199       let synopsis =
7200         match snd style with
7201         | [] -> name2
7202         | args ->
7203             sprintf "%s %s"
7204               name2 (String.concat " " (List.map name_of_argt args)) in
7205
7206       let warnings =
7207         if List.mem ProtocolLimitWarning flags then
7208           ("\n\n" ^ protocol_limit_warning)
7209         else "" in
7210
7211       (* For DangerWillRobinson commands, we should probably have
7212        * guestfish prompt before allowing you to use them (especially
7213        * in interactive mode). XXX
7214        *)
7215       let warnings =
7216         warnings ^
7217           if List.mem DangerWillRobinson flags then
7218             ("\n\n" ^ danger_will_robinson)
7219           else "" in
7220
7221       let warnings =
7222         warnings ^
7223           match deprecation_notice flags with
7224           | None -> ""
7225           | Some txt -> "\n\n" ^ txt in
7226
7227       let describe_alias =
7228         if name <> alias then
7229           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7230         else "" in
7231
7232       pr "  if (";
7233       pr "STRCASEEQ (cmd, \"%s\")" name;
7234       if name <> name2 then
7235         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7236       if name <> alias then
7237         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7238       pr ")\n";
7239       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7240         name2 shortdesc
7241         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7242          "=head1 DESCRIPTION\n\n" ^
7243          longdesc ^ warnings ^ describe_alias);
7244       pr "  else\n"
7245   ) all_functions;
7246   pr "    display_builtin_command (cmd);\n";
7247   pr "}\n";
7248   pr "\n";
7249
7250   let emit_print_list_function typ =
7251     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7252       typ typ typ;
7253     pr "{\n";
7254     pr "  unsigned int i;\n";
7255     pr "\n";
7256     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7257     pr "    printf (\"[%%d] = {\\n\", i);\n";
7258     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7259     pr "    printf (\"}\\n\");\n";
7260     pr "  }\n";
7261     pr "}\n";
7262     pr "\n";
7263   in
7264
7265   (* print_* functions *)
7266   List.iter (
7267     fun (typ, cols) ->
7268       let needs_i =
7269         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7270
7271       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7272       pr "{\n";
7273       if needs_i then (
7274         pr "  unsigned int i;\n";
7275         pr "\n"
7276       );
7277       List.iter (
7278         function
7279         | name, FString ->
7280             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7281         | name, FUUID ->
7282             pr "  printf (\"%%s%s: \", indent);\n" name;
7283             pr "  for (i = 0; i < 32; ++i)\n";
7284             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7285             pr "  printf (\"\\n\");\n"
7286         | name, FBuffer ->
7287             pr "  printf (\"%%s%s: \", indent);\n" name;
7288             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7289             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7290             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7291             pr "    else\n";
7292             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7293             pr "  printf (\"\\n\");\n"
7294         | name, (FUInt64|FBytes) ->
7295             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7296               name typ name
7297         | name, FInt64 ->
7298             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7299               name typ name
7300         | name, FUInt32 ->
7301             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7302               name typ name
7303         | name, FInt32 ->
7304             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7305               name typ name
7306         | name, FChar ->
7307             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7308               name typ name
7309         | name, FOptPercent ->
7310             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7311               typ name name typ name;
7312             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7313       ) cols;
7314       pr "}\n";
7315       pr "\n";
7316   ) structs;
7317
7318   (* Emit a print_TYPE_list function definition only if that function is used. *)
7319   List.iter (
7320     function
7321     | typ, (RStructListOnly | RStructAndList) ->
7322         (* generate the function for typ *)
7323         emit_print_list_function typ
7324     | typ, _ -> () (* empty *)
7325   ) (rstructs_used_by all_functions);
7326
7327   (* Emit a print_TYPE function definition only if that function is used. *)
7328   List.iter (
7329     function
7330     | typ, (RStructOnly | RStructAndList) ->
7331         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7332         pr "{\n";
7333         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7334         pr "}\n";
7335         pr "\n";
7336     | typ, _ -> () (* empty *)
7337   ) (rstructs_used_by all_functions);
7338
7339   (* run_<action> actions *)
7340   List.iter (
7341     fun (name, style, _, flags, _, _, _) ->
7342       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7343       pr "{\n";
7344       (match fst style with
7345        | RErr
7346        | RInt _
7347        | RBool _ -> pr "  int r;\n"
7348        | RInt64 _ -> pr "  int64_t r;\n"
7349        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7350        | RString _ -> pr "  char *r;\n"
7351        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7352        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7353        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7354        | RBufferOut _ ->
7355            pr "  char *r;\n";
7356            pr "  size_t size;\n";
7357       );
7358       List.iter (
7359         function
7360         | Device n
7361         | String n
7362         | OptString n
7363         | FileIn n
7364         | FileOut n -> pr "  const char *%s;\n" n
7365         | Pathname n
7366         | Dev_or_Path n -> pr "  char *%s;\n" n
7367         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7368         | Bool n -> pr "  int %s;\n" n
7369         | Int n -> pr "  int %s;\n" n
7370         | Int64 n -> pr "  int64_t %s;\n" n
7371       ) (snd style);
7372
7373       (* Check and convert parameters. *)
7374       let argc_expected = List.length (snd style) in
7375       pr "  if (argc != %d) {\n" argc_expected;
7376       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7377         argc_expected;
7378       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7379       pr "    return -1;\n";
7380       pr "  }\n";
7381
7382       let parse_integer fn fntyp rtyp range name i =
7383         pr "  {\n";
7384         pr "    strtol_error xerr;\n";
7385         pr "    %s r;\n" fntyp;
7386         pr "\n";
7387         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7388         pr "    if (xerr != LONGINT_OK) {\n";
7389         pr "      fprintf (stderr,\n";
7390         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7391         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7392         pr "      return -1;\n";
7393         pr "    }\n";
7394         (match range with
7395          | None -> ()
7396          | Some (min, max, comment) ->
7397              pr "    /* %s */\n" comment;
7398              pr "    if (r < %s || r > %s) {\n" min max;
7399              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7400                name;
7401              pr "      return -1;\n";
7402              pr "    }\n";
7403              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7404         );
7405         pr "    %s = r;\n" name;
7406         pr "  }\n";
7407       in
7408
7409       iteri (
7410         fun i ->
7411           function
7412           | Device name
7413           | String name ->
7414               pr "  %s = argv[%d];\n" name i
7415           | Pathname name
7416           | Dev_or_Path name ->
7417               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7418               pr "  if (%s == NULL) return -1;\n" name
7419           | OptString name ->
7420               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7421                 name i i
7422           | FileIn name ->
7423               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7424                 name i i
7425           | FileOut name ->
7426               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7427                 name i i
7428           | StringList name | DeviceList name ->
7429               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7430               pr "  if (%s == NULL) return -1;\n" name;
7431           | Bool name ->
7432               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7433           | Int name ->
7434               let range =
7435                 let min = "(-(2LL<<30))"
7436                 and max = "((2LL<<30)-1)"
7437                 and comment =
7438                   "The Int type in the generator is a signed 31 bit int." in
7439                 Some (min, max, comment) in
7440               parse_integer "xstrtoll" "long long" "int" range name i
7441           | Int64 name ->
7442               parse_integer "xstrtoll" "long long" "int64_t" None name i
7443       ) (snd style);
7444
7445       (* Call C API function. *)
7446       let fn =
7447         try find_map (function FishAction n -> Some n | _ -> None) flags
7448         with Not_found -> sprintf "guestfs_%s" name in
7449       pr "  r = %s " fn;
7450       generate_c_call_args ~handle:"g" style;
7451       pr ";\n";
7452
7453       List.iter (
7454         function
7455         | Device name | String name
7456         | OptString name | FileIn name | FileOut name | Bool name
7457         | Int name | Int64 name -> ()
7458         | Pathname name | Dev_or_Path name ->
7459             pr "  free (%s);\n" name
7460         | StringList name | DeviceList name ->
7461             pr "  free_strings (%s);\n" name
7462       ) (snd style);
7463
7464       (* Check return value for errors and display command results. *)
7465       (match fst style with
7466        | RErr -> pr "  return r;\n"
7467        | RInt _ ->
7468            pr "  if (r == -1) return -1;\n";
7469            pr "  printf (\"%%d\\n\", r);\n";
7470            pr "  return 0;\n"
7471        | RInt64 _ ->
7472            pr "  if (r == -1) return -1;\n";
7473            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7474            pr "  return 0;\n"
7475        | RBool _ ->
7476            pr "  if (r == -1) return -1;\n";
7477            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7478            pr "  return 0;\n"
7479        | RConstString _ ->
7480            pr "  if (r == NULL) return -1;\n";
7481            pr "  printf (\"%%s\\n\", r);\n";
7482            pr "  return 0;\n"
7483        | RConstOptString _ ->
7484            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7485            pr "  return 0;\n"
7486        | RString _ ->
7487            pr "  if (r == NULL) return -1;\n";
7488            pr "  printf (\"%%s\\n\", r);\n";
7489            pr "  free (r);\n";
7490            pr "  return 0;\n"
7491        | RStringList _ ->
7492            pr "  if (r == NULL) return -1;\n";
7493            pr "  print_strings (r);\n";
7494            pr "  free_strings (r);\n";
7495            pr "  return 0;\n"
7496        | RStruct (_, typ) ->
7497            pr "  if (r == NULL) return -1;\n";
7498            pr "  print_%s (r);\n" typ;
7499            pr "  guestfs_free_%s (r);\n" typ;
7500            pr "  return 0;\n"
7501        | RStructList (_, typ) ->
7502            pr "  if (r == NULL) return -1;\n";
7503            pr "  print_%s_list (r);\n" typ;
7504            pr "  guestfs_free_%s_list (r);\n" typ;
7505            pr "  return 0;\n"
7506        | RHashtable _ ->
7507            pr "  if (r == NULL) return -1;\n";
7508            pr "  print_table (r);\n";
7509            pr "  free_strings (r);\n";
7510            pr "  return 0;\n"
7511        | RBufferOut _ ->
7512            pr "  if (r == NULL) return -1;\n";
7513            pr "  if (full_write (1, r, size) != size) {\n";
7514            pr "    perror (\"write\");\n";
7515            pr "    free (r);\n";
7516            pr "    return -1;\n";
7517            pr "  }\n";
7518            pr "  free (r);\n";
7519            pr "  return 0;\n"
7520       );
7521       pr "}\n";
7522       pr "\n"
7523   ) all_functions;
7524
7525   (* run_action function *)
7526   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7527   pr "{\n";
7528   List.iter (
7529     fun (name, _, _, flags, _, _, _) ->
7530       let name2 = replace_char name '_' '-' in
7531       let alias =
7532         try find_map (function FishAlias n -> Some n | _ -> None) flags
7533         with Not_found -> name in
7534       pr "  if (";
7535       pr "STRCASEEQ (cmd, \"%s\")" name;
7536       if name <> name2 then
7537         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7538       if name <> alias then
7539         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7540       pr ")\n";
7541       pr "    return run_%s (cmd, argc, argv);\n" name;
7542       pr "  else\n";
7543   ) all_functions;
7544   pr "    {\n";
7545   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7546   pr "      if (command_num == 1)\n";
7547   pr "        extended_help_message ();\n";
7548   pr "      return -1;\n";
7549   pr "    }\n";
7550   pr "  return 0;\n";
7551   pr "}\n";
7552   pr "\n"
7553
7554 (* Readline completion for guestfish. *)
7555 and generate_fish_completion () =
7556   generate_header CStyle GPLv2plus;
7557
7558   let all_functions =
7559     List.filter (
7560       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7561     ) all_functions in
7562
7563   pr "\
7564 #include <config.h>
7565
7566 #include <stdio.h>
7567 #include <stdlib.h>
7568 #include <string.h>
7569
7570 #ifdef HAVE_LIBREADLINE
7571 #include <readline/readline.h>
7572 #endif
7573
7574 #include \"fish.h\"
7575
7576 #ifdef HAVE_LIBREADLINE
7577
7578 static const char *const commands[] = {
7579   BUILTIN_COMMANDS_FOR_COMPLETION,
7580 ";
7581
7582   (* Get the commands, including the aliases.  They don't need to be
7583    * sorted - the generator() function just does a dumb linear search.
7584    *)
7585   let commands =
7586     List.map (
7587       fun (name, _, _, flags, _, _, _) ->
7588         let name2 = replace_char name '_' '-' in
7589         let alias =
7590           try find_map (function FishAlias n -> Some n | _ -> None) flags
7591           with Not_found -> name in
7592
7593         if name <> alias then [name2; alias] else [name2]
7594     ) all_functions in
7595   let commands = List.flatten commands in
7596
7597   List.iter (pr "  \"%s\",\n") commands;
7598
7599   pr "  NULL
7600 };
7601
7602 static char *
7603 generator (const char *text, int state)
7604 {
7605   static int index, len;
7606   const char *name;
7607
7608   if (!state) {
7609     index = 0;
7610     len = strlen (text);
7611   }
7612
7613   rl_attempted_completion_over = 1;
7614
7615   while ((name = commands[index]) != NULL) {
7616     index++;
7617     if (STRCASEEQLEN (name, text, len))
7618       return strdup (name);
7619   }
7620
7621   return NULL;
7622 }
7623
7624 #endif /* HAVE_LIBREADLINE */
7625
7626 #ifdef HAVE_RL_COMPLETION_MATCHES
7627 #define RL_COMPLETION_MATCHES rl_completion_matches
7628 #else
7629 #ifdef HAVE_COMPLETION_MATCHES
7630 #define RL_COMPLETION_MATCHES completion_matches
7631 #endif
7632 #endif /* else just fail if we don't have either symbol */
7633
7634 char **
7635 do_completion (const char *text, int start, int end)
7636 {
7637   char **matches = NULL;
7638
7639 #ifdef HAVE_LIBREADLINE
7640   rl_completion_append_character = ' ';
7641
7642   if (start == 0)
7643     matches = RL_COMPLETION_MATCHES (text, generator);
7644   else if (complete_dest_paths)
7645     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7646 #endif
7647
7648   return matches;
7649 }
7650 ";
7651
7652 (* Generate the POD documentation for guestfish. *)
7653 and generate_fish_actions_pod () =
7654   let all_functions_sorted =
7655     List.filter (
7656       fun (_, _, _, flags, _, _, _) ->
7657         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7658     ) all_functions_sorted in
7659
7660   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7661
7662   List.iter (
7663     fun (name, style, _, flags, _, _, longdesc) ->
7664       let longdesc =
7665         Str.global_substitute rex (
7666           fun s ->
7667             let sub =
7668               try Str.matched_group 1 s
7669               with Not_found ->
7670                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7671             "C<" ^ replace_char sub '_' '-' ^ ">"
7672         ) longdesc in
7673       let name = replace_char name '_' '-' in
7674       let alias =
7675         try find_map (function FishAlias n -> Some n | _ -> None) flags
7676         with Not_found -> name in
7677
7678       pr "=head2 %s" name;
7679       if name <> alias then
7680         pr " | %s" alias;
7681       pr "\n";
7682       pr "\n";
7683       pr " %s" name;
7684       List.iter (
7685         function
7686         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7687         | OptString n -> pr " %s" n
7688         | StringList n | DeviceList n -> pr " '%s ...'" n
7689         | Bool _ -> pr " true|false"
7690         | Int n -> pr " %s" n
7691         | Int64 n -> pr " %s" n
7692         | FileIn n | FileOut n -> pr " (%s|-)" n
7693       ) (snd style);
7694       pr "\n";
7695       pr "\n";
7696       pr "%s\n\n" longdesc;
7697
7698       if List.exists (function FileIn _ | FileOut _ -> true
7699                       | _ -> false) (snd style) then
7700         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7701
7702       if List.mem ProtocolLimitWarning flags then
7703         pr "%s\n\n" protocol_limit_warning;
7704
7705       if List.mem DangerWillRobinson flags then
7706         pr "%s\n\n" danger_will_robinson;
7707
7708       match deprecation_notice flags with
7709       | None -> ()
7710       | Some txt -> pr "%s\n\n" txt
7711   ) all_functions_sorted
7712
7713 (* Generate a C function prototype. *)
7714 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7715     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7716     ?(prefix = "")
7717     ?handle name style =
7718   if extern then pr "extern ";
7719   if static then pr "static ";
7720   (match fst style with
7721    | RErr -> pr "int "
7722    | RInt _ -> pr "int "
7723    | RInt64 _ -> pr "int64_t "
7724    | RBool _ -> pr "int "
7725    | RConstString _ | RConstOptString _ -> pr "const char *"
7726    | RString _ | RBufferOut _ -> pr "char *"
7727    | RStringList _ | RHashtable _ -> pr "char **"
7728    | RStruct (_, typ) ->
7729        if not in_daemon then pr "struct guestfs_%s *" typ
7730        else pr "guestfs_int_%s *" typ
7731    | RStructList (_, typ) ->
7732        if not in_daemon then pr "struct guestfs_%s_list *" typ
7733        else pr "guestfs_int_%s_list *" typ
7734   );
7735   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7736   pr "%s%s (" prefix name;
7737   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7738     pr "void"
7739   else (
7740     let comma = ref false in
7741     (match handle with
7742      | None -> ()
7743      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7744     );
7745     let next () =
7746       if !comma then (
7747         if single_line then pr ", " else pr ",\n\t\t"
7748       );
7749       comma := true
7750     in
7751     List.iter (
7752       function
7753       | Pathname n
7754       | Device n | Dev_or_Path n
7755       | String n
7756       | OptString n ->
7757           next ();
7758           pr "const char *%s" n
7759       | StringList n | DeviceList n ->
7760           next ();
7761           pr "char *const *%s" n
7762       | Bool n -> next (); pr "int %s" n
7763       | Int n -> next (); pr "int %s" n
7764       | Int64 n -> next (); pr "int64_t %s" n
7765       | FileIn n
7766       | FileOut n ->
7767           if not in_daemon then (next (); pr "const char *%s" n)
7768     ) (snd style);
7769     if is_RBufferOut then (next (); pr "size_t *size_r");
7770   );
7771   pr ")";
7772   if semicolon then pr ";";
7773   if newline then pr "\n"
7774
7775 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7776 and generate_c_call_args ?handle ?(decl = false) style =
7777   pr "(";
7778   let comma = ref false in
7779   let next () =
7780     if !comma then pr ", ";
7781     comma := true
7782   in
7783   (match handle with
7784    | None -> ()
7785    | Some handle -> pr "%s" handle; comma := true
7786   );
7787   List.iter (
7788     fun arg ->
7789       next ();
7790       pr "%s" (name_of_argt arg)
7791   ) (snd style);
7792   (* For RBufferOut calls, add implicit &size parameter. *)
7793   if not decl then (
7794     match fst style with
7795     | RBufferOut _ ->
7796         next ();
7797         pr "&size"
7798     | _ -> ()
7799   );
7800   pr ")"
7801
7802 (* Generate the OCaml bindings interface. *)
7803 and generate_ocaml_mli () =
7804   generate_header OCamlStyle LGPLv2plus;
7805
7806   pr "\
7807 (** For API documentation you should refer to the C API
7808     in the guestfs(3) manual page.  The OCaml API uses almost
7809     exactly the same calls. *)
7810
7811 type t
7812 (** A [guestfs_h] handle. *)
7813
7814 exception Error of string
7815 (** This exception is raised when there is an error. *)
7816
7817 exception Handle_closed of string
7818 (** This exception is raised if you use a {!Guestfs.t} handle
7819     after calling {!close} on it.  The string is the name of
7820     the function. *)
7821
7822 val create : unit -> t
7823 (** Create a {!Guestfs.t} handle. *)
7824
7825 val close : t -> unit
7826 (** Close the {!Guestfs.t} handle and free up all resources used
7827     by it immediately.
7828
7829     Handles are closed by the garbage collector when they become
7830     unreferenced, but callers can call this in order to provide
7831     predictable cleanup. *)
7832
7833 ";
7834   generate_ocaml_structure_decls ();
7835
7836   (* The actions. *)
7837   List.iter (
7838     fun (name, style, _, _, _, shortdesc, _) ->
7839       generate_ocaml_prototype name style;
7840       pr "(** %s *)\n" shortdesc;
7841       pr "\n"
7842   ) all_functions_sorted
7843
7844 (* Generate the OCaml bindings implementation. *)
7845 and generate_ocaml_ml () =
7846   generate_header OCamlStyle LGPLv2plus;
7847
7848   pr "\
7849 type t
7850
7851 exception Error of string
7852 exception Handle_closed of string
7853
7854 external create : unit -> t = \"ocaml_guestfs_create\"
7855 external close : t -> unit = \"ocaml_guestfs_close\"
7856
7857 (* Give the exceptions names, so they can be raised from the C code. *)
7858 let () =
7859   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7860   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7861
7862 ";
7863
7864   generate_ocaml_structure_decls ();
7865
7866   (* The actions. *)
7867   List.iter (
7868     fun (name, style, _, _, _, shortdesc, _) ->
7869       generate_ocaml_prototype ~is_external:true name style;
7870   ) all_functions_sorted
7871
7872 (* Generate the OCaml bindings C implementation. *)
7873 and generate_ocaml_c () =
7874   generate_header CStyle LGPLv2plus;
7875
7876   pr "\
7877 #include <stdio.h>
7878 #include <stdlib.h>
7879 #include <string.h>
7880
7881 #include <caml/config.h>
7882 #include <caml/alloc.h>
7883 #include <caml/callback.h>
7884 #include <caml/fail.h>
7885 #include <caml/memory.h>
7886 #include <caml/mlvalues.h>
7887 #include <caml/signals.h>
7888
7889 #include <guestfs.h>
7890
7891 #include \"guestfs_c.h\"
7892
7893 /* Copy a hashtable of string pairs into an assoc-list.  We return
7894  * the list in reverse order, but hashtables aren't supposed to be
7895  * ordered anyway.
7896  */
7897 static CAMLprim value
7898 copy_table (char * const * argv)
7899 {
7900   CAMLparam0 ();
7901   CAMLlocal5 (rv, pairv, kv, vv, cons);
7902   int i;
7903
7904   rv = Val_int (0);
7905   for (i = 0; argv[i] != NULL; i += 2) {
7906     kv = caml_copy_string (argv[i]);
7907     vv = caml_copy_string (argv[i+1]);
7908     pairv = caml_alloc (2, 0);
7909     Store_field (pairv, 0, kv);
7910     Store_field (pairv, 1, vv);
7911     cons = caml_alloc (2, 0);
7912     Store_field (cons, 1, rv);
7913     rv = cons;
7914     Store_field (cons, 0, pairv);
7915   }
7916
7917   CAMLreturn (rv);
7918 }
7919
7920 ";
7921
7922   (* Struct copy functions. *)
7923
7924   let emit_ocaml_copy_list_function typ =
7925     pr "static CAMLprim value\n";
7926     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7927     pr "{\n";
7928     pr "  CAMLparam0 ();\n";
7929     pr "  CAMLlocal2 (rv, v);\n";
7930     pr "  unsigned int i;\n";
7931     pr "\n";
7932     pr "  if (%ss->len == 0)\n" typ;
7933     pr "    CAMLreturn (Atom (0));\n";
7934     pr "  else {\n";
7935     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7936     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7937     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7938     pr "      caml_modify (&Field (rv, i), v);\n";
7939     pr "    }\n";
7940     pr "    CAMLreturn (rv);\n";
7941     pr "  }\n";
7942     pr "}\n";
7943     pr "\n";
7944   in
7945
7946   List.iter (
7947     fun (typ, cols) ->
7948       let has_optpercent_col =
7949         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7950
7951       pr "static CAMLprim value\n";
7952       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7953       pr "{\n";
7954       pr "  CAMLparam0 ();\n";
7955       if has_optpercent_col then
7956         pr "  CAMLlocal3 (rv, v, v2);\n"
7957       else
7958         pr "  CAMLlocal2 (rv, v);\n";
7959       pr "\n";
7960       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7961       iteri (
7962         fun i col ->
7963           (match col with
7964            | name, FString ->
7965                pr "  v = caml_copy_string (%s->%s);\n" typ name
7966            | name, FBuffer ->
7967                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7968                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7969                  typ name typ name
7970            | name, FUUID ->
7971                pr "  v = caml_alloc_string (32);\n";
7972                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7973            | name, (FBytes|FInt64|FUInt64) ->
7974                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7975            | name, (FInt32|FUInt32) ->
7976                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7977            | name, FOptPercent ->
7978                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7979                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7980                pr "    v = caml_alloc (1, 0);\n";
7981                pr "    Store_field (v, 0, v2);\n";
7982                pr "  } else /* None */\n";
7983                pr "    v = Val_int (0);\n";
7984            | name, FChar ->
7985                pr "  v = Val_int (%s->%s);\n" typ name
7986           );
7987           pr "  Store_field (rv, %d, v);\n" i
7988       ) cols;
7989       pr "  CAMLreturn (rv);\n";
7990       pr "}\n";
7991       pr "\n";
7992   ) structs;
7993
7994   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7995   List.iter (
7996     function
7997     | typ, (RStructListOnly | RStructAndList) ->
7998         (* generate the function for typ *)
7999         emit_ocaml_copy_list_function typ
8000     | typ, _ -> () (* empty *)
8001   ) (rstructs_used_by all_functions);
8002
8003   (* The wrappers. *)
8004   List.iter (
8005     fun (name, style, _, _, _, _, _) ->
8006       pr "/* Automatically generated wrapper for function\n";
8007       pr " * ";
8008       generate_ocaml_prototype name style;
8009       pr " */\n";
8010       pr "\n";
8011
8012       let params =
8013         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8014
8015       let needs_extra_vs =
8016         match fst style with RConstOptString _ -> true | _ -> false in
8017
8018       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8019       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8020       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8021       pr "\n";
8022
8023       pr "CAMLprim value\n";
8024       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8025       List.iter (pr ", value %s") (List.tl params);
8026       pr ")\n";
8027       pr "{\n";
8028
8029       (match params with
8030        | [p1; p2; p3; p4; p5] ->
8031            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8032        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8033            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8034            pr "  CAMLxparam%d (%s);\n"
8035              (List.length rest) (String.concat ", " rest)
8036        | ps ->
8037            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8038       );
8039       if not needs_extra_vs then
8040         pr "  CAMLlocal1 (rv);\n"
8041       else
8042         pr "  CAMLlocal3 (rv, v, v2);\n";
8043       pr "\n";
8044
8045       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8046       pr "  if (g == NULL)\n";
8047       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8048       pr "\n";
8049
8050       List.iter (
8051         function
8052         | Pathname n
8053         | Device n | Dev_or_Path n
8054         | String n
8055         | FileIn n
8056         | FileOut n ->
8057             pr "  const char *%s = String_val (%sv);\n" n n
8058         | OptString n ->
8059             pr "  const char *%s =\n" n;
8060             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8061               n n
8062         | StringList n | DeviceList n ->
8063             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8064         | Bool n ->
8065             pr "  int %s = Bool_val (%sv);\n" n n
8066         | Int n ->
8067             pr "  int %s = Int_val (%sv);\n" n n
8068         | Int64 n ->
8069             pr "  int64_t %s = Int64_val (%sv);\n" n n
8070       ) (snd style);
8071       let error_code =
8072         match fst style with
8073         | RErr -> pr "  int r;\n"; "-1"
8074         | RInt _ -> pr "  int r;\n"; "-1"
8075         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8076         | RBool _ -> pr "  int r;\n"; "-1"
8077         | RConstString _ | RConstOptString _ ->
8078             pr "  const char *r;\n"; "NULL"
8079         | RString _ -> pr "  char *r;\n"; "NULL"
8080         | RStringList _ ->
8081             pr "  int i;\n";
8082             pr "  char **r;\n";
8083             "NULL"
8084         | RStruct (_, typ) ->
8085             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8086         | RStructList (_, typ) ->
8087             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8088         | RHashtable _ ->
8089             pr "  int i;\n";
8090             pr "  char **r;\n";
8091             "NULL"
8092         | RBufferOut _ ->
8093             pr "  char *r;\n";
8094             pr "  size_t size;\n";
8095             "NULL" in
8096       pr "\n";
8097
8098       pr "  caml_enter_blocking_section ();\n";
8099       pr "  r = guestfs_%s " name;
8100       generate_c_call_args ~handle:"g" style;
8101       pr ";\n";
8102       pr "  caml_leave_blocking_section ();\n";
8103
8104       List.iter (
8105         function
8106         | StringList n | DeviceList n ->
8107             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8108         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8109         | Bool _ | Int _ | Int64 _
8110         | FileIn _ | FileOut _ -> ()
8111       ) (snd style);
8112
8113       pr "  if (r == %s)\n" error_code;
8114       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8115       pr "\n";
8116
8117       (match fst style with
8118        | RErr -> pr "  rv = Val_unit;\n"
8119        | RInt _ -> pr "  rv = Val_int (r);\n"
8120        | RInt64 _ ->
8121            pr "  rv = caml_copy_int64 (r);\n"
8122        | RBool _ -> pr "  rv = Val_bool (r);\n"
8123        | RConstString _ ->
8124            pr "  rv = caml_copy_string (r);\n"
8125        | RConstOptString _ ->
8126            pr "  if (r) { /* Some string */\n";
8127            pr "    v = caml_alloc (1, 0);\n";
8128            pr "    v2 = caml_copy_string (r);\n";
8129            pr "    Store_field (v, 0, v2);\n";
8130            pr "  } else /* None */\n";
8131            pr "    v = Val_int (0);\n";
8132        | RString _ ->
8133            pr "  rv = caml_copy_string (r);\n";
8134            pr "  free (r);\n"
8135        | RStringList _ ->
8136            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8137            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8138            pr "  free (r);\n"
8139        | RStruct (_, typ) ->
8140            pr "  rv = copy_%s (r);\n" typ;
8141            pr "  guestfs_free_%s (r);\n" typ;
8142        | RStructList (_, typ) ->
8143            pr "  rv = copy_%s_list (r);\n" typ;
8144            pr "  guestfs_free_%s_list (r);\n" typ;
8145        | RHashtable _ ->
8146            pr "  rv = copy_table (r);\n";
8147            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8148            pr "  free (r);\n";
8149        | RBufferOut _ ->
8150            pr "  rv = caml_alloc_string (size);\n";
8151            pr "  memcpy (String_val (rv), r, size);\n";
8152       );
8153
8154       pr "  CAMLreturn (rv);\n";
8155       pr "}\n";
8156       pr "\n";
8157
8158       if List.length params > 5 then (
8159         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8160         pr "CAMLprim value ";
8161         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8162         pr "CAMLprim value\n";
8163         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8164         pr "{\n";
8165         pr "  return ocaml_guestfs_%s (argv[0]" name;
8166         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8167         pr ");\n";
8168         pr "}\n";
8169         pr "\n"
8170       )
8171   ) all_functions_sorted
8172
8173 and generate_ocaml_structure_decls () =
8174   List.iter (
8175     fun (typ, cols) ->
8176       pr "type %s = {\n" typ;
8177       List.iter (
8178         function
8179         | name, FString -> pr "  %s : string;\n" name
8180         | name, FBuffer -> pr "  %s : string;\n" name
8181         | name, FUUID -> pr "  %s : string;\n" name
8182         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8183         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8184         | name, FChar -> pr "  %s : char;\n" name
8185         | name, FOptPercent -> pr "  %s : float option;\n" name
8186       ) cols;
8187       pr "}\n";
8188       pr "\n"
8189   ) structs
8190
8191 and generate_ocaml_prototype ?(is_external = false) name style =
8192   if is_external then pr "external " else pr "val ";
8193   pr "%s : t -> " name;
8194   List.iter (
8195     function
8196     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8197     | OptString _ -> pr "string option -> "
8198     | StringList _ | DeviceList _ -> pr "string array -> "
8199     | Bool _ -> pr "bool -> "
8200     | Int _ -> pr "int -> "
8201     | Int64 _ -> pr "int64 -> "
8202   ) (snd style);
8203   (match fst style with
8204    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8205    | RInt _ -> pr "int"
8206    | RInt64 _ -> pr "int64"
8207    | RBool _ -> pr "bool"
8208    | RConstString _ -> pr "string"
8209    | RConstOptString _ -> pr "string option"
8210    | RString _ | RBufferOut _ -> pr "string"
8211    | RStringList _ -> pr "string array"
8212    | RStruct (_, typ) -> pr "%s" typ
8213    | RStructList (_, typ) -> pr "%s array" typ
8214    | RHashtable _ -> pr "(string * string) list"
8215   );
8216   if is_external then (
8217     pr " = ";
8218     if List.length (snd style) + 1 > 5 then
8219       pr "\"ocaml_guestfs_%s_byte\" " name;
8220     pr "\"ocaml_guestfs_%s\"" name
8221   );
8222   pr "\n"
8223
8224 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8225 and generate_perl_xs () =
8226   generate_header CStyle LGPLv2plus;
8227
8228   pr "\
8229 #include \"EXTERN.h\"
8230 #include \"perl.h\"
8231 #include \"XSUB.h\"
8232
8233 #include <guestfs.h>
8234
8235 #ifndef PRId64
8236 #define PRId64 \"lld\"
8237 #endif
8238
8239 static SV *
8240 my_newSVll(long long val) {
8241 #ifdef USE_64_BIT_ALL
8242   return newSViv(val);
8243 #else
8244   char buf[100];
8245   int len;
8246   len = snprintf(buf, 100, \"%%\" PRId64, val);
8247   return newSVpv(buf, len);
8248 #endif
8249 }
8250
8251 #ifndef PRIu64
8252 #define PRIu64 \"llu\"
8253 #endif
8254
8255 static SV *
8256 my_newSVull(unsigned long long val) {
8257 #ifdef USE_64_BIT_ALL
8258   return newSVuv(val);
8259 #else
8260   char buf[100];
8261   int len;
8262   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8263   return newSVpv(buf, len);
8264 #endif
8265 }
8266
8267 /* http://www.perlmonks.org/?node_id=680842 */
8268 static char **
8269 XS_unpack_charPtrPtr (SV *arg) {
8270   char **ret;
8271   AV *av;
8272   I32 i;
8273
8274   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8275     croak (\"array reference expected\");
8276
8277   av = (AV *)SvRV (arg);
8278   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8279   if (!ret)
8280     croak (\"malloc failed\");
8281
8282   for (i = 0; i <= av_len (av); i++) {
8283     SV **elem = av_fetch (av, i, 0);
8284
8285     if (!elem || !*elem)
8286       croak (\"missing element in list\");
8287
8288     ret[i] = SvPV_nolen (*elem);
8289   }
8290
8291   ret[i] = NULL;
8292
8293   return ret;
8294 }
8295
8296 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8297
8298 PROTOTYPES: ENABLE
8299
8300 guestfs_h *
8301 _create ()
8302    CODE:
8303       RETVAL = guestfs_create ();
8304       if (!RETVAL)
8305         croak (\"could not create guestfs handle\");
8306       guestfs_set_error_handler (RETVAL, NULL, NULL);
8307  OUTPUT:
8308       RETVAL
8309
8310 void
8311 DESTROY (g)
8312       guestfs_h *g;
8313  PPCODE:
8314       guestfs_close (g);
8315
8316 ";
8317
8318   List.iter (
8319     fun (name, style, _, _, _, _, _) ->
8320       (match fst style with
8321        | RErr -> pr "void\n"
8322        | RInt _ -> pr "SV *\n"
8323        | RInt64 _ -> pr "SV *\n"
8324        | RBool _ -> pr "SV *\n"
8325        | RConstString _ -> pr "SV *\n"
8326        | RConstOptString _ -> pr "SV *\n"
8327        | RString _ -> pr "SV *\n"
8328        | RBufferOut _ -> pr "SV *\n"
8329        | RStringList _
8330        | RStruct _ | RStructList _
8331        | RHashtable _ ->
8332            pr "void\n" (* all lists returned implictly on the stack *)
8333       );
8334       (* Call and arguments. *)
8335       pr "%s " name;
8336       generate_c_call_args ~handle:"g" ~decl:true style;
8337       pr "\n";
8338       pr "      guestfs_h *g;\n";
8339       iteri (
8340         fun i ->
8341           function
8342           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8343               pr "      char *%s;\n" n
8344           | OptString n ->
8345               (* http://www.perlmonks.org/?node_id=554277
8346                * Note that the implicit handle argument means we have
8347                * to add 1 to the ST(x) operator.
8348                *)
8349               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8350           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8351           | Bool n -> pr "      int %s;\n" n
8352           | Int n -> pr "      int %s;\n" n
8353           | Int64 n -> pr "      int64_t %s;\n" n
8354       ) (snd style);
8355
8356       let do_cleanups () =
8357         List.iter (
8358           function
8359           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8360           | Bool _ | Int _ | Int64 _
8361           | FileIn _ | FileOut _ -> ()
8362           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8363         ) (snd style)
8364       in
8365
8366       (* Code. *)
8367       (match fst style with
8368        | RErr ->
8369            pr "PREINIT:\n";
8370            pr "      int r;\n";
8371            pr " PPCODE:\n";
8372            pr "      r = guestfs_%s " name;
8373            generate_c_call_args ~handle:"g" style;
8374            pr ";\n";
8375            do_cleanups ();
8376            pr "      if (r == -1)\n";
8377            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8378        | RInt n
8379        | RBool n ->
8380            pr "PREINIT:\n";
8381            pr "      int %s;\n" n;
8382            pr "   CODE:\n";
8383            pr "      %s = guestfs_%s " n name;
8384            generate_c_call_args ~handle:"g" style;
8385            pr ";\n";
8386            do_cleanups ();
8387            pr "      if (%s == -1)\n" n;
8388            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8389            pr "      RETVAL = newSViv (%s);\n" n;
8390            pr " OUTPUT:\n";
8391            pr "      RETVAL\n"
8392        | RInt64 n ->
8393            pr "PREINIT:\n";
8394            pr "      int64_t %s;\n" n;
8395            pr "   CODE:\n";
8396            pr "      %s = guestfs_%s " n name;
8397            generate_c_call_args ~handle:"g" style;
8398            pr ";\n";
8399            do_cleanups ();
8400            pr "      if (%s == -1)\n" n;
8401            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8402            pr "      RETVAL = my_newSVll (%s);\n" n;
8403            pr " OUTPUT:\n";
8404            pr "      RETVAL\n"
8405        | RConstString n ->
8406            pr "PREINIT:\n";
8407            pr "      const char *%s;\n" n;
8408            pr "   CODE:\n";
8409            pr "      %s = guestfs_%s " n name;
8410            generate_c_call_args ~handle:"g" style;
8411            pr ";\n";
8412            do_cleanups ();
8413            pr "      if (%s == NULL)\n" n;
8414            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8415            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8416            pr " OUTPUT:\n";
8417            pr "      RETVAL\n"
8418        | RConstOptString n ->
8419            pr "PREINIT:\n";
8420            pr "      const char *%s;\n" n;
8421            pr "   CODE:\n";
8422            pr "      %s = guestfs_%s " n name;
8423            generate_c_call_args ~handle:"g" style;
8424            pr ";\n";
8425            do_cleanups ();
8426            pr "      if (%s == NULL)\n" n;
8427            pr "        RETVAL = &PL_sv_undef;\n";
8428            pr "      else\n";
8429            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8430            pr " OUTPUT:\n";
8431            pr "      RETVAL\n"
8432        | RString n ->
8433            pr "PREINIT:\n";
8434            pr "      char *%s;\n" n;
8435            pr "   CODE:\n";
8436            pr "      %s = guestfs_%s " n name;
8437            generate_c_call_args ~handle:"g" style;
8438            pr ";\n";
8439            do_cleanups ();
8440            pr "      if (%s == NULL)\n" n;
8441            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8442            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8443            pr "      free (%s);\n" n;
8444            pr " OUTPUT:\n";
8445            pr "      RETVAL\n"
8446        | RStringList n | RHashtable n ->
8447            pr "PREINIT:\n";
8448            pr "      char **%s;\n" n;
8449            pr "      int i, n;\n";
8450            pr " PPCODE:\n";
8451            pr "      %s = guestfs_%s " n name;
8452            generate_c_call_args ~handle:"g" style;
8453            pr ";\n";
8454            do_cleanups ();
8455            pr "      if (%s == NULL)\n" n;
8456            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8457            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8458            pr "      EXTEND (SP, n);\n";
8459            pr "      for (i = 0; i < n; ++i) {\n";
8460            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8461            pr "        free (%s[i]);\n" n;
8462            pr "      }\n";
8463            pr "      free (%s);\n" n;
8464        | RStruct (n, typ) ->
8465            let cols = cols_of_struct typ in
8466            generate_perl_struct_code typ cols name style n do_cleanups
8467        | RStructList (n, typ) ->
8468            let cols = cols_of_struct typ in
8469            generate_perl_struct_list_code typ cols name style n do_cleanups
8470        | RBufferOut n ->
8471            pr "PREINIT:\n";
8472            pr "      char *%s;\n" n;
8473            pr "      size_t size;\n";
8474            pr "   CODE:\n";
8475            pr "      %s = guestfs_%s " n name;
8476            generate_c_call_args ~handle:"g" style;
8477            pr ";\n";
8478            do_cleanups ();
8479            pr "      if (%s == NULL)\n" n;
8480            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8481            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8482            pr "      free (%s);\n" n;
8483            pr " OUTPUT:\n";
8484            pr "      RETVAL\n"
8485       );
8486
8487       pr "\n"
8488   ) all_functions
8489
8490 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8491   pr "PREINIT:\n";
8492   pr "      struct guestfs_%s_list *%s;\n" typ n;
8493   pr "      int i;\n";
8494   pr "      HV *hv;\n";
8495   pr " PPCODE:\n";
8496   pr "      %s = guestfs_%s " n name;
8497   generate_c_call_args ~handle:"g" style;
8498   pr ";\n";
8499   do_cleanups ();
8500   pr "      if (%s == NULL)\n" n;
8501   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8502   pr "      EXTEND (SP, %s->len);\n" n;
8503   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8504   pr "        hv = newHV ();\n";
8505   List.iter (
8506     function
8507     | name, FString ->
8508         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8509           name (String.length name) n name
8510     | name, FUUID ->
8511         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8512           name (String.length name) n name
8513     | name, FBuffer ->
8514         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8515           name (String.length name) n name n name
8516     | name, (FBytes|FUInt64) ->
8517         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8518           name (String.length name) n name
8519     | name, FInt64 ->
8520         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8521           name (String.length name) n name
8522     | name, (FInt32|FUInt32) ->
8523         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8524           name (String.length name) n name
8525     | name, FChar ->
8526         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8527           name (String.length name) n name
8528     | name, FOptPercent ->
8529         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8530           name (String.length name) n name
8531   ) cols;
8532   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8533   pr "      }\n";
8534   pr "      guestfs_free_%s_list (%s);\n" typ n
8535
8536 and generate_perl_struct_code typ cols name style n do_cleanups =
8537   pr "PREINIT:\n";
8538   pr "      struct guestfs_%s *%s;\n" typ n;
8539   pr " PPCODE:\n";
8540   pr "      %s = guestfs_%s " n name;
8541   generate_c_call_args ~handle:"g" style;
8542   pr ";\n";
8543   do_cleanups ();
8544   pr "      if (%s == NULL)\n" n;
8545   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8546   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8547   List.iter (
8548     fun ((name, _) as col) ->
8549       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8550
8551       match col with
8552       | name, FString ->
8553           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8554             n name
8555       | name, FBuffer ->
8556           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8557             n name n name
8558       | name, FUUID ->
8559           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8560             n name
8561       | name, (FBytes|FUInt64) ->
8562           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8563             n name
8564       | name, FInt64 ->
8565           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8566             n name
8567       | name, (FInt32|FUInt32) ->
8568           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8569             n name
8570       | name, FChar ->
8571           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8572             n name
8573       | name, FOptPercent ->
8574           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8575             n name
8576   ) cols;
8577   pr "      free (%s);\n" n
8578
8579 (* Generate Sys/Guestfs.pm. *)
8580 and generate_perl_pm () =
8581   generate_header HashStyle LGPLv2plus;
8582
8583   pr "\
8584 =pod
8585
8586 =head1 NAME
8587
8588 Sys::Guestfs - Perl bindings for libguestfs
8589
8590 =head1 SYNOPSIS
8591
8592  use Sys::Guestfs;
8593
8594  my $h = Sys::Guestfs->new ();
8595  $h->add_drive ('guest.img');
8596  $h->launch ();
8597  $h->mount ('/dev/sda1', '/');
8598  $h->touch ('/hello');
8599  $h->sync ();
8600
8601 =head1 DESCRIPTION
8602
8603 The C<Sys::Guestfs> module provides a Perl XS binding to the
8604 libguestfs API for examining and modifying virtual machine
8605 disk images.
8606
8607 Amongst the things this is good for: making batch configuration
8608 changes to guests, getting disk used/free statistics (see also:
8609 virt-df), migrating between virtualization systems (see also:
8610 virt-p2v), performing partial backups, performing partial guest
8611 clones, cloning guests and changing registry/UUID/hostname info, and
8612 much else besides.
8613
8614 Libguestfs uses Linux kernel and qemu code, and can access any type of
8615 guest filesystem that Linux and qemu can, including but not limited
8616 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8617 schemes, qcow, qcow2, vmdk.
8618
8619 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8620 LVs, what filesystem is in each LV, etc.).  It can also run commands
8621 in the context of the guest.  Also you can access filesystems over
8622 FUSE.
8623
8624 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8625 functions for using libguestfs from Perl, including integration
8626 with libvirt.
8627
8628 =head1 ERRORS
8629
8630 All errors turn into calls to C<croak> (see L<Carp(3)>).
8631
8632 =head1 METHODS
8633
8634 =over 4
8635
8636 =cut
8637
8638 package Sys::Guestfs;
8639
8640 use strict;
8641 use warnings;
8642
8643 require XSLoader;
8644 XSLoader::load ('Sys::Guestfs');
8645
8646 =item $h = Sys::Guestfs->new ();
8647
8648 Create a new guestfs handle.
8649
8650 =cut
8651
8652 sub new {
8653   my $proto = shift;
8654   my $class = ref ($proto) || $proto;
8655
8656   my $self = Sys::Guestfs::_create ();
8657   bless $self, $class;
8658   return $self;
8659 }
8660
8661 ";
8662
8663   (* Actions.  We only need to print documentation for these as
8664    * they are pulled in from the XS code automatically.
8665    *)
8666   List.iter (
8667     fun (name, style, _, flags, _, _, longdesc) ->
8668       if not (List.mem NotInDocs flags) then (
8669         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8670         pr "=item ";
8671         generate_perl_prototype name style;
8672         pr "\n\n";
8673         pr "%s\n\n" longdesc;
8674         if List.mem ProtocolLimitWarning flags then
8675           pr "%s\n\n" protocol_limit_warning;
8676         if List.mem DangerWillRobinson flags then
8677           pr "%s\n\n" danger_will_robinson;
8678         match deprecation_notice flags with
8679         | None -> ()
8680         | Some txt -> pr "%s\n\n" txt
8681       )
8682   ) all_functions_sorted;
8683
8684   (* End of file. *)
8685   pr "\
8686 =cut
8687
8688 1;
8689
8690 =back
8691
8692 =head1 COPYRIGHT
8693
8694 Copyright (C) %s Red Hat Inc.
8695
8696 =head1 LICENSE
8697
8698 Please see the file COPYING.LIB for the full license.
8699
8700 =head1 SEE ALSO
8701
8702 L<guestfs(3)>,
8703 L<guestfish(1)>,
8704 L<http://libguestfs.org>,
8705 L<Sys::Guestfs::Lib(3)>.
8706
8707 =cut
8708 " copyright_years
8709
8710 and generate_perl_prototype name style =
8711   (match fst style with
8712    | RErr -> ()
8713    | RBool n
8714    | RInt n
8715    | RInt64 n
8716    | RConstString n
8717    | RConstOptString n
8718    | RString n
8719    | RBufferOut n -> pr "$%s = " n
8720    | RStruct (n,_)
8721    | RHashtable n -> pr "%%%s = " n
8722    | RStringList n
8723    | RStructList (n,_) -> pr "@%s = " n
8724   );
8725   pr "$h->%s (" name;
8726   let comma = ref false in
8727   List.iter (
8728     fun arg ->
8729       if !comma then pr ", ";
8730       comma := true;
8731       match arg with
8732       | Pathname n | Device n | Dev_or_Path n | String n
8733       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8734           pr "$%s" n
8735       | StringList n | DeviceList n ->
8736           pr "\\@%s" n
8737   ) (snd style);
8738   pr ");"
8739
8740 (* Generate Python C module. *)
8741 and generate_python_c () =
8742   generate_header CStyle LGPLv2plus;
8743
8744   pr "\
8745 #include <Python.h>
8746
8747 #include <stdio.h>
8748 #include <stdlib.h>
8749 #include <assert.h>
8750
8751 #include \"guestfs.h\"
8752
8753 typedef struct {
8754   PyObject_HEAD
8755   guestfs_h *g;
8756 } Pyguestfs_Object;
8757
8758 static guestfs_h *
8759 get_handle (PyObject *obj)
8760 {
8761   assert (obj);
8762   assert (obj != Py_None);
8763   return ((Pyguestfs_Object *) obj)->g;
8764 }
8765
8766 static PyObject *
8767 put_handle (guestfs_h *g)
8768 {
8769   assert (g);
8770   return
8771     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8772 }
8773
8774 /* This list should be freed (but not the strings) after use. */
8775 static char **
8776 get_string_list (PyObject *obj)
8777 {
8778   int i, len;
8779   char **r;
8780
8781   assert (obj);
8782
8783   if (!PyList_Check (obj)) {
8784     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8785     return NULL;
8786   }
8787
8788   len = PyList_Size (obj);
8789   r = malloc (sizeof (char *) * (len+1));
8790   if (r == NULL) {
8791     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8792     return NULL;
8793   }
8794
8795   for (i = 0; i < len; ++i)
8796     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8797   r[len] = NULL;
8798
8799   return r;
8800 }
8801
8802 static PyObject *
8803 put_string_list (char * const * const argv)
8804 {
8805   PyObject *list;
8806   int argc, i;
8807
8808   for (argc = 0; argv[argc] != NULL; ++argc)
8809     ;
8810
8811   list = PyList_New (argc);
8812   for (i = 0; i < argc; ++i)
8813     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8814
8815   return list;
8816 }
8817
8818 static PyObject *
8819 put_table (char * const * const argv)
8820 {
8821   PyObject *list, *item;
8822   int argc, i;
8823
8824   for (argc = 0; argv[argc] != NULL; ++argc)
8825     ;
8826
8827   list = PyList_New (argc >> 1);
8828   for (i = 0; i < argc; i += 2) {
8829     item = PyTuple_New (2);
8830     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8831     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8832     PyList_SetItem (list, i >> 1, item);
8833   }
8834
8835   return list;
8836 }
8837
8838 static void
8839 free_strings (char **argv)
8840 {
8841   int argc;
8842
8843   for (argc = 0; argv[argc] != NULL; ++argc)
8844     free (argv[argc]);
8845   free (argv);
8846 }
8847
8848 static PyObject *
8849 py_guestfs_create (PyObject *self, PyObject *args)
8850 {
8851   guestfs_h *g;
8852
8853   g = guestfs_create ();
8854   if (g == NULL) {
8855     PyErr_SetString (PyExc_RuntimeError,
8856                      \"guestfs.create: failed to allocate handle\");
8857     return NULL;
8858   }
8859   guestfs_set_error_handler (g, NULL, NULL);
8860   return put_handle (g);
8861 }
8862
8863 static PyObject *
8864 py_guestfs_close (PyObject *self, PyObject *args)
8865 {
8866   PyObject *py_g;
8867   guestfs_h *g;
8868
8869   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8870     return NULL;
8871   g = get_handle (py_g);
8872
8873   guestfs_close (g);
8874
8875   Py_INCREF (Py_None);
8876   return Py_None;
8877 }
8878
8879 ";
8880
8881   let emit_put_list_function typ =
8882     pr "static PyObject *\n";
8883     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8884     pr "{\n";
8885     pr "  PyObject *list;\n";
8886     pr "  int i;\n";
8887     pr "\n";
8888     pr "  list = PyList_New (%ss->len);\n" typ;
8889     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8890     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8891     pr "  return list;\n";
8892     pr "};\n";
8893     pr "\n"
8894   in
8895
8896   (* Structures, turned into Python dictionaries. *)
8897   List.iter (
8898     fun (typ, cols) ->
8899       pr "static PyObject *\n";
8900       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8901       pr "{\n";
8902       pr "  PyObject *dict;\n";
8903       pr "\n";
8904       pr "  dict = PyDict_New ();\n";
8905       List.iter (
8906         function
8907         | name, FString ->
8908             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8909             pr "                        PyString_FromString (%s->%s));\n"
8910               typ name
8911         | name, FBuffer ->
8912             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8913             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8914               typ name typ name
8915         | name, FUUID ->
8916             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8917             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8918               typ name
8919         | name, (FBytes|FUInt64) ->
8920             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8921             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8922               typ name
8923         | name, FInt64 ->
8924             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8925             pr "                        PyLong_FromLongLong (%s->%s));\n"
8926               typ name
8927         | name, FUInt32 ->
8928             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8929             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8930               typ name
8931         | name, FInt32 ->
8932             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8933             pr "                        PyLong_FromLong (%s->%s));\n"
8934               typ name
8935         | name, FOptPercent ->
8936             pr "  if (%s->%s >= 0)\n" typ name;
8937             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8938             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8939               typ name;
8940             pr "  else {\n";
8941             pr "    Py_INCREF (Py_None);\n";
8942             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8943             pr "  }\n"
8944         | name, FChar ->
8945             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8946             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8947       ) cols;
8948       pr "  return dict;\n";
8949       pr "};\n";
8950       pr "\n";
8951
8952   ) structs;
8953
8954   (* Emit a put_TYPE_list function definition only if that function is used. *)
8955   List.iter (
8956     function
8957     | typ, (RStructListOnly | RStructAndList) ->
8958         (* generate the function for typ *)
8959         emit_put_list_function typ
8960     | typ, _ -> () (* empty *)
8961   ) (rstructs_used_by all_functions);
8962
8963   (* Python wrapper functions. *)
8964   List.iter (
8965     fun (name, style, _, _, _, _, _) ->
8966       pr "static PyObject *\n";
8967       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8968       pr "{\n";
8969
8970       pr "  PyObject *py_g;\n";
8971       pr "  guestfs_h *g;\n";
8972       pr "  PyObject *py_r;\n";
8973
8974       let error_code =
8975         match fst style with
8976         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8977         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8978         | RConstString _ | RConstOptString _ ->
8979             pr "  const char *r;\n"; "NULL"
8980         | RString _ -> pr "  char *r;\n"; "NULL"
8981         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8982         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8983         | RStructList (_, typ) ->
8984             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8985         | RBufferOut _ ->
8986             pr "  char *r;\n";
8987             pr "  size_t size;\n";
8988             "NULL" in
8989
8990       List.iter (
8991         function
8992         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8993             pr "  const char *%s;\n" n
8994         | OptString n -> pr "  const char *%s;\n" n
8995         | StringList n | DeviceList n ->
8996             pr "  PyObject *py_%s;\n" n;
8997             pr "  char **%s;\n" n
8998         | Bool n -> pr "  int %s;\n" n
8999         | Int n -> pr "  int %s;\n" n
9000         | Int64 n -> pr "  long long %s;\n" n
9001       ) (snd style);
9002
9003       pr "\n";
9004
9005       (* Convert the parameters. *)
9006       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9007       List.iter (
9008         function
9009         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9010         | OptString _ -> pr "z"
9011         | StringList _ | DeviceList _ -> pr "O"
9012         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9013         | Int _ -> pr "i"
9014         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9015                              * emulate C's int/long/long long in Python?
9016                              *)
9017       ) (snd style);
9018       pr ":guestfs_%s\",\n" name;
9019       pr "                         &py_g";
9020       List.iter (
9021         function
9022         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9023         | OptString n -> pr ", &%s" n
9024         | StringList n | DeviceList n -> pr ", &py_%s" n
9025         | Bool n -> pr ", &%s" n
9026         | Int n -> pr ", &%s" n
9027         | Int64 n -> pr ", &%s" n
9028       ) (snd style);
9029
9030       pr "))\n";
9031       pr "    return NULL;\n";
9032
9033       pr "  g = get_handle (py_g);\n";
9034       List.iter (
9035         function
9036         | Pathname _ | Device _ | Dev_or_Path _ | String _
9037         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9038         | StringList n | DeviceList n ->
9039             pr "  %s = get_string_list (py_%s);\n" n n;
9040             pr "  if (!%s) return NULL;\n" n
9041       ) (snd style);
9042
9043       pr "\n";
9044
9045       pr "  r = guestfs_%s " name;
9046       generate_c_call_args ~handle:"g" style;
9047       pr ";\n";
9048
9049       List.iter (
9050         function
9051         | Pathname _ | Device _ | Dev_or_Path _ | String _
9052         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9053         | StringList n | DeviceList n ->
9054             pr "  free (%s);\n" n
9055       ) (snd style);
9056
9057       pr "  if (r == %s) {\n" error_code;
9058       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9059       pr "    return NULL;\n";
9060       pr "  }\n";
9061       pr "\n";
9062
9063       (match fst style with
9064        | RErr ->
9065            pr "  Py_INCREF (Py_None);\n";
9066            pr "  py_r = Py_None;\n"
9067        | RInt _
9068        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9069        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9070        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9071        | RConstOptString _ ->
9072            pr "  if (r)\n";
9073            pr "    py_r = PyString_FromString (r);\n";
9074            pr "  else {\n";
9075            pr "    Py_INCREF (Py_None);\n";
9076            pr "    py_r = Py_None;\n";
9077            pr "  }\n"
9078        | RString _ ->
9079            pr "  py_r = PyString_FromString (r);\n";
9080            pr "  free (r);\n"
9081        | RStringList _ ->
9082            pr "  py_r = put_string_list (r);\n";
9083            pr "  free_strings (r);\n"
9084        | RStruct (_, typ) ->
9085            pr "  py_r = put_%s (r);\n" typ;
9086            pr "  guestfs_free_%s (r);\n" typ
9087        | RStructList (_, typ) ->
9088            pr "  py_r = put_%s_list (r);\n" typ;
9089            pr "  guestfs_free_%s_list (r);\n" typ
9090        | RHashtable n ->
9091            pr "  py_r = put_table (r);\n";
9092            pr "  free_strings (r);\n"
9093        | RBufferOut _ ->
9094            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9095            pr "  free (r);\n"
9096       );
9097
9098       pr "  return py_r;\n";
9099       pr "}\n";
9100       pr "\n"
9101   ) all_functions;
9102
9103   (* Table of functions. *)
9104   pr "static PyMethodDef methods[] = {\n";
9105   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9106   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9107   List.iter (
9108     fun (name, _, _, _, _, _, _) ->
9109       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9110         name name
9111   ) all_functions;
9112   pr "  { NULL, NULL, 0, NULL }\n";
9113   pr "};\n";
9114   pr "\n";
9115
9116   (* Init function. *)
9117   pr "\
9118 void
9119 initlibguestfsmod (void)
9120 {
9121   static int initialized = 0;
9122
9123   if (initialized) return;
9124   Py_InitModule ((char *) \"libguestfsmod\", methods);
9125   initialized = 1;
9126 }
9127 "
9128
9129 (* Generate Python module. *)
9130 and generate_python_py () =
9131   generate_header HashStyle LGPLv2plus;
9132
9133   pr "\
9134 u\"\"\"Python bindings for libguestfs
9135
9136 import guestfs
9137 g = guestfs.GuestFS ()
9138 g.add_drive (\"guest.img\")
9139 g.launch ()
9140 parts = g.list_partitions ()
9141
9142 The guestfs module provides a Python binding to the libguestfs API
9143 for examining and modifying virtual machine disk images.
9144
9145 Amongst the things this is good for: making batch configuration
9146 changes to guests, getting disk used/free statistics (see also:
9147 virt-df), migrating between virtualization systems (see also:
9148 virt-p2v), performing partial backups, performing partial guest
9149 clones, cloning guests and changing registry/UUID/hostname info, and
9150 much else besides.
9151
9152 Libguestfs uses Linux kernel and qemu code, and can access any type of
9153 guest filesystem that Linux and qemu can, including but not limited
9154 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9155 schemes, qcow, qcow2, vmdk.
9156
9157 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9158 LVs, what filesystem is in each LV, etc.).  It can also run commands
9159 in the context of the guest.  Also you can access filesystems over
9160 FUSE.
9161
9162 Errors which happen while using the API are turned into Python
9163 RuntimeError exceptions.
9164
9165 To create a guestfs handle you usually have to perform the following
9166 sequence of calls:
9167
9168 # Create the handle, call add_drive at least once, and possibly
9169 # several times if the guest has multiple block devices:
9170 g = guestfs.GuestFS ()
9171 g.add_drive (\"guest.img\")
9172
9173 # Launch the qemu subprocess and wait for it to become ready:
9174 g.launch ()
9175
9176 # Now you can issue commands, for example:
9177 logvols = g.lvs ()
9178
9179 \"\"\"
9180
9181 import libguestfsmod
9182
9183 class GuestFS:
9184     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9185
9186     def __init__ (self):
9187         \"\"\"Create a new libguestfs handle.\"\"\"
9188         self._o = libguestfsmod.create ()
9189
9190     def __del__ (self):
9191         libguestfsmod.close (self._o)
9192
9193 ";
9194
9195   List.iter (
9196     fun (name, style, _, flags, _, _, longdesc) ->
9197       pr "    def %s " name;
9198       generate_py_call_args ~handle:"self" (snd style);
9199       pr ":\n";
9200
9201       if not (List.mem NotInDocs flags) then (
9202         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9203         let doc =
9204           match fst style with
9205           | RErr | RInt _ | RInt64 _ | RBool _
9206           | RConstOptString _ | RConstString _
9207           | RString _ | RBufferOut _ -> doc
9208           | RStringList _ ->
9209               doc ^ "\n\nThis function returns a list of strings."
9210           | RStruct (_, typ) ->
9211               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9212           | RStructList (_, typ) ->
9213               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9214           | RHashtable _ ->
9215               doc ^ "\n\nThis function returns a dictionary." in
9216         let doc =
9217           if List.mem ProtocolLimitWarning flags then
9218             doc ^ "\n\n" ^ protocol_limit_warning
9219           else doc in
9220         let doc =
9221           if List.mem DangerWillRobinson flags then
9222             doc ^ "\n\n" ^ danger_will_robinson
9223           else doc in
9224         let doc =
9225           match deprecation_notice flags with
9226           | None -> doc
9227           | Some txt -> doc ^ "\n\n" ^ txt in
9228         let doc = pod2text ~width:60 name doc in
9229         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9230         let doc = String.concat "\n        " doc in
9231         pr "        u\"\"\"%s\"\"\"\n" doc;
9232       );
9233       pr "        return libguestfsmod.%s " name;
9234       generate_py_call_args ~handle:"self._o" (snd style);
9235       pr "\n";
9236       pr "\n";
9237   ) all_functions
9238
9239 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9240 and generate_py_call_args ~handle args =
9241   pr "(%s" handle;
9242   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9243   pr ")"
9244
9245 (* Useful if you need the longdesc POD text as plain text.  Returns a
9246  * list of lines.
9247  *
9248  * Because this is very slow (the slowest part of autogeneration),
9249  * we memoize the results.
9250  *)
9251 and pod2text ~width name longdesc =
9252   let key = width, name, longdesc in
9253   try Hashtbl.find pod2text_memo key
9254   with Not_found ->
9255     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9256     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9257     close_out chan;
9258     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9259     let chan = open_process_in cmd in
9260     let lines = ref [] in
9261     let rec loop i =
9262       let line = input_line chan in
9263       if i = 1 then             (* discard the first line of output *)
9264         loop (i+1)
9265       else (
9266         let line = triml line in
9267         lines := line :: !lines;
9268         loop (i+1)
9269       ) in
9270     let lines = try loop 1 with End_of_file -> List.rev !lines in
9271     unlink filename;
9272     (match close_process_in chan with
9273      | WEXITED 0 -> ()
9274      | WEXITED i ->
9275          failwithf "pod2text: process exited with non-zero status (%d)" i
9276      | WSIGNALED i | WSTOPPED i ->
9277          failwithf "pod2text: process signalled or stopped by signal %d" i
9278     );
9279     Hashtbl.add pod2text_memo key lines;
9280     pod2text_memo_updated ();
9281     lines
9282
9283 (* Generate ruby bindings. *)
9284 and generate_ruby_c () =
9285   generate_header CStyle LGPLv2plus;
9286
9287   pr "\
9288 #include <stdio.h>
9289 #include <stdlib.h>
9290
9291 #include <ruby.h>
9292
9293 #include \"guestfs.h\"
9294
9295 #include \"extconf.h\"
9296
9297 /* For Ruby < 1.9 */
9298 #ifndef RARRAY_LEN
9299 #define RARRAY_LEN(r) (RARRAY((r))->len)
9300 #endif
9301
9302 static VALUE m_guestfs;                 /* guestfs module */
9303 static VALUE c_guestfs;                 /* guestfs_h handle */
9304 static VALUE e_Error;                   /* used for all errors */
9305
9306 static void ruby_guestfs_free (void *p)
9307 {
9308   if (!p) return;
9309   guestfs_close ((guestfs_h *) p);
9310 }
9311
9312 static VALUE ruby_guestfs_create (VALUE m)
9313 {
9314   guestfs_h *g;
9315
9316   g = guestfs_create ();
9317   if (!g)
9318     rb_raise (e_Error, \"failed to create guestfs handle\");
9319
9320   /* Don't print error messages to stderr by default. */
9321   guestfs_set_error_handler (g, NULL, NULL);
9322
9323   /* Wrap it, and make sure the close function is called when the
9324    * handle goes away.
9325    */
9326   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9327 }
9328
9329 static VALUE ruby_guestfs_close (VALUE gv)
9330 {
9331   guestfs_h *g;
9332   Data_Get_Struct (gv, guestfs_h, g);
9333
9334   ruby_guestfs_free (g);
9335   DATA_PTR (gv) = NULL;
9336
9337   return Qnil;
9338 }
9339
9340 ";
9341
9342   List.iter (
9343     fun (name, style, _, _, _, _, _) ->
9344       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9345       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9346       pr ")\n";
9347       pr "{\n";
9348       pr "  guestfs_h *g;\n";
9349       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9350       pr "  if (!g)\n";
9351       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9352         name;
9353       pr "\n";
9354
9355       List.iter (
9356         function
9357         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9358             pr "  Check_Type (%sv, T_STRING);\n" n;
9359             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9360             pr "  if (!%s)\n" n;
9361             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9362             pr "              \"%s\", \"%s\");\n" n name
9363         | OptString n ->
9364             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9365         | StringList n | DeviceList n ->
9366             pr "  char **%s;\n" n;
9367             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9368             pr "  {\n";
9369             pr "    int i, len;\n";
9370             pr "    len = RARRAY_LEN (%sv);\n" n;
9371             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9372               n;
9373             pr "    for (i = 0; i < len; ++i) {\n";
9374             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9375             pr "      %s[i] = StringValueCStr (v);\n" n;
9376             pr "    }\n";
9377             pr "    %s[len] = NULL;\n" n;
9378             pr "  }\n";
9379         | Bool n ->
9380             pr "  int %s = RTEST (%sv);\n" n n
9381         | Int n ->
9382             pr "  int %s = NUM2INT (%sv);\n" n n
9383         | Int64 n ->
9384             pr "  long long %s = NUM2LL (%sv);\n" n n
9385       ) (snd style);
9386       pr "\n";
9387
9388       let error_code =
9389         match fst style with
9390         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9391         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9392         | RConstString _ | RConstOptString _ ->
9393             pr "  const char *r;\n"; "NULL"
9394         | RString _ -> pr "  char *r;\n"; "NULL"
9395         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9396         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9397         | RStructList (_, typ) ->
9398             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9399         | RBufferOut _ ->
9400             pr "  char *r;\n";
9401             pr "  size_t size;\n";
9402             "NULL" in
9403       pr "\n";
9404
9405       pr "  r = guestfs_%s " name;
9406       generate_c_call_args ~handle:"g" style;
9407       pr ";\n";
9408
9409       List.iter (
9410         function
9411         | Pathname _ | Device _ | Dev_or_Path _ | String _
9412         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9413         | StringList n | DeviceList n ->
9414             pr "  free (%s);\n" n
9415       ) (snd style);
9416
9417       pr "  if (r == %s)\n" error_code;
9418       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9419       pr "\n";
9420
9421       (match fst style with
9422        | RErr ->
9423            pr "  return Qnil;\n"
9424        | RInt _ | RBool _ ->
9425            pr "  return INT2NUM (r);\n"
9426        | RInt64 _ ->
9427            pr "  return ULL2NUM (r);\n"
9428        | RConstString _ ->
9429            pr "  return rb_str_new2 (r);\n";
9430        | RConstOptString _ ->
9431            pr "  if (r)\n";
9432            pr "    return rb_str_new2 (r);\n";
9433            pr "  else\n";
9434            pr "    return Qnil;\n";
9435        | RString _ ->
9436            pr "  VALUE rv = rb_str_new2 (r);\n";
9437            pr "  free (r);\n";
9438            pr "  return rv;\n";
9439        | RStringList _ ->
9440            pr "  int i, len = 0;\n";
9441            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9442            pr "  VALUE rv = rb_ary_new2 (len);\n";
9443            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9444            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9445            pr "    free (r[i]);\n";
9446            pr "  }\n";
9447            pr "  free (r);\n";
9448            pr "  return rv;\n"
9449        | RStruct (_, typ) ->
9450            let cols = cols_of_struct typ in
9451            generate_ruby_struct_code typ cols
9452        | RStructList (_, typ) ->
9453            let cols = cols_of_struct typ in
9454            generate_ruby_struct_list_code typ cols
9455        | RHashtable _ ->
9456            pr "  VALUE rv = rb_hash_new ();\n";
9457            pr "  int i;\n";
9458            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9459            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9460            pr "    free (r[i]);\n";
9461            pr "    free (r[i+1]);\n";
9462            pr "  }\n";
9463            pr "  free (r);\n";
9464            pr "  return rv;\n"
9465        | RBufferOut _ ->
9466            pr "  VALUE rv = rb_str_new (r, size);\n";
9467            pr "  free (r);\n";
9468            pr "  return rv;\n";
9469       );
9470
9471       pr "}\n";
9472       pr "\n"
9473   ) all_functions;
9474
9475   pr "\
9476 /* Initialize the module. */
9477 void Init__guestfs ()
9478 {
9479   m_guestfs = rb_define_module (\"Guestfs\");
9480   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9481   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9482
9483   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9484   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9485
9486 ";
9487   (* Define the rest of the methods. *)
9488   List.iter (
9489     fun (name, style, _, _, _, _, _) ->
9490       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9491       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9492   ) all_functions;
9493
9494   pr "}\n"
9495
9496 (* Ruby code to return a struct. *)
9497 and generate_ruby_struct_code typ cols =
9498   pr "  VALUE rv = rb_hash_new ();\n";
9499   List.iter (
9500     function
9501     | name, FString ->
9502         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9503     | name, FBuffer ->
9504         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9505     | name, FUUID ->
9506         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9507     | name, (FBytes|FUInt64) ->
9508         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9509     | name, FInt64 ->
9510         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9511     | name, FUInt32 ->
9512         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9513     | name, FInt32 ->
9514         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9515     | name, FOptPercent ->
9516         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9517     | name, FChar -> (* XXX wrong? *)
9518         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9519   ) cols;
9520   pr "  guestfs_free_%s (r);\n" typ;
9521   pr "  return rv;\n"
9522
9523 (* Ruby code to return a struct list. *)
9524 and generate_ruby_struct_list_code typ cols =
9525   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9526   pr "  int i;\n";
9527   pr "  for (i = 0; i < r->len; ++i) {\n";
9528   pr "    VALUE hv = rb_hash_new ();\n";
9529   List.iter (
9530     function
9531     | name, FString ->
9532         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9533     | name, FBuffer ->
9534         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
9535     | name, FUUID ->
9536         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9537     | name, (FBytes|FUInt64) ->
9538         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9539     | name, FInt64 ->
9540         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9541     | name, FUInt32 ->
9542         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9543     | name, FInt32 ->
9544         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9545     | name, FOptPercent ->
9546         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9547     | name, FChar -> (* XXX wrong? *)
9548         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9549   ) cols;
9550   pr "    rb_ary_push (rv, hv);\n";
9551   pr "  }\n";
9552   pr "  guestfs_free_%s_list (r);\n" typ;
9553   pr "  return rv;\n"
9554
9555 (* Generate Java bindings GuestFS.java file. *)
9556 and generate_java_java () =
9557   generate_header CStyle LGPLv2plus;
9558
9559   pr "\
9560 package com.redhat.et.libguestfs;
9561
9562 import java.util.HashMap;
9563 import com.redhat.et.libguestfs.LibGuestFSException;
9564 import com.redhat.et.libguestfs.PV;
9565 import com.redhat.et.libguestfs.VG;
9566 import com.redhat.et.libguestfs.LV;
9567 import com.redhat.et.libguestfs.Stat;
9568 import com.redhat.et.libguestfs.StatVFS;
9569 import com.redhat.et.libguestfs.IntBool;
9570 import com.redhat.et.libguestfs.Dirent;
9571
9572 /**
9573  * The GuestFS object is a libguestfs handle.
9574  *
9575  * @author rjones
9576  */
9577 public class GuestFS {
9578   // Load the native code.
9579   static {
9580     System.loadLibrary (\"guestfs_jni\");
9581   }
9582
9583   /**
9584    * The native guestfs_h pointer.
9585    */
9586   long g;
9587
9588   /**
9589    * Create a libguestfs handle.
9590    *
9591    * @throws LibGuestFSException
9592    */
9593   public GuestFS () throws LibGuestFSException
9594   {
9595     g = _create ();
9596   }
9597   private native long _create () throws LibGuestFSException;
9598
9599   /**
9600    * Close a libguestfs handle.
9601    *
9602    * You can also leave handles to be collected by the garbage
9603    * collector, but this method ensures that the resources used
9604    * by the handle are freed up immediately.  If you call any
9605    * other methods after closing the handle, you will get an
9606    * exception.
9607    *
9608    * @throws LibGuestFSException
9609    */
9610   public void close () throws LibGuestFSException
9611   {
9612     if (g != 0)
9613       _close (g);
9614     g = 0;
9615   }
9616   private native void _close (long g) throws LibGuestFSException;
9617
9618   public void finalize () throws LibGuestFSException
9619   {
9620     close ();
9621   }
9622
9623 ";
9624
9625   List.iter (
9626     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9627       if not (List.mem NotInDocs flags); then (
9628         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9629         let doc =
9630           if List.mem ProtocolLimitWarning flags then
9631             doc ^ "\n\n" ^ protocol_limit_warning
9632           else doc in
9633         let doc =
9634           if List.mem DangerWillRobinson flags then
9635             doc ^ "\n\n" ^ danger_will_robinson
9636           else doc in
9637         let doc =
9638           match deprecation_notice flags with
9639           | None -> doc
9640           | Some txt -> doc ^ "\n\n" ^ txt in
9641         let doc = pod2text ~width:60 name doc in
9642         let doc = List.map (            (* RHBZ#501883 *)
9643           function
9644           | "" -> "<p>"
9645           | nonempty -> nonempty
9646         ) doc in
9647         let doc = String.concat "\n   * " doc in
9648
9649         pr "  /**\n";
9650         pr "   * %s\n" shortdesc;
9651         pr "   * <p>\n";
9652         pr "   * %s\n" doc;
9653         pr "   * @throws LibGuestFSException\n";
9654         pr "   */\n";
9655         pr "  ";
9656       );
9657       generate_java_prototype ~public:true ~semicolon:false name style;
9658       pr "\n";
9659       pr "  {\n";
9660       pr "    if (g == 0)\n";
9661       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9662         name;
9663       pr "    ";
9664       if fst style <> RErr then pr "return ";
9665       pr "_%s " name;
9666       generate_java_call_args ~handle:"g" (snd style);
9667       pr ";\n";
9668       pr "  }\n";
9669       pr "  ";
9670       generate_java_prototype ~privat:true ~native:true name style;
9671       pr "\n";
9672       pr "\n";
9673   ) all_functions;
9674
9675   pr "}\n"
9676
9677 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9678 and generate_java_call_args ~handle args =
9679   pr "(%s" handle;
9680   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9681   pr ")"
9682
9683 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9684     ?(semicolon=true) name style =
9685   if privat then pr "private ";
9686   if public then pr "public ";
9687   if native then pr "native ";
9688
9689   (* return type *)
9690   (match fst style with
9691    | RErr -> pr "void ";
9692    | RInt _ -> pr "int ";
9693    | RInt64 _ -> pr "long ";
9694    | RBool _ -> pr "boolean ";
9695    | RConstString _ | RConstOptString _ | RString _
9696    | RBufferOut _ -> pr "String ";
9697    | RStringList _ -> pr "String[] ";
9698    | RStruct (_, typ) ->
9699        let name = java_name_of_struct typ in
9700        pr "%s " name;
9701    | RStructList (_, typ) ->
9702        let name = java_name_of_struct typ in
9703        pr "%s[] " name;
9704    | RHashtable _ -> pr "HashMap<String,String> ";
9705   );
9706
9707   if native then pr "_%s " name else pr "%s " name;
9708   pr "(";
9709   let needs_comma = ref false in
9710   if native then (
9711     pr "long g";
9712     needs_comma := true
9713   );
9714
9715   (* args *)
9716   List.iter (
9717     fun arg ->
9718       if !needs_comma then pr ", ";
9719       needs_comma := true;
9720
9721       match arg with
9722       | Pathname n
9723       | Device n | Dev_or_Path n
9724       | String n
9725       | OptString n
9726       | FileIn n
9727       | FileOut n ->
9728           pr "String %s" n
9729       | StringList n | DeviceList n ->
9730           pr "String[] %s" n
9731       | Bool n ->
9732           pr "boolean %s" n
9733       | Int n ->
9734           pr "int %s" n
9735       | Int64 n ->
9736           pr "long %s" n
9737   ) (snd style);
9738
9739   pr ")\n";
9740   pr "    throws LibGuestFSException";
9741   if semicolon then pr ";"
9742
9743 and generate_java_struct jtyp cols () =
9744   generate_header CStyle LGPLv2plus;
9745
9746   pr "\
9747 package com.redhat.et.libguestfs;
9748
9749 /**
9750  * Libguestfs %s structure.
9751  *
9752  * @author rjones
9753  * @see GuestFS
9754  */
9755 public class %s {
9756 " jtyp jtyp;
9757
9758   List.iter (
9759     function
9760     | name, FString
9761     | name, FUUID
9762     | name, FBuffer -> pr "  public String %s;\n" name
9763     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9764     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9765     | name, FChar -> pr "  public char %s;\n" name
9766     | name, FOptPercent ->
9767         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9768         pr "  public float %s;\n" name
9769   ) cols;
9770
9771   pr "}\n"
9772
9773 and generate_java_c () =
9774   generate_header CStyle LGPLv2plus;
9775
9776   pr "\
9777 #include <stdio.h>
9778 #include <stdlib.h>
9779 #include <string.h>
9780
9781 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9782 #include \"guestfs.h\"
9783
9784 /* Note that this function returns.  The exception is not thrown
9785  * until after the wrapper function returns.
9786  */
9787 static void
9788 throw_exception (JNIEnv *env, const char *msg)
9789 {
9790   jclass cl;
9791   cl = (*env)->FindClass (env,
9792                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9793   (*env)->ThrowNew (env, cl, msg);
9794 }
9795
9796 JNIEXPORT jlong JNICALL
9797 Java_com_redhat_et_libguestfs_GuestFS__1create
9798   (JNIEnv *env, jobject obj)
9799 {
9800   guestfs_h *g;
9801
9802   g = guestfs_create ();
9803   if (g == NULL) {
9804     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9805     return 0;
9806   }
9807   guestfs_set_error_handler (g, NULL, NULL);
9808   return (jlong) (long) g;
9809 }
9810
9811 JNIEXPORT void JNICALL
9812 Java_com_redhat_et_libguestfs_GuestFS__1close
9813   (JNIEnv *env, jobject obj, jlong jg)
9814 {
9815   guestfs_h *g = (guestfs_h *) (long) jg;
9816   guestfs_close (g);
9817 }
9818
9819 ";
9820
9821   List.iter (
9822     fun (name, style, _, _, _, _, _) ->
9823       pr "JNIEXPORT ";
9824       (match fst style with
9825        | RErr -> pr "void ";
9826        | RInt _ -> pr "jint ";
9827        | RInt64 _ -> pr "jlong ";
9828        | RBool _ -> pr "jboolean ";
9829        | RConstString _ | RConstOptString _ | RString _
9830        | RBufferOut _ -> pr "jstring ";
9831        | RStruct _ | RHashtable _ ->
9832            pr "jobject ";
9833        | RStringList _ | RStructList _ ->
9834            pr "jobjectArray ";
9835       );
9836       pr "JNICALL\n";
9837       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9838       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9839       pr "\n";
9840       pr "  (JNIEnv *env, jobject obj, jlong jg";
9841       List.iter (
9842         function
9843         | Pathname n
9844         | Device n | Dev_or_Path n
9845         | String n
9846         | OptString n
9847         | FileIn n
9848         | FileOut n ->
9849             pr ", jstring j%s" n
9850         | StringList n | DeviceList n ->
9851             pr ", jobjectArray j%s" n
9852         | Bool n ->
9853             pr ", jboolean j%s" n
9854         | Int n ->
9855             pr ", jint j%s" n
9856         | Int64 n ->
9857             pr ", jlong j%s" n
9858       ) (snd style);
9859       pr ")\n";
9860       pr "{\n";
9861       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9862       let error_code, no_ret =
9863         match fst style with
9864         | RErr -> pr "  int r;\n"; "-1", ""
9865         | RBool _
9866         | RInt _ -> pr "  int r;\n"; "-1", "0"
9867         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9868         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9869         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9870         | RString _ ->
9871             pr "  jstring jr;\n";
9872             pr "  char *r;\n"; "NULL", "NULL"
9873         | RStringList _ ->
9874             pr "  jobjectArray jr;\n";
9875             pr "  int r_len;\n";
9876             pr "  jclass cl;\n";
9877             pr "  jstring jstr;\n";
9878             pr "  char **r;\n"; "NULL", "NULL"
9879         | RStruct (_, typ) ->
9880             pr "  jobject jr;\n";
9881             pr "  jclass cl;\n";
9882             pr "  jfieldID fl;\n";
9883             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9884         | RStructList (_, typ) ->
9885             pr "  jobjectArray jr;\n";
9886             pr "  jclass cl;\n";
9887             pr "  jfieldID fl;\n";
9888             pr "  jobject jfl;\n";
9889             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9890         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9891         | RBufferOut _ ->
9892             pr "  jstring jr;\n";
9893             pr "  char *r;\n";
9894             pr "  size_t size;\n";
9895             "NULL", "NULL" in
9896       List.iter (
9897         function
9898         | Pathname n
9899         | Device n | Dev_or_Path n
9900         | String n
9901         | OptString n
9902         | FileIn n
9903         | FileOut n ->
9904             pr "  const char *%s;\n" n
9905         | StringList n | DeviceList n ->
9906             pr "  int %s_len;\n" n;
9907             pr "  const char **%s;\n" n
9908         | Bool n
9909         | Int n ->
9910             pr "  int %s;\n" n
9911         | Int64 n ->
9912             pr "  int64_t %s;\n" n
9913       ) (snd style);
9914
9915       let needs_i =
9916         (match fst style with
9917          | RStringList _ | RStructList _ -> true
9918          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9919          | RConstOptString _
9920          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9921           List.exists (function
9922                        | StringList _ -> true
9923                        | DeviceList _ -> true
9924                        | _ -> false) (snd style) in
9925       if needs_i then
9926         pr "  int i;\n";
9927
9928       pr "\n";
9929
9930       (* Get the parameters. *)
9931       List.iter (
9932         function
9933         | Pathname n
9934         | Device n | Dev_or_Path n
9935         | String n
9936         | FileIn n
9937         | FileOut n ->
9938             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9939         | OptString n ->
9940             (* This is completely undocumented, but Java null becomes
9941              * a NULL parameter.
9942              *)
9943             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9944         | StringList n | DeviceList n ->
9945             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9946             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9947             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9948             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9949               n;
9950             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9951             pr "  }\n";
9952             pr "  %s[%s_len] = NULL;\n" n n;
9953         | Bool n
9954         | Int n
9955         | Int64 n ->
9956             pr "  %s = j%s;\n" n n
9957       ) (snd style);
9958
9959       (* Make the call. *)
9960       pr "  r = guestfs_%s " name;
9961       generate_c_call_args ~handle:"g" style;
9962       pr ";\n";
9963
9964       (* Release the parameters. *)
9965       List.iter (
9966         function
9967         | Pathname n
9968         | Device n | Dev_or_Path n
9969         | String n
9970         | FileIn n
9971         | FileOut n ->
9972             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9973         | OptString n ->
9974             pr "  if (j%s)\n" n;
9975             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9976         | StringList n | DeviceList n ->
9977             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9978             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9979               n;
9980             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9981             pr "  }\n";
9982             pr "  free (%s);\n" n
9983         | Bool n
9984         | Int n
9985         | Int64 n -> ()
9986       ) (snd style);
9987
9988       (* Check for errors. *)
9989       pr "  if (r == %s) {\n" error_code;
9990       pr "    throw_exception (env, guestfs_last_error (g));\n";
9991       pr "    return %s;\n" no_ret;
9992       pr "  }\n";
9993
9994       (* Return value. *)
9995       (match fst style with
9996        | RErr -> ()
9997        | RInt _ -> pr "  return (jint) r;\n"
9998        | RBool _ -> pr "  return (jboolean) r;\n"
9999        | RInt64 _ -> pr "  return (jlong) r;\n"
10000        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10001        | RConstOptString _ ->
10002            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10003        | RString _ ->
10004            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10005            pr "  free (r);\n";
10006            pr "  return jr;\n"
10007        | RStringList _ ->
10008            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10009            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10010            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10011            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10012            pr "  for (i = 0; i < r_len; ++i) {\n";
10013            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10014            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10015            pr "    free (r[i]);\n";
10016            pr "  }\n";
10017            pr "  free (r);\n";
10018            pr "  return jr;\n"
10019        | RStruct (_, typ) ->
10020            let jtyp = java_name_of_struct typ in
10021            let cols = cols_of_struct typ in
10022            generate_java_struct_return typ jtyp cols
10023        | RStructList (_, typ) ->
10024            let jtyp = java_name_of_struct typ in
10025            let cols = cols_of_struct typ in
10026            generate_java_struct_list_return typ jtyp cols
10027        | RHashtable _ ->
10028            (* XXX *)
10029            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10030            pr "  return NULL;\n"
10031        | RBufferOut _ ->
10032            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10033            pr "  free (r);\n";
10034            pr "  return jr;\n"
10035       );
10036
10037       pr "}\n";
10038       pr "\n"
10039   ) all_functions
10040
10041 and generate_java_struct_return typ jtyp cols =
10042   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10043   pr "  jr = (*env)->AllocObject (env, cl);\n";
10044   List.iter (
10045     function
10046     | name, FString ->
10047         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10048         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10049     | name, FUUID ->
10050         pr "  {\n";
10051         pr "    char s[33];\n";
10052         pr "    memcpy (s, r->%s, 32);\n" name;
10053         pr "    s[32] = 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, FBuffer ->
10058         pr "  {\n";
10059         pr "    int len = r->%s_len;\n" name;
10060         pr "    char s[len+1];\n";
10061         pr "    memcpy (s, r->%s, len);\n" name;
10062         pr "    s[len] = 0;\n";
10063         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10064         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10065         pr "  }\n";
10066     | name, (FBytes|FUInt64|FInt64) ->
10067         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10068         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10069     | name, (FUInt32|FInt32) ->
10070         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10071         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10072     | name, FOptPercent ->
10073         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10074         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10075     | name, FChar ->
10076         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10077         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10078   ) cols;
10079   pr "  free (r);\n";
10080   pr "  return jr;\n"
10081
10082 and generate_java_struct_list_return typ jtyp cols =
10083   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10084   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10085   pr "  for (i = 0; i < r->len; ++i) {\n";
10086   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10087   List.iter (
10088     function
10089     | name, FString ->
10090         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10091         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10092     | name, FUUID ->
10093         pr "    {\n";
10094         pr "      char s[33];\n";
10095         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10096         pr "      s[32] = 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, FBuffer ->
10101         pr "    {\n";
10102         pr "      int len = r->val[i].%s_len;\n" name;
10103         pr "      char s[len+1];\n";
10104         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10105         pr "      s[len] = 0;\n";
10106         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10107         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10108         pr "    }\n";
10109     | name, (FBytes|FUInt64|FInt64) ->
10110         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10111         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10112     | name, (FUInt32|FInt32) ->
10113         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10114         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10115     | name, FOptPercent ->
10116         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10117         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10118     | name, FChar ->
10119         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10120         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10121   ) cols;
10122   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10123   pr "  }\n";
10124   pr "  guestfs_free_%s_list (r);\n" typ;
10125   pr "  return jr;\n"
10126
10127 and generate_java_makefile_inc () =
10128   generate_header HashStyle GPLv2plus;
10129
10130   pr "java_built_sources = \\\n";
10131   List.iter (
10132     fun (typ, jtyp) ->
10133         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10134   ) java_structs;
10135   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10136
10137 and generate_haskell_hs () =
10138   generate_header HaskellStyle LGPLv2plus;
10139
10140   (* XXX We only know how to generate partial FFI for Haskell
10141    * at the moment.  Please help out!
10142    *)
10143   let can_generate style =
10144     match style with
10145     | RErr, _
10146     | RInt _, _
10147     | RInt64 _, _ -> true
10148     | RBool _, _
10149     | RConstString _, _
10150     | RConstOptString _, _
10151     | RString _, _
10152     | RStringList _, _
10153     | RStruct _, _
10154     | RStructList _, _
10155     | RHashtable _, _
10156     | RBufferOut _, _ -> false in
10157
10158   pr "\
10159 {-# INCLUDE <guestfs.h> #-}
10160 {-# LANGUAGE ForeignFunctionInterface #-}
10161
10162 module Guestfs (
10163   create";
10164
10165   (* List out the names of the actions we want to export. *)
10166   List.iter (
10167     fun (name, style, _, _, _, _, _) ->
10168       if can_generate style then pr ",\n  %s" name
10169   ) all_functions;
10170
10171   pr "
10172   ) where
10173
10174 -- Unfortunately some symbols duplicate ones already present
10175 -- in Prelude.  We don't know which, so we hard-code a list
10176 -- here.
10177 import Prelude hiding (truncate)
10178
10179 import Foreign
10180 import Foreign.C
10181 import Foreign.C.Types
10182 import IO
10183 import Control.Exception
10184 import Data.Typeable
10185
10186 data GuestfsS = GuestfsS            -- represents the opaque C struct
10187 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10188 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10189
10190 -- XXX define properly later XXX
10191 data PV = PV
10192 data VG = VG
10193 data LV = LV
10194 data IntBool = IntBool
10195 data Stat = Stat
10196 data StatVFS = StatVFS
10197 data Hashtable = Hashtable
10198
10199 foreign import ccall unsafe \"guestfs_create\" c_create
10200   :: IO GuestfsP
10201 foreign import ccall unsafe \"&guestfs_close\" c_close
10202   :: FunPtr (GuestfsP -> IO ())
10203 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10204   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10205
10206 create :: IO GuestfsH
10207 create = do
10208   p <- c_create
10209   c_set_error_handler p nullPtr nullPtr
10210   h <- newForeignPtr c_close p
10211   return h
10212
10213 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10214   :: GuestfsP -> IO CString
10215
10216 -- last_error :: GuestfsH -> IO (Maybe String)
10217 -- last_error h = do
10218 --   str <- withForeignPtr h (\\p -> c_last_error p)
10219 --   maybePeek peekCString str
10220
10221 last_error :: GuestfsH -> IO (String)
10222 last_error h = do
10223   str <- withForeignPtr h (\\p -> c_last_error p)
10224   if (str == nullPtr)
10225     then return \"no error\"
10226     else peekCString str
10227
10228 ";
10229
10230   (* Generate wrappers for each foreign function. *)
10231   List.iter (
10232     fun (name, style, _, _, _, _, _) ->
10233       if can_generate style then (
10234         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10235         pr "  :: ";
10236         generate_haskell_prototype ~handle:"GuestfsP" style;
10237         pr "\n";
10238         pr "\n";
10239         pr "%s :: " name;
10240         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10241         pr "\n";
10242         pr "%s %s = do\n" name
10243           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10244         pr "  r <- ";
10245         (* Convert pointer arguments using with* functions. *)
10246         List.iter (
10247           function
10248           | FileIn n
10249           | FileOut n
10250           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10251           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10252           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10253           | Bool _ | Int _ | Int64 _ -> ()
10254         ) (snd style);
10255         (* Convert integer arguments. *)
10256         let args =
10257           List.map (
10258             function
10259             | Bool n -> sprintf "(fromBool %s)" n
10260             | Int n -> sprintf "(fromIntegral %s)" n
10261             | Int64 n -> sprintf "(fromIntegral %s)" n
10262             | FileIn n | FileOut n
10263             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10264           ) (snd style) in
10265         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10266           (String.concat " " ("p" :: args));
10267         (match fst style with
10268          | RErr | RInt _ | RInt64 _ | RBool _ ->
10269              pr "  if (r == -1)\n";
10270              pr "    then do\n";
10271              pr "      err <- last_error h\n";
10272              pr "      fail err\n";
10273          | RConstString _ | RConstOptString _ | RString _
10274          | RStringList _ | RStruct _
10275          | RStructList _ | RHashtable _ | RBufferOut _ ->
10276              pr "  if (r == nullPtr)\n";
10277              pr "    then do\n";
10278              pr "      err <- last_error h\n";
10279              pr "      fail err\n";
10280         );
10281         (match fst style with
10282          | RErr ->
10283              pr "    else return ()\n"
10284          | RInt _ ->
10285              pr "    else return (fromIntegral r)\n"
10286          | RInt64 _ ->
10287              pr "    else return (fromIntegral r)\n"
10288          | RBool _ ->
10289              pr "    else return (toBool r)\n"
10290          | RConstString _
10291          | RConstOptString _
10292          | RString _
10293          | RStringList _
10294          | RStruct _
10295          | RStructList _
10296          | RHashtable _
10297          | RBufferOut _ ->
10298              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10299         );
10300         pr "\n";
10301       )
10302   ) all_functions
10303
10304 and generate_haskell_prototype ~handle ?(hs = false) style =
10305   pr "%s -> " handle;
10306   let string = if hs then "String" else "CString" in
10307   let int = if hs then "Int" else "CInt" in
10308   let bool = if hs then "Bool" else "CInt" in
10309   let int64 = if hs then "Integer" else "Int64" in
10310   List.iter (
10311     fun arg ->
10312       (match arg with
10313        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10314        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10315        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10316        | Bool _ -> pr "%s" bool
10317        | Int _ -> pr "%s" int
10318        | Int64 _ -> pr "%s" int
10319        | FileIn _ -> pr "%s" string
10320        | FileOut _ -> pr "%s" string
10321       );
10322       pr " -> ";
10323   ) (snd style);
10324   pr "IO (";
10325   (match fst style with
10326    | RErr -> if not hs then pr "CInt"
10327    | RInt _ -> pr "%s" int
10328    | RInt64 _ -> pr "%s" int64
10329    | RBool _ -> pr "%s" bool
10330    | RConstString _ -> pr "%s" string
10331    | RConstOptString _ -> pr "Maybe %s" string
10332    | RString _ -> pr "%s" string
10333    | RStringList _ -> pr "[%s]" string
10334    | RStruct (_, typ) ->
10335        let name = java_name_of_struct typ in
10336        pr "%s" name
10337    | RStructList (_, typ) ->
10338        let name = java_name_of_struct typ in
10339        pr "[%s]" name
10340    | RHashtable _ -> pr "Hashtable"
10341    | RBufferOut _ -> pr "%s" string
10342   );
10343   pr ")"
10344
10345 and generate_csharp () =
10346   generate_header CPlusPlusStyle LGPLv2plus;
10347
10348   (* XXX Make this configurable by the C# assembly users. *)
10349   let library = "libguestfs.so.0" in
10350
10351   pr "\
10352 // These C# bindings are highly experimental at present.
10353 //
10354 // Firstly they only work on Linux (ie. Mono).  In order to get them
10355 // to work on Windows (ie. .Net) you would need to port the library
10356 // itself to Windows first.
10357 //
10358 // The second issue is that some calls are known to be incorrect and
10359 // can cause Mono to segfault.  Particularly: calls which pass or
10360 // return string[], or return any structure value.  This is because
10361 // we haven't worked out the correct way to do this from C#.
10362 //
10363 // The third issue is that when compiling you get a lot of warnings.
10364 // We are not sure whether the warnings are important or not.
10365 //
10366 // Fourthly we do not routinely build or test these bindings as part
10367 // of the make && make check cycle, which means that regressions might
10368 // go unnoticed.
10369 //
10370 // Suggestions and patches are welcome.
10371
10372 // To compile:
10373 //
10374 // gmcs Libguestfs.cs
10375 // mono Libguestfs.exe
10376 //
10377 // (You'll probably want to add a Test class / static main function
10378 // otherwise this won't do anything useful).
10379
10380 using System;
10381 using System.IO;
10382 using System.Runtime.InteropServices;
10383 using System.Runtime.Serialization;
10384 using System.Collections;
10385
10386 namespace Guestfs
10387 {
10388   class Error : System.ApplicationException
10389   {
10390     public Error (string message) : base (message) {}
10391     protected Error (SerializationInfo info, StreamingContext context) {}
10392   }
10393
10394   class Guestfs
10395   {
10396     IntPtr _handle;
10397
10398     [DllImport (\"%s\")]
10399     static extern IntPtr guestfs_create ();
10400
10401     public Guestfs ()
10402     {
10403       _handle = guestfs_create ();
10404       if (_handle == IntPtr.Zero)
10405         throw new Error (\"could not create guestfs handle\");
10406     }
10407
10408     [DllImport (\"%s\")]
10409     static extern void guestfs_close (IntPtr h);
10410
10411     ~Guestfs ()
10412     {
10413       guestfs_close (_handle);
10414     }
10415
10416     [DllImport (\"%s\")]
10417     static extern string guestfs_last_error (IntPtr h);
10418
10419 " library library library;
10420
10421   (* Generate C# structure bindings.  We prefix struct names with
10422    * underscore because C# cannot have conflicting struct names and
10423    * method names (eg. "class stat" and "stat").
10424    *)
10425   List.iter (
10426     fun (typ, cols) ->
10427       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10428       pr "    public class _%s {\n" typ;
10429       List.iter (
10430         function
10431         | name, FChar -> pr "      char %s;\n" name
10432         | name, FString -> pr "      string %s;\n" name
10433         | name, FBuffer ->
10434             pr "      uint %s_len;\n" name;
10435             pr "      string %s;\n" name
10436         | name, FUUID ->
10437             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10438             pr "      string %s;\n" name
10439         | name, FUInt32 -> pr "      uint %s;\n" name
10440         | name, FInt32 -> pr "      int %s;\n" name
10441         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10442         | name, FInt64 -> pr "      long %s;\n" name
10443         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10444       ) cols;
10445       pr "    }\n";
10446       pr "\n"
10447   ) structs;
10448
10449   (* Generate C# function bindings. *)
10450   List.iter (
10451     fun (name, style, _, _, _, shortdesc, _) ->
10452       let rec csharp_return_type () =
10453         match fst style with
10454         | RErr -> "void"
10455         | RBool n -> "bool"
10456         | RInt n -> "int"
10457         | RInt64 n -> "long"
10458         | RConstString n
10459         | RConstOptString n
10460         | RString n
10461         | RBufferOut n -> "string"
10462         | RStruct (_,n) -> "_" ^ n
10463         | RHashtable n -> "Hashtable"
10464         | RStringList n -> "string[]"
10465         | RStructList (_,n) -> sprintf "_%s[]" n
10466
10467       and c_return_type () =
10468         match fst style with
10469         | RErr
10470         | RBool _
10471         | RInt _ -> "int"
10472         | RInt64 _ -> "long"
10473         | RConstString _
10474         | RConstOptString _
10475         | RString _
10476         | RBufferOut _ -> "string"
10477         | RStruct (_,n) -> "_" ^ n
10478         | RHashtable _
10479         | RStringList _ -> "string[]"
10480         | RStructList (_,n) -> sprintf "_%s[]" n
10481
10482       and c_error_comparison () =
10483         match fst style with
10484         | RErr
10485         | RBool _
10486         | RInt _
10487         | RInt64 _ -> "== -1"
10488         | RConstString _
10489         | RConstOptString _
10490         | RString _
10491         | RBufferOut _
10492         | RStruct (_,_)
10493         | RHashtable _
10494         | RStringList _
10495         | RStructList (_,_) -> "== null"
10496
10497       and generate_extern_prototype () =
10498         pr "    static extern %s guestfs_%s (IntPtr h"
10499           (c_return_type ()) name;
10500         List.iter (
10501           function
10502           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10503           | FileIn n | FileOut n ->
10504               pr ", [In] string %s" n
10505           | StringList n | DeviceList n ->
10506               pr ", [In] string[] %s" n
10507           | Bool n ->
10508               pr ", bool %s" n
10509           | Int n ->
10510               pr ", int %s" n
10511           | Int64 n ->
10512               pr ", long %s" n
10513         ) (snd style);
10514         pr ");\n"
10515
10516       and generate_public_prototype () =
10517         pr "    public %s %s (" (csharp_return_type ()) name;
10518         let comma = ref false in
10519         let next () =
10520           if !comma then pr ", ";
10521           comma := true
10522         in
10523         List.iter (
10524           function
10525           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10526           | FileIn n | FileOut n ->
10527               next (); pr "string %s" n
10528           | StringList n | DeviceList n ->
10529               next (); pr "string[] %s" n
10530           | Bool n ->
10531               next (); pr "bool %s" n
10532           | Int n ->
10533               next (); pr "int %s" n
10534           | Int64 n ->
10535               next (); pr "long %s" n
10536         ) (snd style);
10537         pr ")\n"
10538
10539       and generate_call () =
10540         pr "guestfs_%s (_handle" name;
10541         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10542         pr ");\n";
10543       in
10544
10545       pr "    [DllImport (\"%s\")]\n" library;
10546       generate_extern_prototype ();
10547       pr "\n";
10548       pr "    /// <summary>\n";
10549       pr "    /// %s\n" shortdesc;
10550       pr "    /// </summary>\n";
10551       generate_public_prototype ();
10552       pr "    {\n";
10553       pr "      %s r;\n" (c_return_type ());
10554       pr "      r = ";
10555       generate_call ();
10556       pr "      if (r %s)\n" (c_error_comparison ());
10557       pr "        throw new Error (guestfs_last_error (_handle));\n";
10558       (match fst style with
10559        | RErr -> ()
10560        | RBool _ ->
10561            pr "      return r != 0 ? true : false;\n"
10562        | RHashtable _ ->
10563            pr "      Hashtable rr = new Hashtable ();\n";
10564            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10565            pr "        rr.Add (r[i], r[i+1]);\n";
10566            pr "      return rr;\n"
10567        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10568        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10569        | RStructList _ ->
10570            pr "      return r;\n"
10571       );
10572       pr "    }\n";
10573       pr "\n";
10574   ) all_functions_sorted;
10575
10576   pr "  }
10577 }
10578 "
10579
10580 and generate_bindtests () =
10581   generate_header CStyle LGPLv2plus;
10582
10583   pr "\
10584 #include <stdio.h>
10585 #include <stdlib.h>
10586 #include <inttypes.h>
10587 #include <string.h>
10588
10589 #include \"guestfs.h\"
10590 #include \"guestfs-internal.h\"
10591 #include \"guestfs-internal-actions.h\"
10592 #include \"guestfs_protocol.h\"
10593
10594 #define error guestfs_error
10595 #define safe_calloc guestfs_safe_calloc
10596 #define safe_malloc guestfs_safe_malloc
10597
10598 static void
10599 print_strings (char *const *argv)
10600 {
10601   int argc;
10602
10603   printf (\"[\");
10604   for (argc = 0; argv[argc] != NULL; ++argc) {
10605     if (argc > 0) printf (\", \");
10606     printf (\"\\\"%%s\\\"\", argv[argc]);
10607   }
10608   printf (\"]\\n\");
10609 }
10610
10611 /* The test0 function prints its parameters to stdout. */
10612 ";
10613
10614   let test0, tests =
10615     match test_functions with
10616     | [] -> assert false
10617     | test0 :: tests -> test0, tests in
10618
10619   let () =
10620     let (name, style, _, _, _, _, _) = test0 in
10621     generate_prototype ~extern:false ~semicolon:false ~newline:true
10622       ~handle:"g" ~prefix:"guestfs__" name style;
10623     pr "{\n";
10624     List.iter (
10625       function
10626       | Pathname n
10627       | Device n | Dev_or_Path n
10628       | String n
10629       | FileIn n
10630       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10631       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10632       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10633       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10634       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10635       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10636     ) (snd style);
10637     pr "  /* Java changes stdout line buffering so we need this: */\n";
10638     pr "  fflush (stdout);\n";
10639     pr "  return 0;\n";
10640     pr "}\n";
10641     pr "\n" in
10642
10643   List.iter (
10644     fun (name, style, _, _, _, _, _) ->
10645       if String.sub name (String.length name - 3) 3 <> "err" then (
10646         pr "/* Test normal return. */\n";
10647         generate_prototype ~extern:false ~semicolon:false ~newline:true
10648           ~handle:"g" ~prefix:"guestfs__" name style;
10649         pr "{\n";
10650         (match fst style with
10651          | RErr ->
10652              pr "  return 0;\n"
10653          | RInt _ ->
10654              pr "  int r;\n";
10655              pr "  sscanf (val, \"%%d\", &r);\n";
10656              pr "  return r;\n"
10657          | RInt64 _ ->
10658              pr "  int64_t r;\n";
10659              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10660              pr "  return r;\n"
10661          | RBool _ ->
10662              pr "  return STREQ (val, \"true\");\n"
10663          | RConstString _
10664          | RConstOptString _ ->
10665              (* Can't return the input string here.  Return a static
10666               * string so we ensure we get a segfault if the caller
10667               * tries to free it.
10668               *)
10669              pr "  return \"static string\";\n"
10670          | RString _ ->
10671              pr "  return strdup (val);\n"
10672          | RStringList _ ->
10673              pr "  char **strs;\n";
10674              pr "  int n, i;\n";
10675              pr "  sscanf (val, \"%%d\", &n);\n";
10676              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10677              pr "  for (i = 0; i < n; ++i) {\n";
10678              pr "    strs[i] = safe_malloc (g, 16);\n";
10679              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10680              pr "  }\n";
10681              pr "  strs[n] = NULL;\n";
10682              pr "  return strs;\n"
10683          | RStruct (_, typ) ->
10684              pr "  struct guestfs_%s *r;\n" typ;
10685              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10686              pr "  return r;\n"
10687          | RStructList (_, typ) ->
10688              pr "  struct guestfs_%s_list *r;\n" typ;
10689              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10690              pr "  sscanf (val, \"%%d\", &r->len);\n";
10691              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10692              pr "  return r;\n"
10693          | RHashtable _ ->
10694              pr "  char **strs;\n";
10695              pr "  int n, i;\n";
10696              pr "  sscanf (val, \"%%d\", &n);\n";
10697              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10698              pr "  for (i = 0; i < n; ++i) {\n";
10699              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10700              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10701              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10702              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10703              pr "  }\n";
10704              pr "  strs[n*2] = NULL;\n";
10705              pr "  return strs;\n"
10706          | RBufferOut _ ->
10707              pr "  return strdup (val);\n"
10708         );
10709         pr "}\n";
10710         pr "\n"
10711       ) else (
10712         pr "/* Test error return. */\n";
10713         generate_prototype ~extern:false ~semicolon:false ~newline:true
10714           ~handle:"g" ~prefix:"guestfs__" name style;
10715         pr "{\n";
10716         pr "  error (g, \"error\");\n";
10717         (match fst style with
10718          | RErr | RInt _ | RInt64 _ | RBool _ ->
10719              pr "  return -1;\n"
10720          | RConstString _ | RConstOptString _
10721          | RString _ | RStringList _ | RStruct _
10722          | RStructList _
10723          | RHashtable _
10724          | RBufferOut _ ->
10725              pr "  return NULL;\n"
10726         );
10727         pr "}\n";
10728         pr "\n"
10729       )
10730   ) tests
10731
10732 and generate_ocaml_bindtests () =
10733   generate_header OCamlStyle GPLv2plus;
10734
10735   pr "\
10736 let () =
10737   let g = Guestfs.create () in
10738 ";
10739
10740   let mkargs args =
10741     String.concat " " (
10742       List.map (
10743         function
10744         | CallString s -> "\"" ^ s ^ "\""
10745         | CallOptString None -> "None"
10746         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10747         | CallStringList xs ->
10748             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10749         | CallInt i when i >= 0 -> string_of_int i
10750         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10751         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10752         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10753         | CallBool b -> string_of_bool b
10754       ) args
10755     )
10756   in
10757
10758   generate_lang_bindtests (
10759     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10760   );
10761
10762   pr "print_endline \"EOF\"\n"
10763
10764 and generate_perl_bindtests () =
10765   pr "#!/usr/bin/perl -w\n";
10766   generate_header HashStyle GPLv2plus;
10767
10768   pr "\
10769 use strict;
10770
10771 use Sys::Guestfs;
10772
10773 my $g = Sys::Guestfs->new ();
10774 ";
10775
10776   let mkargs args =
10777     String.concat ", " (
10778       List.map (
10779         function
10780         | CallString s -> "\"" ^ s ^ "\""
10781         | CallOptString None -> "undef"
10782         | CallOptString (Some s) -> sprintf "\"%s\"" s
10783         | CallStringList xs ->
10784             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10785         | CallInt i -> string_of_int i
10786         | CallInt64 i -> Int64.to_string i
10787         | CallBool b -> if b then "1" else "0"
10788       ) args
10789     )
10790   in
10791
10792   generate_lang_bindtests (
10793     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10794   );
10795
10796   pr "print \"EOF\\n\"\n"
10797
10798 and generate_python_bindtests () =
10799   generate_header HashStyle GPLv2plus;
10800
10801   pr "\
10802 import guestfs
10803
10804 g = guestfs.GuestFS ()
10805 ";
10806
10807   let mkargs args =
10808     String.concat ", " (
10809       List.map (
10810         function
10811         | CallString s -> "\"" ^ s ^ "\""
10812         | CallOptString None -> "None"
10813         | CallOptString (Some s) -> sprintf "\"%s\"" s
10814         | CallStringList xs ->
10815             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10816         | CallInt i -> string_of_int i
10817         | CallInt64 i -> Int64.to_string i
10818         | CallBool b -> if b then "1" else "0"
10819       ) args
10820     )
10821   in
10822
10823   generate_lang_bindtests (
10824     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10825   );
10826
10827   pr "print \"EOF\"\n"
10828
10829 and generate_ruby_bindtests () =
10830   generate_header HashStyle GPLv2plus;
10831
10832   pr "\
10833 require 'guestfs'
10834
10835 g = Guestfs::create()
10836 ";
10837
10838   let mkargs args =
10839     String.concat ", " (
10840       List.map (
10841         function
10842         | CallString s -> "\"" ^ s ^ "\""
10843         | CallOptString None -> "nil"
10844         | CallOptString (Some s) -> sprintf "\"%s\"" s
10845         | CallStringList xs ->
10846             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10847         | CallInt i -> string_of_int i
10848         | CallInt64 i -> Int64.to_string i
10849         | CallBool b -> string_of_bool b
10850       ) args
10851     )
10852   in
10853
10854   generate_lang_bindtests (
10855     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10856   );
10857
10858   pr "print \"EOF\\n\"\n"
10859
10860 and generate_java_bindtests () =
10861   generate_header CStyle GPLv2plus;
10862
10863   pr "\
10864 import com.redhat.et.libguestfs.*;
10865
10866 public class Bindtests {
10867     public static void main (String[] argv)
10868     {
10869         try {
10870             GuestFS g = new GuestFS ();
10871 ";
10872
10873   let mkargs args =
10874     String.concat ", " (
10875       List.map (
10876         function
10877         | CallString s -> "\"" ^ s ^ "\""
10878         | CallOptString None -> "null"
10879         | CallOptString (Some s) -> sprintf "\"%s\"" s
10880         | CallStringList xs ->
10881             "new String[]{" ^
10882               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10883         | CallInt i -> string_of_int i
10884         | CallInt64 i -> Int64.to_string i
10885         | CallBool b -> string_of_bool b
10886       ) args
10887     )
10888   in
10889
10890   generate_lang_bindtests (
10891     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10892   );
10893
10894   pr "
10895             System.out.println (\"EOF\");
10896         }
10897         catch (Exception exn) {
10898             System.err.println (exn);
10899             System.exit (1);
10900         }
10901     }
10902 }
10903 "
10904
10905 and generate_haskell_bindtests () =
10906   generate_header HaskellStyle GPLv2plus;
10907
10908   pr "\
10909 module Bindtests where
10910 import qualified Guestfs
10911
10912 main = do
10913   g <- Guestfs.create
10914 ";
10915
10916   let mkargs args =
10917     String.concat " " (
10918       List.map (
10919         function
10920         | CallString s -> "\"" ^ s ^ "\""
10921         | CallOptString None -> "Nothing"
10922         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10923         | CallStringList xs ->
10924             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10925         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10926         | CallInt i -> string_of_int i
10927         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10928         | CallInt64 i -> Int64.to_string i
10929         | CallBool true -> "True"
10930         | CallBool false -> "False"
10931       ) args
10932     )
10933   in
10934
10935   generate_lang_bindtests (
10936     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10937   );
10938
10939   pr "  putStrLn \"EOF\"\n"
10940
10941 (* Language-independent bindings tests - we do it this way to
10942  * ensure there is parity in testing bindings across all languages.
10943  *)
10944 and generate_lang_bindtests call =
10945   call "test0" [CallString "abc"; CallOptString (Some "def");
10946                 CallStringList []; CallBool false;
10947                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10948   call "test0" [CallString "abc"; CallOptString None;
10949                 CallStringList []; CallBool false;
10950                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10951   call "test0" [CallString ""; CallOptString (Some "def");
10952                 CallStringList []; CallBool false;
10953                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10954   call "test0" [CallString ""; CallOptString (Some "");
10955                 CallStringList []; CallBool false;
10956                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10957   call "test0" [CallString "abc"; CallOptString (Some "def");
10958                 CallStringList ["1"]; CallBool false;
10959                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10960   call "test0" [CallString "abc"; CallOptString (Some "def");
10961                 CallStringList ["1"; "2"]; CallBool false;
10962                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10963   call "test0" [CallString "abc"; CallOptString (Some "def");
10964                 CallStringList ["1"]; CallBool true;
10965                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10966   call "test0" [CallString "abc"; CallOptString (Some "def");
10967                 CallStringList ["1"]; CallBool false;
10968                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10969   call "test0" [CallString "abc"; CallOptString (Some "def");
10970                 CallStringList ["1"]; CallBool false;
10971                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10972   call "test0" [CallString "abc"; CallOptString (Some "def");
10973                 CallStringList ["1"]; CallBool false;
10974                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10975   call "test0" [CallString "abc"; CallOptString (Some "def");
10976                 CallStringList ["1"]; CallBool false;
10977                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10978   call "test0" [CallString "abc"; CallOptString (Some "def");
10979                 CallStringList ["1"]; CallBool false;
10980                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10981   call "test0" [CallString "abc"; CallOptString (Some "def");
10982                 CallStringList ["1"]; CallBool false;
10983                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10984
10985 (* XXX Add here tests of the return and error functions. *)
10986
10987 (* Code to generator bindings for virt-inspector.  Currently only
10988  * implemented for OCaml code (for virt-p2v 2.0).
10989  *)
10990 let rng_input = "inspector/virt-inspector.rng"
10991
10992 (* Read the input file and parse it into internal structures.  This is
10993  * by no means a complete RELAX NG parser, but is just enough to be
10994  * able to parse the specific input file.
10995  *)
10996 type rng =
10997   | Element of string * rng list        (* <element name=name/> *)
10998   | Attribute of string * rng list        (* <attribute name=name/> *)
10999   | Interleave of rng list                (* <interleave/> *)
11000   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11001   | OneOrMore of rng                        (* <oneOrMore/> *)
11002   | Optional of rng                        (* <optional/> *)
11003   | Choice of string list                (* <choice><value/>*</choice> *)
11004   | Value of string                        (* <value>str</value> *)
11005   | Text                                (* <text/> *)
11006
11007 let rec string_of_rng = function
11008   | Element (name, xs) ->
11009       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11010   | Attribute (name, xs) ->
11011       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11012   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11013   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11014   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11015   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11016   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11017   | Value value -> "Value \"" ^ value ^ "\""
11018   | Text -> "Text"
11019
11020 and string_of_rng_list xs =
11021   String.concat ", " (List.map string_of_rng xs)
11022
11023 let rec parse_rng ?defines context = function
11024   | [] -> []
11025   | Xml.Element ("element", ["name", name], children) :: rest ->
11026       Element (name, parse_rng ?defines context children)
11027       :: parse_rng ?defines context rest
11028   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11029       Attribute (name, parse_rng ?defines context children)
11030       :: parse_rng ?defines context rest
11031   | Xml.Element ("interleave", [], children) :: rest ->
11032       Interleave (parse_rng ?defines context children)
11033       :: parse_rng ?defines context rest
11034   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11035       let rng = parse_rng ?defines context [child] in
11036       (match rng with
11037        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11038        | _ ->
11039            failwithf "%s: <zeroOrMore> contains more than one child element"
11040              context
11041       )
11042   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11043       let rng = parse_rng ?defines context [child] in
11044       (match rng with
11045        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11046        | _ ->
11047            failwithf "%s: <oneOrMore> contains more than one child element"
11048              context
11049       )
11050   | Xml.Element ("optional", [], [child]) :: rest ->
11051       let rng = parse_rng ?defines context [child] in
11052       (match rng with
11053        | [child] -> Optional child :: parse_rng ?defines context rest
11054        | _ ->
11055            failwithf "%s: <optional> contains more than one child element"
11056              context
11057       )
11058   | Xml.Element ("choice", [], children) :: rest ->
11059       let values = List.map (
11060         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11061         | _ ->
11062             failwithf "%s: can't handle anything except <value> in <choice>"
11063               context
11064       ) children in
11065       Choice values
11066       :: parse_rng ?defines context rest
11067   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11068       Value value :: parse_rng ?defines context rest
11069   | Xml.Element ("text", [], []) :: rest ->
11070       Text :: parse_rng ?defines context rest
11071   | Xml.Element ("ref", ["name", name], []) :: rest ->
11072       (* Look up the reference.  Because of limitations in this parser,
11073        * we can't handle arbitrarily nested <ref> yet.  You can only
11074        * use <ref> from inside <start>.
11075        *)
11076       (match defines with
11077        | None ->
11078            failwithf "%s: contains <ref>, but no refs are defined yet" context
11079        | Some map ->
11080            let rng = StringMap.find name map in
11081            rng @ parse_rng ?defines context rest
11082       )
11083   | x :: _ ->
11084       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11085
11086 let grammar =
11087   let xml = Xml.parse_file rng_input in
11088   match xml with
11089   | Xml.Element ("grammar", _,
11090                  Xml.Element ("start", _, gram) :: defines) ->
11091       (* The <define/> elements are referenced in the <start> section,
11092        * so build a map of those first.
11093        *)
11094       let defines = List.fold_left (
11095         fun map ->
11096           function Xml.Element ("define", ["name", name], defn) ->
11097             StringMap.add name defn map
11098           | _ ->
11099               failwithf "%s: expected <define name=name/>" rng_input
11100       ) StringMap.empty defines in
11101       let defines = StringMap.mapi parse_rng defines in
11102
11103       (* Parse the <start> clause, passing the defines. *)
11104       parse_rng ~defines "<start>" gram
11105   | _ ->
11106       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11107         rng_input
11108
11109 let name_of_field = function
11110   | Element (name, _) | Attribute (name, _)
11111   | ZeroOrMore (Element (name, _))
11112   | OneOrMore (Element (name, _))
11113   | Optional (Element (name, _)) -> name
11114   | Optional (Attribute (name, _)) -> name
11115   | Text -> (* an unnamed field in an element *)
11116       "data"
11117   | rng ->
11118       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11119
11120 (* At the moment this function only generates OCaml types.  However we
11121  * should parameterize it later so it can generate types/structs in a
11122  * variety of languages.
11123  *)
11124 let generate_types xs =
11125   (* A simple type is one that can be printed out directly, eg.
11126    * "string option".  A complex type is one which has a name and has
11127    * to be defined via another toplevel definition, eg. a struct.
11128    *
11129    * generate_type generates code for either simple or complex types.
11130    * In the simple case, it returns the string ("string option").  In
11131    * the complex case, it returns the name ("mountpoint").  In the
11132    * complex case it has to print out the definition before returning,
11133    * so it should only be called when we are at the beginning of a
11134    * new line (BOL context).
11135    *)
11136   let rec generate_type = function
11137     | Text ->                                (* string *)
11138         "string", true
11139     | Choice values ->                        (* [`val1|`val2|...] *)
11140         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11141     | ZeroOrMore rng ->                        (* <rng> list *)
11142         let t, is_simple = generate_type rng in
11143         t ^ " list (* 0 or more *)", is_simple
11144     | OneOrMore rng ->                        (* <rng> list *)
11145         let t, is_simple = generate_type rng in
11146         t ^ " list (* 1 or more *)", is_simple
11147                                         (* virt-inspector hack: bool *)
11148     | Optional (Attribute (name, [Value "1"])) ->
11149         "bool", true
11150     | Optional rng ->                        (* <rng> list *)
11151         let t, is_simple = generate_type rng in
11152         t ^ " option", is_simple
11153                                         (* type name = { fields ... } *)
11154     | Element (name, fields) when is_attrs_interleave fields ->
11155         generate_type_struct name (get_attrs_interleave fields)
11156     | Element (name, [field])                (* type name = field *)
11157     | Attribute (name, [field]) ->
11158         let t, is_simple = generate_type field in
11159         if is_simple then (t, true)
11160         else (
11161           pr "type %s = %s\n" name t;
11162           name, false
11163         )
11164     | Element (name, fields) ->              (* type name = { fields ... } *)
11165         generate_type_struct name fields
11166     | rng ->
11167         failwithf "generate_type failed at: %s" (string_of_rng rng)
11168
11169   and is_attrs_interleave = function
11170     | [Interleave _] -> true
11171     | Attribute _ :: fields -> is_attrs_interleave fields
11172     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11173     | _ -> false
11174
11175   and get_attrs_interleave = function
11176     | [Interleave fields] -> fields
11177     | ((Attribute _) as field) :: fields
11178     | ((Optional (Attribute _)) as field) :: fields ->
11179         field :: get_attrs_interleave fields
11180     | _ -> assert false
11181
11182   and generate_types xs =
11183     List.iter (fun x -> ignore (generate_type x)) xs
11184
11185   and generate_type_struct name fields =
11186     (* Calculate the types of the fields first.  We have to do this
11187      * before printing anything so we are still in BOL context.
11188      *)
11189     let types = List.map fst (List.map generate_type fields) in
11190
11191     (* Special case of a struct containing just a string and another
11192      * field.  Turn it into an assoc list.
11193      *)
11194     match types with
11195     | ["string"; other] ->
11196         let fname1, fname2 =
11197           match fields with
11198           | [f1; f2] -> name_of_field f1, name_of_field f2
11199           | _ -> assert false in
11200         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11201         name, false
11202
11203     | types ->
11204         pr "type %s = {\n" name;
11205         List.iter (
11206           fun (field, ftype) ->
11207             let fname = name_of_field field in
11208             pr "  %s_%s : %s;\n" name fname ftype
11209         ) (List.combine fields types);
11210         pr "}\n";
11211         (* Return the name of this type, and
11212          * false because it's not a simple type.
11213          *)
11214         name, false
11215   in
11216
11217   generate_types xs
11218
11219 let generate_parsers xs =
11220   (* As for generate_type above, generate_parser makes a parser for
11221    * some type, and returns the name of the parser it has generated.
11222    * Because it (may) need to print something, it should always be
11223    * called in BOL context.
11224    *)
11225   let rec generate_parser = function
11226     | Text ->                                (* string *)
11227         "string_child_or_empty"
11228     | Choice values ->                        (* [`val1|`val2|...] *)
11229         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11230           (String.concat "|"
11231              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11232     | ZeroOrMore rng ->                        (* <rng> list *)
11233         let pa = generate_parser rng in
11234         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11235     | OneOrMore rng ->                        (* <rng> list *)
11236         let pa = generate_parser rng in
11237         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11238                                         (* virt-inspector hack: bool *)
11239     | Optional (Attribute (name, [Value "1"])) ->
11240         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11241     | Optional rng ->                        (* <rng> list *)
11242         let pa = generate_parser rng in
11243         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11244                                         (* type name = { fields ... } *)
11245     | Element (name, fields) when is_attrs_interleave fields ->
11246         generate_parser_struct name (get_attrs_interleave fields)
11247     | Element (name, [field]) ->        (* type name = field *)
11248         let pa = generate_parser field in
11249         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11250         pr "let %s =\n" parser_name;
11251         pr "  %s\n" pa;
11252         pr "let parse_%s = %s\n" name parser_name;
11253         parser_name
11254     | Attribute (name, [field]) ->
11255         let pa = generate_parser field in
11256         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11257         pr "let %s =\n" parser_name;
11258         pr "  %s\n" pa;
11259         pr "let parse_%s = %s\n" name parser_name;
11260         parser_name
11261     | Element (name, fields) ->              (* type name = { fields ... } *)
11262         generate_parser_struct name ([], fields)
11263     | rng ->
11264         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11265
11266   and is_attrs_interleave = function
11267     | [Interleave _] -> true
11268     | Attribute _ :: fields -> is_attrs_interleave fields
11269     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11270     | _ -> false
11271
11272   and get_attrs_interleave = function
11273     | [Interleave fields] -> [], fields
11274     | ((Attribute _) as field) :: fields
11275     | ((Optional (Attribute _)) as field) :: fields ->
11276         let attrs, interleaves = get_attrs_interleave fields in
11277         (field :: attrs), interleaves
11278     | _ -> assert false
11279
11280   and generate_parsers xs =
11281     List.iter (fun x -> ignore (generate_parser x)) xs
11282
11283   and generate_parser_struct name (attrs, interleaves) =
11284     (* Generate parsers for the fields first.  We have to do this
11285      * before printing anything so we are still in BOL context.
11286      *)
11287     let fields = attrs @ interleaves in
11288     let pas = List.map generate_parser fields in
11289
11290     (* Generate an intermediate tuple from all the fields first.
11291      * If the type is just a string + another field, then we will
11292      * return this directly, otherwise it is turned into a record.
11293      *
11294      * RELAX NG note: This code treats <interleave> and plain lists of
11295      * fields the same.  In other words, it doesn't bother enforcing
11296      * any ordering of fields in the XML.
11297      *)
11298     pr "let parse_%s x =\n" name;
11299     pr "  let t = (\n    ";
11300     let comma = ref false in
11301     List.iter (
11302       fun x ->
11303         if !comma then pr ",\n    ";
11304         comma := true;
11305         match x with
11306         | Optional (Attribute (fname, [field])), pa ->
11307             pr "%s x" pa
11308         | Optional (Element (fname, [field])), pa ->
11309             pr "%s (optional_child %S x)" pa fname
11310         | Attribute (fname, [Text]), _ ->
11311             pr "attribute %S x" fname
11312         | (ZeroOrMore _ | OneOrMore _), pa ->
11313             pr "%s x" pa
11314         | Text, pa ->
11315             pr "%s x" pa
11316         | (field, pa) ->
11317             let fname = name_of_field field in
11318             pr "%s (child %S x)" pa fname
11319     ) (List.combine fields pas);
11320     pr "\n  ) in\n";
11321
11322     (match fields with
11323      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11324          pr "  t\n"
11325
11326      | _ ->
11327          pr "  (Obj.magic t : %s)\n" name
11328 (*
11329          List.iter (
11330            function
11331            | (Optional (Attribute (fname, [field])), pa) ->
11332                pr "  %s_%s =\n" name fname;
11333                pr "    %s x;\n" pa
11334            | (Optional (Element (fname, [field])), pa) ->
11335                pr "  %s_%s =\n" name fname;
11336                pr "    (let x = optional_child %S x in\n" fname;
11337                pr "     %s x);\n" pa
11338            | (field, pa) ->
11339                let fname = name_of_field field in
11340                pr "  %s_%s =\n" name fname;
11341                pr "    (let x = child %S x in\n" fname;
11342                pr "     %s x);\n" pa
11343          ) (List.combine fields pas);
11344          pr "}\n"
11345 *)
11346     );
11347     sprintf "parse_%s" name
11348   in
11349
11350   generate_parsers xs
11351
11352 (* Generate ocaml/guestfs_inspector.mli. *)
11353 let generate_ocaml_inspector_mli () =
11354   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11355
11356   pr "\
11357 (** This is an OCaml language binding to the external [virt-inspector]
11358     program.
11359
11360     For more information, please read the man page [virt-inspector(1)].
11361 *)
11362
11363 ";
11364
11365   generate_types grammar;
11366   pr "(** The nested information returned from the {!inspect} function. *)\n";
11367   pr "\n";
11368
11369   pr "\
11370 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11371 (** To inspect a libvirt domain called [name], pass a singleton
11372     list: [inspect [name]].  When using libvirt only, you may
11373     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11374
11375     To inspect a disk image or images, pass a list of the filenames
11376     of the disk images: [inspect filenames]
11377
11378     This function inspects the given guest or disk images and
11379     returns a list of operating system(s) found and a large amount
11380     of information about them.  In the vast majority of cases,
11381     a virtual machine only contains a single operating system.
11382
11383     If the optional [~xml] parameter is given, then this function
11384     skips running the external virt-inspector program and just
11385     parses the given XML directly (which is expected to be XML
11386     produced from a previous run of virt-inspector).  The list of
11387     names and connect URI are ignored in this case.
11388
11389     This function can throw a wide variety of exceptions, for example
11390     if the external virt-inspector program cannot be found, or if
11391     it doesn't generate valid XML.
11392 *)
11393 "
11394
11395 (* Generate ocaml/guestfs_inspector.ml. *)
11396 let generate_ocaml_inspector_ml () =
11397   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11398
11399   pr "open Unix\n";
11400   pr "\n";
11401
11402   generate_types grammar;
11403   pr "\n";
11404
11405   pr "\
11406 (* Misc functions which are used by the parser code below. *)
11407 let first_child = function
11408   | Xml.Element (_, _, c::_) -> c
11409   | Xml.Element (name, _, []) ->
11410       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11411   | Xml.PCData str ->
11412       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11413
11414 let string_child_or_empty = function
11415   | Xml.Element (_, _, [Xml.PCData s]) -> s
11416   | Xml.Element (_, _, []) -> \"\"
11417   | Xml.Element (x, _, _) ->
11418       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11419                 x ^ \" instead\")
11420   | Xml.PCData str ->
11421       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11422
11423 let optional_child name xml =
11424   let children = Xml.children xml in
11425   try
11426     Some (List.find (function
11427                      | Xml.Element (n, _, _) when n = name -> true
11428                      | _ -> false) children)
11429   with
11430     Not_found -> None
11431
11432 let child name xml =
11433   match optional_child name xml with
11434   | Some c -> c
11435   | None ->
11436       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11437
11438 let attribute name xml =
11439   try Xml.attrib xml name
11440   with Xml.No_attribute _ ->
11441     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11442
11443 ";
11444
11445   generate_parsers grammar;
11446   pr "\n";
11447
11448   pr "\
11449 (* Run external virt-inspector, then use parser to parse the XML. *)
11450 let inspect ?connect ?xml names =
11451   let xml =
11452     match xml with
11453     | None ->
11454         if names = [] then invalid_arg \"inspect: no names given\";
11455         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11456           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11457           names in
11458         let cmd = List.map Filename.quote cmd in
11459         let cmd = String.concat \" \" cmd in
11460         let chan = open_process_in cmd in
11461         let xml = Xml.parse_in chan in
11462         (match close_process_in chan with
11463          | WEXITED 0 -> ()
11464          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11465          | WSIGNALED i | WSTOPPED i ->
11466              failwith (\"external virt-inspector command died or stopped on sig \" ^
11467                        string_of_int i)
11468         );
11469         xml
11470     | Some doc ->
11471         Xml.parse_string doc in
11472   parse_operatingsystems xml
11473 "
11474
11475 (* This is used to generate the src/MAX_PROC_NR file which
11476  * contains the maximum procedure number, a surrogate for the
11477  * ABI version number.  See src/Makefile.am for the details.
11478  *)
11479 and generate_max_proc_nr () =
11480   let proc_nrs = List.map (
11481     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11482   ) daemon_functions in
11483
11484   let max_proc_nr = List.fold_left max 0 proc_nrs in
11485
11486   pr "%d\n" max_proc_nr
11487
11488 let output_to filename k =
11489   let filename_new = filename ^ ".new" in
11490   chan := open_out filename_new;
11491   k ();
11492   close_out !chan;
11493   chan := Pervasives.stdout;
11494
11495   (* Is the new file different from the current file? *)
11496   if Sys.file_exists filename && files_equal filename filename_new then
11497     unlink filename_new                 (* same, so skip it *)
11498   else (
11499     (* different, overwrite old one *)
11500     (try chmod filename 0o644 with Unix_error _ -> ());
11501     rename filename_new filename;
11502     chmod filename 0o444;
11503     printf "written %s\n%!" filename;
11504   )
11505
11506 let perror msg = function
11507   | Unix_error (err, _, _) ->
11508       eprintf "%s: %s\n" msg (error_message err)
11509   | exn ->
11510       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11511
11512 (* Main program. *)
11513 let () =
11514   let lock_fd =
11515     try openfile "HACKING" [O_RDWR] 0
11516     with
11517     | Unix_error (ENOENT, _, _) ->
11518         eprintf "\
11519 You are probably running this from the wrong directory.
11520 Run it from the top source directory using the command
11521   src/generator.ml
11522 ";
11523         exit 1
11524     | exn ->
11525         perror "open: HACKING" exn;
11526         exit 1 in
11527
11528   (* Acquire a lock so parallel builds won't try to run the generator
11529    * twice at the same time.  Subsequent builds will wait for the first
11530    * one to finish.  Note the lock is released implicitly when the
11531    * program exits.
11532    *)
11533   (try lockf lock_fd F_LOCK 1
11534    with exn ->
11535      perror "lock: HACKING" exn;
11536      exit 1);
11537
11538   check_functions ();
11539
11540   output_to "src/guestfs_protocol.x" generate_xdr;
11541   output_to "src/guestfs-structs.h" generate_structs_h;
11542   output_to "src/guestfs-actions.h" generate_actions_h;
11543   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11544   output_to "src/guestfs-actions.c" generate_client_actions;
11545   output_to "src/guestfs-bindtests.c" generate_bindtests;
11546   output_to "src/guestfs-structs.pod" generate_structs_pod;
11547   output_to "src/guestfs-actions.pod" generate_actions_pod;
11548   output_to "src/guestfs-availability.pod" generate_availability_pod;
11549   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11550   output_to "src/libguestfs.syms" generate_linker_script;
11551   output_to "daemon/actions.h" generate_daemon_actions_h;
11552   output_to "daemon/stubs.c" generate_daemon_actions;
11553   output_to "daemon/names.c" generate_daemon_names;
11554   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11555   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11556   output_to "capitests/tests.c" generate_tests;
11557   output_to "fish/cmds.c" generate_fish_cmds;
11558   output_to "fish/completion.c" generate_fish_completion;
11559   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11560   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11561   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11562   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11563   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11564   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11565   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11566   output_to "perl/Guestfs.xs" generate_perl_xs;
11567   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11568   output_to "perl/bindtests.pl" generate_perl_bindtests;
11569   output_to "python/guestfs-py.c" generate_python_c;
11570   output_to "python/guestfs.py" generate_python_py;
11571   output_to "python/bindtests.py" generate_python_bindtests;
11572   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11573   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11574   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11575
11576   List.iter (
11577     fun (typ, jtyp) ->
11578       let cols = cols_of_struct typ in
11579       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11580       output_to filename (generate_java_struct jtyp cols);
11581   ) java_structs;
11582
11583   output_to "java/Makefile.inc" generate_java_makefile_inc;
11584   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11585   output_to "java/Bindtests.java" generate_java_bindtests;
11586   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11587   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11588   output_to "csharp/Libguestfs.cs" generate_csharp;
11589
11590   (* Always generate this file last, and unconditionally.  It's used
11591    * by the Makefile to know when we must re-run the generator.
11592    *)
11593   let chan = open_out "src/stamp-generator" in
11594   fprintf chan "1\n";
11595   close_out chan;
11596
11597   printf "generated %d lines of code\n" !lines