Documentation: Clarify documentation on the bootable flag.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167 (* Not implemented:
168     (* Opaque buffer which can contain arbitrary 8 bit data.
169      * In the C API, this is expressed as <char *, int> pair.
170      * Most other languages have a string type which can contain
171      * ASCII NUL.  We use whatever type is appropriate for each
172      * language.
173      * Buffers are limited by the total message size.  To transfer
174      * large blocks of data, use FileIn/FileOut parameters instead.
175      * To return an arbitrary buffer, use RBufferOut.
176      *)
177   | BufferIn of string
178 *)
179
180 type flags =
181   | ProtocolLimitWarning  (* display warning about protocol size limits *)
182   | DangerWillRobinson    (* flags particularly dangerous commands *)
183   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
184   | FishAction of string  (* call this function in guestfish *)
185   | NotInFish             (* do not export via guestfish *)
186   | NotInDocs             (* do not add this function to documentation *)
187   | DeprecatedBy of string (* function is deprecated, use .. instead *)
188   | Optional of string    (* function is part of an optional group *)
189
190 (* You can supply zero or as many tests as you want per API call.
191  *
192  * Note that the test environment has 3 block devices, of size 500MB,
193  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
194  * a fourth ISO block device with some known files on it (/dev/sdd).
195  *
196  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
197  * Number of cylinders was 63 for IDE emulated disks with precisely
198  * the same size.  How exactly this is calculated is a mystery.
199  *
200  * The ISO block device (/dev/sdd) comes from images/test.iso.
201  *
202  * To be able to run the tests in a reasonable amount of time,
203  * the virtual machine and block devices are reused between tests.
204  * So don't try testing kill_subprocess :-x
205  *
206  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
207  *
208  * Don't assume anything about the previous contents of the block
209  * devices.  Use 'Init*' to create some initial scenarios.
210  *
211  * You can add a prerequisite clause to any individual test.  This
212  * is a run-time check, which, if it fails, causes the test to be
213  * skipped.  Useful if testing a command which might not work on
214  * all variations of libguestfs builds.  A test that has prerequisite
215  * of 'Always' is run unconditionally.
216  *
217  * In addition, packagers can skip individual tests by setting the
218  * environment variables:     eg:
219  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
220  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
221  *)
222 type tests = (test_init * test_prereq * test) list
223 and test =
224     (* Run the command sequence and just expect nothing to fail. *)
225   | TestRun of seq
226
227     (* Run the command sequence and expect the output of the final
228      * command to be the string.
229      *)
230   | TestOutput of seq * string
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the list of strings.
234      *)
235   | TestOutputList of seq * string list
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of block devices (could be either
239      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
240      * character of each string).
241      *)
242   | TestOutputListOfDevices of seq * string list
243
244     (* Run the command sequence and expect the output of the final
245      * command to be the integer.
246      *)
247   | TestOutputInt of seq * int
248
249     (* Run the command sequence and expect the output of the final
250      * command to be <op> <int>, eg. ">=", "1".
251      *)
252   | TestOutputIntOp of seq * string * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be a true value (!= 0 or != NULL).
256      *)
257   | TestOutputTrue of seq
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a false value (== 0 or == NULL, but not an error).
261      *)
262   | TestOutputFalse of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a list of the given length (but don't care about
266      * content).
267      *)
268   | TestOutputLength of seq * int
269
270     (* Run the command sequence and expect the output of the final
271      * command to be a buffer (RBufferOut), ie. string + size.
272      *)
273   | TestOutputBuffer of seq * string
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a structure.
277      *)
278   | TestOutputStruct of seq * test_field_compare list
279
280     (* Run the command sequence and expect the final command (only)
281      * to fail.
282      *)
283   | TestLastFail of seq
284
285 and test_field_compare =
286   | CompareWithInt of string * int
287   | CompareWithIntOp of string * string * int
288   | CompareWithString of string * string
289   | CompareFieldsIntEq of string * string
290   | CompareFieldsStrEq of string * string
291
292 (* Test prerequisites. *)
293 and test_prereq =
294     (* Test always runs. *)
295   | Always
296
297     (* Test is currently disabled - eg. it fails, or it tests some
298      * unimplemented feature.
299      *)
300   | Disabled
301
302     (* 'string' is some C code (a function body) that should return
303      * true or false.  The test will run if the code returns true.
304      *)
305   | If of string
306
307     (* As for 'If' but the test runs _unless_ the code returns true. *)
308   | Unless of string
309
310 (* Some initial scenarios for testing. *)
311 and test_init =
312     (* Do nothing, block devices could contain random stuff including
313      * LVM PVs, and some filesystems might be mounted.  This is usually
314      * a bad idea.
315      *)
316   | InitNone
317
318     (* Block devices are empty and no filesystems are mounted. *)
319   | InitEmpty
320
321     (* /dev/sda contains a single partition /dev/sda1, with random
322      * content.  /dev/sdb and /dev/sdc may have random content.
323      * No LVM.
324      *)
325   | InitPartition
326
327     (* /dev/sda contains a single partition /dev/sda1, which is formatted
328      * as ext2, empty [except for lost+found] and mounted on /.
329      * /dev/sdb and /dev/sdc may have random content.
330      * No LVM.
331      *)
332   | InitBasicFS
333
334     (* /dev/sda:
335      *   /dev/sda1 (is a PV):
336      *     /dev/VG/LV (size 8MB):
337      *       formatted as ext2, empty [except for lost+found], mounted on /
338      * /dev/sdb and /dev/sdc may have random content.
339      *)
340   | InitBasicFSonLVM
341
342     (* /dev/sdd (the ISO, see images/ directory in source)
343      * is mounted on /
344      *)
345   | InitISOFS
346
347 (* Sequence of commands for testing. *)
348 and seq = cmd list
349 and cmd = string list
350
351 (* Note about long descriptions: When referring to another
352  * action, use the format C<guestfs_other> (ie. the full name of
353  * the C function).  This will be replaced as appropriate in other
354  * language bindings.
355  *
356  * Apart from that, long descriptions are just perldoc paragraphs.
357  *)
358
359 (* Generate a random UUID (used in tests). *)
360 let uuidgen () =
361   let chan = open_process_in "uuidgen" in
362   let uuid = input_line chan in
363   (match close_process_in chan with
364    | WEXITED 0 -> ()
365    | WEXITED _ ->
366        failwith "uuidgen: process exited with non-zero status"
367    | WSIGNALED _ | WSTOPPED _ ->
368        failwith "uuidgen: process signalled or stopped by signal"
369   );
370   uuid
371
372 (* These test functions are used in the language binding tests. *)
373
374 let test_all_args = [
375   String "str";
376   OptString "optstr";
377   StringList "strlist";
378   Bool "b";
379   Int "integer";
380   Int64 "integer64";
381   FileIn "filein";
382   FileOut "fileout";
383 ]
384
385 let test_all_rets = [
386   (* except for RErr, which is tested thoroughly elsewhere *)
387   "test0rint",         RInt "valout";
388   "test0rint64",       RInt64 "valout";
389   "test0rbool",        RBool "valout";
390   "test0rconststring", RConstString "valout";
391   "test0rconstoptstring", RConstOptString "valout";
392   "test0rstring",      RString "valout";
393   "test0rstringlist",  RStringList "valout";
394   "test0rstruct",      RStruct ("valout", "lvm_pv");
395   "test0rstructlist",  RStructList ("valout", "lvm_pv");
396   "test0rhashtable",   RHashtable "valout";
397 ]
398
399 let test_functions = [
400   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
401    [],
402    "internal test function - do not use",
403    "\
404 This is an internal test function which is used to test whether
405 the automatically generated bindings can handle every possible
406 parameter type correctly.
407
408 It echos the contents of each parameter to stdout.
409
410 You probably don't want to call this function.");
411 ] @ List.flatten (
412   List.map (
413     fun (name, ret) ->
414       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
415         [],
416         "internal test function - do not use",
417         "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 return type correctly.
421
422 It converts string C<val> to the return type.
423
424 You probably don't want to call this function.");
425        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
426         [],
427         "internal test function - do not use",
428         "\
429 This is an internal test function which is used to test whether
430 the automatically generated bindings can handle every possible
431 return type correctly.
432
433 This function always returns an error.
434
435 You probably don't want to call this function.")]
436   ) test_all_rets
437 )
438
439 (* non_daemon_functions are any functions which don't get processed
440  * in the daemon, eg. functions for setting and getting local
441  * configuration values.
442  *)
443
444 let non_daemon_functions = test_functions @ [
445   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
446    [],
447    "launch the qemu subprocess",
448    "\
449 Internally libguestfs is implemented by running a virtual machine
450 using L<qemu(1)>.
451
452 You should call this after configuring the handle
453 (eg. adding drives) but before performing any actions.");
454
455   ("wait_ready", (RErr, []), -1, [NotInFish],
456    [],
457    "wait until the qemu subprocess launches (no op)",
458    "\
459 This function is a no op.
460
461 In versions of the API E<lt> 1.0.71 you had to call this function
462 just after calling C<guestfs_launch> to wait for the launch
463 to complete.  However this is no longer necessary because
464 C<guestfs_launch> now does the waiting.
465
466 If you see any calls to this function in code then you can just
467 remove them, unless you want to retain compatibility with older
468 versions of the API.");
469
470   ("kill_subprocess", (RErr, []), -1, [],
471    [],
472    "kill the qemu subprocess",
473    "\
474 This kills the qemu subprocess.  You should never need to call this.");
475
476   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
477    [],
478    "add an image to examine or modify",
479    "\
480 This function adds a virtual machine disk image C<filename> to the
481 guest.  The first time you call this function, the disk appears as IDE
482 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
483 so on.
484
485 You don't necessarily need to be root when using libguestfs.  However
486 you obviously do need sufficient permissions to access the filename
487 for whatever operations you want to perform (ie. read access if you
488 just want to read the image or write access if you want to modify the
489 image).
490
491 This is equivalent to the qemu parameter
492 C<-drive file=filename,cache=off,if=...>.
493
494 C<cache=off> is omitted in cases where it is not supported by
495 the underlying filesystem.
496
497 C<if=...> is set at compile time by the configuration option
498 C<./configure --with-drive-if=...>.  In the rare case where you
499 might need to change this at run time, use C<guestfs_add_drive_with_if>
500 or C<guestfs_add_drive_ro_with_if>.
501
502 Note that this call checks for the existence of C<filename>.  This
503 stops you from specifying other types of drive which are supported
504 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
505 the general C<guestfs_config> call instead.");
506
507   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
508    [],
509    "add a CD-ROM disk image to examine",
510    "\
511 This function adds a virtual CD-ROM disk image to the guest.
512
513 This is equivalent to the qemu parameter C<-cdrom filename>.
514
515 Notes:
516
517 =over 4
518
519 =item *
520
521 This call checks for the existence of C<filename>.  This
522 stops you from specifying other types of drive which are supported
523 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
524 the general C<guestfs_config> call instead.
525
526 =item *
527
528 If you just want to add an ISO file (often you use this as an
529 efficient way to transfer large files into the guest), then you
530 should probably use C<guestfs_add_drive_ro> instead.
531
532 =back");
533
534   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
535    [],
536    "add a drive in snapshot mode (read-only)",
537    "\
538 This adds a drive in snapshot mode, making it effectively
539 read-only.
540
541 Note that writes to the device are allowed, and will be seen for
542 the duration of the guestfs handle, but they are written
543 to a temporary file which is discarded as soon as the guestfs
544 handle is closed.  We don't currently have any method to enable
545 changes to be committed, although qemu can support this.
546
547 This is equivalent to the qemu parameter
548 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
549
550 C<if=...> is set at compile time by the configuration option
551 C<./configure --with-drive-if=...>.  In the rare case where you
552 might need to change this at run time, use C<guestfs_add_drive_with_if>
553 or C<guestfs_add_drive_ro_with_if>.
554
555 C<readonly=on> is only added where qemu supports this option.
556
557 Note that this call checks for the existence of C<filename>.  This
558 stops you from specifying other types of drive which are supported
559 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
560 the general C<guestfs_config> call instead.");
561
562   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
563    [],
564    "add qemu parameters",
565    "\
566 This can be used to add arbitrary qemu command line parameters
567 of the form C<-param value>.  Actually it's not quite arbitrary - we
568 prevent you from setting some parameters which would interfere with
569 parameters that we use.
570
571 The first character of C<param> string must be a C<-> (dash).
572
573 C<value> can be NULL.");
574
575   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
576    [],
577    "set the qemu binary",
578    "\
579 Set the qemu binary that we will use.
580
581 The default is chosen when the library was compiled by the
582 configure script.
583
584 You can also override this by setting the C<LIBGUESTFS_QEMU>
585 environment variable.
586
587 Setting C<qemu> to C<NULL> restores the default qemu binary.
588
589 Note that you should call this function as early as possible
590 after creating the handle.  This is because some pre-launch
591 operations depend on testing qemu features (by running C<qemu -help>).
592 If the qemu binary changes, we don't retest features, and
593 so you might see inconsistent results.  Using the environment
594 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
595 the qemu binary at the same time as the handle is created.");
596
597   ("get_qemu", (RConstString "qemu", []), -1, [],
598    [InitNone, Always, TestRun (
599       [["get_qemu"]])],
600    "get the qemu binary",
601    "\
602 Return the current qemu binary.
603
604 This is always non-NULL.  If it wasn't set already, then this will
605 return the default qemu binary name.");
606
607   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
608    [],
609    "set the search path",
610    "\
611 Set the path that libguestfs searches for kernel and initrd.img.
612
613 The default is C<$libdir/guestfs> unless overridden by setting
614 C<LIBGUESTFS_PATH> environment variable.
615
616 Setting C<path> to C<NULL> restores the default path.");
617
618   ("get_path", (RConstString "path", []), -1, [],
619    [InitNone, Always, TestRun (
620       [["get_path"]])],
621    "get the search path",
622    "\
623 Return the current search path.
624
625 This is always non-NULL.  If it wasn't set already, then this will
626 return the default path.");
627
628   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
629    [],
630    "add options to kernel command line",
631    "\
632 This function is used to add additional options to the
633 guest kernel command line.
634
635 The default is C<NULL> unless overridden by setting
636 C<LIBGUESTFS_APPEND> environment variable.
637
638 Setting C<append> to C<NULL> means I<no> additional options
639 are passed (libguestfs always adds a few of its own).");
640
641   ("get_append", (RConstOptString "append", []), -1, [],
642    (* This cannot be tested with the current framework.  The
643     * function can return NULL in normal operations, which the
644     * test framework interprets as an error.
645     *)
646    [],
647    "get the additional kernel options",
648    "\
649 Return the additional kernel options which are added to the
650 guest kernel command line.
651
652 If C<NULL> then no options are added.");
653
654   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
655    [],
656    "set autosync mode",
657    "\
658 If C<autosync> is true, this enables autosync.  Libguestfs will make a
659 best effort attempt to run C<guestfs_umount_all> followed by
660 C<guestfs_sync> when the handle is closed
661 (also if the program exits without closing handles).
662
663 This is disabled by default (except in guestfish where it is
664 enabled by default).");
665
666   ("get_autosync", (RBool "autosync", []), -1, [],
667    [InitNone, Always, TestRun (
668       [["get_autosync"]])],
669    "get autosync mode",
670    "\
671 Get the autosync flag.");
672
673   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
674    [],
675    "set verbose mode",
676    "\
677 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
678
679 Verbose messages are disabled unless the environment variable
680 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
681
682   ("get_verbose", (RBool "verbose", []), -1, [],
683    [],
684    "get verbose mode",
685    "\
686 This returns the verbose messages flag.");
687
688   ("is_ready", (RBool "ready", []), -1, [],
689    [InitNone, Always, TestOutputTrue (
690       [["is_ready"]])],
691    "is ready to accept commands",
692    "\
693 This returns true iff this handle is ready to accept commands
694 (in the C<READY> state).
695
696 For more information on states, see L<guestfs(3)>.");
697
698   ("is_config", (RBool "config", []), -1, [],
699    [InitNone, Always, TestOutputFalse (
700       [["is_config"]])],
701    "is in configuration state",
702    "\
703 This returns true iff this handle is being configured
704 (in the C<CONFIG> state).
705
706 For more information on states, see L<guestfs(3)>.");
707
708   ("is_launching", (RBool "launching", []), -1, [],
709    [InitNone, Always, TestOutputFalse (
710       [["is_launching"]])],
711    "is launching subprocess",
712    "\
713 This returns true iff this handle is launching the subprocess
714 (in the C<LAUNCHING> state).
715
716 For more information on states, see L<guestfs(3)>.");
717
718   ("is_busy", (RBool "busy", []), -1, [],
719    [InitNone, Always, TestOutputFalse (
720       [["is_busy"]])],
721    "is busy processing a command",
722    "\
723 This returns true iff this handle is busy processing a command
724 (in the C<BUSY> state).
725
726 For more information on states, see L<guestfs(3)>.");
727
728   ("get_state", (RInt "state", []), -1, [],
729    [],
730    "get the current state",
731    "\
732 This returns the current state as an opaque integer.  This is
733 only useful for printing debug and internal error messages.
734
735 For more information on states, see L<guestfs(3)>.");
736
737   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
738    [InitNone, Always, TestOutputInt (
739       [["set_memsize"; "500"];
740        ["get_memsize"]], 500)],
741    "set memory allocated to the qemu subprocess",
742    "\
743 This sets the memory size in megabytes allocated to the
744 qemu subprocess.  This only has any effect if called before
745 C<guestfs_launch>.
746
747 You can also change this by setting the environment
748 variable C<LIBGUESTFS_MEMSIZE> before the handle is
749 created.
750
751 For more information on the architecture of libguestfs,
752 see L<guestfs(3)>.");
753
754   ("get_memsize", (RInt "memsize", []), -1, [],
755    [InitNone, Always, TestOutputIntOp (
756       [["get_memsize"]], ">=", 256)],
757    "get memory allocated to the qemu subprocess",
758    "\
759 This gets the memory size in megabytes allocated to the
760 qemu subprocess.
761
762 If C<guestfs_set_memsize> was not called
763 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
764 then this returns the compiled-in default value for memsize.
765
766 For more information on the architecture of libguestfs,
767 see L<guestfs(3)>.");
768
769   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
770    [InitNone, Always, TestOutputIntOp (
771       [["get_pid"]], ">=", 1)],
772    "get PID of qemu subprocess",
773    "\
774 Return the process ID of the qemu subprocess.  If there is no
775 qemu subprocess, then this will return an error.
776
777 This is an internal call used for debugging and testing.");
778
779   ("version", (RStruct ("version", "version"), []), -1, [],
780    [InitNone, Always, TestOutputStruct (
781       [["version"]], [CompareWithInt ("major", 1)])],
782    "get the library version number",
783    "\
784 Return the libguestfs version number that the program is linked
785 against.
786
787 Note that because of dynamic linking this is not necessarily
788 the version of libguestfs that you compiled against.  You can
789 compile the program, and then at runtime dynamically link
790 against a completely different C<libguestfs.so> library.
791
792 This call was added in version C<1.0.58>.  In previous
793 versions of libguestfs there was no way to get the version
794 number.  From C code you can use ELF weak linking tricks to find out if
795 this symbol exists (if it doesn't, then it's an earlier version).
796
797 The call returns a structure with four elements.  The first
798 three (C<major>, C<minor> and C<release>) are numbers and
799 correspond to the usual version triplet.  The fourth element
800 (C<extra>) is a string and is normally empty, but may be
801 used for distro-specific information.
802
803 To construct the original version string:
804 C<$major.$minor.$release$extra>
805
806 I<Note:> Don't use this call to test for availability
807 of features.  Distro backports makes this unreliable.  Use
808 C<guestfs_available> instead.");
809
810   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
811    [InitNone, Always, TestOutputTrue (
812       [["set_selinux"; "true"];
813        ["get_selinux"]])],
814    "set SELinux enabled or disabled at appliance boot",
815    "\
816 This sets the selinux flag that is passed to the appliance
817 at boot time.  The default is C<selinux=0> (disabled).
818
819 Note that if SELinux is enabled, it is always in
820 Permissive mode (C<enforcing=0>).
821
822 For more information on the architecture of libguestfs,
823 see L<guestfs(3)>.");
824
825   ("get_selinux", (RBool "selinux", []), -1, [],
826    [],
827    "get SELinux enabled flag",
828    "\
829 This returns the current setting of the selinux flag which
830 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
831
832 For more information on the architecture of libguestfs,
833 see L<guestfs(3)>.");
834
835   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
836    [InitNone, Always, TestOutputFalse (
837       [["set_trace"; "false"];
838        ["get_trace"]])],
839    "enable or disable command traces",
840    "\
841 If the command trace flag is set to 1, then commands are
842 printed on stdout before they are executed in a format
843 which is very similar to the one used by guestfish.  In
844 other words, you can run a program with this enabled, and
845 you will get out a script which you can feed to guestfish
846 to perform the same set of actions.
847
848 If you want to trace C API calls into libguestfs (and
849 other libraries) then possibly a better way is to use
850 the external ltrace(1) command.
851
852 Command traces are disabled unless the environment variable
853 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
854
855   ("get_trace", (RBool "trace", []), -1, [],
856    [],
857    "get command trace enabled flag",
858    "\
859 Return the command trace flag.");
860
861   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
862    [InitNone, Always, TestOutputFalse (
863       [["set_direct"; "false"];
864        ["get_direct"]])],
865    "enable or disable direct appliance mode",
866    "\
867 If the direct appliance mode flag is enabled, then stdin and
868 stdout are passed directly through to the appliance once it
869 is launched.
870
871 One consequence of this is that log messages aren't caught
872 by the library and handled by C<guestfs_set_log_message_callback>,
873 but go straight to stdout.
874
875 You probably don't want to use this unless you know what you
876 are doing.
877
878 The default is disabled.");
879
880   ("get_direct", (RBool "direct", []), -1, [],
881    [],
882    "get direct appliance mode flag",
883    "\
884 Return the direct appliance mode flag.");
885
886   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
887    [InitNone, Always, TestOutputTrue (
888       [["set_recovery_proc"; "true"];
889        ["get_recovery_proc"]])],
890    "enable or disable the recovery process",
891    "\
892 If this is called with the parameter C<false> then
893 C<guestfs_launch> does not create a recovery process.  The
894 purpose of the recovery process is to stop runaway qemu
895 processes in the case where the main program aborts abruptly.
896
897 This only has any effect if called before C<guestfs_launch>,
898 and the default is true.
899
900 About the only time when you would want to disable this is
901 if the main process will fork itself into the background
902 (\"daemonize\" itself).  In this case the recovery process
903 thinks that the main program has disappeared and so kills
904 qemu, which is not very helpful.");
905
906   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
907    [],
908    "get recovery process enabled flag",
909    "\
910 Return the recovery process enabled flag.");
911
912   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
913    [],
914    "add a drive specifying the QEMU block emulation to use",
915    "\
916 This is the same as C<guestfs_add_drive> but it allows you
917 to specify the QEMU interface emulation to use at run time.");
918
919   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
920    [],
921    "add a drive read-only specifying the QEMU block emulation to use",
922    "\
923 This is the same as C<guestfs_add_drive_ro> but it allows you
924 to specify the QEMU interface emulation to use at run time.");
925
926 ]
927
928 (* daemon_functions are any functions which cause some action
929  * to take place in the daemon.
930  *)
931
932 let daemon_functions = [
933   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
934    [InitEmpty, Always, TestOutput (
935       [["part_disk"; "/dev/sda"; "mbr"];
936        ["mkfs"; "ext2"; "/dev/sda1"];
937        ["mount"; "/dev/sda1"; "/"];
938        ["write_file"; "/new"; "new file contents"; "0"];
939        ["cat"; "/new"]], "new file contents")],
940    "mount a guest disk at a position in the filesystem",
941    "\
942 Mount a guest disk at a position in the filesystem.  Block devices
943 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
944 the guest.  If those block devices contain partitions, they will have
945 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
946 names can be used.
947
948 The rules are the same as for L<mount(2)>:  A filesystem must
949 first be mounted on C</> before others can be mounted.  Other
950 filesystems can only be mounted on directories which already
951 exist.
952
953 The mounted filesystem is writable, if we have sufficient permissions
954 on the underlying device.
955
956 The filesystem options C<sync> and C<noatime> are set with this
957 call, in order to improve reliability.");
958
959   ("sync", (RErr, []), 2, [],
960    [ InitEmpty, Always, TestRun [["sync"]]],
961    "sync disks, writes are flushed through to the disk image",
962    "\
963 This syncs the disk, so that any writes are flushed through to the
964 underlying disk image.
965
966 You should always call this if you have modified a disk image, before
967 closing the handle.");
968
969   ("touch", (RErr, [Pathname "path"]), 3, [],
970    [InitBasicFS, Always, TestOutputTrue (
971       [["touch"; "/new"];
972        ["exists"; "/new"]])],
973    "update file timestamps or create a new file",
974    "\
975 Touch acts like the L<touch(1)> command.  It can be used to
976 update the timestamps on a file, or, if the file does not exist,
977 to create a new zero-length file.");
978
979   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
980    [InitISOFS, Always, TestOutput (
981       [["cat"; "/known-2"]], "abcdef\n")],
982    "list the contents of a file",
983    "\
984 Return the contents of the file named C<path>.
985
986 Note that this function cannot correctly handle binary files
987 (specifically, files containing C<\\0> character which is treated
988 as end of string).  For those you need to use the C<guestfs_read_file>
989 or C<guestfs_download> functions which have a more complex interface.");
990
991   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
992    [], (* XXX Tricky to test because it depends on the exact format
993         * of the 'ls -l' command, which changes between F10 and F11.
994         *)
995    "list the files in a directory (long format)",
996    "\
997 List the files in C<directory> (relative to the root directory,
998 there is no cwd) in the format of 'ls -la'.
999
1000 This command is mostly useful for interactive sessions.  It
1001 is I<not> intended that you try to parse the output string.");
1002
1003   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1004    [InitBasicFS, Always, TestOutputList (
1005       [["touch"; "/new"];
1006        ["touch"; "/newer"];
1007        ["touch"; "/newest"];
1008        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1009    "list the files in a directory",
1010    "\
1011 List the files in C<directory> (relative to the root directory,
1012 there is no cwd).  The '.' and '..' entries are not returned, but
1013 hidden files are shown.
1014
1015 This command is mostly useful for interactive sessions.  Programs
1016 should probably use C<guestfs_readdir> instead.");
1017
1018   ("list_devices", (RStringList "devices", []), 7, [],
1019    [InitEmpty, Always, TestOutputListOfDevices (
1020       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1021    "list the block devices",
1022    "\
1023 List all the block devices.
1024
1025 The full block device names are returned, eg. C</dev/sda>");
1026
1027   ("list_partitions", (RStringList "partitions", []), 8, [],
1028    [InitBasicFS, Always, TestOutputListOfDevices (
1029       [["list_partitions"]], ["/dev/sda1"]);
1030     InitEmpty, Always, TestOutputListOfDevices (
1031       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1032        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1033    "list the partitions",
1034    "\
1035 List all the partitions detected on all block devices.
1036
1037 The full partition device names are returned, eg. C</dev/sda1>
1038
1039 This does not return logical volumes.  For that you will need to
1040 call C<guestfs_lvs>.");
1041
1042   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1043    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1044       [["pvs"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["pvcreate"; "/dev/sda1"];
1048        ["pvcreate"; "/dev/sda2"];
1049        ["pvcreate"; "/dev/sda3"];
1050        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1051    "list the LVM physical volumes (PVs)",
1052    "\
1053 List all the physical volumes detected.  This is the equivalent
1054 of the L<pvs(8)> command.
1055
1056 This returns a list of just the device names that contain
1057 PVs (eg. C</dev/sda2>).
1058
1059 See also C<guestfs_pvs_full>.");
1060
1061   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputList (
1063       [["vgs"]], ["VG"]);
1064     InitEmpty, Always, TestOutputList (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1070        ["vgcreate"; "VG2"; "/dev/sda3"];
1071        ["vgs"]], ["VG1"; "VG2"])],
1072    "list the LVM volume groups (VGs)",
1073    "\
1074 List all the volumes groups detected.  This is the equivalent
1075 of the L<vgs(8)> command.
1076
1077 This returns a list of just the volume group names that were
1078 detected (eg. C<VolGroup00>).
1079
1080 See also C<guestfs_vgs_full>.");
1081
1082   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["lvs"]], ["/dev/VG/LV"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["lvcreate"; "LV1"; "VG1"; "50"];
1093        ["lvcreate"; "LV2"; "VG1"; "50"];
1094        ["lvcreate"; "LV3"; "VG2"; "50"];
1095        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1096    "list the LVM logical volumes (LVs)",
1097    "\
1098 List all the logical volumes detected.  This is the equivalent
1099 of the L<lvs(8)> command.
1100
1101 This returns a list of the logical volume device names
1102 (eg. C</dev/VolGroup00/LogVol00>).
1103
1104 See also C<guestfs_lvs_full>.");
1105
1106   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1107    [], (* XXX how to test? *)
1108    "list the LVM physical volumes (PVs)",
1109    "\
1110 List all the physical volumes detected.  This is the equivalent
1111 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1112
1113   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1114    [], (* XXX how to test? *)
1115    "list the LVM volume groups (VGs)",
1116    "\
1117 List all the volumes groups detected.  This is the equivalent
1118 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1119
1120   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1121    [], (* XXX how to test? *)
1122    "list the LVM logical volumes (LVs)",
1123    "\
1124 List all the logical volumes detected.  This is the equivalent
1125 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1126
1127   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1128    [InitISOFS, Always, TestOutputList (
1129       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1130     InitISOFS, Always, TestOutputList (
1131       [["read_lines"; "/empty"]], [])],
1132    "read file as lines",
1133    "\
1134 Return the contents of the file named C<path>.
1135
1136 The file contents are returned as a list of lines.  Trailing
1137 C<LF> and C<CRLF> character sequences are I<not> returned.
1138
1139 Note that this function cannot correctly handle binary files
1140 (specifically, files containing C<\\0> character which is treated
1141 as end of line).  For those you need to use the C<guestfs_read_file>
1142 function which has a more complex interface.");
1143
1144   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1145    [], (* XXX Augeas code needs tests. *)
1146    "create a new Augeas handle",
1147    "\
1148 Create a new Augeas handle for editing configuration files.
1149 If there was any previous Augeas handle associated with this
1150 guestfs session, then it is closed.
1151
1152 You must call this before using any other C<guestfs_aug_*>
1153 commands.
1154
1155 C<root> is the filesystem root.  C<root> must not be NULL,
1156 use C</> instead.
1157
1158 The flags are the same as the flags defined in
1159 E<lt>augeas.hE<gt>, the logical I<or> of the following
1160 integers:
1161
1162 =over 4
1163
1164 =item C<AUG_SAVE_BACKUP> = 1
1165
1166 Keep the original file with a C<.augsave> extension.
1167
1168 =item C<AUG_SAVE_NEWFILE> = 2
1169
1170 Save changes into a file with extension C<.augnew>, and
1171 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1172
1173 =item C<AUG_TYPE_CHECK> = 4
1174
1175 Typecheck lenses (can be expensive).
1176
1177 =item C<AUG_NO_STDINC> = 8
1178
1179 Do not use standard load path for modules.
1180
1181 =item C<AUG_SAVE_NOOP> = 16
1182
1183 Make save a no-op, just record what would have been changed.
1184
1185 =item C<AUG_NO_LOAD> = 32
1186
1187 Do not load the tree in C<guestfs_aug_init>.
1188
1189 =back
1190
1191 To close the handle, you can call C<guestfs_aug_close>.
1192
1193 To find out more about Augeas, see L<http://augeas.net/>.");
1194
1195   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1196    [], (* XXX Augeas code needs tests. *)
1197    "close the current Augeas handle",
1198    "\
1199 Close the current Augeas handle and free up any resources
1200 used by it.  After calling this, you have to call
1201 C<guestfs_aug_init> again before you can use any other
1202 Augeas functions.");
1203
1204   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas variable",
1207    "\
1208 Defines an Augeas variable C<name> whose value is the result
1209 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1210 undefined.
1211
1212 On success this returns the number of nodes in C<expr>, or
1213 C<0> if C<expr> evaluates to something which is not a nodeset.");
1214
1215   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas node",
1218    "\
1219 Defines a variable C<name> whose value is the result of
1220 evaluating C<expr>.
1221
1222 If C<expr> evaluates to an empty nodeset, a node is created,
1223 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1224 C<name> will be the nodeset containing that single node.
1225
1226 On success this returns a pair containing the
1227 number of nodes in the nodeset, and a boolean flag
1228 if a node was created.");
1229
1230   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "look up the value of an Augeas path",
1233    "\
1234 Look up the value associated with C<path>.  If C<path>
1235 matches exactly one node, the C<value> is returned.");
1236
1237   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1238    [], (* XXX Augeas code needs tests. *)
1239    "set Augeas path to value",
1240    "\
1241 Set the value associated with C<path> to C<value>.");
1242
1243   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1244    [], (* XXX Augeas code needs tests. *)
1245    "insert a sibling Augeas node",
1246    "\
1247 Create a new sibling C<label> for C<path>, inserting it into
1248 the tree before or after C<path> (depending on the boolean
1249 flag C<before>).
1250
1251 C<path> must match exactly one existing node in the tree, and
1252 C<label> must be a label, ie. not contain C</>, C<*> or end
1253 with a bracketed index C<[N]>.");
1254
1255   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1256    [], (* XXX Augeas code needs tests. *)
1257    "remove an Augeas path",
1258    "\
1259 Remove C<path> and all of its children.
1260
1261 On success this returns the number of entries which were removed.");
1262
1263   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "move Augeas node",
1266    "\
1267 Move the node C<src> to C<dest>.  C<src> must match exactly
1268 one node.  C<dest> is overwritten if it exists.");
1269
1270   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "return Augeas nodes which match augpath",
1273    "\
1274 Returns a list of paths which match the path expression C<path>.
1275 The returned paths are sufficiently qualified so that they match
1276 exactly one node in the current tree.");
1277
1278   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "write all pending Augeas changes to disk",
1281    "\
1282 This writes all pending changes to disk.
1283
1284 The flags which were passed to C<guestfs_aug_init> affect exactly
1285 how files are saved.");
1286
1287   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "load files into the tree",
1290    "\
1291 Load files into the tree.
1292
1293 See C<aug_load> in the Augeas documentation for the full gory
1294 details.");
1295
1296   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "list Augeas nodes under augpath",
1299    "\
1300 This is just a shortcut for listing C<guestfs_aug_match>
1301 C<path/*> and sorting the resulting nodes into alphabetical order.");
1302
1303   ("rm", (RErr, [Pathname "path"]), 29, [],
1304    [InitBasicFS, Always, TestRun
1305       [["touch"; "/new"];
1306        ["rm"; "/new"]];
1307     InitBasicFS, Always, TestLastFail
1308       [["rm"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["mkdir"; "/new"];
1311        ["rm"; "/new"]]],
1312    "remove a file",
1313    "\
1314 Remove the single file C<path>.");
1315
1316   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1317    [InitBasicFS, Always, TestRun
1318       [["mkdir"; "/new"];
1319        ["rmdir"; "/new"]];
1320     InitBasicFS, Always, TestLastFail
1321       [["rmdir"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["touch"; "/new"];
1324        ["rmdir"; "/new"]]],
1325    "remove a directory",
1326    "\
1327 Remove the single directory C<path>.");
1328
1329   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1330    [InitBasicFS, Always, TestOutputFalse
1331       [["mkdir"; "/new"];
1332        ["mkdir"; "/new/foo"];
1333        ["touch"; "/new/foo/bar"];
1334        ["rm_rf"; "/new"];
1335        ["exists"; "/new"]]],
1336    "remove a file or directory recursively",
1337    "\
1338 Remove the file or directory C<path>, recursively removing the
1339 contents if its a directory.  This is like the C<rm -rf> shell
1340 command.");
1341
1342   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1343    [InitBasicFS, Always, TestOutputTrue
1344       [["mkdir"; "/new"];
1345        ["is_dir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["mkdir"; "/new/foo/bar"]]],
1348    "create a directory",
1349    "\
1350 Create a directory named C<path>.");
1351
1352   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir_p"; "/new/foo/bar"];
1355        ["is_dir"; "/new/foo/bar"]];
1356     InitBasicFS, Always, TestOutputTrue
1357       [["mkdir_p"; "/new/foo/bar"];
1358        ["is_dir"; "/new/foo"]];
1359     InitBasicFS, Always, TestOutputTrue
1360       [["mkdir_p"; "/new/foo/bar"];
1361        ["is_dir"; "/new"]];
1362     (* Regression tests for RHBZ#503133: *)
1363     InitBasicFS, Always, TestRun
1364       [["mkdir"; "/new"];
1365        ["mkdir_p"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["touch"; "/new"];
1368        ["mkdir_p"; "/new"]]],
1369    "create a directory and parents",
1370    "\
1371 Create a directory named C<path>, creating any parent directories
1372 as necessary.  This is like the C<mkdir -p> shell command.");
1373
1374   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file mode",
1377    "\
1378 Change the mode (permissions) of C<path> to C<mode>.  Only
1379 numeric modes are supported.
1380
1381 I<Note>: When using this command from guestfish, C<mode>
1382 by default would be decimal, unless you prefix it with
1383 C<0> to get octal, ie. use C<0700> not C<700>.");
1384
1385   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1386    [], (* XXX Need stat command to test *)
1387    "change file owner and group",
1388    "\
1389 Change the file owner to C<owner> and group to C<group>.
1390
1391 Only numeric uid and gid are supported.  If you want to use
1392 names, you will need to locate and parse the password file
1393 yourself (Augeas support makes this relatively easy).");
1394
1395   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1396    [InitISOFS, Always, TestOutputTrue (
1397       [["exists"; "/empty"]]);
1398     InitISOFS, Always, TestOutputTrue (
1399       [["exists"; "/directory"]])],
1400    "test if file or directory exists",
1401    "\
1402 This returns C<true> if and only if there is a file, directory
1403 (or anything) with the given C<path> name.
1404
1405 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1406
1407   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1408    [InitISOFS, Always, TestOutputTrue (
1409       [["is_file"; "/known-1"]]);
1410     InitISOFS, Always, TestOutputFalse (
1411       [["is_file"; "/directory"]])],
1412    "test if file exists",
1413    "\
1414 This returns C<true> if and only if there is a file
1415 with the given C<path> name.  Note that it returns false for
1416 other objects like directories.
1417
1418 See also C<guestfs_stat>.");
1419
1420   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1421    [InitISOFS, Always, TestOutputFalse (
1422       [["is_dir"; "/known-3"]]);
1423     InitISOFS, Always, TestOutputTrue (
1424       [["is_dir"; "/directory"]])],
1425    "test if file exists",
1426    "\
1427 This returns C<true> if and only if there is a directory
1428 with the given C<path> name.  Note that it returns false for
1429 other objects like files.
1430
1431 See also C<guestfs_stat>.");
1432
1433   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1434    [InitEmpty, Always, TestOutputListOfDevices (
1435       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1436        ["pvcreate"; "/dev/sda1"];
1437        ["pvcreate"; "/dev/sda2"];
1438        ["pvcreate"; "/dev/sda3"];
1439        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1440    "create an LVM physical volume",
1441    "\
1442 This creates an LVM physical volume on the named C<device>,
1443 where C<device> should usually be a partition name such
1444 as C</dev/sda1>.");
1445
1446   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1447    [InitEmpty, Always, TestOutputList (
1448       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1449        ["pvcreate"; "/dev/sda1"];
1450        ["pvcreate"; "/dev/sda2"];
1451        ["pvcreate"; "/dev/sda3"];
1452        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1453        ["vgcreate"; "VG2"; "/dev/sda3"];
1454        ["vgs"]], ["VG1"; "VG2"])],
1455    "create an LVM volume group",
1456    "\
1457 This creates an LVM volume group called C<volgroup>
1458 from the non-empty list of physical volumes C<physvols>.");
1459
1460   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1461    [InitEmpty, Always, TestOutputList (
1462       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1463        ["pvcreate"; "/dev/sda1"];
1464        ["pvcreate"; "/dev/sda2"];
1465        ["pvcreate"; "/dev/sda3"];
1466        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1467        ["vgcreate"; "VG2"; "/dev/sda3"];
1468        ["lvcreate"; "LV1"; "VG1"; "50"];
1469        ["lvcreate"; "LV2"; "VG1"; "50"];
1470        ["lvcreate"; "LV3"; "VG2"; "50"];
1471        ["lvcreate"; "LV4"; "VG2"; "50"];
1472        ["lvcreate"; "LV5"; "VG2"; "50"];
1473        ["lvs"]],
1474       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1475        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1476    "create an LVM volume group",
1477    "\
1478 This creates an LVM volume group called C<logvol>
1479 on the volume group C<volgroup>, with C<size> megabytes.");
1480
1481   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1482    [InitEmpty, Always, TestOutput (
1483       [["part_disk"; "/dev/sda"; "mbr"];
1484        ["mkfs"; "ext2"; "/dev/sda1"];
1485        ["mount_options"; ""; "/dev/sda1"; "/"];
1486        ["write_file"; "/new"; "new file contents"; "0"];
1487        ["cat"; "/new"]], "new file contents")],
1488    "make a filesystem",
1489    "\
1490 This creates a filesystem on C<device> (usually a partition
1491 or LVM logical volume).  The filesystem type is C<fstype>, for
1492 example C<ext3>.");
1493
1494   ("sfdisk", (RErr, [Device "device";
1495                      Int "cyls"; Int "heads"; Int "sectors";
1496                      StringList "lines"]), 43, [DangerWillRobinson],
1497    [],
1498    "create partitions on a block device",
1499    "\
1500 This is a direct interface to the L<sfdisk(8)> program for creating
1501 partitions on block devices.
1502
1503 C<device> should be a block device, for example C</dev/sda>.
1504
1505 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1506 and sectors on the device, which are passed directly to sfdisk as
1507 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1508 of these, then the corresponding parameter is omitted.  Usually for
1509 'large' disks, you can just pass C<0> for these, but for small
1510 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1511 out the right geometry and you will need to tell it.
1512
1513 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1514 information refer to the L<sfdisk(8)> manpage.
1515
1516 To create a single partition occupying the whole disk, you would
1517 pass C<lines> as a single element list, when the single element being
1518 the string C<,> (comma).
1519
1520 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1521 C<guestfs_part_init>");
1522
1523   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1524    [InitBasicFS, Always, TestOutput (
1525       [["write_file"; "/new"; "new file contents"; "0"];
1526        ["cat"; "/new"]], "new file contents");
1527     InitBasicFS, Always, TestOutput (
1528       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1529        ["cat"; "/new"]], "\nnew file contents\n");
1530     InitBasicFS, Always, TestOutput (
1531       [["write_file"; "/new"; "\n\n"; "0"];
1532        ["cat"; "/new"]], "\n\n");
1533     InitBasicFS, Always, TestOutput (
1534       [["write_file"; "/new"; ""; "0"];
1535        ["cat"; "/new"]], "");
1536     InitBasicFS, Always, TestOutput (
1537       [["write_file"; "/new"; "\n\n\n"; "0"];
1538        ["cat"; "/new"]], "\n\n\n");
1539     InitBasicFS, Always, TestOutput (
1540       [["write_file"; "/new"; "\n"; "0"];
1541        ["cat"; "/new"]], "\n")],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.
1554 We hope to resolve this bug in a future version.  In the meantime
1555 use C<guestfs_upload>.");
1556
1557   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1558    [InitEmpty, Always, TestOutputListOfDevices (
1559       [["part_disk"; "/dev/sda"; "mbr"];
1560        ["mkfs"; "ext2"; "/dev/sda1"];
1561        ["mount_options"; ""; "/dev/sda1"; "/"];
1562        ["mounts"]], ["/dev/sda1"]);
1563     InitEmpty, Always, TestOutputList (
1564       [["part_disk"; "/dev/sda"; "mbr"];
1565        ["mkfs"; "ext2"; "/dev/sda1"];
1566        ["mount_options"; ""; "/dev/sda1"; "/"];
1567        ["umount"; "/"];
1568        ["mounts"]], [])],
1569    "unmount a filesystem",
1570    "\
1571 This unmounts the given filesystem.  The filesystem may be
1572 specified either by its mountpoint (path) or the device which
1573 contains the filesystem.");
1574
1575   ("mounts", (RStringList "devices", []), 46, [],
1576    [InitBasicFS, Always, TestOutputListOfDevices (
1577       [["mounts"]], ["/dev/sda1"])],
1578    "show mounted filesystems",
1579    "\
1580 This returns the list of currently mounted filesystems.  It returns
1581 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1582
1583 Some internal mounts are not shown.
1584
1585 See also: C<guestfs_mountpoints>");
1586
1587   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1588    [InitBasicFS, Always, TestOutputList (
1589       [["umount_all"];
1590        ["mounts"]], []);
1591     (* check that umount_all can unmount nested mounts correctly: *)
1592     InitEmpty, Always, TestOutputList (
1593       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1594        ["mkfs"; "ext2"; "/dev/sda1"];
1595        ["mkfs"; "ext2"; "/dev/sda2"];
1596        ["mkfs"; "ext2"; "/dev/sda3"];
1597        ["mount_options"; ""; "/dev/sda1"; "/"];
1598        ["mkdir"; "/mp1"];
1599        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1600        ["mkdir"; "/mp1/mp2"];
1601        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1602        ["mkdir"; "/mp1/mp2/mp3"];
1603        ["umount_all"];
1604        ["mounts"]], [])],
1605    "unmount all filesystems",
1606    "\
1607 This unmounts all mounted filesystems.
1608
1609 Some internal mounts are not unmounted by this call.");
1610
1611   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1612    [],
1613    "remove all LVM LVs, VGs and PVs",
1614    "\
1615 This command removes all LVM logical volumes, volume groups
1616 and physical volumes.");
1617
1618   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1619    [InitISOFS, Always, TestOutput (
1620       [["file"; "/empty"]], "empty");
1621     InitISOFS, Always, TestOutput (
1622       [["file"; "/known-1"]], "ASCII text");
1623     InitISOFS, Always, TestLastFail (
1624       [["file"; "/notexists"]])],
1625    "determine file type",
1626    "\
1627 This call uses the standard L<file(1)> command to determine
1628 the type or contents of the file.  This also works on devices,
1629 for example to find out whether a partition contains a filesystem.
1630
1631 This call will also transparently look inside various types
1632 of compressed file.
1633
1634 The exact command which runs is C<file -zbsL path>.  Note in
1635 particular that the filename is not prepended to the output
1636 (the C<-b> option).");
1637
1638   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1639    [InitBasicFS, Always, TestOutput (
1640       [["upload"; "test-command"; "/test-command"];
1641        ["chmod"; "0o755"; "/test-command"];
1642        ["command"; "/test-command 1"]], "Result1");
1643     InitBasicFS, Always, TestOutput (
1644       [["upload"; "test-command"; "/test-command"];
1645        ["chmod"; "0o755"; "/test-command"];
1646        ["command"; "/test-command 2"]], "Result2\n");
1647     InitBasicFS, Always, TestOutput (
1648       [["upload"; "test-command"; "/test-command"];
1649        ["chmod"; "0o755"; "/test-command"];
1650        ["command"; "/test-command 3"]], "\nResult3");
1651     InitBasicFS, Always, TestOutput (
1652       [["upload"; "test-command"; "/test-command"];
1653        ["chmod"; "0o755"; "/test-command"];
1654        ["command"; "/test-command 4"]], "\nResult4\n");
1655     InitBasicFS, Always, TestOutput (
1656       [["upload"; "test-command"; "/test-command"];
1657        ["chmod"; "0o755"; "/test-command"];
1658        ["command"; "/test-command 5"]], "\nResult5\n\n");
1659     InitBasicFS, Always, TestOutput (
1660       [["upload"; "test-command"; "/test-command"];
1661        ["chmod"; "0o755"; "/test-command"];
1662        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1663     InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 7"]], "");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 8"]], "\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 9"]], "\n\n");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1683     InitBasicFS, Always, TestLastFail (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command"]])],
1687    "run a command from the guest filesystem",
1688    "\
1689 This call runs a command from the guest filesystem.  The
1690 filesystem must be mounted, and must contain a compatible
1691 operating system (ie. something Linux, with the same
1692 or compatible processor architecture).
1693
1694 The single parameter is an argv-style list of arguments.
1695 The first element is the name of the program to run.
1696 Subsequent elements are parameters.  The list must be
1697 non-empty (ie. must contain a program name).  Note that
1698 the command runs directly, and is I<not> invoked via
1699 the shell (see C<guestfs_sh>).
1700
1701 The return value is anything printed to I<stdout> by
1702 the command.
1703
1704 If the command returns a non-zero exit status, then
1705 this function returns an error message.  The error message
1706 string is the content of I<stderr> from the command.
1707
1708 The C<$PATH> environment variable will contain at least
1709 C</usr/bin> and C</bin>.  If you require a program from
1710 another location, you should provide the full path in the
1711 first parameter.
1712
1713 Shared libraries and data files required by the program
1714 must be available on filesystems which are mounted in the
1715 correct places.  It is the caller's responsibility to ensure
1716 all filesystems that are needed are mounted at the right
1717 locations.");
1718
1719   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1720    [InitBasicFS, Always, TestOutputList (
1721       [["upload"; "test-command"; "/test-command"];
1722        ["chmod"; "0o755"; "/test-command"];
1723        ["command_lines"; "/test-command 1"]], ["Result1"]);
1724     InitBasicFS, Always, TestOutputList (
1725       [["upload"; "test-command"; "/test-command"];
1726        ["chmod"; "0o755"; "/test-command"];
1727        ["command_lines"; "/test-command 2"]], ["Result2"]);
1728     InitBasicFS, Always, TestOutputList (
1729       [["upload"; "test-command"; "/test-command"];
1730        ["chmod"; "0o755"; "/test-command"];
1731        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1732     InitBasicFS, Always, TestOutputList (
1733       [["upload"; "test-command"; "/test-command"];
1734        ["chmod"; "0o755"; "/test-command"];
1735        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1736     InitBasicFS, Always, TestOutputList (
1737       [["upload"; "test-command"; "/test-command"];
1738        ["chmod"; "0o755"; "/test-command"];
1739        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1740     InitBasicFS, Always, TestOutputList (
1741       [["upload"; "test-command"; "/test-command"];
1742        ["chmod"; "0o755"; "/test-command"];
1743        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1744     InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 7"]], []);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 8"]], [""]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 9"]], ["";""]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1764    "run a command, returning lines",
1765    "\
1766 This is the same as C<guestfs_command>, but splits the
1767 result into a list of lines.
1768
1769 See also: C<guestfs_sh_lines>");
1770
1771   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1772    [InitISOFS, Always, TestOutputStruct (
1773       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1774    "get file information",
1775    "\
1776 Returns file information for the given C<path>.
1777
1778 This is the same as the C<stat(2)> system call.");
1779
1780   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1781    [InitISOFS, Always, TestOutputStruct (
1782       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1783    "get file information for a symbolic link",
1784    "\
1785 Returns file information for the given C<path>.
1786
1787 This is the same as C<guestfs_stat> except that if C<path>
1788 is a symbolic link, then the link is stat-ed, not the file it
1789 refers to.
1790
1791 This is the same as the C<lstat(2)> system call.");
1792
1793   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1796    "get file system statistics",
1797    "\
1798 Returns file system statistics for any mounted file system.
1799 C<path> should be a file or directory in the mounted file system
1800 (typically it is the mount point itself, but it doesn't need to be).
1801
1802 This is the same as the C<statvfs(2)> system call.");
1803
1804   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1805    [], (* XXX test *)
1806    "get ext2/ext3/ext4 superblock details",
1807    "\
1808 This returns the contents of the ext2, ext3 or ext4 filesystem
1809 superblock on C<device>.
1810
1811 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1812 manpage for more details.  The list of fields returned isn't
1813 clearly defined, and depends on both the version of C<tune2fs>
1814 that libguestfs was built against, and the filesystem itself.");
1815
1816   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1817    [InitEmpty, Always, TestOutputTrue (
1818       [["blockdev_setro"; "/dev/sda"];
1819        ["blockdev_getro"; "/dev/sda"]])],
1820    "set block device to read-only",
1821    "\
1822 Sets the block device named C<device> to read-only.
1823
1824 This uses the L<blockdev(8)> command.");
1825
1826   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1827    [InitEmpty, Always, TestOutputFalse (
1828       [["blockdev_setrw"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-write",
1831    "\
1832 Sets the block device named C<device> to read-write.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1837    [InitEmpty, Always, TestOutputTrue (
1838       [["blockdev_setro"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "is block device set to read-only",
1841    "\
1842 Returns a boolean indicating if the block device is read-only
1843 (true if read-only, false if not).
1844
1845 This uses the L<blockdev(8)> command.");
1846
1847   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1848    [InitEmpty, Always, TestOutputInt (
1849       [["blockdev_getss"; "/dev/sda"]], 512)],
1850    "get sectorsize of block device",
1851    "\
1852 This returns the size of sectors on a block device.
1853 Usually 512, but can be larger for modern devices.
1854
1855 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1856 for that).
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1861    [InitEmpty, Always, TestOutputInt (
1862       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1863    "get blocksize of block device",
1864    "\
1865 This returns the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1873    [], (* XXX test *)
1874    "set blocksize of block device",
1875    "\
1876 This sets the block size of a device.
1877
1878 (Note this is different from both I<size in blocks> and
1879 I<filesystem block size>).
1880
1881 This uses the L<blockdev(8)> command.");
1882
1883   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1884    [InitEmpty, Always, TestOutputInt (
1885       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1886    "get total size of device in 512-byte sectors",
1887    "\
1888 This returns the size of the device in units of 512-byte sectors
1889 (even if the sectorsize isn't 512 bytes ... weird).
1890
1891 See also C<guestfs_blockdev_getss> for the real sector size of
1892 the device, and C<guestfs_blockdev_getsize64> for the more
1893 useful I<size in bytes>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1898    [InitEmpty, Always, TestOutputInt (
1899       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1900    "get total size of device in bytes",
1901    "\
1902 This returns the size of the device in bytes.
1903
1904 See also C<guestfs_blockdev_getsz>.
1905
1906 This uses the L<blockdev(8)> command.");
1907
1908   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1909    [InitEmpty, Always, TestRun
1910       [["blockdev_flushbufs"; "/dev/sda"]]],
1911    "flush device buffers",
1912    "\
1913 This tells the kernel to flush internal buffers associated
1914 with C<device>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_rereadpt"; "/dev/sda"]]],
1921    "reread partition table",
1922    "\
1923 Reread the partition table on C<device>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1928    [InitBasicFS, Always, TestOutput (
1929       (* Pick a file from cwd which isn't likely to change. *)
1930       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1931        ["checksum"; "md5"; "/COPYING.LIB"]],
1932       Digest.to_hex (Digest.file "COPYING.LIB"))],
1933    "upload a file from the local machine",
1934    "\
1935 Upload local file C<filename> to C<remotefilename> on the
1936 filesystem.
1937
1938 C<filename> can also be a named pipe.
1939
1940 See also C<guestfs_download>.");
1941
1942   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1943    [InitBasicFS, Always, TestOutput (
1944       (* Pick a file from cwd which isn't likely to change. *)
1945       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1946        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1947        ["upload"; "testdownload.tmp"; "/upload"];
1948        ["checksum"; "md5"; "/upload"]],
1949       Digest.to_hex (Digest.file "COPYING.LIB"))],
1950    "download a file to the local machine",
1951    "\
1952 Download file C<remotefilename> and save it as C<filename>
1953 on the local machine.
1954
1955 C<filename> can also be a named pipe.
1956
1957 See also C<guestfs_upload>, C<guestfs_cat>.");
1958
1959   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1960    [InitISOFS, Always, TestOutput (
1961       [["checksum"; "crc"; "/known-3"]], "2891671662");
1962     InitISOFS, Always, TestLastFail (
1963       [["checksum"; "crc"; "/notexists"]]);
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1976    "compute MD5, SHAx or CRC checksum of file",
1977    "\
1978 This call computes the MD5, SHAx or CRC checksum of the
1979 file named C<path>.
1980
1981 The type of checksum to compute is given by the C<csumtype>
1982 parameter which must have one of the following values:
1983
1984 =over 4
1985
1986 =item C<crc>
1987
1988 Compute the cyclic redundancy check (CRC) specified by POSIX
1989 for the C<cksum> command.
1990
1991 =item C<md5>
1992
1993 Compute the MD5 hash (using the C<md5sum> program).
1994
1995 =item C<sha1>
1996
1997 Compute the SHA1 hash (using the C<sha1sum> program).
1998
1999 =item C<sha224>
2000
2001 Compute the SHA224 hash (using the C<sha224sum> program).
2002
2003 =item C<sha256>
2004
2005 Compute the SHA256 hash (using the C<sha256sum> program).
2006
2007 =item C<sha384>
2008
2009 Compute the SHA384 hash (using the C<sha384sum> program).
2010
2011 =item C<sha512>
2012
2013 Compute the SHA512 hash (using the C<sha512sum> program).
2014
2015 =back
2016
2017 The checksum is returned as a printable string.");
2018
2019   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2020    [InitBasicFS, Always, TestOutput (
2021       [["tar_in"; "../images/helloworld.tar"; "/"];
2022        ["cat"; "/hello"]], "hello\n")],
2023    "unpack tarfile to directory",
2024    "\
2025 This command uploads and unpacks local file C<tarfile> (an
2026 I<uncompressed> tar file) into C<directory>.
2027
2028 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2029
2030   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2031    [],
2032    "pack directory into tarfile",
2033    "\
2034 This command packs the contents of C<directory> and downloads
2035 it to local file C<tarfile>.
2036
2037 To download a compressed tarball, use C<guestfs_tgz_out>.");
2038
2039   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2040    [InitBasicFS, Always, TestOutput (
2041       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2042        ["cat"; "/hello"]], "hello\n")],
2043    "unpack compressed tarball to directory",
2044    "\
2045 This command uploads and unpacks local file C<tarball> (a
2046 I<gzip compressed> tar file) into C<directory>.
2047
2048 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2049
2050   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2051    [],
2052    "pack directory into compressed tarball",
2053    "\
2054 This command packs the contents of C<directory> and downloads
2055 it to local file C<tarball>.
2056
2057 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2058
2059   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2060    [InitBasicFS, Always, TestLastFail (
2061       [["umount"; "/"];
2062        ["mount_ro"; "/dev/sda1"; "/"];
2063        ["touch"; "/new"]]);
2064     InitBasicFS, Always, TestOutput (
2065       [["write_file"; "/new"; "data"; "0"];
2066        ["umount"; "/"];
2067        ["mount_ro"; "/dev/sda1"; "/"];
2068        ["cat"; "/new"]], "data")],
2069    "mount a guest disk, read-only",
2070    "\
2071 This is the same as the C<guestfs_mount> command, but it
2072 mounts the filesystem with the read-only (I<-o ro>) flag.");
2073
2074   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2075    [],
2076    "mount a guest disk with mount options",
2077    "\
2078 This is the same as the C<guestfs_mount> command, but it
2079 allows you to set the mount options as for the
2080 L<mount(8)> I<-o> flag.");
2081
2082   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2083    [],
2084    "mount a guest disk with mount options and vfstype",
2085    "\
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set both the mount options and the vfstype
2088 as for the L<mount(8)> I<-o> and I<-t> flags.");
2089
2090   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2091    [],
2092    "debugging and internals",
2093    "\
2094 The C<guestfs_debug> command exposes some internals of
2095 C<guestfsd> (the guestfs daemon) that runs inside the
2096 qemu subprocess.
2097
2098 There is no comprehensive help for this command.  You have
2099 to look at the file C<daemon/debug.c> in the libguestfs source
2100 to find out what you can do.");
2101
2102   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2103    [InitEmpty, Always, TestOutputList (
2104       [["part_disk"; "/dev/sda"; "mbr"];
2105        ["pvcreate"; "/dev/sda1"];
2106        ["vgcreate"; "VG"; "/dev/sda1"];
2107        ["lvcreate"; "LV1"; "VG"; "50"];
2108        ["lvcreate"; "LV2"; "VG"; "50"];
2109        ["lvremove"; "/dev/VG/LV1"];
2110        ["lvs"]], ["/dev/VG/LV2"]);
2111     InitEmpty, Always, TestOutputList (
2112       [["part_disk"; "/dev/sda"; "mbr"];
2113        ["pvcreate"; "/dev/sda1"];
2114        ["vgcreate"; "VG"; "/dev/sda1"];
2115        ["lvcreate"; "LV1"; "VG"; "50"];
2116        ["lvcreate"; "LV2"; "VG"; "50"];
2117        ["lvremove"; "/dev/VG"];
2118        ["lvs"]], []);
2119     InitEmpty, Always, TestOutputList (
2120       [["part_disk"; "/dev/sda"; "mbr"];
2121        ["pvcreate"; "/dev/sda1"];
2122        ["vgcreate"; "VG"; "/dev/sda1"];
2123        ["lvcreate"; "LV1"; "VG"; "50"];
2124        ["lvcreate"; "LV2"; "VG"; "50"];
2125        ["lvremove"; "/dev/VG"];
2126        ["vgs"]], ["VG"])],
2127    "remove an LVM logical volume",
2128    "\
2129 Remove an LVM logical volume C<device>, where C<device> is
2130 the path to the LV, such as C</dev/VG/LV>.
2131
2132 You can also remove all LVs in a volume group by specifying
2133 the VG name, C</dev/VG>.");
2134
2135   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2136    [InitEmpty, Always, TestOutputList (
2137       [["part_disk"; "/dev/sda"; "mbr"];
2138        ["pvcreate"; "/dev/sda1"];
2139        ["vgcreate"; "VG"; "/dev/sda1"];
2140        ["lvcreate"; "LV1"; "VG"; "50"];
2141        ["lvcreate"; "LV2"; "VG"; "50"];
2142        ["vgremove"; "VG"];
2143        ["lvs"]], []);
2144     InitEmpty, Always, TestOutputList (
2145       [["part_disk"; "/dev/sda"; "mbr"];
2146        ["pvcreate"; "/dev/sda1"];
2147        ["vgcreate"; "VG"; "/dev/sda1"];
2148        ["lvcreate"; "LV1"; "VG"; "50"];
2149        ["lvcreate"; "LV2"; "VG"; "50"];
2150        ["vgremove"; "VG"];
2151        ["vgs"]], [])],
2152    "remove an LVM volume group",
2153    "\
2154 Remove an LVM volume group C<vgname>, (for example C<VG>).
2155
2156 This also forcibly removes all logical volumes in the volume
2157 group (if any).");
2158
2159   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2160    [InitEmpty, Always, TestOutputListOfDevices (
2161       [["part_disk"; "/dev/sda"; "mbr"];
2162        ["pvcreate"; "/dev/sda1"];
2163        ["vgcreate"; "VG"; "/dev/sda1"];
2164        ["lvcreate"; "LV1"; "VG"; "50"];
2165        ["lvcreate"; "LV2"; "VG"; "50"];
2166        ["vgremove"; "VG"];
2167        ["pvremove"; "/dev/sda1"];
2168        ["lvs"]], []);
2169     InitEmpty, Always, TestOutputListOfDevices (
2170       [["part_disk"; "/dev/sda"; "mbr"];
2171        ["pvcreate"; "/dev/sda1"];
2172        ["vgcreate"; "VG"; "/dev/sda1"];
2173        ["lvcreate"; "LV1"; "VG"; "50"];
2174        ["lvcreate"; "LV2"; "VG"; "50"];
2175        ["vgremove"; "VG"];
2176        ["pvremove"; "/dev/sda1"];
2177        ["vgs"]], []);
2178     InitEmpty, Always, TestOutputListOfDevices (
2179       [["part_disk"; "/dev/sda"; "mbr"];
2180        ["pvcreate"; "/dev/sda1"];
2181        ["vgcreate"; "VG"; "/dev/sda1"];
2182        ["lvcreate"; "LV1"; "VG"; "50"];
2183        ["lvcreate"; "LV2"; "VG"; "50"];
2184        ["vgremove"; "VG"];
2185        ["pvremove"; "/dev/sda1"];
2186        ["pvs"]], [])],
2187    "remove an LVM physical volume",
2188    "\
2189 This wipes a physical volume C<device> so that LVM will no longer
2190 recognise it.
2191
2192 The implementation uses the C<pvremove> command which refuses to
2193 wipe physical volumes that contain any volume groups, so you have
2194 to remove those first.");
2195
2196   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2197    [InitBasicFS, Always, TestOutput (
2198       [["set_e2label"; "/dev/sda1"; "testlabel"];
2199        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2200    "set the ext2/3/4 filesystem label",
2201    "\
2202 This sets the ext2/3/4 filesystem label of the filesystem on
2203 C<device> to C<label>.  Filesystem labels are limited to
2204 16 characters.
2205
2206 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2207 to return the existing label on a filesystem.");
2208
2209   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2210    [],
2211    "get the ext2/3/4 filesystem label",
2212    "\
2213 This returns the ext2/3/4 filesystem label of the filesystem on
2214 C<device>.");
2215
2216   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2217    (let uuid = uuidgen () in
2218     [InitBasicFS, Always, TestOutput (
2219        [["set_e2uuid"; "/dev/sda1"; uuid];
2220         ["get_e2uuid"; "/dev/sda1"]], uuid);
2221      InitBasicFS, Always, TestOutput (
2222        [["set_e2uuid"; "/dev/sda1"; "clear"];
2223         ["get_e2uuid"; "/dev/sda1"]], "");
2224      (* We can't predict what UUIDs will be, so just check the commands run. *)
2225      InitBasicFS, Always, TestRun (
2226        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2227      InitBasicFS, Always, TestRun (
2228        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2229    "set the ext2/3/4 filesystem UUID",
2230    "\
2231 This sets the ext2/3/4 filesystem UUID of the filesystem on
2232 C<device> to C<uuid>.  The format of the UUID and alternatives
2233 such as C<clear>, C<random> and C<time> are described in the
2234 L<tune2fs(8)> manpage.
2235
2236 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2237 to return the existing UUID of a filesystem.");
2238
2239   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2240    [],
2241    "get the ext2/3/4 filesystem UUID",
2242    "\
2243 This returns the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device>.");
2245
2246   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2247    [InitBasicFS, Always, TestOutputInt (
2248       [["umount"; "/dev/sda1"];
2249        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2250     InitBasicFS, Always, TestOutputInt (
2251       [["umount"; "/dev/sda1"];
2252        ["zero"; "/dev/sda1"];
2253        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2254    "run the filesystem checker",
2255    "\
2256 This runs the filesystem checker (fsck) on C<device> which
2257 should have filesystem type C<fstype>.
2258
2259 The returned integer is the status.  See L<fsck(8)> for the
2260 list of status codes from C<fsck>.
2261
2262 Notes:
2263
2264 =over 4
2265
2266 =item *
2267
2268 Multiple status codes can be summed together.
2269
2270 =item *
2271
2272 A non-zero return code can mean \"success\", for example if
2273 errors have been corrected on the filesystem.
2274
2275 =item *
2276
2277 Checking or repairing NTFS volumes is not supported
2278 (by linux-ntfs).
2279
2280 =back
2281
2282 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2283
2284   ("zero", (RErr, [Device "device"]), 85, [],
2285    [InitBasicFS, Always, TestOutput (
2286       [["umount"; "/dev/sda1"];
2287        ["zero"; "/dev/sda1"];
2288        ["file"; "/dev/sda1"]], "data")],
2289    "write zeroes to the device",
2290    "\
2291 This command writes zeroes over the first few blocks of C<device>.
2292
2293 How many blocks are zeroed isn't specified (but it's I<not> enough
2294 to securely wipe the device).  It should be sufficient to remove
2295 any partition tables, filesystem superblocks and so on.
2296
2297 See also: C<guestfs_scrub_device>.");
2298
2299   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2300    (* Test disabled because grub-install incompatible with virtio-blk driver.
2301     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2302     *)
2303    [InitBasicFS, Disabled, TestOutputTrue (
2304       [["grub_install"; "/"; "/dev/sda1"];
2305        ["is_dir"; "/boot"]])],
2306    "install GRUB",
2307    "\
2308 This command installs GRUB (the Grand Unified Bootloader) on
2309 C<device>, with the root directory being C<root>.");
2310
2311   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2312    [InitBasicFS, Always, TestOutput (
2313       [["write_file"; "/old"; "file content"; "0"];
2314        ["cp"; "/old"; "/new"];
2315        ["cat"; "/new"]], "file content");
2316     InitBasicFS, Always, TestOutputTrue (
2317       [["write_file"; "/old"; "file content"; "0"];
2318        ["cp"; "/old"; "/new"];
2319        ["is_file"; "/old"]]);
2320     InitBasicFS, Always, TestOutput (
2321       [["write_file"; "/old"; "file content"; "0"];
2322        ["mkdir"; "/dir"];
2323        ["cp"; "/old"; "/dir/new"];
2324        ["cat"; "/dir/new"]], "file content")],
2325    "copy a file",
2326    "\
2327 This copies a file from C<src> to C<dest> where C<dest> is
2328 either a destination filename or destination directory.");
2329
2330   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2331    [InitBasicFS, Always, TestOutput (
2332       [["mkdir"; "/olddir"];
2333        ["mkdir"; "/newdir"];
2334        ["write_file"; "/olddir/file"; "file content"; "0"];
2335        ["cp_a"; "/olddir"; "/newdir"];
2336        ["cat"; "/newdir/olddir/file"]], "file content")],
2337    "copy a file or directory recursively",
2338    "\
2339 This copies a file or directory from C<src> to C<dest>
2340 recursively using the C<cp -a> command.");
2341
2342   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["write_file"; "/old"; "file content"; "0"];
2345        ["mv"; "/old"; "/new"];
2346        ["cat"; "/new"]], "file content");
2347     InitBasicFS, Always, TestOutputFalse (
2348       [["write_file"; "/old"; "file content"; "0"];
2349        ["mv"; "/old"; "/new"];
2350        ["is_file"; "/old"]])],
2351    "move a file",
2352    "\
2353 This moves a file from C<src> to C<dest> where C<dest> is
2354 either a destination filename or destination directory.");
2355
2356   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2357    [InitEmpty, Always, TestRun (
2358       [["drop_caches"; "3"]])],
2359    "drop kernel page cache, dentries and inodes",
2360    "\
2361 This instructs the guest kernel to drop its page cache,
2362 and/or dentries and inode caches.  The parameter C<whattodrop>
2363 tells the kernel what precisely to drop, see
2364 L<http://linux-mm.org/Drop_Caches>
2365
2366 Setting C<whattodrop> to 3 should drop everything.
2367
2368 This automatically calls L<sync(2)> before the operation,
2369 so that the maximum guest memory is freed.");
2370
2371   ("dmesg", (RString "kmsgs", []), 91, [],
2372    [InitEmpty, Always, TestRun (
2373       [["dmesg"]])],
2374    "return kernel messages",
2375    "\
2376 This returns the kernel messages (C<dmesg> output) from
2377 the guest kernel.  This is sometimes useful for extended
2378 debugging of problems.
2379
2380 Another way to get the same information is to enable
2381 verbose messages with C<guestfs_set_verbose> or by setting
2382 the environment variable C<LIBGUESTFS_DEBUG=1> before
2383 running the program.");
2384
2385   ("ping_daemon", (RErr, []), 92, [],
2386    [InitEmpty, Always, TestRun (
2387       [["ping_daemon"]])],
2388    "ping the guest daemon",
2389    "\
2390 This is a test probe into the guestfs daemon running inside
2391 the qemu subprocess.  Calling this function checks that the
2392 daemon responds to the ping message, without affecting the daemon
2393 or attached block device(s) in any other way.");
2394
2395   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2396    [InitBasicFS, Always, TestOutputTrue (
2397       [["write_file"; "/file1"; "contents of a file"; "0"];
2398        ["cp"; "/file1"; "/file2"];
2399        ["equal"; "/file1"; "/file2"]]);
2400     InitBasicFS, Always, TestOutputFalse (
2401       [["write_file"; "/file1"; "contents of a file"; "0"];
2402        ["write_file"; "/file2"; "contents of another file"; "0"];
2403        ["equal"; "/file1"; "/file2"]]);
2404     InitBasicFS, Always, TestLastFail (
2405       [["equal"; "/file1"; "/file2"]])],
2406    "test if two files have equal contents",
2407    "\
2408 This compares the two files C<file1> and C<file2> and returns
2409 true if their content is exactly equal, or false otherwise.
2410
2411 The external L<cmp(1)> program is used for the comparison.");
2412
2413   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2414    [InitISOFS, Always, TestOutputList (
2415       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2416     InitISOFS, Always, TestOutputList (
2417       [["strings"; "/empty"]], [])],
2418    "print the printable strings in a file",
2419    "\
2420 This runs the L<strings(1)> command on a file and returns
2421 the list of printable strings found.");
2422
2423   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2424    [InitISOFS, Always, TestOutputList (
2425       [["strings_e"; "b"; "/known-5"]], []);
2426     InitBasicFS, Disabled, TestOutputList (
2427       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2428        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2429    "print the printable strings in a file",
2430    "\
2431 This is like the C<guestfs_strings> command, but allows you to
2432 specify the encoding.
2433
2434 See the L<strings(1)> manpage for the full list of encodings.
2435
2436 Commonly useful encodings are C<l> (lower case L) which will
2437 show strings inside Windows/x86 files.
2438
2439 The returned strings are transcoded to UTF-8.");
2440
2441   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2442    [InitISOFS, Always, TestOutput (
2443       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2444     (* Test for RHBZ#501888c2 regression which caused large hexdump
2445      * commands to segfault.
2446      *)
2447     InitISOFS, Always, TestRun (
2448       [["hexdump"; "/100krandom"]])],
2449    "dump a file in hexadecimal",
2450    "\
2451 This runs C<hexdump -C> on the given C<path>.  The result is
2452 the human-readable, canonical hex dump of the file.");
2453
2454   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2455    [InitNone, Always, TestOutput (
2456       [["part_disk"; "/dev/sda"; "mbr"];
2457        ["mkfs"; "ext3"; "/dev/sda1"];
2458        ["mount_options"; ""; "/dev/sda1"; "/"];
2459        ["write_file"; "/new"; "test file"; "0"];
2460        ["umount"; "/dev/sda1"];
2461        ["zerofree"; "/dev/sda1"];
2462        ["mount_options"; ""; "/dev/sda1"; "/"];
2463        ["cat"; "/new"]], "test file")],
2464    "zero unused inodes and disk blocks on ext2/3 filesystem",
2465    "\
2466 This runs the I<zerofree> program on C<device>.  This program
2467 claims to zero unused inodes and disk blocks on an ext2/3
2468 filesystem, thus making it possible to compress the filesystem
2469 more effectively.
2470
2471 You should B<not> run this program if the filesystem is
2472 mounted.
2473
2474 It is possible that using this program can damage the filesystem
2475 or data on the filesystem.");
2476
2477   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2478    [],
2479    "resize an LVM physical volume",
2480    "\
2481 This resizes (expands or shrinks) an existing LVM physical
2482 volume to match the new size of the underlying device.");
2483
2484   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2485                        Int "cyls"; Int "heads"; Int "sectors";
2486                        String "line"]), 99, [DangerWillRobinson],
2487    [],
2488    "modify a single partition on a block device",
2489    "\
2490 This runs L<sfdisk(8)> option to modify just the single
2491 partition C<n> (note: C<n> counts from 1).
2492
2493 For other parameters, see C<guestfs_sfdisk>.  You should usually
2494 pass C<0> for the cyls/heads/sectors parameters.
2495
2496 See also: C<guestfs_part_add>");
2497
2498   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2499    [],
2500    "display the partition table",
2501    "\
2502 This displays the partition table on C<device>, in the
2503 human-readable output of the L<sfdisk(8)> command.  It is
2504 not intended to be parsed.
2505
2506 See also: C<guestfs_part_list>");
2507
2508   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2509    [],
2510    "display the kernel geometry",
2511    "\
2512 This displays the kernel's idea of the geometry of C<device>.
2513
2514 The result is in human-readable format, and not designed to
2515 be parsed.");
2516
2517   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2518    [],
2519    "display the disk geometry from the partition table",
2520    "\
2521 This displays the disk geometry of C<device> read from the
2522 partition table.  Especially in the case where the underlying
2523 block device has been resized, this can be different from the
2524 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2525
2526 The result is in human-readable format, and not designed to
2527 be parsed.");
2528
2529   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2530    [],
2531    "activate or deactivate all volume groups",
2532    "\
2533 This command activates or (if C<activate> is false) deactivates
2534 all logical volumes in all volume groups.
2535 If activated, then they are made known to the
2536 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2537 then those devices disappear.
2538
2539 This command is the same as running C<vgchange -a y|n>");
2540
2541   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2542    [],
2543    "activate or deactivate some volume groups",
2544    "\
2545 This command activates or (if C<activate> is false) deactivates
2546 all logical volumes in the listed volume groups C<volgroups>.
2547 If activated, then they are made known to the
2548 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2549 then those devices disappear.
2550
2551 This command is the same as running C<vgchange -a y|n volgroups...>
2552
2553 Note that if C<volgroups> is an empty list then B<all> volume groups
2554 are activated or deactivated.");
2555
2556   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2557    [InitNone, Always, TestOutput (
2558       [["part_disk"; "/dev/sda"; "mbr"];
2559        ["pvcreate"; "/dev/sda1"];
2560        ["vgcreate"; "VG"; "/dev/sda1"];
2561        ["lvcreate"; "LV"; "VG"; "10"];
2562        ["mkfs"; "ext2"; "/dev/VG/LV"];
2563        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2564        ["write_file"; "/new"; "test content"; "0"];
2565        ["umount"; "/"];
2566        ["lvresize"; "/dev/VG/LV"; "20"];
2567        ["e2fsck_f"; "/dev/VG/LV"];
2568        ["resize2fs"; "/dev/VG/LV"];
2569        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2570        ["cat"; "/new"]], "test content")],
2571    "resize an LVM logical volume",
2572    "\
2573 This resizes (expands or shrinks) an existing LVM logical
2574 volume to C<mbytes>.  When reducing, data in the reduced part
2575 is lost.");
2576
2577   ("resize2fs", (RErr, [Device "device"]), 106, [],
2578    [], (* lvresize tests this *)
2579    "resize an ext2/ext3 filesystem",
2580    "\
2581 This resizes an ext2 or ext3 filesystem to match the size of
2582 the underlying device.
2583
2584 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2585 on the C<device> before calling this command.  For unknown reasons
2586 C<resize2fs> sometimes gives an error about this and sometimes not.
2587 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2588 calling this function.");
2589
2590   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2591    [InitBasicFS, Always, TestOutputList (
2592       [["find"; "/"]], ["lost+found"]);
2593     InitBasicFS, Always, TestOutputList (
2594       [["touch"; "/a"];
2595        ["mkdir"; "/b"];
2596        ["touch"; "/b/c"];
2597        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2598     InitBasicFS, Always, TestOutputList (
2599       [["mkdir_p"; "/a/b/c"];
2600        ["touch"; "/a/b/c/d"];
2601        ["find"; "/a/b/"]], ["c"; "c/d"])],
2602    "find all files and directories",
2603    "\
2604 This command lists out all files and directories, recursively,
2605 starting at C<directory>.  It is essentially equivalent to
2606 running the shell command C<find directory -print> but some
2607 post-processing happens on the output, described below.
2608
2609 This returns a list of strings I<without any prefix>.  Thus
2610 if the directory structure was:
2611
2612  /tmp/a
2613  /tmp/b
2614  /tmp/c/d
2615
2616 then the returned list from C<guestfs_find> C</tmp> would be
2617 4 elements:
2618
2619  a
2620  b
2621  c
2622  c/d
2623
2624 If C<directory> is not a directory, then this command returns
2625 an error.
2626
2627 The returned list is sorted.
2628
2629 See also C<guestfs_find0>.");
2630
2631   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2632    [], (* lvresize tests this *)
2633    "check an ext2/ext3 filesystem",
2634    "\
2635 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2636 filesystem checker on C<device>, noninteractively (C<-p>),
2637 even if the filesystem appears to be clean (C<-f>).
2638
2639 This command is only needed because of C<guestfs_resize2fs>
2640 (q.v.).  Normally you should use C<guestfs_fsck>.");
2641
2642   ("sleep", (RErr, [Int "secs"]), 109, [],
2643    [InitNone, Always, TestRun (
2644       [["sleep"; "1"]])],
2645    "sleep for some seconds",
2646    "\
2647 Sleep for C<secs> seconds.");
2648
2649   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2650    [InitNone, Always, TestOutputInt (
2651       [["part_disk"; "/dev/sda"; "mbr"];
2652        ["mkfs"; "ntfs"; "/dev/sda1"];
2653        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2654     InitNone, Always, TestOutputInt (
2655       [["part_disk"; "/dev/sda"; "mbr"];
2656        ["mkfs"; "ext2"; "/dev/sda1"];
2657        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2658    "probe NTFS volume",
2659    "\
2660 This command runs the L<ntfs-3g.probe(8)> command which probes
2661 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2662 be mounted read-write, and some cannot be mounted at all).
2663
2664 C<rw> is a boolean flag.  Set it to true if you want to test
2665 if the volume can be mounted read-write.  Set it to false if
2666 you want to test if the volume can be mounted read-only.
2667
2668 The return value is an integer which C<0> if the operation
2669 would succeed, or some non-zero value documented in the
2670 L<ntfs-3g.probe(8)> manual page.");
2671
2672   ("sh", (RString "output", [String "command"]), 111, [],
2673    [], (* XXX needs tests *)
2674    "run a command via the shell",
2675    "\
2676 This call runs a command from the guest filesystem via the
2677 guest's C</bin/sh>.
2678
2679 This is like C<guestfs_command>, but passes the command to:
2680
2681  /bin/sh -c \"command\"
2682
2683 Depending on the guest's shell, this usually results in
2684 wildcards being expanded, shell expressions being interpolated
2685 and so on.
2686
2687 All the provisos about C<guestfs_command> apply to this call.");
2688
2689   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2690    [], (* XXX needs tests *)
2691    "run a command via the shell returning lines",
2692    "\
2693 This is the same as C<guestfs_sh>, but splits the result
2694 into a list of lines.
2695
2696 See also: C<guestfs_command_lines>");
2697
2698   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2699    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2700     * code in stubs.c, since all valid glob patterns must start with "/".
2701     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2702     *)
2703    [InitBasicFS, Always, TestOutputList (
2704       [["mkdir_p"; "/a/b/c"];
2705        ["touch"; "/a/b/c/d"];
2706        ["touch"; "/a/b/c/e"];
2707        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2708     InitBasicFS, Always, TestOutputList (
2709       [["mkdir_p"; "/a/b/c"];
2710        ["touch"; "/a/b/c/d"];
2711        ["touch"; "/a/b/c/e"];
2712        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2713     InitBasicFS, Always, TestOutputList (
2714       [["mkdir_p"; "/a/b/c"];
2715        ["touch"; "/a/b/c/d"];
2716        ["touch"; "/a/b/c/e"];
2717        ["glob_expand"; "/a/*/x/*"]], [])],
2718    "expand a wildcard path",
2719    "\
2720 This command searches for all the pathnames matching
2721 C<pattern> according to the wildcard expansion rules
2722 used by the shell.
2723
2724 If no paths match, then this returns an empty list
2725 (note: not an error).
2726
2727 It is just a wrapper around the C L<glob(3)> function
2728 with flags C<GLOB_MARK|GLOB_BRACE>.
2729 See that manual page for more details.");
2730
2731   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2732    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2733       [["scrub_device"; "/dev/sdc"]])],
2734    "scrub (securely wipe) a device",
2735    "\
2736 This command writes patterns over C<device> to make data retrieval
2737 more difficult.
2738
2739 It is an interface to the L<scrub(1)> program.  See that
2740 manual page for more details.");
2741
2742   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2743    [InitBasicFS, Always, TestRun (
2744       [["write_file"; "/file"; "content"; "0"];
2745        ["scrub_file"; "/file"]])],
2746    "scrub (securely wipe) a file",
2747    "\
2748 This command writes patterns over a file to make data retrieval
2749 more difficult.
2750
2751 The file is I<removed> after scrubbing.
2752
2753 It is an interface to the L<scrub(1)> program.  See that
2754 manual page for more details.");
2755
2756   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2757    [], (* XXX needs testing *)
2758    "scrub (securely wipe) free space",
2759    "\
2760 This command creates the directory C<dir> and then fills it
2761 with files until the filesystem is full, and scrubs the files
2762 as for C<guestfs_scrub_file>, and deletes them.
2763 The intention is to scrub any free space on the partition
2764 containing C<dir>.
2765
2766 It is an interface to the L<scrub(1)> program.  See that
2767 manual page for more details.");
2768
2769   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2770    [InitBasicFS, Always, TestRun (
2771       [["mkdir"; "/tmp"];
2772        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2773    "create a temporary directory",
2774    "\
2775 This command creates a temporary directory.  The
2776 C<template> parameter should be a full pathname for the
2777 temporary directory name with the final six characters being
2778 \"XXXXXX\".
2779
2780 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2781 the second one being suitable for Windows filesystems.
2782
2783 The name of the temporary directory that was created
2784 is returned.
2785
2786 The temporary directory is created with mode 0700
2787 and is owned by root.
2788
2789 The caller is responsible for deleting the temporary
2790 directory and its contents after use.
2791
2792 See also: L<mkdtemp(3)>");
2793
2794   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2795    [InitISOFS, Always, TestOutputInt (
2796       [["wc_l"; "/10klines"]], 10000)],
2797    "count lines in a file",
2798    "\
2799 This command counts the lines in a file, using the
2800 C<wc -l> external command.");
2801
2802   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2803    [InitISOFS, Always, TestOutputInt (
2804       [["wc_w"; "/10klines"]], 10000)],
2805    "count words in a file",
2806    "\
2807 This command counts the words in a file, using the
2808 C<wc -w> external command.");
2809
2810   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2811    [InitISOFS, Always, TestOutputInt (
2812       [["wc_c"; "/100kallspaces"]], 102400)],
2813    "count characters in a file",
2814    "\
2815 This command counts the characters in a file, using the
2816 C<wc -c> external command.");
2817
2818   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2819    [InitISOFS, Always, TestOutputList (
2820       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2821    "return first 10 lines of a file",
2822    "\
2823 This command returns up to the first 10 lines of a file as
2824 a list of strings.");
2825
2826   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2827    [InitISOFS, Always, TestOutputList (
2828       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2829     InitISOFS, Always, TestOutputList (
2830       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2831     InitISOFS, Always, TestOutputList (
2832       [["head_n"; "0"; "/10klines"]], [])],
2833    "return first N lines of a file",
2834    "\
2835 If the parameter C<nrlines> is a positive number, this returns the first
2836 C<nrlines> lines of the file C<path>.
2837
2838 If the parameter C<nrlines> is a negative number, this returns lines
2839 from the file C<path>, excluding the last C<nrlines> lines.
2840
2841 If the parameter C<nrlines> is zero, this returns an empty list.");
2842
2843   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2844    [InitISOFS, Always, TestOutputList (
2845       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2846    "return last 10 lines of a file",
2847    "\
2848 This command returns up to the last 10 lines of a file as
2849 a list of strings.");
2850
2851   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2852    [InitISOFS, Always, TestOutputList (
2853       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2854     InitISOFS, Always, TestOutputList (
2855       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2856     InitISOFS, Always, TestOutputList (
2857       [["tail_n"; "0"; "/10klines"]], [])],
2858    "return last N lines of a file",
2859    "\
2860 If the parameter C<nrlines> is a positive number, this returns the last
2861 C<nrlines> lines of the file C<path>.
2862
2863 If the parameter C<nrlines> is a negative number, this returns lines
2864 from the file C<path>, starting with the C<-nrlines>th line.
2865
2866 If the parameter C<nrlines> is zero, this returns an empty list.");
2867
2868   ("df", (RString "output", []), 125, [],
2869    [], (* XXX Tricky to test because it depends on the exact format
2870         * of the 'df' command and other imponderables.
2871         *)
2872    "report file system disk space usage",
2873    "\
2874 This command runs the C<df> command to report disk space used.
2875
2876 This command is mostly useful for interactive sessions.  It
2877 is I<not> intended that you try to parse the output string.
2878 Use C<statvfs> from programs.");
2879
2880   ("df_h", (RString "output", []), 126, [],
2881    [], (* XXX Tricky to test because it depends on the exact format
2882         * of the 'df' command and other imponderables.
2883         *)
2884    "report file system disk space usage (human readable)",
2885    "\
2886 This command runs the C<df -h> command to report disk space used
2887 in human-readable format.
2888
2889 This command is mostly useful for interactive sessions.  It
2890 is I<not> intended that you try to parse the output string.
2891 Use C<statvfs> from programs.");
2892
2893   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2894    [InitISOFS, Always, TestOutputInt (
2895       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2896    "estimate file space usage",
2897    "\
2898 This command runs the C<du -s> command to estimate file space
2899 usage for C<path>.
2900
2901 C<path> can be a file or a directory.  If C<path> is a directory
2902 then the estimate includes the contents of the directory and all
2903 subdirectories (recursively).
2904
2905 The result is the estimated size in I<kilobytes>
2906 (ie. units of 1024 bytes).");
2907
2908   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2909    [InitISOFS, Always, TestOutputList (
2910       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2911    "list files in an initrd",
2912    "\
2913 This command lists out files contained in an initrd.
2914
2915 The files are listed without any initial C</> character.  The
2916 files are listed in the order they appear (not necessarily
2917 alphabetical).  Directory names are listed as separate items.
2918
2919 Old Linux kernels (2.4 and earlier) used a compressed ext2
2920 filesystem as initrd.  We I<only> support the newer initramfs
2921 format (compressed cpio files).");
2922
2923   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2924    [],
2925    "mount a file using the loop device",
2926    "\
2927 This command lets you mount C<file> (a filesystem image
2928 in a file) on a mount point.  It is entirely equivalent to
2929 the command C<mount -o loop file mountpoint>.");
2930
2931   ("mkswap", (RErr, [Device "device"]), 130, [],
2932    [InitEmpty, Always, TestRun (
2933       [["part_disk"; "/dev/sda"; "mbr"];
2934        ["mkswap"; "/dev/sda1"]])],
2935    "create a swap partition",
2936    "\
2937 Create a swap partition on C<device>.");
2938
2939   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2940    [InitEmpty, Always, TestRun (
2941       [["part_disk"; "/dev/sda"; "mbr"];
2942        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2943    "create a swap partition with a label",
2944    "\
2945 Create a swap partition on C<device> with label C<label>.
2946
2947 Note that you cannot attach a swap label to a block device
2948 (eg. C</dev/sda>), just to a partition.  This appears to be
2949 a limitation of the kernel or swap tools.");
2950
2951   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2952    (let uuid = uuidgen () in
2953     [InitEmpty, Always, TestRun (
2954        [["part_disk"; "/dev/sda"; "mbr"];
2955         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2956    "create a swap partition with an explicit UUID",
2957    "\
2958 Create a swap partition on C<device> with UUID C<uuid>.");
2959
2960   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2961    [InitBasicFS, Always, TestOutputStruct (
2962       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2963        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2964        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2965     InitBasicFS, Always, TestOutputStruct (
2966       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2967        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2968    "make block, character or FIFO devices",
2969    "\
2970 This call creates block or character special devices, or
2971 named pipes (FIFOs).
2972
2973 The C<mode> parameter should be the mode, using the standard
2974 constants.  C<devmajor> and C<devminor> are the
2975 device major and minor numbers, only used when creating block
2976 and character special devices.");
2977
2978   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2979    [InitBasicFS, Always, TestOutputStruct (
2980       [["mkfifo"; "0o777"; "/node"];
2981        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2982    "make FIFO (named pipe)",
2983    "\
2984 This call creates a FIFO (named pipe) called C<path> with
2985 mode C<mode>.  It is just a convenient wrapper around
2986 C<guestfs_mknod>.");
2987
2988   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2989    [InitBasicFS, Always, TestOutputStruct (
2990       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2991        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2992    "make block device node",
2993    "\
2994 This call creates a block device node called C<path> with
2995 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2996 It is just a convenient wrapper around C<guestfs_mknod>.");
2997
2998   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2999    [InitBasicFS, Always, TestOutputStruct (
3000       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3001        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3002    "make char device node",
3003    "\
3004 This call creates a char device node called C<path> with
3005 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3006 It is just a convenient wrapper around C<guestfs_mknod>.");
3007
3008   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
3009    [], (* XXX umask is one of those stateful things that we should
3010         * reset between each test.
3011         *)
3012    "set file mode creation mask (umask)",
3013    "\
3014 This function sets the mask used for creating new files and
3015 device nodes to C<mask & 0777>.
3016
3017 Typical umask values would be C<022> which creates new files
3018 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3019 C<002> which creates new files with permissions like
3020 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3021
3022 The default umask is C<022>.  This is important because it
3023 means that directories and device nodes will be created with
3024 C<0644> or C<0755> mode even if you specify C<0777>.
3025
3026 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3027
3028 This call returns the previous umask.");
3029
3030   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3031    [],
3032    "read directories entries",
3033    "\
3034 This returns the list of directory entries in directory C<dir>.
3035
3036 All entries in the directory are returned, including C<.> and
3037 C<..>.  The entries are I<not> sorted, but returned in the same
3038 order as the underlying filesystem.
3039
3040 Also this call returns basic file type information about each
3041 file.  The C<ftyp> field will contain one of the following characters:
3042
3043 =over 4
3044
3045 =item 'b'
3046
3047 Block special
3048
3049 =item 'c'
3050
3051 Char special
3052
3053 =item 'd'
3054
3055 Directory
3056
3057 =item 'f'
3058
3059 FIFO (named pipe)
3060
3061 =item 'l'
3062
3063 Symbolic link
3064
3065 =item 'r'
3066
3067 Regular file
3068
3069 =item 's'
3070
3071 Socket
3072
3073 =item 'u'
3074
3075 Unknown file type
3076
3077 =item '?'
3078
3079 The L<readdir(3)> returned a C<d_type> field with an
3080 unexpected value
3081
3082 =back
3083
3084 This function is primarily intended for use by programs.  To
3085 get a simple list of names, use C<guestfs_ls>.  To get a printable
3086 directory for human consumption, use C<guestfs_ll>.");
3087
3088   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3089    [],
3090    "create partitions on a block device",
3091    "\
3092 This is a simplified interface to the C<guestfs_sfdisk>
3093 command, where partition sizes are specified in megabytes
3094 only (rounded to the nearest cylinder) and you don't need
3095 to specify the cyls, heads and sectors parameters which
3096 were rarely if ever used anyway.
3097
3098 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3099 and C<guestfs_part_disk>");
3100
3101   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3102    [],
3103    "determine file type inside a compressed file",
3104    "\
3105 This command runs C<file> after first decompressing C<path>
3106 using C<method>.
3107
3108 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3109
3110 Since 1.0.63, use C<guestfs_file> instead which can now
3111 process compressed files.");
3112
3113   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3114    [],
3115    "list extended attributes of a file or directory",
3116    "\
3117 This call lists the extended attributes of the file or directory
3118 C<path>.
3119
3120 At the system call level, this is a combination of the
3121 L<listxattr(2)> and L<getxattr(2)> calls.
3122
3123 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3124
3125   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3126    [],
3127    "list extended attributes of a file or directory",
3128    "\
3129 This is the same as C<guestfs_getxattrs>, but if C<path>
3130 is a symbolic link, then it returns the extended attributes
3131 of the link itself.");
3132
3133   ("setxattr", (RErr, [String "xattr";
3134                        String "val"; Int "vallen"; (* will be BufferIn *)
3135                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3136    [],
3137    "set extended attribute of a file or directory",
3138    "\
3139 This call sets the extended attribute named C<xattr>
3140 of the file C<path> to the value C<val> (of length C<vallen>).
3141 The value is arbitrary 8 bit data.
3142
3143 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3144
3145   ("lsetxattr", (RErr, [String "xattr";
3146                         String "val"; Int "vallen"; (* will be BufferIn *)
3147                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3148    [],
3149    "set extended attribute of a file or directory",
3150    "\
3151 This is the same as C<guestfs_setxattr>, but if C<path>
3152 is a symbolic link, then it sets an extended attribute
3153 of the link itself.");
3154
3155   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3156    [],
3157    "remove extended attribute of a file or directory",
3158    "\
3159 This call removes the extended attribute named C<xattr>
3160 of the file C<path>.
3161
3162 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3163
3164   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3165    [],
3166    "remove extended attribute of a file or directory",
3167    "\
3168 This is the same as C<guestfs_removexattr>, but if C<path>
3169 is a symbolic link, then it removes an extended attribute
3170 of the link itself.");
3171
3172   ("mountpoints", (RHashtable "mps", []), 147, [],
3173    [],
3174    "show mountpoints",
3175    "\
3176 This call is similar to C<guestfs_mounts>.  That call returns
3177 a list of devices.  This one returns a hash table (map) of
3178 device name to directory where the device is mounted.");
3179
3180   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3181    (* This is a special case: while you would expect a parameter
3182     * of type "Pathname", that doesn't work, because it implies
3183     * NEED_ROOT in the generated calling code in stubs.c, and
3184     * this function cannot use NEED_ROOT.
3185     *)
3186    [],
3187    "create a mountpoint",
3188    "\
3189 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3190 specialized calls that can be used to create extra mountpoints
3191 before mounting the first filesystem.
3192
3193 These calls are I<only> necessary in some very limited circumstances,
3194 mainly the case where you want to mount a mix of unrelated and/or
3195 read-only filesystems together.
3196
3197 For example, live CDs often contain a \"Russian doll\" nest of
3198 filesystems, an ISO outer layer, with a squashfs image inside, with
3199 an ext2/3 image inside that.  You can unpack this as follows
3200 in guestfish:
3201
3202  add-ro Fedora-11-i686-Live.iso
3203  run
3204  mkmountpoint /cd
3205  mkmountpoint /squash
3206  mkmountpoint /ext3
3207  mount /dev/sda /cd
3208  mount-loop /cd/LiveOS/squashfs.img /squash
3209  mount-loop /squash/LiveOS/ext3fs.img /ext3
3210
3211 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3212
3213   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3214    [],
3215    "remove a mountpoint",
3216    "\
3217 This calls removes a mountpoint that was previously created
3218 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3219 for full details.");
3220
3221   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3222    [InitISOFS, Always, TestOutputBuffer (
3223       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3224    "read a file",
3225    "\
3226 This calls returns the contents of the file C<path> as a
3227 buffer.
3228
3229 Unlike C<guestfs_cat>, this function can correctly
3230 handle files that contain embedded ASCII NUL characters.
3231 However unlike C<guestfs_download>, this function is limited
3232 in the total size of file that can be handled.");
3233
3234   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3235    [InitISOFS, Always, TestOutputList (
3236       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3237     InitISOFS, Always, TestOutputList (
3238       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3239    "return lines matching a pattern",
3240    "\
3241 This calls the external C<grep> program and returns the
3242 matching lines.");
3243
3244   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3245    [InitISOFS, Always, TestOutputList (
3246       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3247    "return lines matching a pattern",
3248    "\
3249 This calls the external C<egrep> program and returns the
3250 matching lines.");
3251
3252   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3253    [InitISOFS, Always, TestOutputList (
3254       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3255    "return lines matching a pattern",
3256    "\
3257 This calls the external C<fgrep> program and returns the
3258 matching lines.");
3259
3260   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3261    [InitISOFS, Always, TestOutputList (
3262       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3263    "return lines matching a pattern",
3264    "\
3265 This calls the external C<grep -i> program and returns the
3266 matching lines.");
3267
3268   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3269    [InitISOFS, Always, TestOutputList (
3270       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3271    "return lines matching a pattern",
3272    "\
3273 This calls the external C<egrep -i> program and returns the
3274 matching lines.");
3275
3276   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3277    [InitISOFS, Always, TestOutputList (
3278       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3279    "return lines matching a pattern",
3280    "\
3281 This calls the external C<fgrep -i> program and returns the
3282 matching lines.");
3283
3284   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3285    [InitISOFS, Always, TestOutputList (
3286       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3287    "return lines matching a pattern",
3288    "\
3289 This calls the external C<zgrep> program and returns the
3290 matching lines.");
3291
3292   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3293    [InitISOFS, Always, TestOutputList (
3294       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3295    "return lines matching a pattern",
3296    "\
3297 This calls the external C<zegrep> program and returns the
3298 matching lines.");
3299
3300   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3301    [InitISOFS, Always, TestOutputList (
3302       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3303    "return lines matching a pattern",
3304    "\
3305 This calls the external C<zfgrep> program and returns the
3306 matching lines.");
3307
3308   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3309    [InitISOFS, Always, TestOutputList (
3310       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3311    "return lines matching a pattern",
3312    "\
3313 This calls the external C<zgrep -i> program and returns the
3314 matching lines.");
3315
3316   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3317    [InitISOFS, Always, TestOutputList (
3318       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3319    "return lines matching a pattern",
3320    "\
3321 This calls the external C<zegrep -i> program and returns the
3322 matching lines.");
3323
3324   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3325    [InitISOFS, Always, TestOutputList (
3326       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3327    "return lines matching a pattern",
3328    "\
3329 This calls the external C<zfgrep -i> program and returns the
3330 matching lines.");
3331
3332   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3333    [InitISOFS, Always, TestOutput (
3334       [["realpath"; "/../directory"]], "/directory")],
3335    "canonicalized absolute pathname",
3336    "\
3337 Return the canonicalized absolute pathname of C<path>.  The
3338 returned path has no C<.>, C<..> or symbolic link path elements.");
3339
3340   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3341    [InitBasicFS, Always, TestOutputStruct (
3342       [["touch"; "/a"];
3343        ["ln"; "/a"; "/b"];
3344        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3345    "create a hard link",
3346    "\
3347 This command creates a hard link using the C<ln> command.");
3348
3349   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3350    [InitBasicFS, Always, TestOutputStruct (
3351       [["touch"; "/a"];
3352        ["touch"; "/b"];
3353        ["ln_f"; "/a"; "/b"];
3354        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3355    "create a hard link",
3356    "\
3357 This command creates a hard link using the C<ln -f> command.
3358 The C<-f> option removes the link (C<linkname>) if it exists already.");
3359
3360   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3361    [InitBasicFS, Always, TestOutputStruct (
3362       [["touch"; "/a"];
3363        ["ln_s"; "a"; "/b"];
3364        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3365    "create a symbolic link",
3366    "\
3367 This command creates a symbolic link using the C<ln -s> command.");
3368
3369   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3370    [InitBasicFS, Always, TestOutput (
3371       [["mkdir_p"; "/a/b"];
3372        ["touch"; "/a/b/c"];
3373        ["ln_sf"; "../d"; "/a/b/c"];
3374        ["readlink"; "/a/b/c"]], "../d")],
3375    "create a symbolic link",
3376    "\
3377 This command creates a symbolic link using the C<ln -sf> command,
3378 The C<-f> option removes the link (C<linkname>) if it exists already.");
3379
3380   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3381    [] (* XXX tested above *),
3382    "read the target of a symbolic link",
3383    "\
3384 This command reads the target of a symbolic link.");
3385
3386   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3387    [InitBasicFS, Always, TestOutputStruct (
3388       [["fallocate"; "/a"; "1000000"];
3389        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3390    "preallocate a file in the guest filesystem",
3391    "\
3392 This command preallocates a file (containing zero bytes) named
3393 C<path> of size C<len> bytes.  If the file exists already, it
3394 is overwritten.
3395
3396 Do not confuse this with the guestfish-specific
3397 C<alloc> command which allocates a file in the host and
3398 attaches it as a device.");
3399
3400   ("swapon_device", (RErr, [Device "device"]), 170, [],
3401    [InitPartition, Always, TestRun (
3402       [["mkswap"; "/dev/sda1"];
3403        ["swapon_device"; "/dev/sda1"];
3404        ["swapoff_device"; "/dev/sda1"]])],
3405    "enable swap on device",
3406    "\
3407 This command enables the libguestfs appliance to use the
3408 swap device or partition named C<device>.  The increased
3409 memory is made available for all commands, for example
3410 those run using C<guestfs_command> or C<guestfs_sh>.
3411
3412 Note that you should not swap to existing guest swap
3413 partitions unless you know what you are doing.  They may
3414 contain hibernation information, or other information that
3415 the guest doesn't want you to trash.  You also risk leaking
3416 information about the host to the guest this way.  Instead,
3417 attach a new host device to the guest and swap on that.");
3418
3419   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3420    [], (* XXX tested by swapon_device *)
3421    "disable swap on device",
3422    "\
3423 This command disables the libguestfs appliance swap
3424 device or partition named C<device>.
3425 See C<guestfs_swapon_device>.");
3426
3427   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3428    [InitBasicFS, Always, TestRun (
3429       [["fallocate"; "/swap"; "8388608"];
3430        ["mkswap_file"; "/swap"];
3431        ["swapon_file"; "/swap"];
3432        ["swapoff_file"; "/swap"]])],
3433    "enable swap on file",
3434    "\
3435 This command enables swap to a file.
3436 See C<guestfs_swapon_device> for other notes.");
3437
3438   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3439    [], (* XXX tested by swapon_file *)
3440    "disable swap on file",
3441    "\
3442 This command disables the libguestfs appliance swap on file.");
3443
3444   ("swapon_label", (RErr, [String "label"]), 174, [],
3445    [InitEmpty, Always, TestRun (
3446       [["part_disk"; "/dev/sdb"; "mbr"];
3447        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3448        ["swapon_label"; "swapit"];
3449        ["swapoff_label"; "swapit"];
3450        ["zero"; "/dev/sdb"];
3451        ["blockdev_rereadpt"; "/dev/sdb"]])],
3452    "enable swap on labeled swap partition",
3453    "\
3454 This command enables swap to a labeled swap partition.
3455 See C<guestfs_swapon_device> for other notes.");
3456
3457   ("swapoff_label", (RErr, [String "label"]), 175, [],
3458    [], (* XXX tested by swapon_label *)
3459    "disable swap on labeled swap partition",
3460    "\
3461 This command disables the libguestfs appliance swap on
3462 labeled swap partition.");
3463
3464   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3465    (let uuid = uuidgen () in
3466     [InitEmpty, Always, TestRun (
3467        [["mkswap_U"; uuid; "/dev/sdb"];
3468         ["swapon_uuid"; uuid];
3469         ["swapoff_uuid"; uuid]])]),
3470    "enable swap on swap partition by UUID",
3471    "\
3472 This command enables swap to a swap partition with the given UUID.
3473 See C<guestfs_swapon_device> for other notes.");
3474
3475   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3476    [], (* XXX tested by swapon_uuid *)
3477    "disable swap on swap partition by UUID",
3478    "\
3479 This command disables the libguestfs appliance swap partition
3480 with the given UUID.");
3481
3482   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3483    [InitBasicFS, Always, TestRun (
3484       [["fallocate"; "/swap"; "8388608"];
3485        ["mkswap_file"; "/swap"]])],
3486    "create a swap file",
3487    "\
3488 Create a swap file.
3489
3490 This command just writes a swap file signature to an existing
3491 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3492
3493   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3494    [InitISOFS, Always, TestRun (
3495       [["inotify_init"; "0"]])],
3496    "create an inotify handle",
3497    "\
3498 This command creates a new inotify handle.
3499 The inotify subsystem can be used to notify events which happen to
3500 objects in the guest filesystem.
3501
3502 C<maxevents> is the maximum number of events which will be
3503 queued up between calls to C<guestfs_inotify_read> or
3504 C<guestfs_inotify_files>.
3505 If this is passed as C<0>, then the kernel (or previously set)
3506 default is used.  For Linux 2.6.29 the default was 16384 events.
3507 Beyond this limit, the kernel throws away events, but records
3508 the fact that it threw them away by setting a flag
3509 C<IN_Q_OVERFLOW> in the returned structure list (see
3510 C<guestfs_inotify_read>).
3511
3512 Before any events are generated, you have to add some
3513 watches to the internal watch list.  See:
3514 C<guestfs_inotify_add_watch>,
3515 C<guestfs_inotify_rm_watch> and
3516 C<guestfs_inotify_watch_all>.
3517
3518 Queued up events should be read periodically by calling
3519 C<guestfs_inotify_read>
3520 (or C<guestfs_inotify_files> which is just a helpful
3521 wrapper around C<guestfs_inotify_read>).  If you don't
3522 read the events out often enough then you risk the internal
3523 queue overflowing.
3524
3525 The handle should be closed after use by calling
3526 C<guestfs_inotify_close>.  This also removes any
3527 watches automatically.
3528
3529 See also L<inotify(7)> for an overview of the inotify interface
3530 as exposed by the Linux kernel, which is roughly what we expose
3531 via libguestfs.  Note that there is one global inotify handle
3532 per libguestfs instance.");
3533
3534   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3535    [InitBasicFS, Always, TestOutputList (
3536       [["inotify_init"; "0"];
3537        ["inotify_add_watch"; "/"; "1073741823"];
3538        ["touch"; "/a"];
3539        ["touch"; "/b"];
3540        ["inotify_files"]], ["a"; "b"])],
3541    "add an inotify watch",
3542    "\
3543 Watch C<path> for the events listed in C<mask>.
3544
3545 Note that if C<path> is a directory then events within that
3546 directory are watched, but this does I<not> happen recursively
3547 (in subdirectories).
3548
3549 Note for non-C or non-Linux callers: the inotify events are
3550 defined by the Linux kernel ABI and are listed in
3551 C</usr/include/sys/inotify.h>.");
3552
3553   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3554    [],
3555    "remove an inotify watch",
3556    "\
3557 Remove a previously defined inotify watch.
3558 See C<guestfs_inotify_add_watch>.");
3559
3560   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3561    [],
3562    "return list of inotify events",
3563    "\
3564 Return the complete queue of events that have happened
3565 since the previous read call.
3566
3567 If no events have happened, this returns an empty list.
3568
3569 I<Note>: In order to make sure that all events have been
3570 read, you must call this function repeatedly until it
3571 returns an empty list.  The reason is that the call will
3572 read events up to the maximum appliance-to-host message
3573 size and leave remaining events in the queue.");
3574
3575   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3576    [],
3577    "return list of watched files that had events",
3578    "\
3579 This function is a helpful wrapper around C<guestfs_inotify_read>
3580 which just returns a list of pathnames of objects that were
3581 touched.  The returned pathnames are sorted and deduplicated.");
3582
3583   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3584    [],
3585    "close the inotify handle",
3586    "\
3587 This closes the inotify handle which was previously
3588 opened by inotify_init.  It removes all watches, throws
3589 away any pending events, and deallocates all resources.");
3590
3591   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3592    [],
3593    "set SELinux security context",
3594    "\
3595 This sets the SELinux security context of the daemon
3596 to the string C<context>.
3597
3598 See the documentation about SELINUX in L<guestfs(3)>.");
3599
3600   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3601    [],
3602    "get SELinux security context",
3603    "\
3604 This gets the SELinux security context of the daemon.
3605
3606 See the documentation about SELINUX in L<guestfs(3)>,
3607 and C<guestfs_setcon>");
3608
3609   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3610    [InitEmpty, Always, TestOutput (
3611       [["part_disk"; "/dev/sda"; "mbr"];
3612        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3613        ["mount_options"; ""; "/dev/sda1"; "/"];
3614        ["write_file"; "/new"; "new file contents"; "0"];
3615        ["cat"; "/new"]], "new file contents")],
3616    "make a filesystem with block size",
3617    "\
3618 This call is similar to C<guestfs_mkfs>, but it allows you to
3619 control the block size of the resulting filesystem.  Supported
3620 block sizes depend on the filesystem type, but typically they
3621 are C<1024>, C<2048> or C<4096> only.");
3622
3623   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3624    [InitEmpty, Always, TestOutput (
3625       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3626        ["mke2journal"; "4096"; "/dev/sda1"];
3627        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3628        ["mount_options"; ""; "/dev/sda2"; "/"];
3629        ["write_file"; "/new"; "new file contents"; "0"];
3630        ["cat"; "/new"]], "new file contents")],
3631    "make ext2/3/4 external journal",
3632    "\
3633 This creates an ext2 external journal on C<device>.  It is equivalent
3634 to the command:
3635
3636  mke2fs -O journal_dev -b blocksize device");
3637
3638   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3639    [InitEmpty, Always, TestOutput (
3640       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3641        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3642        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3643        ["mount_options"; ""; "/dev/sda2"; "/"];
3644        ["write_file"; "/new"; "new file contents"; "0"];
3645        ["cat"; "/new"]], "new file contents")],
3646    "make ext2/3/4 external journal with label",
3647    "\
3648 This creates an ext2 external journal on C<device> with label C<label>.");
3649
3650   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3651    (let uuid = uuidgen () in
3652     [InitEmpty, Always, TestOutput (
3653        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3654         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3655         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3656         ["mount_options"; ""; "/dev/sda2"; "/"];
3657         ["write_file"; "/new"; "new file contents"; "0"];
3658         ["cat"; "/new"]], "new file contents")]),
3659    "make ext2/3/4 external journal with UUID",
3660    "\
3661 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3662
3663   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3664    [],
3665    "make ext2/3/4 filesystem with external journal",
3666    "\
3667 This creates an ext2/3/4 filesystem on C<device> with
3668 an external journal on C<journal>.  It is equivalent
3669 to the command:
3670
3671  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3672
3673 See also C<guestfs_mke2journal>.");
3674
3675   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3676    [],
3677    "make ext2/3/4 filesystem with external journal",
3678    "\
3679 This creates an ext2/3/4 filesystem on C<device> with
3680 an external journal on the journal labeled C<label>.
3681
3682 See also C<guestfs_mke2journal_L>.");
3683
3684   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3685    [],
3686    "make ext2/3/4 filesystem with external journal",
3687    "\
3688 This creates an ext2/3/4 filesystem on C<device> with
3689 an external journal on the journal with UUID C<uuid>.
3690
3691 See also C<guestfs_mke2journal_U>.");
3692
3693   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3694    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3695    "load a kernel module",
3696    "\
3697 This loads a kernel module in the appliance.
3698
3699 The kernel module must have been whitelisted when libguestfs
3700 was built (see C<appliance/kmod.whitelist.in> in the source).");
3701
3702   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3703    [InitNone, Always, TestOutput (
3704       [["echo_daemon"; "This is a test"]], "This is a test"
3705     )],
3706    "echo arguments back to the client",
3707    "\
3708 This command concatenate the list of C<words> passed with single spaces between
3709 them and returns the resulting string.
3710
3711 You can use this command to test the connection through to the daemon.
3712
3713 See also C<guestfs_ping_daemon>.");
3714
3715   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3716    [], (* There is a regression test for this. *)
3717    "find all files and directories, returning NUL-separated list",
3718    "\
3719 This command lists out all files and directories, recursively,
3720 starting at C<directory>, placing the resulting list in the
3721 external file called C<files>.
3722
3723 This command works the same way as C<guestfs_find> with the
3724 following exceptions:
3725
3726 =over 4
3727
3728 =item *
3729
3730 The resulting list is written to an external file.
3731
3732 =item *
3733
3734 Items (filenames) in the result are separated
3735 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3736
3737 =item *
3738
3739 This command is not limited in the number of names that it
3740 can return.
3741
3742 =item *
3743
3744 The result list is not sorted.
3745
3746 =back");
3747
3748   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3749    [InitISOFS, Always, TestOutput (
3750       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3751     InitISOFS, Always, TestOutput (
3752       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3753     InitISOFS, Always, TestOutput (
3754       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3755     InitISOFS, Always, TestLastFail (
3756       [["case_sensitive_path"; "/Known-1/"]]);
3757     InitBasicFS, Always, TestOutput (
3758       [["mkdir"; "/a"];
3759        ["mkdir"; "/a/bbb"];
3760        ["touch"; "/a/bbb/c"];
3761        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3762     InitBasicFS, Always, TestOutput (
3763       [["mkdir"; "/a"];
3764        ["mkdir"; "/a/bbb"];
3765        ["touch"; "/a/bbb/c"];
3766        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3767     InitBasicFS, Always, TestLastFail (
3768       [["mkdir"; "/a"];
3769        ["mkdir"; "/a/bbb"];
3770        ["touch"; "/a/bbb/c"];
3771        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3772    "return true path on case-insensitive filesystem",
3773    "\
3774 This can be used to resolve case insensitive paths on
3775 a filesystem which is case sensitive.  The use case is
3776 to resolve paths which you have read from Windows configuration
3777 files or the Windows Registry, to the true path.
3778
3779 The command handles a peculiarity of the Linux ntfs-3g
3780 filesystem driver (and probably others), which is that although
3781 the underlying filesystem is case-insensitive, the driver
3782 exports the filesystem to Linux as case-sensitive.
3783
3784 One consequence of this is that special directories such
3785 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3786 (or other things) depending on the precise details of how
3787 they were created.  In Windows itself this would not be
3788 a problem.
3789
3790 Bug or feature?  You decide:
3791 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3792
3793 This function resolves the true case of each element in the
3794 path and returns the case-sensitive path.
3795
3796 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3797 might return C<\"/WINDOWS/system32\"> (the exact return value
3798 would depend on details of how the directories were originally
3799 created under Windows).
3800
3801 I<Note>:
3802 This function does not handle drive names, backslashes etc.
3803
3804 See also C<guestfs_realpath>.");
3805
3806   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3807    [InitBasicFS, Always, TestOutput (
3808       [["vfs_type"; "/dev/sda1"]], "ext2")],
3809    "get the Linux VFS type corresponding to a mounted device",
3810    "\
3811 This command gets the block device type corresponding to
3812 a mounted device called C<device>.
3813
3814 Usually the result is the name of the Linux VFS module that
3815 is used to mount this device (probably determined automatically
3816 if you used the C<guestfs_mount> call).");
3817
3818   ("truncate", (RErr, [Pathname "path"]), 199, [],
3819    [InitBasicFS, Always, TestOutputStruct (
3820       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3821        ["truncate"; "/test"];
3822        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3823    "truncate a file to zero size",
3824    "\
3825 This command truncates C<path> to a zero-length file.  The
3826 file must exist already.");
3827
3828   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3829    [InitBasicFS, Always, TestOutputStruct (
3830       [["touch"; "/test"];
3831        ["truncate_size"; "/test"; "1000"];
3832        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3833    "truncate a file to a particular size",
3834    "\
3835 This command truncates C<path> to size C<size> bytes.  The file
3836 must exist already.  If the file is smaller than C<size> then
3837 the file is extended to the required size with null bytes.");
3838
3839   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3840    [InitBasicFS, Always, TestOutputStruct (
3841       [["touch"; "/test"];
3842        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3843        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3844    "set timestamp of a file with nanosecond precision",
3845    "\
3846 This command sets the timestamps of a file with nanosecond
3847 precision.
3848
3849 C<atsecs, atnsecs> are the last access time (atime) in secs and
3850 nanoseconds from the epoch.
3851
3852 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3853 secs and nanoseconds from the epoch.
3854
3855 If the C<*nsecs> field contains the special value C<-1> then
3856 the corresponding timestamp is set to the current time.  (The
3857 C<*secs> field is ignored in this case).
3858
3859 If the C<*nsecs> field contains the special value C<-2> then
3860 the corresponding timestamp is left unchanged.  (The
3861 C<*secs> field is ignored in this case).");
3862
3863   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3864    [InitBasicFS, Always, TestOutputStruct (
3865       [["mkdir_mode"; "/test"; "0o111"];
3866        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3867    "create a directory with a particular mode",
3868    "\
3869 This command creates a directory, setting the initial permissions
3870 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3871
3872   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3873    [], (* XXX *)
3874    "change file owner and group",
3875    "\
3876 Change the file owner to C<owner> and group to C<group>.
3877 This is like C<guestfs_chown> but if C<path> is a symlink then
3878 the link itself is changed, not the target.
3879
3880 Only numeric uid and gid are supported.  If you want to use
3881 names, you will need to locate and parse the password file
3882 yourself (Augeas support makes this relatively easy).");
3883
3884   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3885    [], (* XXX *)
3886    "lstat on multiple files",
3887    "\
3888 This call allows you to perform the C<guestfs_lstat> operation
3889 on multiple files, where all files are in the directory C<path>.
3890 C<names> is the list of files from this directory.
3891
3892 On return you get a list of stat structs, with a one-to-one
3893 correspondence to the C<names> list.  If any name did not exist
3894 or could not be lstat'd, then the C<ino> field of that structure
3895 is set to C<-1>.
3896
3897 This call is intended for programs that want to efficiently
3898 list a directory contents without making many round-trips.
3899 See also C<guestfs_lxattrlist> for a similarly efficient call
3900 for getting extended attributes.  Very long directory listings
3901 might cause the protocol message size to be exceeded, causing
3902 this call to fail.  The caller must split up such requests
3903 into smaller groups of names.");
3904
3905   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3906    [], (* XXX *)
3907    "lgetxattr on multiple files",
3908    "\
3909 This call allows you to get the extended attributes
3910 of multiple files, where all files are in the directory C<path>.
3911 C<names> is the list of files from this directory.
3912
3913 On return you get a flat list of xattr structs which must be
3914 interpreted sequentially.  The first xattr struct always has a zero-length
3915 C<attrname>.  C<attrval> in this struct is zero-length
3916 to indicate there was an error doing C<lgetxattr> for this
3917 file, I<or> is a C string which is a decimal number
3918 (the number of following attributes for this file, which could
3919 be C<\"0\">).  Then after the first xattr struct are the
3920 zero or more attributes for the first named file.
3921 This repeats for the second and subsequent files.
3922
3923 This call is intended for programs that want to efficiently
3924 list a directory contents without making many round-trips.
3925 See also C<guestfs_lstatlist> for a similarly efficient call
3926 for getting standard stats.  Very long directory listings
3927 might cause the protocol message size to be exceeded, causing
3928 this call to fail.  The caller must split up such requests
3929 into smaller groups of names.");
3930
3931   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3932    [], (* XXX *)
3933    "readlink on multiple files",
3934    "\
3935 This call allows you to do a C<readlink> operation
3936 on multiple files, where all files are in the directory C<path>.
3937 C<names> is the list of files from this directory.
3938
3939 On return you get a list of strings, with a one-to-one
3940 correspondence to the C<names> list.  Each string is the
3941 value of the symbol link.
3942
3943 If the C<readlink(2)> operation fails on any name, then
3944 the corresponding result string is the empty string C<\"\">.
3945 However the whole operation is completed even if there
3946 were C<readlink(2)> errors, and so you can call this
3947 function with names where you don't know if they are
3948 symbolic links already (albeit slightly less efficient).
3949
3950 This call is intended for programs that want to efficiently
3951 list a directory contents without making many round-trips.
3952 Very long directory listings might cause the protocol
3953 message size to be exceeded, causing
3954 this call to fail.  The caller must split up such requests
3955 into smaller groups of names.");
3956
3957   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3958    [InitISOFS, Always, TestOutputBuffer (
3959       [["pread"; "/known-4"; "1"; "3"]], "\n");
3960     InitISOFS, Always, TestOutputBuffer (
3961       [["pread"; "/empty"; "0"; "100"]], "")],
3962    "read part of a file",
3963    "\
3964 This command lets you read part of a file.  It reads C<count>
3965 bytes of the file, starting at C<offset>, from file C<path>.
3966
3967 This may read fewer bytes than requested.  For further details
3968 see the L<pread(2)> system call.");
3969
3970   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3971    [InitEmpty, Always, TestRun (
3972       [["part_init"; "/dev/sda"; "gpt"]])],
3973    "create an empty partition table",
3974    "\
3975 This creates an empty partition table on C<device> of one of the
3976 partition types listed below.  Usually C<parttype> should be
3977 either C<msdos> or C<gpt> (for large disks).
3978
3979 Initially there are no partitions.  Following this, you should
3980 call C<guestfs_part_add> for each partition required.
3981
3982 Possible values for C<parttype> are:
3983
3984 =over 4
3985
3986 =item B<efi> | B<gpt>
3987
3988 Intel EFI / GPT partition table.
3989
3990 This is recommended for >= 2 TB partitions that will be accessed
3991 from Linux and Intel-based Mac OS X.  It also has limited backwards
3992 compatibility with the C<mbr> format.
3993
3994 =item B<mbr> | B<msdos>
3995
3996 The standard PC \"Master Boot Record\" (MBR) format used
3997 by MS-DOS and Windows.  This partition type will B<only> work
3998 for device sizes up to 2 TB.  For large disks we recommend
3999 using C<gpt>.
4000
4001 =back
4002
4003 Other partition table types that may work but are not
4004 supported include:
4005
4006 =over 4
4007
4008 =item B<aix>
4009
4010 AIX disk labels.
4011
4012 =item B<amiga> | B<rdb>
4013
4014 Amiga \"Rigid Disk Block\" format.
4015
4016 =item B<bsd>
4017
4018 BSD disk labels.
4019
4020 =item B<dasd>
4021
4022 DASD, used on IBM mainframes.
4023
4024 =item B<dvh>
4025
4026 MIPS/SGI volumes.
4027
4028 =item B<mac>
4029
4030 Old Mac partition format.  Modern Macs use C<gpt>.
4031
4032 =item B<pc98>
4033
4034 NEC PC-98 format, common in Japan apparently.
4035
4036 =item B<sun>
4037
4038 Sun disk labels.
4039
4040 =back");
4041
4042   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4043    [InitEmpty, Always, TestRun (
4044       [["part_init"; "/dev/sda"; "mbr"];
4045        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4046     InitEmpty, Always, TestRun (
4047       [["part_init"; "/dev/sda"; "gpt"];
4048        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4049        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4050     InitEmpty, Always, TestRun (
4051       [["part_init"; "/dev/sda"; "mbr"];
4052        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4053        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4054        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4055        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4056    "add a partition to the device",
4057    "\
4058 This command adds a partition to C<device>.  If there is no partition
4059 table on the device, call C<guestfs_part_init> first.
4060
4061 The C<prlogex> parameter is the type of partition.  Normally you
4062 should pass C<p> or C<primary> here, but MBR partition tables also
4063 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4064 types.
4065
4066 C<startsect> and C<endsect> are the start and end of the partition
4067 in I<sectors>.  C<endsect> may be negative, which means it counts
4068 backwards from the end of the disk (C<-1> is the last sector).
4069
4070 Creating a partition which covers the whole disk is not so easy.
4071 Use C<guestfs_part_disk> to do that.");
4072
4073   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4074    [InitEmpty, Always, TestRun (
4075       [["part_disk"; "/dev/sda"; "mbr"]]);
4076     InitEmpty, Always, TestRun (
4077       [["part_disk"; "/dev/sda"; "gpt"]])],
4078    "partition whole disk with a single primary partition",
4079    "\
4080 This command is simply a combination of C<guestfs_part_init>
4081 followed by C<guestfs_part_add> to create a single primary partition
4082 covering the whole disk.
4083
4084 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4085 but other possible values are described in C<guestfs_part_init>.");
4086
4087   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4088    [InitEmpty, Always, TestRun (
4089       [["part_disk"; "/dev/sda"; "mbr"];
4090        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4091    "make a partition bootable",
4092    "\
4093 This sets the bootable flag on partition numbered C<partnum> on
4094 device C<device>.  Note that partitions are numbered from 1.
4095
4096 The bootable flag is used by some operating systems (notably
4097 Windows) to determine which partition to boot from.  It is by
4098 no means universally recognized.");
4099
4100   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4101    [InitEmpty, Always, TestRun (
4102       [["part_disk"; "/dev/sda"; "gpt"];
4103        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4104    "set partition name",
4105    "\
4106 This sets the partition name on partition numbered C<partnum> on
4107 device C<device>.  Note that partitions are numbered from 1.
4108
4109 The partition name can only be set on certain types of partition
4110 table.  This works on C<gpt> but not on C<mbr> partitions.");
4111
4112   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4113    [], (* XXX Add a regression test for this. *)
4114    "list partitions on a device",
4115    "\
4116 This command parses the partition table on C<device> and
4117 returns the list of partitions found.
4118
4119 The fields in the returned structure are:
4120
4121 =over 4
4122
4123 =item B<part_num>
4124
4125 Partition number, counting from 1.
4126
4127 =item B<part_start>
4128
4129 Start of the partition I<in bytes>.  To get sectors you have to
4130 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4131
4132 =item B<part_end>
4133
4134 End of the partition in bytes.
4135
4136 =item B<part_size>
4137
4138 Size of the partition in bytes.
4139
4140 =back");
4141
4142   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4143    [InitEmpty, Always, TestOutput (
4144       [["part_disk"; "/dev/sda"; "gpt"];
4145        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4146    "get the partition table type",
4147    "\
4148 This command examines the partition table on C<device> and
4149 returns the partition table type (format) being used.
4150
4151 Common return values include: C<msdos> (a DOS/Windows style MBR
4152 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4153 values are possible, although unusual.  See C<guestfs_part_init>
4154 for a full list.");
4155
4156   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4157    [InitBasicFS, Always, TestOutputBuffer (
4158       [["fill"; "0x63"; "10"; "/test"];
4159        ["read_file"; "/test"]], "cccccccccc")],
4160    "fill a file with octets",
4161    "\
4162 This command creates a new file called C<path>.  The initial
4163 content of the file is C<len> octets of C<c>, where C<c>
4164 must be a number in the range C<[0..255]>.
4165
4166 To fill a file with zero bytes (sparsely), it is
4167 much more efficient to use C<guestfs_truncate_size>.");
4168
4169   ("available", (RErr, [StringList "groups"]), 216, [],
4170    [InitNone, Always, TestRun [["available"; ""]]],
4171    "test availability of some parts of the API",
4172    "\
4173 This command is used to check the availability of some
4174 groups of functionality in the appliance, which not all builds of
4175 the libguestfs appliance will be able to provide.
4176
4177 The libguestfs groups, and the functions that those
4178 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4179
4180 The argument C<groups> is a list of group names, eg:
4181 C<[\"inotify\", \"augeas\"]> would check for the availability of
4182 the Linux inotify functions and Augeas (configuration file
4183 editing) functions.
4184
4185 The command returns no error if I<all> requested groups are available.
4186
4187 It fails with an error if one or more of the requested
4188 groups is unavailable in the appliance.
4189
4190 If an unknown group name is included in the
4191 list of groups then an error is always returned.
4192
4193 I<Notes:>
4194
4195 =over 4
4196
4197 =item *
4198
4199 You must call C<guestfs_launch> before calling this function.
4200
4201 The reason is because we don't know what groups are
4202 supported by the appliance/daemon until it is running and can
4203 be queried.
4204
4205 =item *
4206
4207 If a group of functions is available, this does not necessarily
4208 mean that they will work.  You still have to check for errors
4209 when calling individual API functions even if they are
4210 available.
4211
4212 =item *
4213
4214 It is usually the job of distro packagers to build
4215 complete functionality into the libguestfs appliance.
4216 Upstream libguestfs, if built from source with all
4217 requirements satisfied, will support everything.
4218
4219 =item *
4220
4221 This call was added in version C<1.0.80>.  In previous
4222 versions of libguestfs all you could do would be to speculatively
4223 execute a command to find out if the daemon implemented it.
4224 See also C<guestfs_version>.
4225
4226 =back");
4227
4228   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4229    [InitBasicFS, Always, TestOutputBuffer (
4230       [["write_file"; "/src"; "hello, world"; "0"];
4231        ["dd"; "/src"; "/dest"];
4232        ["read_file"; "/dest"]], "hello, world")],
4233    "copy from source to destination using dd",
4234    "\
4235 This command copies from one source device or file C<src>
4236 to another destination device or file C<dest>.  Normally you
4237 would use this to copy to or from a device or partition, for
4238 example to duplicate a filesystem.
4239
4240 If the destination is a device, it must be as large or larger
4241 than the source file or device, otherwise the copy will fail.
4242 This command cannot do partial copies (see C<guestfs_copy_size>).");
4243
4244   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4245    [InitBasicFS, Always, TestOutputInt (
4246       [["write_file"; "/file"; "hello, world"; "0"];
4247        ["filesize"; "/file"]], 12)],
4248    "return the size of the file in bytes",
4249    "\
4250 This command returns the size of C<file> in bytes.
4251
4252 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4253 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4254 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4255
4256   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4257    [InitBasicFSonLVM, Always, TestOutputList (
4258       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4259        ["lvs"]], ["/dev/VG/LV2"])],
4260    "rename an LVM logical volume",
4261    "\
4262 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4263
4264   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4265    [InitBasicFSonLVM, Always, TestOutputList (
4266       [["umount"; "/"];
4267        ["vg_activate"; "false"; "VG"];
4268        ["vgrename"; "VG"; "VG2"];
4269        ["vg_activate"; "true"; "VG2"];
4270        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4271        ["vgs"]], ["VG2"])],
4272    "rename an LVM volume group",
4273    "\
4274 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4275
4276   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4277    [InitISOFS, Always, TestOutputBuffer (
4278       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4279    "list the contents of a single file in an initrd",
4280    "\
4281 This command unpacks the file C<filename> from the initrd file
4282 called C<initrdpath>.  The filename must be given I<without> the
4283 initial C</> character.
4284
4285 For example, in guestfish you could use the following command
4286 to examine the boot script (usually called C</init>)
4287 contained in a Linux initrd or initramfs image:
4288
4289  initrd-cat /boot/initrd-<version>.img init
4290
4291 See also C<guestfs_initrd_list>.");
4292
4293   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4294    [],
4295    "get the UUID of a physical volume",
4296    "\
4297 This command returns the UUID of the LVM PV C<device>.");
4298
4299   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4300    [],
4301    "get the UUID of a volume group",
4302    "\
4303 This command returns the UUID of the LVM VG named C<vgname>.");
4304
4305   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4306    [],
4307    "get the UUID of a logical volume",
4308    "\
4309 This command returns the UUID of the LVM LV C<device>.");
4310
4311   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4312    [],
4313    "get the PV UUIDs containing the volume group",
4314    "\
4315 Given a VG called C<vgname>, this returns the UUIDs of all
4316 the physical volumes that this volume group resides on.
4317
4318 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4319 calls to associate physical volumes and volume groups.
4320
4321 See also C<guestfs_vglvuuids>.");
4322
4323   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4324    [],
4325    "get the LV UUIDs of all LVs in the volume group",
4326    "\
4327 Given a VG called C<vgname>, this returns the UUIDs of all
4328 the logical volumes created in this volume group.
4329
4330 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4331 calls to associate logical volumes and volume groups.
4332
4333 See also C<guestfs_vgpvuuids>.");
4334
4335   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4336    [InitBasicFS, Always, TestOutputBuffer (
4337       [["write_file"; "/src"; "hello, world"; "0"];
4338        ["copy_size"; "/src"; "/dest"; "5"];
4339        ["read_file"; "/dest"]], "hello")],
4340    "copy size bytes from source to destination using dd",
4341    "\
4342 This command copies exactly C<size> bytes from one source device
4343 or file C<src> to another destination device or file C<dest>.
4344
4345 Note this will fail if the source is too short or if the destination
4346 is not large enough.");
4347
4348 ]
4349
4350 let all_functions = non_daemon_functions @ daemon_functions
4351
4352 (* In some places we want the functions to be displayed sorted
4353  * alphabetically, so this is useful:
4354  *)
4355 let all_functions_sorted =
4356   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4357                compare n1 n2) all_functions
4358
4359 (* Field types for structures. *)
4360 type field =
4361   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4362   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4363   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4364   | FUInt32
4365   | FInt32
4366   | FUInt64
4367   | FInt64
4368   | FBytes                      (* Any int measure that counts bytes. *)
4369   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4370   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4371
4372 (* Because we generate extra parsing code for LVM command line tools,
4373  * we have to pull out the LVM columns separately here.
4374  *)
4375 let lvm_pv_cols = [
4376   "pv_name", FString;
4377   "pv_uuid", FUUID;
4378   "pv_fmt", FString;
4379   "pv_size", FBytes;
4380   "dev_size", FBytes;
4381   "pv_free", FBytes;
4382   "pv_used", FBytes;
4383   "pv_attr", FString (* XXX *);
4384   "pv_pe_count", FInt64;
4385   "pv_pe_alloc_count", FInt64;
4386   "pv_tags", FString;
4387   "pe_start", FBytes;
4388   "pv_mda_count", FInt64;
4389   "pv_mda_free", FBytes;
4390   (* Not in Fedora 10:
4391      "pv_mda_size", FBytes;
4392   *)
4393 ]
4394 let lvm_vg_cols = [
4395   "vg_name", FString;
4396   "vg_uuid", FUUID;
4397   "vg_fmt", FString;
4398   "vg_attr", FString (* XXX *);
4399   "vg_size", FBytes;
4400   "vg_free", FBytes;
4401   "vg_sysid", FString;
4402   "vg_extent_size", FBytes;
4403   "vg_extent_count", FInt64;
4404   "vg_free_count", FInt64;
4405   "max_lv", FInt64;
4406   "max_pv", FInt64;
4407   "pv_count", FInt64;
4408   "lv_count", FInt64;
4409   "snap_count", FInt64;
4410   "vg_seqno", FInt64;
4411   "vg_tags", FString;
4412   "vg_mda_count", FInt64;
4413   "vg_mda_free", FBytes;
4414   (* Not in Fedora 10:
4415      "vg_mda_size", FBytes;
4416   *)
4417 ]
4418 let lvm_lv_cols = [
4419   "lv_name", FString;
4420   "lv_uuid", FUUID;
4421   "lv_attr", FString (* XXX *);
4422   "lv_major", FInt64;
4423   "lv_minor", FInt64;
4424   "lv_kernel_major", FInt64;
4425   "lv_kernel_minor", FInt64;
4426   "lv_size", FBytes;
4427   "seg_count", FInt64;
4428   "origin", FString;
4429   "snap_percent", FOptPercent;
4430   "copy_percent", FOptPercent;
4431   "move_pv", FString;
4432   "lv_tags", FString;
4433   "mirror_log", FString;
4434   "modules", FString;
4435 ]
4436
4437 (* Names and fields in all structures (in RStruct and RStructList)
4438  * that we support.
4439  *)
4440 let structs = [
4441   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4442    * not use this struct in any new code.
4443    *)
4444   "int_bool", [
4445     "i", FInt32;                (* for historical compatibility *)
4446     "b", FInt32;                (* for historical compatibility *)
4447   ];
4448
4449   (* LVM PVs, VGs, LVs. *)
4450   "lvm_pv", lvm_pv_cols;
4451   "lvm_vg", lvm_vg_cols;
4452   "lvm_lv", lvm_lv_cols;
4453
4454   (* Column names and types from stat structures.
4455    * NB. Can't use things like 'st_atime' because glibc header files
4456    * define some of these as macros.  Ugh.
4457    *)
4458   "stat", [
4459     "dev", FInt64;
4460     "ino", FInt64;
4461     "mode", FInt64;
4462     "nlink", FInt64;
4463     "uid", FInt64;
4464     "gid", FInt64;
4465     "rdev", FInt64;
4466     "size", FInt64;
4467     "blksize", FInt64;
4468     "blocks", FInt64;
4469     "atime", FInt64;
4470     "mtime", FInt64;
4471     "ctime", FInt64;
4472   ];
4473   "statvfs", [
4474     "bsize", FInt64;
4475     "frsize", FInt64;
4476     "blocks", FInt64;
4477     "bfree", FInt64;
4478     "bavail", FInt64;
4479     "files", FInt64;
4480     "ffree", FInt64;
4481     "favail", FInt64;
4482     "fsid", FInt64;
4483     "flag", FInt64;
4484     "namemax", FInt64;
4485   ];
4486
4487   (* Column names in dirent structure. *)
4488   "dirent", [
4489     "ino", FInt64;
4490     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4491     "ftyp", FChar;
4492     "name", FString;
4493   ];
4494
4495   (* Version numbers. *)
4496   "version", [
4497     "major", FInt64;
4498     "minor", FInt64;
4499     "release", FInt64;
4500     "extra", FString;
4501   ];
4502
4503   (* Extended attribute. *)
4504   "xattr", [
4505     "attrname", FString;
4506     "attrval", FBuffer;
4507   ];
4508
4509   (* Inotify events. *)
4510   "inotify_event", [
4511     "in_wd", FInt64;
4512     "in_mask", FUInt32;
4513     "in_cookie", FUInt32;
4514     "in_name", FString;
4515   ];
4516
4517   (* Partition table entry. *)
4518   "partition", [
4519     "part_num", FInt32;
4520     "part_start", FBytes;
4521     "part_end", FBytes;
4522     "part_size", FBytes;
4523   ];
4524 ] (* end of structs *)
4525
4526 (* Ugh, Java has to be different ..
4527  * These names are also used by the Haskell bindings.
4528  *)
4529 let java_structs = [
4530   "int_bool", "IntBool";
4531   "lvm_pv", "PV";
4532   "lvm_vg", "VG";
4533   "lvm_lv", "LV";
4534   "stat", "Stat";
4535   "statvfs", "StatVFS";
4536   "dirent", "Dirent";
4537   "version", "Version";
4538   "xattr", "XAttr";
4539   "inotify_event", "INotifyEvent";
4540   "partition", "Partition";
4541 ]
4542
4543 (* What structs are actually returned. *)
4544 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4545
4546 (* Returns a list of RStruct/RStructList structs that are returned
4547  * by any function.  Each element of returned list is a pair:
4548  *
4549  * (structname, RStructOnly)
4550  *    == there exists function which returns RStruct (_, structname)
4551  * (structname, RStructListOnly)
4552  *    == there exists function which returns RStructList (_, structname)
4553  * (structname, RStructAndList)
4554  *    == there are functions returning both RStruct (_, structname)
4555  *                                      and RStructList (_, structname)
4556  *)
4557 let rstructs_used_by functions =
4558   (* ||| is a "logical OR" for rstructs_used_t *)
4559   let (|||) a b =
4560     match a, b with
4561     | RStructAndList, _
4562     | _, RStructAndList -> RStructAndList
4563     | RStructOnly, RStructListOnly
4564     | RStructListOnly, RStructOnly -> RStructAndList
4565     | RStructOnly, RStructOnly -> RStructOnly
4566     | RStructListOnly, RStructListOnly -> RStructListOnly
4567   in
4568
4569   let h = Hashtbl.create 13 in
4570
4571   (* if elem->oldv exists, update entry using ||| operator,
4572    * else just add elem->newv to the hash
4573    *)
4574   let update elem newv =
4575     try  let oldv = Hashtbl.find h elem in
4576          Hashtbl.replace h elem (newv ||| oldv)
4577     with Not_found -> Hashtbl.add h elem newv
4578   in
4579
4580   List.iter (
4581     fun (_, style, _, _, _, _, _) ->
4582       match fst style with
4583       | RStruct (_, structname) -> update structname RStructOnly
4584       | RStructList (_, structname) -> update structname RStructListOnly
4585       | _ -> ()
4586   ) functions;
4587
4588   (* return key->values as a list of (key,value) *)
4589   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4590
4591 (* Used for testing language bindings. *)
4592 type callt =
4593   | CallString of string
4594   | CallOptString of string option
4595   | CallStringList of string list
4596   | CallInt of int
4597   | CallInt64 of int64
4598   | CallBool of bool
4599
4600 (* Used to memoize the result of pod2text. *)
4601 let pod2text_memo_filename = "src/.pod2text.data"
4602 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4603   try
4604     let chan = open_in pod2text_memo_filename in
4605     let v = input_value chan in
4606     close_in chan;
4607     v
4608   with
4609     _ -> Hashtbl.create 13
4610 let pod2text_memo_updated () =
4611   let chan = open_out pod2text_memo_filename in
4612   output_value chan pod2text_memo;
4613   close_out chan
4614
4615 (* Useful functions.
4616  * Note we don't want to use any external OCaml libraries which
4617  * makes this a bit harder than it should be.
4618  *)
4619 module StringMap = Map.Make (String)
4620
4621 let failwithf fs = ksprintf failwith fs
4622
4623 let unique = let i = ref 0 in fun () -> incr i; !i
4624
4625 let replace_char s c1 c2 =
4626   let s2 = String.copy s in
4627   let r = ref false in
4628   for i = 0 to String.length s2 - 1 do
4629     if String.unsafe_get s2 i = c1 then (
4630       String.unsafe_set s2 i c2;
4631       r := true
4632     )
4633   done;
4634   if not !r then s else s2
4635
4636 let isspace c =
4637   c = ' '
4638   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4639
4640 let triml ?(test = isspace) str =
4641   let i = ref 0 in
4642   let n = ref (String.length str) in
4643   while !n > 0 && test str.[!i]; do
4644     decr n;
4645     incr i
4646   done;
4647   if !i = 0 then str
4648   else String.sub str !i !n
4649
4650 let trimr ?(test = isspace) str =
4651   let n = ref (String.length str) in
4652   while !n > 0 && test str.[!n-1]; do
4653     decr n
4654   done;
4655   if !n = String.length str then str
4656   else String.sub str 0 !n
4657
4658 let trim ?(test = isspace) str =
4659   trimr ~test (triml ~test str)
4660
4661 let rec find s sub =
4662   let len = String.length s in
4663   let sublen = String.length sub in
4664   let rec loop i =
4665     if i <= len-sublen then (
4666       let rec loop2 j =
4667         if j < sublen then (
4668           if s.[i+j] = sub.[j] then loop2 (j+1)
4669           else -1
4670         ) else
4671           i (* found *)
4672       in
4673       let r = loop2 0 in
4674       if r = -1 then loop (i+1) else r
4675     ) else
4676       -1 (* not found *)
4677   in
4678   loop 0
4679
4680 let rec replace_str s s1 s2 =
4681   let len = String.length s in
4682   let sublen = String.length s1 in
4683   let i = find s s1 in
4684   if i = -1 then s
4685   else (
4686     let s' = String.sub s 0 i in
4687     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4688     s' ^ s2 ^ replace_str s'' s1 s2
4689   )
4690
4691 let rec string_split sep str =
4692   let len = String.length str in
4693   let seplen = String.length sep in
4694   let i = find str sep in
4695   if i = -1 then [str]
4696   else (
4697     let s' = String.sub str 0 i in
4698     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4699     s' :: string_split sep s''
4700   )
4701
4702 let files_equal n1 n2 =
4703   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4704   match Sys.command cmd with
4705   | 0 -> true
4706   | 1 -> false
4707   | i -> failwithf "%s: failed with error code %d" cmd i
4708
4709 let rec filter_map f = function
4710   | [] -> []
4711   | x :: xs ->
4712       match f x with
4713       | Some y -> y :: filter_map f xs
4714       | None -> filter_map f xs
4715
4716 let rec find_map f = function
4717   | [] -> raise Not_found
4718   | x :: xs ->
4719       match f x with
4720       | Some y -> y
4721       | None -> find_map f xs
4722
4723 let iteri f xs =
4724   let rec loop i = function
4725     | [] -> ()
4726     | x :: xs -> f i x; loop (i+1) xs
4727   in
4728   loop 0 xs
4729
4730 let mapi f xs =
4731   let rec loop i = function
4732     | [] -> []
4733     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4734   in
4735   loop 0 xs
4736
4737 let count_chars c str =
4738   let count = ref 0 in
4739   for i = 0 to String.length str - 1 do
4740     if c = String.unsafe_get str i then incr count
4741   done;
4742   !count
4743
4744 let name_of_argt = function
4745   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4746   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4747   | FileIn n | FileOut n -> n
4748
4749 let java_name_of_struct typ =
4750   try List.assoc typ java_structs
4751   with Not_found ->
4752     failwithf
4753       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4754
4755 let cols_of_struct typ =
4756   try List.assoc typ structs
4757   with Not_found ->
4758     failwithf "cols_of_struct: unknown struct %s" typ
4759
4760 let seq_of_test = function
4761   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4762   | TestOutputListOfDevices (s, _)
4763   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4764   | TestOutputTrue s | TestOutputFalse s
4765   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4766   | TestOutputStruct (s, _)
4767   | TestLastFail s -> s
4768
4769 (* Handling for function flags. *)
4770 let protocol_limit_warning =
4771   "Because of the message protocol, there is a transfer limit
4772 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4773
4774 let danger_will_robinson =
4775   "B<This command is dangerous.  Without careful use you
4776 can easily destroy all your data>."
4777
4778 let deprecation_notice flags =
4779   try
4780     let alt =
4781       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4782     let txt =
4783       sprintf "This function is deprecated.
4784 In new code, use the C<%s> call instead.
4785
4786 Deprecated functions will not be removed from the API, but the
4787 fact that they are deprecated indicates that there are problems
4788 with correct use of these functions." alt in
4789     Some txt
4790   with
4791     Not_found -> None
4792
4793 (* Create list of optional groups. *)
4794 let optgroups =
4795   let h = Hashtbl.create 13 in
4796   List.iter (
4797     fun (name, _, _, flags, _, _, _) ->
4798       List.iter (
4799         function
4800         | Optional group ->
4801             let names = try Hashtbl.find h group with Not_found -> [] in
4802             Hashtbl.replace h group (name :: names)
4803         | _ -> ()
4804       ) flags
4805   ) daemon_functions;
4806   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4807   let groups =
4808     List.map (
4809       fun group -> group, List.sort compare (Hashtbl.find h group)
4810     ) groups in
4811   List.sort (fun x y -> compare (fst x) (fst y)) groups
4812
4813 (* Check function names etc. for consistency. *)
4814 let check_functions () =
4815   let contains_uppercase str =
4816     let len = String.length str in
4817     let rec loop i =
4818       if i >= len then false
4819       else (
4820         let c = str.[i] in
4821         if c >= 'A' && c <= 'Z' then true
4822         else loop (i+1)
4823       )
4824     in
4825     loop 0
4826   in
4827
4828   (* Check function names. *)
4829   List.iter (
4830     fun (name, _, _, _, _, _, _) ->
4831       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4832         failwithf "function name %s does not need 'guestfs' prefix" name;
4833       if name = "" then
4834         failwithf "function name is empty";
4835       if name.[0] < 'a' || name.[0] > 'z' then
4836         failwithf "function name %s must start with lowercase a-z" name;
4837       if String.contains name '-' then
4838         failwithf "function name %s should not contain '-', use '_' instead."
4839           name
4840   ) all_functions;
4841
4842   (* Check function parameter/return names. *)
4843   List.iter (
4844     fun (name, style, _, _, _, _, _) ->
4845       let check_arg_ret_name n =
4846         if contains_uppercase n then
4847           failwithf "%s param/ret %s should not contain uppercase chars"
4848             name n;
4849         if String.contains n '-' || String.contains n '_' then
4850           failwithf "%s param/ret %s should not contain '-' or '_'"
4851             name n;
4852         if n = "value" then
4853           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;
4854         if n = "int" || n = "char" || n = "short" || n = "long" then
4855           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4856         if n = "i" || n = "n" then
4857           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4858         if n = "argv" || n = "args" then
4859           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4860
4861         (* List Haskell, OCaml and C keywords here.
4862          * http://www.haskell.org/haskellwiki/Keywords
4863          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4864          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4865          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4866          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4867          * Omitting _-containing words, since they're handled above.
4868          * Omitting the OCaml reserved word, "val", is ok,
4869          * and saves us from renaming several parameters.
4870          *)
4871         let reserved = [
4872           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4873           "char"; "class"; "const"; "constraint"; "continue"; "data";
4874           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4875           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4876           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4877           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4878           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4879           "interface";
4880           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4881           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4882           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4883           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4884           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4885           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4886           "volatile"; "when"; "where"; "while";
4887           ] in
4888         if List.mem n reserved then
4889           failwithf "%s has param/ret using reserved word %s" name n;
4890       in
4891
4892       (match fst style with
4893        | RErr -> ()
4894        | RInt n | RInt64 n | RBool n
4895        | RConstString n | RConstOptString n | RString n
4896        | RStringList n | RStruct (n, _) | RStructList (n, _)
4897        | RHashtable n | RBufferOut n ->
4898            check_arg_ret_name n
4899       );
4900       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4901   ) all_functions;
4902
4903   (* Check short descriptions. *)
4904   List.iter (
4905     fun (name, _, _, _, _, shortdesc, _) ->
4906       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4907         failwithf "short description of %s should begin with lowercase." name;
4908       let c = shortdesc.[String.length shortdesc-1] in
4909       if c = '\n' || c = '.' then
4910         failwithf "short description of %s should not end with . or \\n." name
4911   ) all_functions;
4912
4913   (* Check long dscriptions. *)
4914   List.iter (
4915     fun (name, _, _, _, _, _, longdesc) ->
4916       if longdesc.[String.length longdesc-1] = '\n' then
4917         failwithf "long description of %s should not end with \\n." name
4918   ) all_functions;
4919
4920   (* Check proc_nrs. *)
4921   List.iter (
4922     fun (name, _, proc_nr, _, _, _, _) ->
4923       if proc_nr <= 0 then
4924         failwithf "daemon function %s should have proc_nr > 0" name
4925   ) daemon_functions;
4926
4927   List.iter (
4928     fun (name, _, proc_nr, _, _, _, _) ->
4929       if proc_nr <> -1 then
4930         failwithf "non-daemon function %s should have proc_nr -1" name
4931   ) non_daemon_functions;
4932
4933   let proc_nrs =
4934     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4935       daemon_functions in
4936   let proc_nrs =
4937     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4938   let rec loop = function
4939     | [] -> ()
4940     | [_] -> ()
4941     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4942         loop rest
4943     | (name1,nr1) :: (name2,nr2) :: _ ->
4944         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4945           name1 name2 nr1 nr2
4946   in
4947   loop proc_nrs;
4948
4949   (* Check tests. *)
4950   List.iter (
4951     function
4952       (* Ignore functions that have no tests.  We generate a
4953        * warning when the user does 'make check' instead.
4954        *)
4955     | name, _, _, _, [], _, _ -> ()
4956     | name, _, _, _, tests, _, _ ->
4957         let funcs =
4958           List.map (
4959             fun (_, _, test) ->
4960               match seq_of_test test with
4961               | [] ->
4962                   failwithf "%s has a test containing an empty sequence" name
4963               | cmds -> List.map List.hd cmds
4964           ) tests in
4965         let funcs = List.flatten funcs in
4966
4967         let tested = List.mem name funcs in
4968
4969         if not tested then
4970           failwithf "function %s has tests but does not test itself" name
4971   ) all_functions
4972
4973 (* 'pr' prints to the current output file. *)
4974 let chan = ref Pervasives.stdout
4975 let lines = ref 0
4976 let pr fs =
4977   ksprintf
4978     (fun str ->
4979        let i = count_chars '\n' str in
4980        lines := !lines + i;
4981        output_string !chan str
4982     ) fs
4983
4984 let copyright_years =
4985   let this_year = 1900 + (localtime (time ())).tm_year in
4986   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4987
4988 (* Generate a header block in a number of standard styles. *)
4989 type comment_style =
4990     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4991 type license = GPLv2plus | LGPLv2plus
4992
4993 let generate_header ?(extra_inputs = []) comment license =
4994   let inputs = "src/generator.ml" :: extra_inputs in
4995   let c = match comment with
4996     | CStyle ->         pr "/* "; " *"
4997     | CPlusPlusStyle -> pr "// "; "//"
4998     | HashStyle ->      pr "# ";  "#"
4999     | OCamlStyle ->     pr "(* "; " *"
5000     | HaskellStyle ->   pr "{- "; "  " in
5001   pr "libguestfs generated file\n";
5002   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5003   List.iter (pr "%s   %s\n" c) inputs;
5004   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5005   pr "%s\n" c;
5006   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5007   pr "%s\n" c;
5008   (match license with
5009    | GPLv2plus ->
5010        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5011        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5012        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5013        pr "%s (at your option) any later version.\n" c;
5014        pr "%s\n" c;
5015        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5016        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5017        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5018        pr "%s GNU General Public License for more details.\n" c;
5019        pr "%s\n" c;
5020        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5021        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5022        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5023
5024    | LGPLv2plus ->
5025        pr "%s This library is free software; you can redistribute it and/or\n" c;
5026        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5027        pr "%s License as published by the Free Software Foundation; either\n" c;
5028        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5029        pr "%s\n" c;
5030        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5031        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5032        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5033        pr "%s Lesser General Public License for more details.\n" c;
5034        pr "%s\n" c;
5035        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5036        pr "%s License along with this library; if not, write to the Free Software\n" c;
5037        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5038   );
5039   (match comment with
5040    | CStyle -> pr " */\n"
5041    | CPlusPlusStyle
5042    | HashStyle -> ()
5043    | OCamlStyle -> pr " *)\n"
5044    | HaskellStyle -> pr "-}\n"
5045   );
5046   pr "\n"
5047
5048 (* Start of main code generation functions below this line. *)
5049
5050 (* Generate the pod documentation for the C API. *)
5051 let rec generate_actions_pod () =
5052   List.iter (
5053     fun (shortname, style, _, flags, _, _, longdesc) ->
5054       if not (List.mem NotInDocs flags) then (
5055         let name = "guestfs_" ^ shortname in
5056         pr "=head2 %s\n\n" name;
5057         pr " ";
5058         generate_prototype ~extern:false ~handle:"handle" name style;
5059         pr "\n\n";
5060         pr "%s\n\n" longdesc;
5061         (match fst style with
5062          | RErr ->
5063              pr "This function returns 0 on success or -1 on error.\n\n"
5064          | RInt _ ->
5065              pr "On error this function returns -1.\n\n"
5066          | RInt64 _ ->
5067              pr "On error this function returns -1.\n\n"
5068          | RBool _ ->
5069              pr "This function returns a C truth value on success or -1 on error.\n\n"
5070          | RConstString _ ->
5071              pr "This function returns a string, or NULL on error.
5072 The string is owned by the guest handle and must I<not> be freed.\n\n"
5073          | RConstOptString _ ->
5074              pr "This function returns a string which may be NULL.
5075 There is way to return an error from this function.
5076 The string is owned by the guest handle and must I<not> be freed.\n\n"
5077          | RString _ ->
5078              pr "This function returns a string, or NULL on error.
5079 I<The caller must free the returned string after use>.\n\n"
5080          | RStringList _ ->
5081              pr "This function returns a NULL-terminated array of strings
5082 (like L<environ(3)>), or NULL if there was an error.
5083 I<The caller must free the strings and the array after use>.\n\n"
5084          | RStruct (_, typ) ->
5085              pr "This function returns a C<struct guestfs_%s *>,
5086 or NULL if there was an error.
5087 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5088          | RStructList (_, typ) ->
5089              pr "This function returns a C<struct guestfs_%s_list *>
5090 (see E<lt>guestfs-structs.hE<gt>),
5091 or NULL if there was an error.
5092 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5093          | RHashtable _ ->
5094              pr "This function returns a NULL-terminated array of
5095 strings, or NULL if there was an error.
5096 The array of strings will always have length C<2n+1>, where
5097 C<n> keys and values alternate, followed by the trailing NULL entry.
5098 I<The caller must free the strings and the array after use>.\n\n"
5099          | RBufferOut _ ->
5100              pr "This function returns a buffer, or NULL on error.
5101 The size of the returned buffer is written to C<*size_r>.
5102 I<The caller must free the returned buffer after use>.\n\n"
5103         );
5104         if List.mem ProtocolLimitWarning flags then
5105           pr "%s\n\n" protocol_limit_warning;
5106         if List.mem DangerWillRobinson flags then
5107           pr "%s\n\n" danger_will_robinson;
5108         match deprecation_notice flags with
5109         | None -> ()
5110         | Some txt -> pr "%s\n\n" txt
5111       )
5112   ) all_functions_sorted
5113
5114 and generate_structs_pod () =
5115   (* Structs documentation. *)
5116   List.iter (
5117     fun (typ, cols) ->
5118       pr "=head2 guestfs_%s\n" typ;
5119       pr "\n";
5120       pr " struct guestfs_%s {\n" typ;
5121       List.iter (
5122         function
5123         | name, FChar -> pr "   char %s;\n" name
5124         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5125         | name, FInt32 -> pr "   int32_t %s;\n" name
5126         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5127         | name, FInt64 -> pr "   int64_t %s;\n" name
5128         | name, FString -> pr "   char *%s;\n" name
5129         | name, FBuffer ->
5130             pr "   /* The next two fields describe a byte array. */\n";
5131             pr "   uint32_t %s_len;\n" name;
5132             pr "   char *%s;\n" name
5133         | name, FUUID ->
5134             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5135             pr "   char %s[32];\n" name
5136         | name, FOptPercent ->
5137             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5138             pr "   float %s;\n" name
5139       ) cols;
5140       pr " };\n";
5141       pr " \n";
5142       pr " struct guestfs_%s_list {\n" typ;
5143       pr "   uint32_t len; /* Number of elements in list. */\n";
5144       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5145       pr " };\n";
5146       pr " \n";
5147       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5148       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5149         typ typ;
5150       pr "\n"
5151   ) structs
5152
5153 and generate_availability_pod () =
5154   (* Availability documentation. *)
5155   pr "=over 4\n";
5156   pr "\n";
5157   List.iter (
5158     fun (group, functions) ->
5159       pr "=item B<%s>\n" group;
5160       pr "\n";
5161       pr "The following functions:\n";
5162       List.iter (pr "L</guestfs_%s>\n") functions;
5163       pr "\n"
5164   ) optgroups;
5165   pr "=back\n";
5166   pr "\n"
5167
5168 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5169  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5170  *
5171  * We have to use an underscore instead of a dash because otherwise
5172  * rpcgen generates incorrect code.
5173  *
5174  * This header is NOT exported to clients, but see also generate_structs_h.
5175  *)
5176 and generate_xdr () =
5177   generate_header CStyle LGPLv2plus;
5178
5179   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5180   pr "typedef string str<>;\n";
5181   pr "\n";
5182
5183   (* Internal structures. *)
5184   List.iter (
5185     function
5186     | typ, cols ->
5187         pr "struct guestfs_int_%s {\n" typ;
5188         List.iter (function
5189                    | name, FChar -> pr "  char %s;\n" name
5190                    | name, FString -> pr "  string %s<>;\n" name
5191                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5192                    | name, FUUID -> pr "  opaque %s[32];\n" name
5193                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5194                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5195                    | name, FOptPercent -> pr "  float %s;\n" name
5196                   ) cols;
5197         pr "};\n";
5198         pr "\n";
5199         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5200         pr "\n";
5201   ) structs;
5202
5203   List.iter (
5204     fun (shortname, style, _, _, _, _, _) ->
5205       let name = "guestfs_" ^ shortname in
5206
5207       (match snd style with
5208        | [] -> ()
5209        | args ->
5210            pr "struct %s_args {\n" name;
5211            List.iter (
5212              function
5213              | Pathname n | Device n | Dev_or_Path n | String n ->
5214                  pr "  string %s<>;\n" n
5215              | OptString n -> pr "  str *%s;\n" n
5216              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5217              | Bool n -> pr "  bool %s;\n" n
5218              | Int n -> pr "  int %s;\n" n
5219              | Int64 n -> pr "  hyper %s;\n" n
5220              | FileIn _ | FileOut _ -> ()
5221            ) args;
5222            pr "};\n\n"
5223       );
5224       (match fst style with
5225        | RErr -> ()
5226        | RInt n ->
5227            pr "struct %s_ret {\n" name;
5228            pr "  int %s;\n" n;
5229            pr "};\n\n"
5230        | RInt64 n ->
5231            pr "struct %s_ret {\n" name;
5232            pr "  hyper %s;\n" n;
5233            pr "};\n\n"
5234        | RBool n ->
5235            pr "struct %s_ret {\n" name;
5236            pr "  bool %s;\n" n;
5237            pr "};\n\n"
5238        | RConstString _ | RConstOptString _ ->
5239            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5240        | RString n ->
5241            pr "struct %s_ret {\n" name;
5242            pr "  string %s<>;\n" n;
5243            pr "};\n\n"
5244        | RStringList n ->
5245            pr "struct %s_ret {\n" name;
5246            pr "  str %s<>;\n" n;
5247            pr "};\n\n"
5248        | RStruct (n, typ) ->
5249            pr "struct %s_ret {\n" name;
5250            pr "  guestfs_int_%s %s;\n" typ n;
5251            pr "};\n\n"
5252        | RStructList (n, typ) ->
5253            pr "struct %s_ret {\n" name;
5254            pr "  guestfs_int_%s_list %s;\n" typ n;
5255            pr "};\n\n"
5256        | RHashtable n ->
5257            pr "struct %s_ret {\n" name;
5258            pr "  str %s<>;\n" n;
5259            pr "};\n\n"
5260        | RBufferOut n ->
5261            pr "struct %s_ret {\n" name;
5262            pr "  opaque %s<>;\n" n;
5263            pr "};\n\n"
5264       );
5265   ) daemon_functions;
5266
5267   (* Table of procedure numbers. *)
5268   pr "enum guestfs_procedure {\n";
5269   List.iter (
5270     fun (shortname, _, proc_nr, _, _, _, _) ->
5271       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5272   ) daemon_functions;
5273   pr "  GUESTFS_PROC_NR_PROCS\n";
5274   pr "};\n";
5275   pr "\n";
5276
5277   (* Having to choose a maximum message size is annoying for several
5278    * reasons (it limits what we can do in the API), but it (a) makes
5279    * the protocol a lot simpler, and (b) provides a bound on the size
5280    * of the daemon which operates in limited memory space.
5281    *)
5282   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5283   pr "\n";
5284
5285   (* Message header, etc. *)
5286   pr "\
5287 /* The communication protocol is now documented in the guestfs(3)
5288  * manpage.
5289  */
5290
5291 const GUESTFS_PROGRAM = 0x2000F5F5;
5292 const GUESTFS_PROTOCOL_VERSION = 1;
5293
5294 /* These constants must be larger than any possible message length. */
5295 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5296 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5297
5298 enum guestfs_message_direction {
5299   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5300   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5301 };
5302
5303 enum guestfs_message_status {
5304   GUESTFS_STATUS_OK = 0,
5305   GUESTFS_STATUS_ERROR = 1
5306 };
5307
5308 const GUESTFS_ERROR_LEN = 256;
5309
5310 struct guestfs_message_error {
5311   string error_message<GUESTFS_ERROR_LEN>;
5312 };
5313
5314 struct guestfs_message_header {
5315   unsigned prog;                     /* GUESTFS_PROGRAM */
5316   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5317   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5318   guestfs_message_direction direction;
5319   unsigned serial;                   /* message serial number */
5320   guestfs_message_status status;
5321 };
5322
5323 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5324
5325 struct guestfs_chunk {
5326   int cancel;                        /* if non-zero, transfer is cancelled */
5327   /* data size is 0 bytes if the transfer has finished successfully */
5328   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5329 };
5330 "
5331
5332 (* Generate the guestfs-structs.h file. *)
5333 and generate_structs_h () =
5334   generate_header CStyle LGPLv2plus;
5335
5336   (* This is a public exported header file containing various
5337    * structures.  The structures are carefully written to have
5338    * exactly the same in-memory format as the XDR structures that
5339    * we use on the wire to the daemon.  The reason for creating
5340    * copies of these structures here is just so we don't have to
5341    * export the whole of guestfs_protocol.h (which includes much
5342    * unrelated and XDR-dependent stuff that we don't want to be
5343    * public, or required by clients).
5344    *
5345    * To reiterate, we will pass these structures to and from the
5346    * client with a simple assignment or memcpy, so the format
5347    * must be identical to what rpcgen / the RFC defines.
5348    *)
5349
5350   (* Public structures. *)
5351   List.iter (
5352     fun (typ, cols) ->
5353       pr "struct guestfs_%s {\n" typ;
5354       List.iter (
5355         function
5356         | name, FChar -> pr "  char %s;\n" name
5357         | name, FString -> pr "  char *%s;\n" name
5358         | name, FBuffer ->
5359             pr "  uint32_t %s_len;\n" name;
5360             pr "  char *%s;\n" name
5361         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5362         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5363         | name, FInt32 -> pr "  int32_t %s;\n" name
5364         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5365         | name, FInt64 -> pr "  int64_t %s;\n" name
5366         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5367       ) cols;
5368       pr "};\n";
5369       pr "\n";
5370       pr "struct guestfs_%s_list {\n" typ;
5371       pr "  uint32_t len;\n";
5372       pr "  struct guestfs_%s *val;\n" typ;
5373       pr "};\n";
5374       pr "\n";
5375       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5376       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5377       pr "\n"
5378   ) structs
5379
5380 (* Generate the guestfs-actions.h file. *)
5381 and generate_actions_h () =
5382   generate_header CStyle LGPLv2plus;
5383   List.iter (
5384     fun (shortname, style, _, _, _, _, _) ->
5385       let name = "guestfs_" ^ shortname in
5386       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5387         name style
5388   ) all_functions
5389
5390 (* Generate the guestfs-internal-actions.h file. *)
5391 and generate_internal_actions_h () =
5392   generate_header CStyle LGPLv2plus;
5393   List.iter (
5394     fun (shortname, style, _, _, _, _, _) ->
5395       let name = "guestfs__" ^ shortname in
5396       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5397         name style
5398   ) non_daemon_functions
5399
5400 (* Generate the client-side dispatch stubs. *)
5401 and generate_client_actions () =
5402   generate_header CStyle LGPLv2plus;
5403
5404   pr "\
5405 #include <stdio.h>
5406 #include <stdlib.h>
5407 #include <stdint.h>
5408 #include <string.h>
5409 #include <inttypes.h>
5410
5411 #include \"guestfs.h\"
5412 #include \"guestfs-internal.h\"
5413 #include \"guestfs-internal-actions.h\"
5414 #include \"guestfs_protocol.h\"
5415
5416 #define error guestfs_error
5417 //#define perrorf guestfs_perrorf
5418 #define safe_malloc guestfs_safe_malloc
5419 #define safe_realloc guestfs_safe_realloc
5420 //#define safe_strdup guestfs_safe_strdup
5421 #define safe_memdup guestfs_safe_memdup
5422
5423 /* Check the return message from a call for validity. */
5424 static int
5425 check_reply_header (guestfs_h *g,
5426                     const struct guestfs_message_header *hdr,
5427                     unsigned int proc_nr, unsigned int serial)
5428 {
5429   if (hdr->prog != GUESTFS_PROGRAM) {
5430     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5431     return -1;
5432   }
5433   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5434     error (g, \"wrong protocol version (%%d/%%d)\",
5435            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5436     return -1;
5437   }
5438   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5439     error (g, \"unexpected message direction (%%d/%%d)\",
5440            hdr->direction, GUESTFS_DIRECTION_REPLY);
5441     return -1;
5442   }
5443   if (hdr->proc != proc_nr) {
5444     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5445     return -1;
5446   }
5447   if (hdr->serial != serial) {
5448     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5449     return -1;
5450   }
5451
5452   return 0;
5453 }
5454
5455 /* Check we are in the right state to run a high-level action. */
5456 static int
5457 check_state (guestfs_h *g, const char *caller)
5458 {
5459   if (!guestfs__is_ready (g)) {
5460     if (guestfs__is_config (g) || guestfs__is_launching (g))
5461       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5462         caller);
5463     else
5464       error (g, \"%%s called from the wrong state, %%d != READY\",
5465         caller, guestfs__get_state (g));
5466     return -1;
5467   }
5468   return 0;
5469 }
5470
5471 ";
5472
5473   (* Generate code to generate guestfish call traces. *)
5474   let trace_call shortname style =
5475     pr "  if (guestfs__get_trace (g)) {\n";
5476
5477     let needs_i =
5478       List.exists (function
5479                    | StringList _ | DeviceList _ -> true
5480                    | _ -> false) (snd style) in
5481     if needs_i then (
5482       pr "    int i;\n";
5483       pr "\n"
5484     );
5485
5486     pr "    printf (\"%s\");\n" shortname;
5487     List.iter (
5488       function
5489       | String n                        (* strings *)
5490       | Device n
5491       | Pathname n
5492       | Dev_or_Path n
5493       | FileIn n
5494       | FileOut n ->
5495           (* guestfish doesn't support string escaping, so neither do we *)
5496           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5497       | OptString n ->                  (* string option *)
5498           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5499           pr "    else printf (\" null\");\n"
5500       | StringList n
5501       | DeviceList n ->                 (* string list *)
5502           pr "    putchar (' ');\n";
5503           pr "    putchar ('\"');\n";
5504           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5505           pr "      if (i > 0) putchar (' ');\n";
5506           pr "      fputs (%s[i], stdout);\n" n;
5507           pr "    }\n";
5508           pr "    putchar ('\"');\n";
5509       | Bool n ->                       (* boolean *)
5510           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5511       | Int n ->                        (* int *)
5512           pr "    printf (\" %%d\", %s);\n" n
5513       | Int64 n ->
5514           pr "    printf (\" %%\" PRIi64, %s);\n" n
5515     ) (snd style);
5516     pr "    putchar ('\\n');\n";
5517     pr "  }\n";
5518     pr "\n";
5519   in
5520
5521   (* For non-daemon functions, generate a wrapper around each function. *)
5522   List.iter (
5523     fun (shortname, style, _, _, _, _, _) ->
5524       let name = "guestfs_" ^ shortname in
5525
5526       generate_prototype ~extern:false ~semicolon:false ~newline:true
5527         ~handle:"g" name style;
5528       pr "{\n";
5529       trace_call shortname style;
5530       pr "  return guestfs__%s " shortname;
5531       generate_c_call_args ~handle:"g" style;
5532       pr ";\n";
5533       pr "}\n";
5534       pr "\n"
5535   ) non_daemon_functions;
5536
5537   (* Client-side stubs for each function. *)
5538   List.iter (
5539     fun (shortname, style, _, _, _, _, _) ->
5540       let name = "guestfs_" ^ shortname in
5541
5542       (* Generate the action stub. *)
5543       generate_prototype ~extern:false ~semicolon:false ~newline:true
5544         ~handle:"g" name style;
5545
5546       let error_code =
5547         match fst style with
5548         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5549         | RConstString _ | RConstOptString _ ->
5550             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5551         | RString _ | RStringList _
5552         | RStruct _ | RStructList _
5553         | RHashtable _ | RBufferOut _ ->
5554             "NULL" in
5555
5556       pr "{\n";
5557
5558       (match snd style with
5559        | [] -> ()
5560        | _ -> pr "  struct %s_args args;\n" name
5561       );
5562
5563       pr "  guestfs_message_header hdr;\n";
5564       pr "  guestfs_message_error err;\n";
5565       let has_ret =
5566         match fst style with
5567         | RErr -> false
5568         | RConstString _ | RConstOptString _ ->
5569             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5570         | RInt _ | RInt64 _
5571         | RBool _ | RString _ | RStringList _
5572         | RStruct _ | RStructList _
5573         | RHashtable _ | RBufferOut _ ->
5574             pr "  struct %s_ret ret;\n" name;
5575             true in
5576
5577       pr "  int serial;\n";
5578       pr "  int r;\n";
5579       pr "\n";
5580       trace_call shortname style;
5581       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5582       pr "  guestfs___set_busy (g);\n";
5583       pr "\n";
5584
5585       (* Send the main header and arguments. *)
5586       (match snd style with
5587        | [] ->
5588            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5589              (String.uppercase shortname)
5590        | args ->
5591            List.iter (
5592              function
5593              | Pathname n | Device n | Dev_or_Path n | String n ->
5594                  pr "  args.%s = (char *) %s;\n" n n
5595              | OptString n ->
5596                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5597              | StringList n | DeviceList n ->
5598                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5599                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5600              | Bool n ->
5601                  pr "  args.%s = %s;\n" n n
5602              | Int n ->
5603                  pr "  args.%s = %s;\n" n n
5604              | Int64 n ->
5605                  pr "  args.%s = %s;\n" n n
5606              | FileIn _ | FileOut _ -> ()
5607            ) args;
5608            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5609              (String.uppercase shortname);
5610            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5611              name;
5612       );
5613       pr "  if (serial == -1) {\n";
5614       pr "    guestfs___end_busy (g);\n";
5615       pr "    return %s;\n" error_code;
5616       pr "  }\n";
5617       pr "\n";
5618
5619       (* Send any additional files (FileIn) requested. *)
5620       let need_read_reply_label = ref false in
5621       List.iter (
5622         function
5623         | FileIn n ->
5624             pr "  r = guestfs___send_file (g, %s);\n" n;
5625             pr "  if (r == -1) {\n";
5626             pr "    guestfs___end_busy (g);\n";
5627             pr "    return %s;\n" error_code;
5628             pr "  }\n";
5629             pr "  if (r == -2) /* daemon cancelled */\n";
5630             pr "    goto read_reply;\n";
5631             need_read_reply_label := true;
5632             pr "\n";
5633         | _ -> ()
5634       ) (snd style);
5635
5636       (* Wait for the reply from the remote end. *)
5637       if !need_read_reply_label then pr " read_reply:\n";
5638       pr "  memset (&hdr, 0, sizeof hdr);\n";
5639       pr "  memset (&err, 0, sizeof err);\n";
5640       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5641       pr "\n";
5642       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5643       if not has_ret then
5644         pr "NULL, NULL"
5645       else
5646         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5647       pr ");\n";
5648
5649       pr "  if (r == -1) {\n";
5650       pr "    guestfs___end_busy (g);\n";
5651       pr "    return %s;\n" error_code;
5652       pr "  }\n";
5653       pr "\n";
5654
5655       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5656         (String.uppercase shortname);
5657       pr "    guestfs___end_busy (g);\n";
5658       pr "    return %s;\n" error_code;
5659       pr "  }\n";
5660       pr "\n";
5661
5662       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5663       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5664       pr "    free (err.error_message);\n";
5665       pr "    guestfs___end_busy (g);\n";
5666       pr "    return %s;\n" error_code;
5667       pr "  }\n";
5668       pr "\n";
5669
5670       (* Expecting to receive further files (FileOut)? *)
5671       List.iter (
5672         function
5673         | FileOut n ->
5674             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5675             pr "    guestfs___end_busy (g);\n";
5676             pr "    return %s;\n" error_code;
5677             pr "  }\n";
5678             pr "\n";
5679         | _ -> ()
5680       ) (snd style);
5681
5682       pr "  guestfs___end_busy (g);\n";
5683
5684       (match fst style with
5685        | RErr -> pr "  return 0;\n"
5686        | RInt n | RInt64 n | RBool n ->
5687            pr "  return ret.%s;\n" n
5688        | RConstString _ | RConstOptString _ ->
5689            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5690        | RString n ->
5691            pr "  return ret.%s; /* caller will free */\n" n
5692        | RStringList n | RHashtable n ->
5693            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5694            pr "  ret.%s.%s_val =\n" n n;
5695            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5696            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5697              n n;
5698            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5699            pr "  return ret.%s.%s_val;\n" n n
5700        | RStruct (n, _) ->
5701            pr "  /* caller will free this */\n";
5702            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5703        | RStructList (n, _) ->
5704            pr "  /* caller will free this */\n";
5705            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5706        | RBufferOut n ->
5707            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5708            pr "   * _val might be NULL here.  To make the API saner for\n";
5709            pr "   * callers, we turn this case into a unique pointer (using\n";
5710            pr "   * malloc(1)).\n";
5711            pr "   */\n";
5712            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5713            pr "    *size_r = ret.%s.%s_len;\n" n n;
5714            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5715            pr "  } else {\n";
5716            pr "    free (ret.%s.%s_val);\n" n n;
5717            pr "    char *p = safe_malloc (g, 1);\n";
5718            pr "    *size_r = ret.%s.%s_len;\n" n n;
5719            pr "    return p;\n";
5720            pr "  }\n";
5721       );
5722
5723       pr "}\n\n"
5724   ) daemon_functions;
5725
5726   (* Functions to free structures. *)
5727   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5728   pr " * structure format is identical to the XDR format.  See note in\n";
5729   pr " * generator.ml.\n";
5730   pr " */\n";
5731   pr "\n";
5732
5733   List.iter (
5734     fun (typ, _) ->
5735       pr "void\n";
5736       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5737       pr "{\n";
5738       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5739       pr "  free (x);\n";
5740       pr "}\n";
5741       pr "\n";
5742
5743       pr "void\n";
5744       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5745       pr "{\n";
5746       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5747       pr "  free (x);\n";
5748       pr "}\n";
5749       pr "\n";
5750
5751   ) structs;
5752
5753 (* Generate daemon/actions.h. *)
5754 and generate_daemon_actions_h () =
5755   generate_header CStyle GPLv2plus;
5756
5757   pr "#include \"../src/guestfs_protocol.h\"\n";
5758   pr "\n";
5759
5760   List.iter (
5761     fun (name, style, _, _, _, _, _) ->
5762       generate_prototype
5763         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5764         name style;
5765   ) daemon_functions
5766
5767 (* Generate the linker script which controls the visibility of
5768  * symbols in the public ABI and ensures no other symbols get
5769  * exported accidentally.
5770  *)
5771 and generate_linker_script () =
5772   generate_header HashStyle GPLv2plus;
5773
5774   let globals = [
5775     "guestfs_create";
5776     "guestfs_close";
5777     "guestfs_get_error_handler";
5778     "guestfs_get_out_of_memory_handler";
5779     "guestfs_last_error";
5780     "guestfs_set_error_handler";
5781     "guestfs_set_launch_done_callback";
5782     "guestfs_set_log_message_callback";
5783     "guestfs_set_out_of_memory_handler";
5784     "guestfs_set_subprocess_quit_callback";
5785
5786     (* Unofficial parts of the API: the bindings code use these
5787      * functions, so it is useful to export them.
5788      *)
5789     "guestfs_safe_calloc";
5790     "guestfs_safe_malloc";
5791   ] in
5792   let functions =
5793     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5794       all_functions in
5795   let structs =
5796     List.concat (
5797       List.map (fun (typ, _) ->
5798                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5799         structs
5800     ) in
5801   let globals = List.sort compare (globals @ functions @ structs) in
5802
5803   pr "{\n";
5804   pr "    global:\n";
5805   List.iter (pr "        %s;\n") globals;
5806   pr "\n";
5807
5808   pr "    local:\n";
5809   pr "        *;\n";
5810   pr "};\n"
5811
5812 (* Generate the server-side stubs. *)
5813 and generate_daemon_actions () =
5814   generate_header CStyle GPLv2plus;
5815
5816   pr "#include <config.h>\n";
5817   pr "\n";
5818   pr "#include <stdio.h>\n";
5819   pr "#include <stdlib.h>\n";
5820   pr "#include <string.h>\n";
5821   pr "#include <inttypes.h>\n";
5822   pr "#include <rpc/types.h>\n";
5823   pr "#include <rpc/xdr.h>\n";
5824   pr "\n";
5825   pr "#include \"daemon.h\"\n";
5826   pr "#include \"c-ctype.h\"\n";
5827   pr "#include \"../src/guestfs_protocol.h\"\n";
5828   pr "#include \"actions.h\"\n";
5829   pr "\n";
5830
5831   List.iter (
5832     fun (name, style, _, _, _, _, _) ->
5833       (* Generate server-side stubs. *)
5834       pr "static void %s_stub (XDR *xdr_in)\n" name;
5835       pr "{\n";
5836       let error_code =
5837         match fst style with
5838         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5839         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5840         | RBool _ -> pr "  int r;\n"; "-1"
5841         | RConstString _ | RConstOptString _ ->
5842             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5843         | RString _ -> pr "  char *r;\n"; "NULL"
5844         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5845         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5846         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5847         | RBufferOut _ ->
5848             pr "  size_t size = 1;\n";
5849             pr "  char *r;\n";
5850             "NULL" in
5851
5852       (match snd style with
5853        | [] -> ()
5854        | args ->
5855            pr "  struct guestfs_%s_args args;\n" name;
5856            List.iter (
5857              function
5858              | Device n | Dev_or_Path n
5859              | Pathname n
5860              | String n -> ()
5861              | OptString n -> pr "  char *%s;\n" n
5862              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5863              | Bool n -> pr "  int %s;\n" n
5864              | Int n -> pr "  int %s;\n" n
5865              | Int64 n -> pr "  int64_t %s;\n" n
5866              | FileIn _ | FileOut _ -> ()
5867            ) args
5868       );
5869       pr "\n";
5870
5871       (match snd style with
5872        | [] -> ()
5873        | args ->
5874            pr "  memset (&args, 0, sizeof args);\n";
5875            pr "\n";
5876            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5877            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5878            pr "    return;\n";
5879            pr "  }\n";
5880            let pr_args n =
5881              pr "  char *%s = args.%s;\n" n n
5882            in
5883            let pr_list_handling_code n =
5884              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5885              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5886              pr "  if (%s == NULL) {\n" n;
5887              pr "    reply_with_perror (\"realloc\");\n";
5888              pr "    goto done;\n";
5889              pr "  }\n";
5890              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5891              pr "  args.%s.%s_val = %s;\n" n n n;
5892            in
5893            List.iter (
5894              function
5895              | Pathname n ->
5896                  pr_args n;
5897                  pr "  ABS_PATH (%s, goto done);\n" n;
5898              | Device n ->
5899                  pr_args n;
5900                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5901              | Dev_or_Path n ->
5902                  pr_args n;
5903                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5904              | String n -> pr_args n
5905              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5906              | StringList n ->
5907                  pr_list_handling_code n;
5908              | DeviceList n ->
5909                  pr_list_handling_code n;
5910                  pr "  /* Ensure that each is a device,\n";
5911                  pr "   * and perform device name translation. */\n";
5912                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5913                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5914                  pr "  }\n";
5915              | Bool n -> pr "  %s = args.%s;\n" n n
5916              | Int n -> pr "  %s = args.%s;\n" n n
5917              | Int64 n -> pr "  %s = args.%s;\n" n n
5918              | FileIn _ | FileOut _ -> ()
5919            ) args;
5920            pr "\n"
5921       );
5922
5923
5924       (* this is used at least for do_equal *)
5925       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5926         (* Emit NEED_ROOT just once, even when there are two or
5927            more Pathname args *)
5928         pr "  NEED_ROOT (goto done);\n";
5929       );
5930
5931       (* Don't want to call the impl with any FileIn or FileOut
5932        * parameters, since these go "outside" the RPC protocol.
5933        *)
5934       let args' =
5935         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5936           (snd style) in
5937       pr "  r = do_%s " name;
5938       generate_c_call_args (fst style, args');
5939       pr ";\n";
5940
5941       (match fst style with
5942        | RErr | RInt _ | RInt64 _ | RBool _
5943        | RConstString _ | RConstOptString _
5944        | RString _ | RStringList _ | RHashtable _
5945        | RStruct (_, _) | RStructList (_, _) ->
5946            pr "  if (r == %s)\n" error_code;
5947            pr "    /* do_%s has already called reply_with_error */\n" name;
5948            pr "    goto done;\n";
5949            pr "\n"
5950        | RBufferOut _ ->
5951            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5952            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5953            pr "   */\n";
5954            pr "  if (size == 1 && r == %s)\n" error_code;
5955            pr "    /* do_%s has already called reply_with_error */\n" name;
5956            pr "    goto done;\n";
5957            pr "\n"
5958       );
5959
5960       (* If there are any FileOut parameters, then the impl must
5961        * send its own reply.
5962        *)
5963       let no_reply =
5964         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5965       if no_reply then
5966         pr "  /* do_%s has already sent a reply */\n" name
5967       else (
5968         match fst style with
5969         | RErr -> pr "  reply (NULL, NULL);\n"
5970         | RInt n | RInt64 n | RBool n ->
5971             pr "  struct guestfs_%s_ret ret;\n" name;
5972             pr "  ret.%s = r;\n" n;
5973             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5974               name
5975         | RConstString _ | RConstOptString _ ->
5976             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5977         | RString n ->
5978             pr "  struct guestfs_%s_ret ret;\n" name;
5979             pr "  ret.%s = r;\n" n;
5980             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5981               name;
5982             pr "  free (r);\n"
5983         | RStringList n | RHashtable n ->
5984             pr "  struct guestfs_%s_ret ret;\n" name;
5985             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5986             pr "  ret.%s.%s_val = r;\n" n n;
5987             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5988               name;
5989             pr "  free_strings (r);\n"
5990         | RStruct (n, _) ->
5991             pr "  struct guestfs_%s_ret ret;\n" name;
5992             pr "  ret.%s = *r;\n" n;
5993             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5994               name;
5995             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5996               name
5997         | RStructList (n, _) ->
5998             pr "  struct guestfs_%s_ret ret;\n" name;
5999             pr "  ret.%s = *r;\n" n;
6000             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6001               name;
6002             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6003               name
6004         | RBufferOut n ->
6005             pr "  struct guestfs_%s_ret ret;\n" name;
6006             pr "  ret.%s.%s_val = r;\n" n n;
6007             pr "  ret.%s.%s_len = size;\n" n n;
6008             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6009               name;
6010             pr "  free (r);\n"
6011       );
6012
6013       (* Free the args. *)
6014       (match snd style with
6015        | [] ->
6016            pr "done: ;\n";
6017        | _ ->
6018            pr "done:\n";
6019            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6020              name
6021       );
6022
6023       pr "}\n\n";
6024   ) daemon_functions;
6025
6026   (* Dispatch function. *)
6027   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6028   pr "{\n";
6029   pr "  switch (proc_nr) {\n";
6030
6031   List.iter (
6032     fun (name, style, _, _, _, _, _) ->
6033       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6034       pr "      %s_stub (xdr_in);\n" name;
6035       pr "      break;\n"
6036   ) daemon_functions;
6037
6038   pr "    default:\n";
6039   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";
6040   pr "  }\n";
6041   pr "}\n";
6042   pr "\n";
6043
6044   (* LVM columns and tokenization functions. *)
6045   (* XXX This generates crap code.  We should rethink how we
6046    * do this parsing.
6047    *)
6048   List.iter (
6049     function
6050     | typ, cols ->
6051         pr "static const char *lvm_%s_cols = \"%s\";\n"
6052           typ (String.concat "," (List.map fst cols));
6053         pr "\n";
6054
6055         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6056         pr "{\n";
6057         pr "  char *tok, *p, *next;\n";
6058         pr "  int i, j;\n";
6059         pr "\n";
6060         (*
6061           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6062           pr "\n";
6063         *)
6064         pr "  if (!str) {\n";
6065         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6066         pr "    return -1;\n";
6067         pr "  }\n";
6068         pr "  if (!*str || c_isspace (*str)) {\n";
6069         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6070         pr "    return -1;\n";
6071         pr "  }\n";
6072         pr "  tok = str;\n";
6073         List.iter (
6074           fun (name, coltype) ->
6075             pr "  if (!tok) {\n";
6076             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6077             pr "    return -1;\n";
6078             pr "  }\n";
6079             pr "  p = strchrnul (tok, ',');\n";
6080             pr "  if (*p) next = p+1; else next = NULL;\n";
6081             pr "  *p = '\\0';\n";
6082             (match coltype with
6083              | FString ->
6084                  pr "  r->%s = strdup (tok);\n" name;
6085                  pr "  if (r->%s == NULL) {\n" name;
6086                  pr "    perror (\"strdup\");\n";
6087                  pr "    return -1;\n";
6088                  pr "  }\n"
6089              | FUUID ->
6090                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6091                  pr "    if (tok[j] == '\\0') {\n";
6092                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6093                  pr "      return -1;\n";
6094                  pr "    } else if (tok[j] != '-')\n";
6095                  pr "      r->%s[i++] = tok[j];\n" name;
6096                  pr "  }\n";
6097              | FBytes ->
6098                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6099                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6100                  pr "    return -1;\n";
6101                  pr "  }\n";
6102              | FInt64 ->
6103                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6104                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6105                  pr "    return -1;\n";
6106                  pr "  }\n";
6107              | FOptPercent ->
6108                  pr "  if (tok[0] == '\\0')\n";
6109                  pr "    r->%s = -1;\n" name;
6110                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6111                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6112                  pr "    return -1;\n";
6113                  pr "  }\n";
6114              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6115                  assert false (* can never be an LVM column *)
6116             );
6117             pr "  tok = next;\n";
6118         ) cols;
6119
6120         pr "  if (tok != NULL) {\n";
6121         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6122         pr "    return -1;\n";
6123         pr "  }\n";
6124         pr "  return 0;\n";
6125         pr "}\n";
6126         pr "\n";
6127
6128         pr "guestfs_int_lvm_%s_list *\n" typ;
6129         pr "parse_command_line_%ss (void)\n" typ;
6130         pr "{\n";
6131         pr "  char *out, *err;\n";
6132         pr "  char *p, *pend;\n";
6133         pr "  int r, i;\n";
6134         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6135         pr "  void *newp;\n";
6136         pr "\n";
6137         pr "  ret = malloc (sizeof *ret);\n";
6138         pr "  if (!ret) {\n";
6139         pr "    reply_with_perror (\"malloc\");\n";
6140         pr "    return NULL;\n";
6141         pr "  }\n";
6142         pr "\n";
6143         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6144         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6145         pr "\n";
6146         pr "  r = command (&out, &err,\n";
6147         pr "           \"lvm\", \"%ss\",\n" typ;
6148         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6149         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6150         pr "  if (r == -1) {\n";
6151         pr "    reply_with_error (\"%%s\", err);\n";
6152         pr "    free (out);\n";
6153         pr "    free (err);\n";
6154         pr "    free (ret);\n";
6155         pr "    return NULL;\n";
6156         pr "  }\n";
6157         pr "\n";
6158         pr "  free (err);\n";
6159         pr "\n";
6160         pr "  /* Tokenize each line of the output. */\n";
6161         pr "  p = out;\n";
6162         pr "  i = 0;\n";
6163         pr "  while (p) {\n";
6164         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6165         pr "    if (pend) {\n";
6166         pr "      *pend = '\\0';\n";
6167         pr "      pend++;\n";
6168         pr "    }\n";
6169         pr "\n";
6170         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6171         pr "      p++;\n";
6172         pr "\n";
6173         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6174         pr "      p = pend;\n";
6175         pr "      continue;\n";
6176         pr "    }\n";
6177         pr "\n";
6178         pr "    /* Allocate some space to store this next entry. */\n";
6179         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6180         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6181         pr "    if (newp == NULL) {\n";
6182         pr "      reply_with_perror (\"realloc\");\n";
6183         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6184         pr "      free (ret);\n";
6185         pr "      free (out);\n";
6186         pr "      return NULL;\n";
6187         pr "    }\n";
6188         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6189         pr "\n";
6190         pr "    /* Tokenize the next entry. */\n";
6191         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6192         pr "    if (r == -1) {\n";
6193         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6194         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6195         pr "      free (ret);\n";
6196         pr "      free (out);\n";
6197         pr "      return NULL;\n";
6198         pr "    }\n";
6199         pr "\n";
6200         pr "    ++i;\n";
6201         pr "    p = pend;\n";
6202         pr "  }\n";
6203         pr "\n";
6204         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6205         pr "\n";
6206         pr "  free (out);\n";
6207         pr "  return ret;\n";
6208         pr "}\n"
6209
6210   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6211
6212 (* Generate a list of function names, for debugging in the daemon.. *)
6213 and generate_daemon_names () =
6214   generate_header CStyle GPLv2plus;
6215
6216   pr "#include <config.h>\n";
6217   pr "\n";
6218   pr "#include \"daemon.h\"\n";
6219   pr "\n";
6220
6221   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6222   pr "const char *function_names[] = {\n";
6223   List.iter (
6224     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6225   ) daemon_functions;
6226   pr "};\n";
6227
6228 (* Generate the optional groups for the daemon to implement
6229  * guestfs_available.
6230  *)
6231 and generate_daemon_optgroups_c () =
6232   generate_header CStyle GPLv2plus;
6233
6234   pr "#include <config.h>\n";
6235   pr "\n";
6236   pr "#include \"daemon.h\"\n";
6237   pr "#include \"optgroups.h\"\n";
6238   pr "\n";
6239
6240   pr "struct optgroup optgroups[] = {\n";
6241   List.iter (
6242     fun (group, _) ->
6243       pr "  { \"%s\", optgroup_%s_available },\n" group group
6244   ) optgroups;
6245   pr "  { NULL, NULL }\n";
6246   pr "};\n"
6247
6248 and generate_daemon_optgroups_h () =
6249   generate_header CStyle GPLv2plus;
6250
6251   List.iter (
6252     fun (group, _) ->
6253       pr "extern int optgroup_%s_available (void);\n" group
6254   ) optgroups
6255
6256 (* Generate the tests. *)
6257 and generate_tests () =
6258   generate_header CStyle GPLv2plus;
6259
6260   pr "\
6261 #include <stdio.h>
6262 #include <stdlib.h>
6263 #include <string.h>
6264 #include <unistd.h>
6265 #include <sys/types.h>
6266 #include <fcntl.h>
6267
6268 #include \"guestfs.h\"
6269 #include \"guestfs-internal.h\"
6270
6271 static guestfs_h *g;
6272 static int suppress_error = 0;
6273
6274 static void print_error (guestfs_h *g, void *data, const char *msg)
6275 {
6276   if (!suppress_error)
6277     fprintf (stderr, \"%%s\\n\", msg);
6278 }
6279
6280 /* FIXME: nearly identical code appears in fish.c */
6281 static void print_strings (char *const *argv)
6282 {
6283   int argc;
6284
6285   for (argc = 0; argv[argc] != NULL; ++argc)
6286     printf (\"\\t%%s\\n\", argv[argc]);
6287 }
6288
6289 /*
6290 static void print_table (char const *const *argv)
6291 {
6292   int i;
6293
6294   for (i = 0; argv[i] != NULL; i += 2)
6295     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6296 }
6297 */
6298
6299 ";
6300
6301   (* Generate a list of commands which are not tested anywhere. *)
6302   pr "static void no_test_warnings (void)\n";
6303   pr "{\n";
6304
6305   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6306   List.iter (
6307     fun (_, _, _, _, tests, _, _) ->
6308       let tests = filter_map (
6309         function
6310         | (_, (Always|If _|Unless _), test) -> Some test
6311         | (_, Disabled, _) -> None
6312       ) tests in
6313       let seq = List.concat (List.map seq_of_test tests) in
6314       let cmds_tested = List.map List.hd seq in
6315       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6316   ) all_functions;
6317
6318   List.iter (
6319     fun (name, _, _, _, _, _, _) ->
6320       if not (Hashtbl.mem hash name) then
6321         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6322   ) all_functions;
6323
6324   pr "}\n";
6325   pr "\n";
6326
6327   (* Generate the actual tests.  Note that we generate the tests
6328    * in reverse order, deliberately, so that (in general) the
6329    * newest tests run first.  This makes it quicker and easier to
6330    * debug them.
6331    *)
6332   let test_names =
6333     List.map (
6334       fun (name, _, _, flags, tests, _, _) ->
6335         mapi (generate_one_test name flags) tests
6336     ) (List.rev all_functions) in
6337   let test_names = List.concat test_names in
6338   let nr_tests = List.length test_names in
6339
6340   pr "\
6341 int main (int argc, char *argv[])
6342 {
6343   char c = 0;
6344   unsigned long int n_failed = 0;
6345   const char *filename;
6346   int fd;
6347   int nr_tests, test_num = 0;
6348
6349   setbuf (stdout, NULL);
6350
6351   no_test_warnings ();
6352
6353   g = guestfs_create ();
6354   if (g == NULL) {
6355     printf (\"guestfs_create FAILED\\n\");
6356     exit (EXIT_FAILURE);
6357   }
6358
6359   guestfs_set_error_handler (g, print_error, NULL);
6360
6361   guestfs_set_path (g, \"../appliance\");
6362
6363   filename = \"test1.img\";
6364   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6365   if (fd == -1) {
6366     perror (filename);
6367     exit (EXIT_FAILURE);
6368   }
6369   if (lseek (fd, %d, SEEK_SET) == -1) {
6370     perror (\"lseek\");
6371     close (fd);
6372     unlink (filename);
6373     exit (EXIT_FAILURE);
6374   }
6375   if (write (fd, &c, 1) == -1) {
6376     perror (\"write\");
6377     close (fd);
6378     unlink (filename);
6379     exit (EXIT_FAILURE);
6380   }
6381   if (close (fd) == -1) {
6382     perror (filename);
6383     unlink (filename);
6384     exit (EXIT_FAILURE);
6385   }
6386   if (guestfs_add_drive (g, filename) == -1) {
6387     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6388     exit (EXIT_FAILURE);
6389   }
6390
6391   filename = \"test2.img\";
6392   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6393   if (fd == -1) {
6394     perror (filename);
6395     exit (EXIT_FAILURE);
6396   }
6397   if (lseek (fd, %d, SEEK_SET) == -1) {
6398     perror (\"lseek\");
6399     close (fd);
6400     unlink (filename);
6401     exit (EXIT_FAILURE);
6402   }
6403   if (write (fd, &c, 1) == -1) {
6404     perror (\"write\");
6405     close (fd);
6406     unlink (filename);
6407     exit (EXIT_FAILURE);
6408   }
6409   if (close (fd) == -1) {
6410     perror (filename);
6411     unlink (filename);
6412     exit (EXIT_FAILURE);
6413   }
6414   if (guestfs_add_drive (g, filename) == -1) {
6415     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6416     exit (EXIT_FAILURE);
6417   }
6418
6419   filename = \"test3.img\";
6420   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6421   if (fd == -1) {
6422     perror (filename);
6423     exit (EXIT_FAILURE);
6424   }
6425   if (lseek (fd, %d, SEEK_SET) == -1) {
6426     perror (\"lseek\");
6427     close (fd);
6428     unlink (filename);
6429     exit (EXIT_FAILURE);
6430   }
6431   if (write (fd, &c, 1) == -1) {
6432     perror (\"write\");
6433     close (fd);
6434     unlink (filename);
6435     exit (EXIT_FAILURE);
6436   }
6437   if (close (fd) == -1) {
6438     perror (filename);
6439     unlink (filename);
6440     exit (EXIT_FAILURE);
6441   }
6442   if (guestfs_add_drive (g, filename) == -1) {
6443     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6444     exit (EXIT_FAILURE);
6445   }
6446
6447   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6448     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6449     exit (EXIT_FAILURE);
6450   }
6451
6452   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6453   alarm (600);
6454
6455   if (guestfs_launch (g) == -1) {
6456     printf (\"guestfs_launch FAILED\\n\");
6457     exit (EXIT_FAILURE);
6458   }
6459
6460   /* Cancel previous alarm. */
6461   alarm (0);
6462
6463   nr_tests = %d;
6464
6465 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6466
6467   iteri (
6468     fun i test_name ->
6469       pr "  test_num++;\n";
6470       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6471       pr "  if (%s () == -1) {\n" test_name;
6472       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6473       pr "    n_failed++;\n";
6474       pr "  }\n";
6475   ) test_names;
6476   pr "\n";
6477
6478   pr "  guestfs_close (g);\n";
6479   pr "  unlink (\"test1.img\");\n";
6480   pr "  unlink (\"test2.img\");\n";
6481   pr "  unlink (\"test3.img\");\n";
6482   pr "\n";
6483
6484   pr "  if (n_failed > 0) {\n";
6485   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6486   pr "    exit (EXIT_FAILURE);\n";
6487   pr "  }\n";
6488   pr "\n";
6489
6490   pr "  exit (EXIT_SUCCESS);\n";
6491   pr "}\n"
6492
6493 and generate_one_test name flags i (init, prereq, test) =
6494   let test_name = sprintf "test_%s_%d" name i in
6495
6496   pr "\
6497 static int %s_skip (void)
6498 {
6499   const char *str;
6500
6501   str = getenv (\"TEST_ONLY\");
6502   if (str)
6503     return strstr (str, \"%s\") == NULL;
6504   str = getenv (\"SKIP_%s\");
6505   if (str && STREQ (str, \"1\")) return 1;
6506   str = getenv (\"SKIP_TEST_%s\");
6507   if (str && STREQ (str, \"1\")) return 1;
6508   return 0;
6509 }
6510
6511 " test_name name (String.uppercase test_name) (String.uppercase name);
6512
6513   (match prereq with
6514    | Disabled | Always -> ()
6515    | If code | Unless code ->
6516        pr "static int %s_prereq (void)\n" test_name;
6517        pr "{\n";
6518        pr "  %s\n" code;
6519        pr "}\n";
6520        pr "\n";
6521   );
6522
6523   pr "\
6524 static int %s (void)
6525 {
6526   if (%s_skip ()) {
6527     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6528     return 0;
6529   }
6530
6531 " test_name test_name test_name;
6532
6533   (* Optional functions should only be tested if the relevant
6534    * support is available in the daemon.
6535    *)
6536   List.iter (
6537     function
6538     | Optional group ->
6539         pr "  {\n";
6540         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6541         pr "    int r;\n";
6542         pr "    suppress_error = 1;\n";
6543         pr "    r = guestfs_available (g, (char **) groups);\n";
6544         pr "    suppress_error = 0;\n";
6545         pr "    if (r == -1) {\n";
6546         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6547         pr "      return 0;\n";
6548         pr "    }\n";
6549         pr "  }\n";
6550     | _ -> ()
6551   ) flags;
6552
6553   (match prereq with
6554    | Disabled ->
6555        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6556    | If _ ->
6557        pr "  if (! %s_prereq ()) {\n" test_name;
6558        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6559        pr "    return 0;\n";
6560        pr "  }\n";
6561        pr "\n";
6562        generate_one_test_body name i test_name init test;
6563    | Unless _ ->
6564        pr "  if (%s_prereq ()) {\n" test_name;
6565        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6566        pr "    return 0;\n";
6567        pr "  }\n";
6568        pr "\n";
6569        generate_one_test_body name i test_name init test;
6570    | Always ->
6571        generate_one_test_body name i test_name init test
6572   );
6573
6574   pr "  return 0;\n";
6575   pr "}\n";
6576   pr "\n";
6577   test_name
6578
6579 and generate_one_test_body name i test_name init test =
6580   (match init with
6581    | InitNone (* XXX at some point, InitNone and InitEmpty became
6582                * folded together as the same thing.  Really we should
6583                * make InitNone do nothing at all, but the tests may
6584                * need to be checked to make sure this is OK.
6585                *)
6586    | InitEmpty ->
6587        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6588        List.iter (generate_test_command_call test_name)
6589          [["blockdev_setrw"; "/dev/sda"];
6590           ["umount_all"];
6591           ["lvm_remove_all"]]
6592    | InitPartition ->
6593        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6594        List.iter (generate_test_command_call test_name)
6595          [["blockdev_setrw"; "/dev/sda"];
6596           ["umount_all"];
6597           ["lvm_remove_all"];
6598           ["part_disk"; "/dev/sda"; "mbr"]]
6599    | InitBasicFS ->
6600        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6601        List.iter (generate_test_command_call test_name)
6602          [["blockdev_setrw"; "/dev/sda"];
6603           ["umount_all"];
6604           ["lvm_remove_all"];
6605           ["part_disk"; "/dev/sda"; "mbr"];
6606           ["mkfs"; "ext2"; "/dev/sda1"];
6607           ["mount_options"; ""; "/dev/sda1"; "/"]]
6608    | InitBasicFSonLVM ->
6609        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6610          test_name;
6611        List.iter (generate_test_command_call test_name)
6612          [["blockdev_setrw"; "/dev/sda"];
6613           ["umount_all"];
6614           ["lvm_remove_all"];
6615           ["part_disk"; "/dev/sda"; "mbr"];
6616           ["pvcreate"; "/dev/sda1"];
6617           ["vgcreate"; "VG"; "/dev/sda1"];
6618           ["lvcreate"; "LV"; "VG"; "8"];
6619           ["mkfs"; "ext2"; "/dev/VG/LV"];
6620           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6621    | InitISOFS ->
6622        pr "  /* InitISOFS for %s */\n" test_name;
6623        List.iter (generate_test_command_call test_name)
6624          [["blockdev_setrw"; "/dev/sda"];
6625           ["umount_all"];
6626           ["lvm_remove_all"];
6627           ["mount_ro"; "/dev/sdd"; "/"]]
6628   );
6629
6630   let get_seq_last = function
6631     | [] ->
6632         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6633           test_name
6634     | seq ->
6635         let seq = List.rev seq in
6636         List.rev (List.tl seq), List.hd seq
6637   in
6638
6639   match test with
6640   | TestRun seq ->
6641       pr "  /* TestRun for %s (%d) */\n" name i;
6642       List.iter (generate_test_command_call test_name) seq
6643   | TestOutput (seq, expected) ->
6644       pr "  /* TestOutput for %s (%d) */\n" name i;
6645       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6646       let seq, last = get_seq_last seq in
6647       let test () =
6648         pr "    if (STRNEQ (r, expected)) {\n";
6649         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6650         pr "      return -1;\n";
6651         pr "    }\n"
6652       in
6653       List.iter (generate_test_command_call test_name) seq;
6654       generate_test_command_call ~test test_name last
6655   | TestOutputList (seq, expected) ->
6656       pr "  /* TestOutputList for %s (%d) */\n" name i;
6657       let seq, last = get_seq_last seq in
6658       let test () =
6659         iteri (
6660           fun i str ->
6661             pr "    if (!r[%d]) {\n" i;
6662             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6663             pr "      print_strings (r);\n";
6664             pr "      return -1;\n";
6665             pr "    }\n";
6666             pr "    {\n";
6667             pr "      const char *expected = \"%s\";\n" (c_quote str);
6668             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6669             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6670             pr "        return -1;\n";
6671             pr "      }\n";
6672             pr "    }\n"
6673         ) expected;
6674         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6675         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6676           test_name;
6677         pr "      print_strings (r);\n";
6678         pr "      return -1;\n";
6679         pr "    }\n"
6680       in
6681       List.iter (generate_test_command_call test_name) seq;
6682       generate_test_command_call ~test test_name last
6683   | TestOutputListOfDevices (seq, expected) ->
6684       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6685       let seq, last = get_seq_last seq in
6686       let test () =
6687         iteri (
6688           fun i str ->
6689             pr "    if (!r[%d]) {\n" i;
6690             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6691             pr "      print_strings (r);\n";
6692             pr "      return -1;\n";
6693             pr "    }\n";
6694             pr "    {\n";
6695             pr "      const char *expected = \"%s\";\n" (c_quote str);
6696             pr "      r[%d][5] = 's';\n" i;
6697             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6698             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6699             pr "        return -1;\n";
6700             pr "      }\n";
6701             pr "    }\n"
6702         ) expected;
6703         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6704         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6705           test_name;
6706         pr "      print_strings (r);\n";
6707         pr "      return -1;\n";
6708         pr "    }\n"
6709       in
6710       List.iter (generate_test_command_call test_name) seq;
6711       generate_test_command_call ~test test_name last
6712   | TestOutputInt (seq, expected) ->
6713       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6714       let seq, last = get_seq_last seq in
6715       let test () =
6716         pr "    if (r != %d) {\n" expected;
6717         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6718           test_name expected;
6719         pr "               (int) r);\n";
6720         pr "      return -1;\n";
6721         pr "    }\n"
6722       in
6723       List.iter (generate_test_command_call test_name) seq;
6724       generate_test_command_call ~test test_name last
6725   | TestOutputIntOp (seq, op, expected) ->
6726       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6727       let seq, last = get_seq_last seq in
6728       let test () =
6729         pr "    if (! (r %s %d)) {\n" op expected;
6730         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6731           test_name op expected;
6732         pr "               (int) r);\n";
6733         pr "      return -1;\n";
6734         pr "    }\n"
6735       in
6736       List.iter (generate_test_command_call test_name) seq;
6737       generate_test_command_call ~test test_name last
6738   | TestOutputTrue seq ->
6739       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6740       let seq, last = get_seq_last seq in
6741       let test () =
6742         pr "    if (!r) {\n";
6743         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6744           test_name;
6745         pr "      return -1;\n";
6746         pr "    }\n"
6747       in
6748       List.iter (generate_test_command_call test_name) seq;
6749       generate_test_command_call ~test test_name last
6750   | TestOutputFalse seq ->
6751       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6752       let seq, last = get_seq_last seq in
6753       let test () =
6754         pr "    if (r) {\n";
6755         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6756           test_name;
6757         pr "      return -1;\n";
6758         pr "    }\n"
6759       in
6760       List.iter (generate_test_command_call test_name) seq;
6761       generate_test_command_call ~test test_name last
6762   | TestOutputLength (seq, expected) ->
6763       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6764       let seq, last = get_seq_last seq in
6765       let test () =
6766         pr "    int j;\n";
6767         pr "    for (j = 0; j < %d; ++j)\n" expected;
6768         pr "      if (r[j] == NULL) {\n";
6769         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6770           test_name;
6771         pr "        print_strings (r);\n";
6772         pr "        return -1;\n";
6773         pr "      }\n";
6774         pr "    if (r[j] != NULL) {\n";
6775         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6776           test_name;
6777         pr "      print_strings (r);\n";
6778         pr "      return -1;\n";
6779         pr "    }\n"
6780       in
6781       List.iter (generate_test_command_call test_name) seq;
6782       generate_test_command_call ~test test_name last
6783   | TestOutputBuffer (seq, expected) ->
6784       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6785       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6786       let seq, last = get_seq_last seq in
6787       let len = String.length expected in
6788       let test () =
6789         pr "    if (size != %d) {\n" len;
6790         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6791         pr "      return -1;\n";
6792         pr "    }\n";
6793         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6794         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6795         pr "      return -1;\n";
6796         pr "    }\n"
6797       in
6798       List.iter (generate_test_command_call test_name) seq;
6799       generate_test_command_call ~test test_name last
6800   | TestOutputStruct (seq, checks) ->
6801       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6802       let seq, last = get_seq_last seq in
6803       let test () =
6804         List.iter (
6805           function
6806           | CompareWithInt (field, expected) ->
6807               pr "    if (r->%s != %d) {\n" field expected;
6808               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6809                 test_name field expected;
6810               pr "               (int) r->%s);\n" field;
6811               pr "      return -1;\n";
6812               pr "    }\n"
6813           | CompareWithIntOp (field, op, expected) ->
6814               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6815               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6816                 test_name field op expected;
6817               pr "               (int) r->%s);\n" field;
6818               pr "      return -1;\n";
6819               pr "    }\n"
6820           | CompareWithString (field, expected) ->
6821               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6822               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6823                 test_name field expected;
6824               pr "               r->%s);\n" field;
6825               pr "      return -1;\n";
6826               pr "    }\n"
6827           | CompareFieldsIntEq (field1, field2) ->
6828               pr "    if (r->%s != r->%s) {\n" field1 field2;
6829               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6830                 test_name field1 field2;
6831               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6832               pr "      return -1;\n";
6833               pr "    }\n"
6834           | CompareFieldsStrEq (field1, field2) ->
6835               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6836               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6837                 test_name field1 field2;
6838               pr "               r->%s, r->%s);\n" field1 field2;
6839               pr "      return -1;\n";
6840               pr "    }\n"
6841         ) checks
6842       in
6843       List.iter (generate_test_command_call test_name) seq;
6844       generate_test_command_call ~test test_name last
6845   | TestLastFail seq ->
6846       pr "  /* TestLastFail for %s (%d) */\n" name i;
6847       let seq, last = get_seq_last seq in
6848       List.iter (generate_test_command_call test_name) seq;
6849       generate_test_command_call test_name ~expect_error:true last
6850
6851 (* Generate the code to run a command, leaving the result in 'r'.
6852  * If you expect to get an error then you should set expect_error:true.
6853  *)
6854 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6855   match cmd with
6856   | [] -> assert false
6857   | name :: args ->
6858       (* Look up the command to find out what args/ret it has. *)
6859       let style =
6860         try
6861           let _, style, _, _, _, _, _ =
6862             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6863           style
6864         with Not_found ->
6865           failwithf "%s: in test, command %s was not found" test_name name in
6866
6867       if List.length (snd style) <> List.length args then
6868         failwithf "%s: in test, wrong number of args given to %s"
6869           test_name name;
6870
6871       pr "  {\n";
6872
6873       List.iter (
6874         function
6875         | OptString n, "NULL" -> ()
6876         | Pathname n, arg
6877         | Device n, arg
6878         | Dev_or_Path n, arg
6879         | String n, arg
6880         | OptString n, arg ->
6881             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6882         | Int _, _
6883         | Int64 _, _
6884         | Bool _, _
6885         | FileIn _, _ | FileOut _, _ -> ()
6886         | StringList n, "" | DeviceList n, "" ->
6887             pr "    const char *const %s[1] = { NULL };\n" n
6888         | StringList n, arg | DeviceList n, arg ->
6889             let strs = string_split " " arg in
6890             iteri (
6891               fun i str ->
6892                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6893             ) strs;
6894             pr "    const char *const %s[] = {\n" n;
6895             iteri (
6896               fun i _ -> pr "      %s_%d,\n" n i
6897             ) strs;
6898             pr "      NULL\n";
6899             pr "    };\n";
6900       ) (List.combine (snd style) args);
6901
6902       let error_code =
6903         match fst style with
6904         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6905         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6906         | RConstString _ | RConstOptString _ ->
6907             pr "    const char *r;\n"; "NULL"
6908         | RString _ -> pr "    char *r;\n"; "NULL"
6909         | RStringList _ | RHashtable _ ->
6910             pr "    char **r;\n";
6911             pr "    int i;\n";
6912             "NULL"
6913         | RStruct (_, typ) ->
6914             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6915         | RStructList (_, typ) ->
6916             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6917         | RBufferOut _ ->
6918             pr "    char *r;\n";
6919             pr "    size_t size;\n";
6920             "NULL" in
6921
6922       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6923       pr "    r = guestfs_%s (g" name;
6924
6925       (* Generate the parameters. *)
6926       List.iter (
6927         function
6928         | OptString _, "NULL" -> pr ", NULL"
6929         | Pathname n, _
6930         | Device n, _ | Dev_or_Path n, _
6931         | String n, _
6932         | OptString n, _ ->
6933             pr ", %s" n
6934         | FileIn _, arg | FileOut _, arg ->
6935             pr ", \"%s\"" (c_quote arg)
6936         | StringList n, _ | DeviceList n, _ ->
6937             pr ", (char **) %s" n
6938         | Int _, arg ->
6939             let i =
6940               try int_of_string arg
6941               with Failure "int_of_string" ->
6942                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6943             pr ", %d" i
6944         | Int64 _, arg ->
6945             let i =
6946               try Int64.of_string arg
6947               with Failure "int_of_string" ->
6948                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6949             pr ", %Ld" i
6950         | Bool _, arg ->
6951             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6952       ) (List.combine (snd style) args);
6953
6954       (match fst style with
6955        | RBufferOut _ -> pr ", &size"
6956        | _ -> ()
6957       );
6958
6959       pr ");\n";
6960
6961       if not expect_error then
6962         pr "    if (r == %s)\n" error_code
6963       else
6964         pr "    if (r != %s)\n" error_code;
6965       pr "      return -1;\n";
6966
6967       (* Insert the test code. *)
6968       (match test with
6969        | None -> ()
6970        | Some f -> f ()
6971       );
6972
6973       (match fst style with
6974        | RErr | RInt _ | RInt64 _ | RBool _
6975        | RConstString _ | RConstOptString _ -> ()
6976        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6977        | RStringList _ | RHashtable _ ->
6978            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6979            pr "      free (r[i]);\n";
6980            pr "    free (r);\n"
6981        | RStruct (_, typ) ->
6982            pr "    guestfs_free_%s (r);\n" typ
6983        | RStructList (_, typ) ->
6984            pr "    guestfs_free_%s_list (r);\n" typ
6985       );
6986
6987       pr "  }\n"
6988
6989 and c_quote str =
6990   let str = replace_str str "\r" "\\r" in
6991   let str = replace_str str "\n" "\\n" in
6992   let str = replace_str str "\t" "\\t" in
6993   let str = replace_str str "\000" "\\0" in
6994   str
6995
6996 (* Generate a lot of different functions for guestfish. *)
6997 and generate_fish_cmds () =
6998   generate_header CStyle GPLv2plus;
6999
7000   let all_functions =
7001     List.filter (
7002       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7003     ) all_functions in
7004   let all_functions_sorted =
7005     List.filter (
7006       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7007     ) all_functions_sorted in
7008
7009   pr "#include <config.h>\n";
7010   pr "\n";
7011   pr "#include <stdio.h>\n";
7012   pr "#include <stdlib.h>\n";
7013   pr "#include <string.h>\n";
7014   pr "#include <inttypes.h>\n";
7015   pr "\n";
7016   pr "#include <guestfs.h>\n";
7017   pr "#include \"c-ctype.h\"\n";
7018   pr "#include \"full-write.h\"\n";
7019   pr "#include \"xstrtol.h\"\n";
7020   pr "#include \"fish.h\"\n";
7021   pr "\n";
7022
7023   (* list_commands function, which implements guestfish -h *)
7024   pr "void list_commands (void)\n";
7025   pr "{\n";
7026   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7027   pr "  list_builtin_commands ();\n";
7028   List.iter (
7029     fun (name, _, _, flags, _, shortdesc, _) ->
7030       let name = replace_char name '_' '-' in
7031       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7032         name shortdesc
7033   ) all_functions_sorted;
7034   pr "  printf (\"    %%s\\n\",";
7035   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7036   pr "}\n";
7037   pr "\n";
7038
7039   (* display_command function, which implements guestfish -h cmd *)
7040   pr "void display_command (const char *cmd)\n";
7041   pr "{\n";
7042   List.iter (
7043     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7044       let name2 = replace_char name '_' '-' in
7045       let alias =
7046         try find_map (function FishAlias n -> Some n | _ -> None) flags
7047         with Not_found -> name in
7048       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7049       let synopsis =
7050         match snd style with
7051         | [] -> name2
7052         | args ->
7053             sprintf "%s %s"
7054               name2 (String.concat " " (List.map name_of_argt args)) in
7055
7056       let warnings =
7057         if List.mem ProtocolLimitWarning flags then
7058           ("\n\n" ^ protocol_limit_warning)
7059         else "" in
7060
7061       (* For DangerWillRobinson commands, we should probably have
7062        * guestfish prompt before allowing you to use them (especially
7063        * in interactive mode). XXX
7064        *)
7065       let warnings =
7066         warnings ^
7067           if List.mem DangerWillRobinson flags then
7068             ("\n\n" ^ danger_will_robinson)
7069           else "" in
7070
7071       let warnings =
7072         warnings ^
7073           match deprecation_notice flags with
7074           | None -> ""
7075           | Some txt -> "\n\n" ^ txt in
7076
7077       let describe_alias =
7078         if name <> alias then
7079           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7080         else "" in
7081
7082       pr "  if (";
7083       pr "STRCASEEQ (cmd, \"%s\")" name;
7084       if name <> name2 then
7085         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7086       if name <> alias then
7087         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7088       pr ")\n";
7089       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7090         name2 shortdesc
7091         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7092          "=head1 DESCRIPTION\n\n" ^
7093          longdesc ^ warnings ^ describe_alias);
7094       pr "  else\n"
7095   ) all_functions;
7096   pr "    display_builtin_command (cmd);\n";
7097   pr "}\n";
7098   pr "\n";
7099
7100   let emit_print_list_function typ =
7101     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7102       typ typ typ;
7103     pr "{\n";
7104     pr "  unsigned int i;\n";
7105     pr "\n";
7106     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7107     pr "    printf (\"[%%d] = {\\n\", i);\n";
7108     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7109     pr "    printf (\"}\\n\");\n";
7110     pr "  }\n";
7111     pr "}\n";
7112     pr "\n";
7113   in
7114
7115   (* print_* functions *)
7116   List.iter (
7117     fun (typ, cols) ->
7118       let needs_i =
7119         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7120
7121       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7122       pr "{\n";
7123       if needs_i then (
7124         pr "  unsigned int i;\n";
7125         pr "\n"
7126       );
7127       List.iter (
7128         function
7129         | name, FString ->
7130             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7131         | name, FUUID ->
7132             pr "  printf (\"%%s%s: \", indent);\n" name;
7133             pr "  for (i = 0; i < 32; ++i)\n";
7134             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7135             pr "  printf (\"\\n\");\n"
7136         | name, FBuffer ->
7137             pr "  printf (\"%%s%s: \", indent);\n" name;
7138             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7139             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7140             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7141             pr "    else\n";
7142             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7143             pr "  printf (\"\\n\");\n"
7144         | name, (FUInt64|FBytes) ->
7145             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7146               name typ name
7147         | name, FInt64 ->
7148             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7149               name typ name
7150         | name, FUInt32 ->
7151             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7152               name typ name
7153         | name, FInt32 ->
7154             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7155               name typ name
7156         | name, FChar ->
7157             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7158               name typ name
7159         | name, FOptPercent ->
7160             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7161               typ name name typ name;
7162             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7163       ) cols;
7164       pr "}\n";
7165       pr "\n";
7166   ) structs;
7167
7168   (* Emit a print_TYPE_list function definition only if that function is used. *)
7169   List.iter (
7170     function
7171     | typ, (RStructListOnly | RStructAndList) ->
7172         (* generate the function for typ *)
7173         emit_print_list_function typ
7174     | typ, _ -> () (* empty *)
7175   ) (rstructs_used_by all_functions);
7176
7177   (* Emit a print_TYPE function definition only if that function is used. *)
7178   List.iter (
7179     function
7180     | typ, (RStructOnly | RStructAndList) ->
7181         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7182         pr "{\n";
7183         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7184         pr "}\n";
7185         pr "\n";
7186     | typ, _ -> () (* empty *)
7187   ) (rstructs_used_by all_functions);
7188
7189   (* run_<action> actions *)
7190   List.iter (
7191     fun (name, style, _, flags, _, _, _) ->
7192       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7193       pr "{\n";
7194       (match fst style with
7195        | RErr
7196        | RInt _
7197        | RBool _ -> pr "  int r;\n"
7198        | RInt64 _ -> pr "  int64_t r;\n"
7199        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7200        | RString _ -> pr "  char *r;\n"
7201        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7202        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7203        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7204        | RBufferOut _ ->
7205            pr "  char *r;\n";
7206            pr "  size_t size;\n";
7207       );
7208       List.iter (
7209         function
7210         | Device n
7211         | String n
7212         | OptString n
7213         | FileIn n
7214         | FileOut n -> pr "  const char *%s;\n" n
7215         | Pathname n
7216         | Dev_or_Path n -> pr "  char *%s;\n" n
7217         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7218         | Bool n -> pr "  int %s;\n" n
7219         | Int n -> pr "  int %s;\n" n
7220         | Int64 n -> pr "  int64_t %s;\n" n
7221       ) (snd style);
7222
7223       (* Check and convert parameters. *)
7224       let argc_expected = List.length (snd style) in
7225       pr "  if (argc != %d) {\n" argc_expected;
7226       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7227         argc_expected;
7228       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7229       pr "    return -1;\n";
7230       pr "  }\n";
7231
7232       let parse_integer fn fntyp rtyp range name i =
7233         pr "  {\n";
7234         pr "    strtol_error xerr;\n";
7235         pr "    %s r;\n" fntyp;
7236         pr "\n";
7237         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7238         pr "    if (xerr != LONGINT_OK) {\n";
7239         pr "      fprintf (stderr,\n";
7240         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7241         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7242         pr "      return -1;\n";
7243         pr "    }\n";
7244         (match range with
7245          | None -> ()
7246          | Some (min, max, comment) ->
7247              pr "    /* %s */\n" comment;
7248              pr "    if (r < %s || r > %s) {\n" min max;
7249              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7250                name;
7251              pr "      return -1;\n";
7252              pr "    }\n";
7253              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7254         );
7255         pr "    %s = r;\n" name;
7256         pr "  }\n";
7257       in
7258
7259       iteri (
7260         fun i ->
7261           function
7262           | Device name
7263           | String name ->
7264               pr "  %s = argv[%d];\n" name i
7265           | Pathname name
7266           | Dev_or_Path name ->
7267               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7268               pr "  if (%s == NULL) return -1;\n" name
7269           | OptString name ->
7270               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7271                 name i i
7272           | FileIn name ->
7273               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7274                 name i i
7275           | FileOut name ->
7276               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7277                 name i i
7278           | StringList name | DeviceList name ->
7279               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7280               pr "  if (%s == NULL) return -1;\n" name;
7281           | Bool name ->
7282               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7283           | Int name ->
7284               let range =
7285                 let min = "(-(2LL<<30))"
7286                 and max = "((2LL<<30)-1)"
7287                 and comment =
7288                   "The Int type in the generator is a signed 31 bit int." in
7289                 Some (min, max, comment) in
7290               parse_integer "xstrtoll" "long long" "int" range name i
7291           | Int64 name ->
7292               parse_integer "xstrtoll" "long long" "int64_t" None name i
7293       ) (snd style);
7294
7295       (* Call C API function. *)
7296       let fn =
7297         try find_map (function FishAction n -> Some n | _ -> None) flags
7298         with Not_found -> sprintf "guestfs_%s" name in
7299       pr "  r = %s " fn;
7300       generate_c_call_args ~handle:"g" style;
7301       pr ";\n";
7302
7303       List.iter (
7304         function
7305         | Device name | String name
7306         | OptString name | FileIn name | FileOut name | Bool name
7307         | Int name | Int64 name -> ()
7308         | Pathname name | Dev_or_Path name ->
7309             pr "  free (%s);\n" name
7310         | StringList name | DeviceList name ->
7311             pr "  free_strings (%s);\n" name
7312       ) (snd style);
7313
7314       (* Check return value for errors and display command results. *)
7315       (match fst style with
7316        | RErr -> pr "  return r;\n"
7317        | RInt _ ->
7318            pr "  if (r == -1) return -1;\n";
7319            pr "  printf (\"%%d\\n\", r);\n";
7320            pr "  return 0;\n"
7321        | RInt64 _ ->
7322            pr "  if (r == -1) return -1;\n";
7323            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7324            pr "  return 0;\n"
7325        | RBool _ ->
7326            pr "  if (r == -1) return -1;\n";
7327            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7328            pr "  return 0;\n"
7329        | RConstString _ ->
7330            pr "  if (r == NULL) return -1;\n";
7331            pr "  printf (\"%%s\\n\", r);\n";
7332            pr "  return 0;\n"
7333        | RConstOptString _ ->
7334            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7335            pr "  return 0;\n"
7336        | RString _ ->
7337            pr "  if (r == NULL) return -1;\n";
7338            pr "  printf (\"%%s\\n\", r);\n";
7339            pr "  free (r);\n";
7340            pr "  return 0;\n"
7341        | RStringList _ ->
7342            pr "  if (r == NULL) return -1;\n";
7343            pr "  print_strings (r);\n";
7344            pr "  free_strings (r);\n";
7345            pr "  return 0;\n"
7346        | RStruct (_, typ) ->
7347            pr "  if (r == NULL) return -1;\n";
7348            pr "  print_%s (r);\n" typ;
7349            pr "  guestfs_free_%s (r);\n" typ;
7350            pr "  return 0;\n"
7351        | RStructList (_, typ) ->
7352            pr "  if (r == NULL) return -1;\n";
7353            pr "  print_%s_list (r);\n" typ;
7354            pr "  guestfs_free_%s_list (r);\n" typ;
7355            pr "  return 0;\n"
7356        | RHashtable _ ->
7357            pr "  if (r == NULL) return -1;\n";
7358            pr "  print_table (r);\n";
7359            pr "  free_strings (r);\n";
7360            pr "  return 0;\n"
7361        | RBufferOut _ ->
7362            pr "  if (r == NULL) return -1;\n";
7363            pr "  if (full_write (1, r, size) != size) {\n";
7364            pr "    perror (\"write\");\n";
7365            pr "    free (r);\n";
7366            pr "    return -1;\n";
7367            pr "  }\n";
7368            pr "  free (r);\n";
7369            pr "  return 0;\n"
7370       );
7371       pr "}\n";
7372       pr "\n"
7373   ) all_functions;
7374
7375   (* run_action function *)
7376   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7377   pr "{\n";
7378   List.iter (
7379     fun (name, _, _, flags, _, _, _) ->
7380       let name2 = replace_char name '_' '-' in
7381       let alias =
7382         try find_map (function FishAlias n -> Some n | _ -> None) flags
7383         with Not_found -> name in
7384       pr "  if (";
7385       pr "STRCASEEQ (cmd, \"%s\")" name;
7386       if name <> name2 then
7387         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7388       if name <> alias then
7389         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7390       pr ")\n";
7391       pr "    return run_%s (cmd, argc, argv);\n" name;
7392       pr "  else\n";
7393   ) all_functions;
7394   pr "    {\n";
7395   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7396   pr "      if (command_num == 1)\n";
7397   pr "        extended_help_message ();\n";
7398   pr "      return -1;\n";
7399   pr "    }\n";
7400   pr "  return 0;\n";
7401   pr "}\n";
7402   pr "\n"
7403
7404 (* Readline completion for guestfish. *)
7405 and generate_fish_completion () =
7406   generate_header CStyle GPLv2plus;
7407
7408   let all_functions =
7409     List.filter (
7410       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7411     ) all_functions in
7412
7413   pr "\
7414 #include <config.h>
7415
7416 #include <stdio.h>
7417 #include <stdlib.h>
7418 #include <string.h>
7419
7420 #ifdef HAVE_LIBREADLINE
7421 #include <readline/readline.h>
7422 #endif
7423
7424 #include \"fish.h\"
7425
7426 #ifdef HAVE_LIBREADLINE
7427
7428 static const char *const commands[] = {
7429   BUILTIN_COMMANDS_FOR_COMPLETION,
7430 ";
7431
7432   (* Get the commands, including the aliases.  They don't need to be
7433    * sorted - the generator() function just does a dumb linear search.
7434    *)
7435   let commands =
7436     List.map (
7437       fun (name, _, _, flags, _, _, _) ->
7438         let name2 = replace_char name '_' '-' in
7439         let alias =
7440           try find_map (function FishAlias n -> Some n | _ -> None) flags
7441           with Not_found -> name in
7442
7443         if name <> alias then [name2; alias] else [name2]
7444     ) all_functions in
7445   let commands = List.flatten commands in
7446
7447   List.iter (pr "  \"%s\",\n") commands;
7448
7449   pr "  NULL
7450 };
7451
7452 static char *
7453 generator (const char *text, int state)
7454 {
7455   static int index, len;
7456   const char *name;
7457
7458   if (!state) {
7459     index = 0;
7460     len = strlen (text);
7461   }
7462
7463   rl_attempted_completion_over = 1;
7464
7465   while ((name = commands[index]) != NULL) {
7466     index++;
7467     if (STRCASEEQLEN (name, text, len))
7468       return strdup (name);
7469   }
7470
7471   return NULL;
7472 }
7473
7474 #endif /* HAVE_LIBREADLINE */
7475
7476 #ifdef HAVE_RL_COMPLETION_MATCHES
7477 #define RL_COMPLETION_MATCHES rl_completion_matches
7478 #else
7479 #ifdef HAVE_COMPLETION_MATCHES
7480 #define RL_COMPLETION_MATCHES completion_matches
7481 #endif
7482 #endif /* else just fail if we don't have either symbol */
7483
7484 char **
7485 do_completion (const char *text, int start, int end)
7486 {
7487   char **matches = NULL;
7488
7489 #ifdef HAVE_LIBREADLINE
7490   rl_completion_append_character = ' ';
7491
7492   if (start == 0)
7493     matches = RL_COMPLETION_MATCHES (text, generator);
7494   else if (complete_dest_paths)
7495     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7496 #endif
7497
7498   return matches;
7499 }
7500 ";
7501
7502 (* Generate the POD documentation for guestfish. *)
7503 and generate_fish_actions_pod () =
7504   let all_functions_sorted =
7505     List.filter (
7506       fun (_, _, _, flags, _, _, _) ->
7507         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7508     ) all_functions_sorted in
7509
7510   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7511
7512   List.iter (
7513     fun (name, style, _, flags, _, _, longdesc) ->
7514       let longdesc =
7515         Str.global_substitute rex (
7516           fun s ->
7517             let sub =
7518               try Str.matched_group 1 s
7519               with Not_found ->
7520                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7521             "C<" ^ replace_char sub '_' '-' ^ ">"
7522         ) longdesc in
7523       let name = replace_char name '_' '-' in
7524       let alias =
7525         try find_map (function FishAlias n -> Some n | _ -> None) flags
7526         with Not_found -> name in
7527
7528       pr "=head2 %s" name;
7529       if name <> alias then
7530         pr " | %s" alias;
7531       pr "\n";
7532       pr "\n";
7533       pr " %s" name;
7534       List.iter (
7535         function
7536         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7537         | OptString n -> pr " %s" n
7538         | StringList n | DeviceList n -> pr " '%s ...'" n
7539         | Bool _ -> pr " true|false"
7540         | Int n -> pr " %s" n
7541         | Int64 n -> pr " %s" n
7542         | FileIn n | FileOut n -> pr " (%s|-)" n
7543       ) (snd style);
7544       pr "\n";
7545       pr "\n";
7546       pr "%s\n\n" longdesc;
7547
7548       if List.exists (function FileIn _ | FileOut _ -> true
7549                       | _ -> false) (snd style) then
7550         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7551
7552       if List.mem ProtocolLimitWarning flags then
7553         pr "%s\n\n" protocol_limit_warning;
7554
7555       if List.mem DangerWillRobinson flags then
7556         pr "%s\n\n" danger_will_robinson;
7557
7558       match deprecation_notice flags with
7559       | None -> ()
7560       | Some txt -> pr "%s\n\n" txt
7561   ) all_functions_sorted
7562
7563 (* Generate a C function prototype. *)
7564 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7565     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7566     ?(prefix = "")
7567     ?handle name style =
7568   if extern then pr "extern ";
7569   if static then pr "static ";
7570   (match fst style with
7571    | RErr -> pr "int "
7572    | RInt _ -> pr "int "
7573    | RInt64 _ -> pr "int64_t "
7574    | RBool _ -> pr "int "
7575    | RConstString _ | RConstOptString _ -> pr "const char *"
7576    | RString _ | RBufferOut _ -> pr "char *"
7577    | RStringList _ | RHashtable _ -> pr "char **"
7578    | RStruct (_, typ) ->
7579        if not in_daemon then pr "struct guestfs_%s *" typ
7580        else pr "guestfs_int_%s *" typ
7581    | RStructList (_, typ) ->
7582        if not in_daemon then pr "struct guestfs_%s_list *" typ
7583        else pr "guestfs_int_%s_list *" typ
7584   );
7585   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7586   pr "%s%s (" prefix name;
7587   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7588     pr "void"
7589   else (
7590     let comma = ref false in
7591     (match handle with
7592      | None -> ()
7593      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7594     );
7595     let next () =
7596       if !comma then (
7597         if single_line then pr ", " else pr ",\n\t\t"
7598       );
7599       comma := true
7600     in
7601     List.iter (
7602       function
7603       | Pathname n
7604       | Device n | Dev_or_Path n
7605       | String n
7606       | OptString n ->
7607           next ();
7608           pr "const char *%s" n
7609       | StringList n | DeviceList n ->
7610           next ();
7611           pr "char *const *%s" n
7612       | Bool n -> next (); pr "int %s" n
7613       | Int n -> next (); pr "int %s" n
7614       | Int64 n -> next (); pr "int64_t %s" n
7615       | FileIn n
7616       | FileOut n ->
7617           if not in_daemon then (next (); pr "const char *%s" n)
7618     ) (snd style);
7619     if is_RBufferOut then (next (); pr "size_t *size_r");
7620   );
7621   pr ")";
7622   if semicolon then pr ";";
7623   if newline then pr "\n"
7624
7625 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7626 and generate_c_call_args ?handle ?(decl = false) style =
7627   pr "(";
7628   let comma = ref false in
7629   let next () =
7630     if !comma then pr ", ";
7631     comma := true
7632   in
7633   (match handle with
7634    | None -> ()
7635    | Some handle -> pr "%s" handle; comma := true
7636   );
7637   List.iter (
7638     fun arg ->
7639       next ();
7640       pr "%s" (name_of_argt arg)
7641   ) (snd style);
7642   (* For RBufferOut calls, add implicit &size parameter. *)
7643   if not decl then (
7644     match fst style with
7645     | RBufferOut _ ->
7646         next ();
7647         pr "&size"
7648     | _ -> ()
7649   );
7650   pr ")"
7651
7652 (* Generate the OCaml bindings interface. *)
7653 and generate_ocaml_mli () =
7654   generate_header OCamlStyle LGPLv2plus;
7655
7656   pr "\
7657 (** For API documentation you should refer to the C API
7658     in the guestfs(3) manual page.  The OCaml API uses almost
7659     exactly the same calls. *)
7660
7661 type t
7662 (** A [guestfs_h] handle. *)
7663
7664 exception Error of string
7665 (** This exception is raised when there is an error. *)
7666
7667 exception Handle_closed of string
7668 (** This exception is raised if you use a {!Guestfs.t} handle
7669     after calling {!close} on it.  The string is the name of
7670     the function. *)
7671
7672 val create : unit -> t
7673 (** Create a {!Guestfs.t} handle. *)
7674
7675 val close : t -> unit
7676 (** Close the {!Guestfs.t} handle and free up all resources used
7677     by it immediately.
7678
7679     Handles are closed by the garbage collector when they become
7680     unreferenced, but callers can call this in order to provide
7681     predictable cleanup. *)
7682
7683 ";
7684   generate_ocaml_structure_decls ();
7685
7686   (* The actions. *)
7687   List.iter (
7688     fun (name, style, _, _, _, shortdesc, _) ->
7689       generate_ocaml_prototype name style;
7690       pr "(** %s *)\n" shortdesc;
7691       pr "\n"
7692   ) all_functions_sorted
7693
7694 (* Generate the OCaml bindings implementation. *)
7695 and generate_ocaml_ml () =
7696   generate_header OCamlStyle LGPLv2plus;
7697
7698   pr "\
7699 type t
7700
7701 exception Error of string
7702 exception Handle_closed of string
7703
7704 external create : unit -> t = \"ocaml_guestfs_create\"
7705 external close : t -> unit = \"ocaml_guestfs_close\"
7706
7707 (* Give the exceptions names, so they can be raised from the C code. *)
7708 let () =
7709   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7710   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7711
7712 ";
7713
7714   generate_ocaml_structure_decls ();
7715
7716   (* The actions. *)
7717   List.iter (
7718     fun (name, style, _, _, _, shortdesc, _) ->
7719       generate_ocaml_prototype ~is_external:true name style;
7720   ) all_functions_sorted
7721
7722 (* Generate the OCaml bindings C implementation. *)
7723 and generate_ocaml_c () =
7724   generate_header CStyle LGPLv2plus;
7725
7726   pr "\
7727 #include <stdio.h>
7728 #include <stdlib.h>
7729 #include <string.h>
7730
7731 #include <caml/config.h>
7732 #include <caml/alloc.h>
7733 #include <caml/callback.h>
7734 #include <caml/fail.h>
7735 #include <caml/memory.h>
7736 #include <caml/mlvalues.h>
7737 #include <caml/signals.h>
7738
7739 #include <guestfs.h>
7740
7741 #include \"guestfs_c.h\"
7742
7743 /* Copy a hashtable of string pairs into an assoc-list.  We return
7744  * the list in reverse order, but hashtables aren't supposed to be
7745  * ordered anyway.
7746  */
7747 static CAMLprim value
7748 copy_table (char * const * argv)
7749 {
7750   CAMLparam0 ();
7751   CAMLlocal5 (rv, pairv, kv, vv, cons);
7752   int i;
7753
7754   rv = Val_int (0);
7755   for (i = 0; argv[i] != NULL; i += 2) {
7756     kv = caml_copy_string (argv[i]);
7757     vv = caml_copy_string (argv[i+1]);
7758     pairv = caml_alloc (2, 0);
7759     Store_field (pairv, 0, kv);
7760     Store_field (pairv, 1, vv);
7761     cons = caml_alloc (2, 0);
7762     Store_field (cons, 1, rv);
7763     rv = cons;
7764     Store_field (cons, 0, pairv);
7765   }
7766
7767   CAMLreturn (rv);
7768 }
7769
7770 ";
7771
7772   (* Struct copy functions. *)
7773
7774   let emit_ocaml_copy_list_function typ =
7775     pr "static CAMLprim value\n";
7776     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7777     pr "{\n";
7778     pr "  CAMLparam0 ();\n";
7779     pr "  CAMLlocal2 (rv, v);\n";
7780     pr "  unsigned int i;\n";
7781     pr "\n";
7782     pr "  if (%ss->len == 0)\n" typ;
7783     pr "    CAMLreturn (Atom (0));\n";
7784     pr "  else {\n";
7785     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7786     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7787     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7788     pr "      caml_modify (&Field (rv, i), v);\n";
7789     pr "    }\n";
7790     pr "    CAMLreturn (rv);\n";
7791     pr "  }\n";
7792     pr "}\n";
7793     pr "\n";
7794   in
7795
7796   List.iter (
7797     fun (typ, cols) ->
7798       let has_optpercent_col =
7799         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7800
7801       pr "static CAMLprim value\n";
7802       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7803       pr "{\n";
7804       pr "  CAMLparam0 ();\n";
7805       if has_optpercent_col then
7806         pr "  CAMLlocal3 (rv, v, v2);\n"
7807       else
7808         pr "  CAMLlocal2 (rv, v);\n";
7809       pr "\n";
7810       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7811       iteri (
7812         fun i col ->
7813           (match col with
7814            | name, FString ->
7815                pr "  v = caml_copy_string (%s->%s);\n" typ name
7816            | name, FBuffer ->
7817                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7818                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7819                  typ name typ name
7820            | name, FUUID ->
7821                pr "  v = caml_alloc_string (32);\n";
7822                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7823            | name, (FBytes|FInt64|FUInt64) ->
7824                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7825            | name, (FInt32|FUInt32) ->
7826                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7827            | name, FOptPercent ->
7828                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7829                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7830                pr "    v = caml_alloc (1, 0);\n";
7831                pr "    Store_field (v, 0, v2);\n";
7832                pr "  } else /* None */\n";
7833                pr "    v = Val_int (0);\n";
7834            | name, FChar ->
7835                pr "  v = Val_int (%s->%s);\n" typ name
7836           );
7837           pr "  Store_field (rv, %d, v);\n" i
7838       ) cols;
7839       pr "  CAMLreturn (rv);\n";
7840       pr "}\n";
7841       pr "\n";
7842   ) structs;
7843
7844   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7845   List.iter (
7846     function
7847     | typ, (RStructListOnly | RStructAndList) ->
7848         (* generate the function for typ *)
7849         emit_ocaml_copy_list_function typ
7850     | typ, _ -> () (* empty *)
7851   ) (rstructs_used_by all_functions);
7852
7853   (* The wrappers. *)
7854   List.iter (
7855     fun (name, style, _, _, _, _, _) ->
7856       pr "/* Automatically generated wrapper for function\n";
7857       pr " * ";
7858       generate_ocaml_prototype name style;
7859       pr " */\n";
7860       pr "\n";
7861
7862       let params =
7863         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7864
7865       let needs_extra_vs =
7866         match fst style with RConstOptString _ -> true | _ -> false in
7867
7868       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7869       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7870       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7871       pr "\n";
7872
7873       pr "CAMLprim value\n";
7874       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7875       List.iter (pr ", value %s") (List.tl params);
7876       pr ")\n";
7877       pr "{\n";
7878
7879       (match params with
7880        | [p1; p2; p3; p4; p5] ->
7881            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7882        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7883            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7884            pr "  CAMLxparam%d (%s);\n"
7885              (List.length rest) (String.concat ", " rest)
7886        | ps ->
7887            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7888       );
7889       if not needs_extra_vs then
7890         pr "  CAMLlocal1 (rv);\n"
7891       else
7892         pr "  CAMLlocal3 (rv, v, v2);\n";
7893       pr "\n";
7894
7895       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7896       pr "  if (g == NULL)\n";
7897       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7898       pr "\n";
7899
7900       List.iter (
7901         function
7902         | Pathname n
7903         | Device n | Dev_or_Path n
7904         | String n
7905         | FileIn n
7906         | FileOut n ->
7907             pr "  const char *%s = String_val (%sv);\n" n n
7908         | OptString n ->
7909             pr "  const char *%s =\n" n;
7910             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7911               n n
7912         | StringList n | DeviceList n ->
7913             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7914         | Bool n ->
7915             pr "  int %s = Bool_val (%sv);\n" n n
7916         | Int n ->
7917             pr "  int %s = Int_val (%sv);\n" n n
7918         | Int64 n ->
7919             pr "  int64_t %s = Int64_val (%sv);\n" n n
7920       ) (snd style);
7921       let error_code =
7922         match fst style with
7923         | RErr -> pr "  int r;\n"; "-1"
7924         | RInt _ -> pr "  int r;\n"; "-1"
7925         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7926         | RBool _ -> pr "  int r;\n"; "-1"
7927         | RConstString _ | RConstOptString _ ->
7928             pr "  const char *r;\n"; "NULL"
7929         | RString _ -> pr "  char *r;\n"; "NULL"
7930         | RStringList _ ->
7931             pr "  int i;\n";
7932             pr "  char **r;\n";
7933             "NULL"
7934         | RStruct (_, typ) ->
7935             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7936         | RStructList (_, typ) ->
7937             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7938         | RHashtable _ ->
7939             pr "  int i;\n";
7940             pr "  char **r;\n";
7941             "NULL"
7942         | RBufferOut _ ->
7943             pr "  char *r;\n";
7944             pr "  size_t size;\n";
7945             "NULL" in
7946       pr "\n";
7947
7948       pr "  caml_enter_blocking_section ();\n";
7949       pr "  r = guestfs_%s " name;
7950       generate_c_call_args ~handle:"g" style;
7951       pr ";\n";
7952       pr "  caml_leave_blocking_section ();\n";
7953
7954       List.iter (
7955         function
7956         | StringList n | DeviceList n ->
7957             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7958         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7959         | Bool _ | Int _ | Int64 _
7960         | FileIn _ | FileOut _ -> ()
7961       ) (snd style);
7962
7963       pr "  if (r == %s)\n" error_code;
7964       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7965       pr "\n";
7966
7967       (match fst style with
7968        | RErr -> pr "  rv = Val_unit;\n"
7969        | RInt _ -> pr "  rv = Val_int (r);\n"
7970        | RInt64 _ ->
7971            pr "  rv = caml_copy_int64 (r);\n"
7972        | RBool _ -> pr "  rv = Val_bool (r);\n"
7973        | RConstString _ ->
7974            pr "  rv = caml_copy_string (r);\n"
7975        | RConstOptString _ ->
7976            pr "  if (r) { /* Some string */\n";
7977            pr "    v = caml_alloc (1, 0);\n";
7978            pr "    v2 = caml_copy_string (r);\n";
7979            pr "    Store_field (v, 0, v2);\n";
7980            pr "  } else /* None */\n";
7981            pr "    v = Val_int (0);\n";
7982        | RString _ ->
7983            pr "  rv = caml_copy_string (r);\n";
7984            pr "  free (r);\n"
7985        | RStringList _ ->
7986            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7987            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7988            pr "  free (r);\n"
7989        | RStruct (_, typ) ->
7990            pr "  rv = copy_%s (r);\n" typ;
7991            pr "  guestfs_free_%s (r);\n" typ;
7992        | RStructList (_, typ) ->
7993            pr "  rv = copy_%s_list (r);\n" typ;
7994            pr "  guestfs_free_%s_list (r);\n" typ;
7995        | RHashtable _ ->
7996            pr "  rv = copy_table (r);\n";
7997            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7998            pr "  free (r);\n";
7999        | RBufferOut _ ->
8000            pr "  rv = caml_alloc_string (size);\n";
8001            pr "  memcpy (String_val (rv), r, size);\n";
8002       );
8003
8004       pr "  CAMLreturn (rv);\n";
8005       pr "}\n";
8006       pr "\n";
8007
8008       if List.length params > 5 then (
8009         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8010         pr "CAMLprim value ";
8011         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8012         pr "CAMLprim value\n";
8013         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8014         pr "{\n";
8015         pr "  return ocaml_guestfs_%s (argv[0]" name;
8016         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8017         pr ");\n";
8018         pr "}\n";
8019         pr "\n"
8020       )
8021   ) all_functions_sorted
8022
8023 and generate_ocaml_structure_decls () =
8024   List.iter (
8025     fun (typ, cols) ->
8026       pr "type %s = {\n" typ;
8027       List.iter (
8028         function
8029         | name, FString -> pr "  %s : string;\n" name
8030         | name, FBuffer -> pr "  %s : string;\n" name
8031         | name, FUUID -> pr "  %s : string;\n" name
8032         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8033         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8034         | name, FChar -> pr "  %s : char;\n" name
8035         | name, FOptPercent -> pr "  %s : float option;\n" name
8036       ) cols;
8037       pr "}\n";
8038       pr "\n"
8039   ) structs
8040
8041 and generate_ocaml_prototype ?(is_external = false) name style =
8042   if is_external then pr "external " else pr "val ";
8043   pr "%s : t -> " name;
8044   List.iter (
8045     function
8046     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8047     | OptString _ -> pr "string option -> "
8048     | StringList _ | DeviceList _ -> pr "string array -> "
8049     | Bool _ -> pr "bool -> "
8050     | Int _ -> pr "int -> "
8051     | Int64 _ -> pr "int64 -> "
8052   ) (snd style);
8053   (match fst style with
8054    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8055    | RInt _ -> pr "int"
8056    | RInt64 _ -> pr "int64"
8057    | RBool _ -> pr "bool"
8058    | RConstString _ -> pr "string"
8059    | RConstOptString _ -> pr "string option"
8060    | RString _ | RBufferOut _ -> pr "string"
8061    | RStringList _ -> pr "string array"
8062    | RStruct (_, typ) -> pr "%s" typ
8063    | RStructList (_, typ) -> pr "%s array" typ
8064    | RHashtable _ -> pr "(string * string) list"
8065   );
8066   if is_external then (
8067     pr " = ";
8068     if List.length (snd style) + 1 > 5 then
8069       pr "\"ocaml_guestfs_%s_byte\" " name;
8070     pr "\"ocaml_guestfs_%s\"" name
8071   );
8072   pr "\n"
8073
8074 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8075 and generate_perl_xs () =
8076   generate_header CStyle LGPLv2plus;
8077
8078   pr "\
8079 #include \"EXTERN.h\"
8080 #include \"perl.h\"
8081 #include \"XSUB.h\"
8082
8083 #include <guestfs.h>
8084
8085 #ifndef PRId64
8086 #define PRId64 \"lld\"
8087 #endif
8088
8089 static SV *
8090 my_newSVll(long long val) {
8091 #ifdef USE_64_BIT_ALL
8092   return newSViv(val);
8093 #else
8094   char buf[100];
8095   int len;
8096   len = snprintf(buf, 100, \"%%\" PRId64, val);
8097   return newSVpv(buf, len);
8098 #endif
8099 }
8100
8101 #ifndef PRIu64
8102 #define PRIu64 \"llu\"
8103 #endif
8104
8105 static SV *
8106 my_newSVull(unsigned long long val) {
8107 #ifdef USE_64_BIT_ALL
8108   return newSVuv(val);
8109 #else
8110   char buf[100];
8111   int len;
8112   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8113   return newSVpv(buf, len);
8114 #endif
8115 }
8116
8117 /* http://www.perlmonks.org/?node_id=680842 */
8118 static char **
8119 XS_unpack_charPtrPtr (SV *arg) {
8120   char **ret;
8121   AV *av;
8122   I32 i;
8123
8124   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8125     croak (\"array reference expected\");
8126
8127   av = (AV *)SvRV (arg);
8128   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8129   if (!ret)
8130     croak (\"malloc failed\");
8131
8132   for (i = 0; i <= av_len (av); i++) {
8133     SV **elem = av_fetch (av, i, 0);
8134
8135     if (!elem || !*elem)
8136       croak (\"missing element in list\");
8137
8138     ret[i] = SvPV_nolen (*elem);
8139   }
8140
8141   ret[i] = NULL;
8142
8143   return ret;
8144 }
8145
8146 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8147
8148 PROTOTYPES: ENABLE
8149
8150 guestfs_h *
8151 _create ()
8152    CODE:
8153       RETVAL = guestfs_create ();
8154       if (!RETVAL)
8155         croak (\"could not create guestfs handle\");
8156       guestfs_set_error_handler (RETVAL, NULL, NULL);
8157  OUTPUT:
8158       RETVAL
8159
8160 void
8161 DESTROY (g)
8162       guestfs_h *g;
8163  PPCODE:
8164       guestfs_close (g);
8165
8166 ";
8167
8168   List.iter (
8169     fun (name, style, _, _, _, _, _) ->
8170       (match fst style with
8171        | RErr -> pr "void\n"
8172        | RInt _ -> pr "SV *\n"
8173        | RInt64 _ -> pr "SV *\n"
8174        | RBool _ -> pr "SV *\n"
8175        | RConstString _ -> pr "SV *\n"
8176        | RConstOptString _ -> pr "SV *\n"
8177        | RString _ -> pr "SV *\n"
8178        | RBufferOut _ -> pr "SV *\n"
8179        | RStringList _
8180        | RStruct _ | RStructList _
8181        | RHashtable _ ->
8182            pr "void\n" (* all lists returned implictly on the stack *)
8183       );
8184       (* Call and arguments. *)
8185       pr "%s " name;
8186       generate_c_call_args ~handle:"g" ~decl:true style;
8187       pr "\n";
8188       pr "      guestfs_h *g;\n";
8189       iteri (
8190         fun i ->
8191           function
8192           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8193               pr "      char *%s;\n" n
8194           | OptString n ->
8195               (* http://www.perlmonks.org/?node_id=554277
8196                * Note that the implicit handle argument means we have
8197                * to add 1 to the ST(x) operator.
8198                *)
8199               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8200           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8201           | Bool n -> pr "      int %s;\n" n
8202           | Int n -> pr "      int %s;\n" n
8203           | Int64 n -> pr "      int64_t %s;\n" n
8204       ) (snd style);
8205
8206       let do_cleanups () =
8207         List.iter (
8208           function
8209           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8210           | Bool _ | Int _ | Int64 _
8211           | FileIn _ | FileOut _ -> ()
8212           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8213         ) (snd style)
8214       in
8215
8216       (* Code. *)
8217       (match fst style with
8218        | RErr ->
8219            pr "PREINIT:\n";
8220            pr "      int r;\n";
8221            pr " PPCODE:\n";
8222            pr "      r = guestfs_%s " name;
8223            generate_c_call_args ~handle:"g" style;
8224            pr ";\n";
8225            do_cleanups ();
8226            pr "      if (r == -1)\n";
8227            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8228        | RInt n
8229        | RBool n ->
8230            pr "PREINIT:\n";
8231            pr "      int %s;\n" n;
8232            pr "   CODE:\n";
8233            pr "      %s = guestfs_%s " n name;
8234            generate_c_call_args ~handle:"g" style;
8235            pr ";\n";
8236            do_cleanups ();
8237            pr "      if (%s == -1)\n" n;
8238            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8239            pr "      RETVAL = newSViv (%s);\n" n;
8240            pr " OUTPUT:\n";
8241            pr "      RETVAL\n"
8242        | RInt64 n ->
8243            pr "PREINIT:\n";
8244            pr "      int64_t %s;\n" n;
8245            pr "   CODE:\n";
8246            pr "      %s = guestfs_%s " n name;
8247            generate_c_call_args ~handle:"g" style;
8248            pr ";\n";
8249            do_cleanups ();
8250            pr "      if (%s == -1)\n" n;
8251            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8252            pr "      RETVAL = my_newSVll (%s);\n" n;
8253            pr " OUTPUT:\n";
8254            pr "      RETVAL\n"
8255        | RConstString n ->
8256            pr "PREINIT:\n";
8257            pr "      const char *%s;\n" n;
8258            pr "   CODE:\n";
8259            pr "      %s = guestfs_%s " n name;
8260            generate_c_call_args ~handle:"g" style;
8261            pr ";\n";
8262            do_cleanups ();
8263            pr "      if (%s == NULL)\n" n;
8264            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8265            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8266            pr " OUTPUT:\n";
8267            pr "      RETVAL\n"
8268        | RConstOptString n ->
8269            pr "PREINIT:\n";
8270            pr "      const char *%s;\n" n;
8271            pr "   CODE:\n";
8272            pr "      %s = guestfs_%s " n name;
8273            generate_c_call_args ~handle:"g" style;
8274            pr ";\n";
8275            do_cleanups ();
8276            pr "      if (%s == NULL)\n" n;
8277            pr "        RETVAL = &PL_sv_undef;\n";
8278            pr "      else\n";
8279            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8280            pr " OUTPUT:\n";
8281            pr "      RETVAL\n"
8282        | RString n ->
8283            pr "PREINIT:\n";
8284            pr "      char *%s;\n" n;
8285            pr "   CODE:\n";
8286            pr "      %s = guestfs_%s " n name;
8287            generate_c_call_args ~handle:"g" style;
8288            pr ";\n";
8289            do_cleanups ();
8290            pr "      if (%s == NULL)\n" n;
8291            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8292            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8293            pr "      free (%s);\n" n;
8294            pr " OUTPUT:\n";
8295            pr "      RETVAL\n"
8296        | RStringList n | RHashtable n ->
8297            pr "PREINIT:\n";
8298            pr "      char **%s;\n" n;
8299            pr "      int i, n;\n";
8300            pr " PPCODE:\n";
8301            pr "      %s = guestfs_%s " n name;
8302            generate_c_call_args ~handle:"g" style;
8303            pr ";\n";
8304            do_cleanups ();
8305            pr "      if (%s == NULL)\n" n;
8306            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8307            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8308            pr "      EXTEND (SP, n);\n";
8309            pr "      for (i = 0; i < n; ++i) {\n";
8310            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8311            pr "        free (%s[i]);\n" n;
8312            pr "      }\n";
8313            pr "      free (%s);\n" n;
8314        | RStruct (n, typ) ->
8315            let cols = cols_of_struct typ in
8316            generate_perl_struct_code typ cols name style n do_cleanups
8317        | RStructList (n, typ) ->
8318            let cols = cols_of_struct typ in
8319            generate_perl_struct_list_code typ cols name style n do_cleanups
8320        | RBufferOut n ->
8321            pr "PREINIT:\n";
8322            pr "      char *%s;\n" n;
8323            pr "      size_t size;\n";
8324            pr "   CODE:\n";
8325            pr "      %s = guestfs_%s " n name;
8326            generate_c_call_args ~handle:"g" style;
8327            pr ";\n";
8328            do_cleanups ();
8329            pr "      if (%s == NULL)\n" n;
8330            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8331            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8332            pr "      free (%s);\n" n;
8333            pr " OUTPUT:\n";
8334            pr "      RETVAL\n"
8335       );
8336
8337       pr "\n"
8338   ) all_functions
8339
8340 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8341   pr "PREINIT:\n";
8342   pr "      struct guestfs_%s_list *%s;\n" typ n;
8343   pr "      int i;\n";
8344   pr "      HV *hv;\n";
8345   pr " PPCODE:\n";
8346   pr "      %s = guestfs_%s " n name;
8347   generate_c_call_args ~handle:"g" style;
8348   pr ";\n";
8349   do_cleanups ();
8350   pr "      if (%s == NULL)\n" n;
8351   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8352   pr "      EXTEND (SP, %s->len);\n" n;
8353   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8354   pr "        hv = newHV ();\n";
8355   List.iter (
8356     function
8357     | name, FString ->
8358         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8359           name (String.length name) n name
8360     | name, FUUID ->
8361         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8362           name (String.length name) n name
8363     | name, FBuffer ->
8364         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8365           name (String.length name) n name n name
8366     | name, (FBytes|FUInt64) ->
8367         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8368           name (String.length name) n name
8369     | name, FInt64 ->
8370         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8371           name (String.length name) n name
8372     | name, (FInt32|FUInt32) ->
8373         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8374           name (String.length name) n name
8375     | name, FChar ->
8376         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8377           name (String.length name) n name
8378     | name, FOptPercent ->
8379         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8380           name (String.length name) n name
8381   ) cols;
8382   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8383   pr "      }\n";
8384   pr "      guestfs_free_%s_list (%s);\n" typ n
8385
8386 and generate_perl_struct_code typ cols name style n do_cleanups =
8387   pr "PREINIT:\n";
8388   pr "      struct guestfs_%s *%s;\n" typ n;
8389   pr " PPCODE:\n";
8390   pr "      %s = guestfs_%s " n name;
8391   generate_c_call_args ~handle:"g" style;
8392   pr ";\n";
8393   do_cleanups ();
8394   pr "      if (%s == NULL)\n" n;
8395   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8396   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8397   List.iter (
8398     fun ((name, _) as col) ->
8399       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8400
8401       match col with
8402       | name, FString ->
8403           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8404             n name
8405       | name, FBuffer ->
8406           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8407             n name n name
8408       | name, FUUID ->
8409           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8410             n name
8411       | name, (FBytes|FUInt64) ->
8412           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8413             n name
8414       | name, FInt64 ->
8415           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8416             n name
8417       | name, (FInt32|FUInt32) ->
8418           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8419             n name
8420       | name, FChar ->
8421           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8422             n name
8423       | name, FOptPercent ->
8424           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8425             n name
8426   ) cols;
8427   pr "      free (%s);\n" n
8428
8429 (* Generate Sys/Guestfs.pm. *)
8430 and generate_perl_pm () =
8431   generate_header HashStyle LGPLv2plus;
8432
8433   pr "\
8434 =pod
8435
8436 =head1 NAME
8437
8438 Sys::Guestfs - Perl bindings for libguestfs
8439
8440 =head1 SYNOPSIS
8441
8442  use Sys::Guestfs;
8443
8444  my $h = Sys::Guestfs->new ();
8445  $h->add_drive ('guest.img');
8446  $h->launch ();
8447  $h->mount ('/dev/sda1', '/');
8448  $h->touch ('/hello');
8449  $h->sync ();
8450
8451 =head1 DESCRIPTION
8452
8453 The C<Sys::Guestfs> module provides a Perl XS binding to the
8454 libguestfs API for examining and modifying virtual machine
8455 disk images.
8456
8457 Amongst the things this is good for: making batch configuration
8458 changes to guests, getting disk used/free statistics (see also:
8459 virt-df), migrating between virtualization systems (see also:
8460 virt-p2v), performing partial backups, performing partial guest
8461 clones, cloning guests and changing registry/UUID/hostname info, and
8462 much else besides.
8463
8464 Libguestfs uses Linux kernel and qemu code, and can access any type of
8465 guest filesystem that Linux and qemu can, including but not limited
8466 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8467 schemes, qcow, qcow2, vmdk.
8468
8469 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8470 LVs, what filesystem is in each LV, etc.).  It can also run commands
8471 in the context of the guest.  Also you can access filesystems over
8472 FUSE.
8473
8474 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8475 functions for using libguestfs from Perl, including integration
8476 with libvirt.
8477
8478 =head1 ERRORS
8479
8480 All errors turn into calls to C<croak> (see L<Carp(3)>).
8481
8482 =head1 METHODS
8483
8484 =over 4
8485
8486 =cut
8487
8488 package Sys::Guestfs;
8489
8490 use strict;
8491 use warnings;
8492
8493 require XSLoader;
8494 XSLoader::load ('Sys::Guestfs');
8495
8496 =item $h = Sys::Guestfs->new ();
8497
8498 Create a new guestfs handle.
8499
8500 =cut
8501
8502 sub new {
8503   my $proto = shift;
8504   my $class = ref ($proto) || $proto;
8505
8506   my $self = Sys::Guestfs::_create ();
8507   bless $self, $class;
8508   return $self;
8509 }
8510
8511 ";
8512
8513   (* Actions.  We only need to print documentation for these as
8514    * they are pulled in from the XS code automatically.
8515    *)
8516   List.iter (
8517     fun (name, style, _, flags, _, _, longdesc) ->
8518       if not (List.mem NotInDocs flags) then (
8519         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8520         pr "=item ";
8521         generate_perl_prototype name style;
8522         pr "\n\n";
8523         pr "%s\n\n" longdesc;
8524         if List.mem ProtocolLimitWarning flags then
8525           pr "%s\n\n" protocol_limit_warning;
8526         if List.mem DangerWillRobinson flags then
8527           pr "%s\n\n" danger_will_robinson;
8528         match deprecation_notice flags with
8529         | None -> ()
8530         | Some txt -> pr "%s\n\n" txt
8531       )
8532   ) all_functions_sorted;
8533
8534   (* End of file. *)
8535   pr "\
8536 =cut
8537
8538 1;
8539
8540 =back
8541
8542 =head1 COPYRIGHT
8543
8544 Copyright (C) %s Red Hat Inc.
8545
8546 =head1 LICENSE
8547
8548 Please see the file COPYING.LIB for the full license.
8549
8550 =head1 SEE ALSO
8551
8552 L<guestfs(3)>,
8553 L<guestfish(1)>,
8554 L<http://libguestfs.org>,
8555 L<Sys::Guestfs::Lib(3)>.
8556
8557 =cut
8558 " copyright_years
8559
8560 and generate_perl_prototype name style =
8561   (match fst style with
8562    | RErr -> ()
8563    | RBool n
8564    | RInt n
8565    | RInt64 n
8566    | RConstString n
8567    | RConstOptString n
8568    | RString n
8569    | RBufferOut n -> pr "$%s = " n
8570    | RStruct (n,_)
8571    | RHashtable n -> pr "%%%s = " n
8572    | RStringList n
8573    | RStructList (n,_) -> pr "@%s = " n
8574   );
8575   pr "$h->%s (" name;
8576   let comma = ref false in
8577   List.iter (
8578     fun arg ->
8579       if !comma then pr ", ";
8580       comma := true;
8581       match arg with
8582       | Pathname n | Device n | Dev_or_Path n | String n
8583       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8584           pr "$%s" n
8585       | StringList n | DeviceList n ->
8586           pr "\\@%s" n
8587   ) (snd style);
8588   pr ");"
8589
8590 (* Generate Python C module. *)
8591 and generate_python_c () =
8592   generate_header CStyle LGPLv2plus;
8593
8594   pr "\
8595 #include <Python.h>
8596
8597 #include <stdio.h>
8598 #include <stdlib.h>
8599 #include <assert.h>
8600
8601 #include \"guestfs.h\"
8602
8603 typedef struct {
8604   PyObject_HEAD
8605   guestfs_h *g;
8606 } Pyguestfs_Object;
8607
8608 static guestfs_h *
8609 get_handle (PyObject *obj)
8610 {
8611   assert (obj);
8612   assert (obj != Py_None);
8613   return ((Pyguestfs_Object *) obj)->g;
8614 }
8615
8616 static PyObject *
8617 put_handle (guestfs_h *g)
8618 {
8619   assert (g);
8620   return
8621     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8622 }
8623
8624 /* This list should be freed (but not the strings) after use. */
8625 static char **
8626 get_string_list (PyObject *obj)
8627 {
8628   int i, len;
8629   char **r;
8630
8631   assert (obj);
8632
8633   if (!PyList_Check (obj)) {
8634     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8635     return NULL;
8636   }
8637
8638   len = PyList_Size (obj);
8639   r = malloc (sizeof (char *) * (len+1));
8640   if (r == NULL) {
8641     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8642     return NULL;
8643   }
8644
8645   for (i = 0; i < len; ++i)
8646     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8647   r[len] = NULL;
8648
8649   return r;
8650 }
8651
8652 static PyObject *
8653 put_string_list (char * const * const argv)
8654 {
8655   PyObject *list;
8656   int argc, i;
8657
8658   for (argc = 0; argv[argc] != NULL; ++argc)
8659     ;
8660
8661   list = PyList_New (argc);
8662   for (i = 0; i < argc; ++i)
8663     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8664
8665   return list;
8666 }
8667
8668 static PyObject *
8669 put_table (char * const * const argv)
8670 {
8671   PyObject *list, *item;
8672   int argc, i;
8673
8674   for (argc = 0; argv[argc] != NULL; ++argc)
8675     ;
8676
8677   list = PyList_New (argc >> 1);
8678   for (i = 0; i < argc; i += 2) {
8679     item = PyTuple_New (2);
8680     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8681     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8682     PyList_SetItem (list, i >> 1, item);
8683   }
8684
8685   return list;
8686 }
8687
8688 static void
8689 free_strings (char **argv)
8690 {
8691   int argc;
8692
8693   for (argc = 0; argv[argc] != NULL; ++argc)
8694     free (argv[argc]);
8695   free (argv);
8696 }
8697
8698 static PyObject *
8699 py_guestfs_create (PyObject *self, PyObject *args)
8700 {
8701   guestfs_h *g;
8702
8703   g = guestfs_create ();
8704   if (g == NULL) {
8705     PyErr_SetString (PyExc_RuntimeError,
8706                      \"guestfs.create: failed to allocate handle\");
8707     return NULL;
8708   }
8709   guestfs_set_error_handler (g, NULL, NULL);
8710   return put_handle (g);
8711 }
8712
8713 static PyObject *
8714 py_guestfs_close (PyObject *self, PyObject *args)
8715 {
8716   PyObject *py_g;
8717   guestfs_h *g;
8718
8719   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8720     return NULL;
8721   g = get_handle (py_g);
8722
8723   guestfs_close (g);
8724
8725   Py_INCREF (Py_None);
8726   return Py_None;
8727 }
8728
8729 ";
8730
8731   let emit_put_list_function typ =
8732     pr "static PyObject *\n";
8733     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8734     pr "{\n";
8735     pr "  PyObject *list;\n";
8736     pr "  int i;\n";
8737     pr "\n";
8738     pr "  list = PyList_New (%ss->len);\n" typ;
8739     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8740     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8741     pr "  return list;\n";
8742     pr "};\n";
8743     pr "\n"
8744   in
8745
8746   (* Structures, turned into Python dictionaries. *)
8747   List.iter (
8748     fun (typ, cols) ->
8749       pr "static PyObject *\n";
8750       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8751       pr "{\n";
8752       pr "  PyObject *dict;\n";
8753       pr "\n";
8754       pr "  dict = PyDict_New ();\n";
8755       List.iter (
8756         function
8757         | name, FString ->
8758             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8759             pr "                        PyString_FromString (%s->%s));\n"
8760               typ name
8761         | name, FBuffer ->
8762             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8763             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8764               typ name typ name
8765         | name, FUUID ->
8766             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8767             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8768               typ name
8769         | name, (FBytes|FUInt64) ->
8770             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8771             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8772               typ name
8773         | name, FInt64 ->
8774             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8775             pr "                        PyLong_FromLongLong (%s->%s));\n"
8776               typ name
8777         | name, FUInt32 ->
8778             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8779             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8780               typ name
8781         | name, FInt32 ->
8782             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8783             pr "                        PyLong_FromLong (%s->%s));\n"
8784               typ name
8785         | name, FOptPercent ->
8786             pr "  if (%s->%s >= 0)\n" typ name;
8787             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8788             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8789               typ name;
8790             pr "  else {\n";
8791             pr "    Py_INCREF (Py_None);\n";
8792             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8793             pr "  }\n"
8794         | name, FChar ->
8795             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8796             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8797       ) cols;
8798       pr "  return dict;\n";
8799       pr "};\n";
8800       pr "\n";
8801
8802   ) structs;
8803
8804   (* Emit a put_TYPE_list function definition only if that function is used. *)
8805   List.iter (
8806     function
8807     | typ, (RStructListOnly | RStructAndList) ->
8808         (* generate the function for typ *)
8809         emit_put_list_function typ
8810     | typ, _ -> () (* empty *)
8811   ) (rstructs_used_by all_functions);
8812
8813   (* Python wrapper functions. *)
8814   List.iter (
8815     fun (name, style, _, _, _, _, _) ->
8816       pr "static PyObject *\n";
8817       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8818       pr "{\n";
8819
8820       pr "  PyObject *py_g;\n";
8821       pr "  guestfs_h *g;\n";
8822       pr "  PyObject *py_r;\n";
8823
8824       let error_code =
8825         match fst style with
8826         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8827         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8828         | RConstString _ | RConstOptString _ ->
8829             pr "  const char *r;\n"; "NULL"
8830         | RString _ -> pr "  char *r;\n"; "NULL"
8831         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8832         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8833         | RStructList (_, typ) ->
8834             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8835         | RBufferOut _ ->
8836             pr "  char *r;\n";
8837             pr "  size_t size;\n";
8838             "NULL" in
8839
8840       List.iter (
8841         function
8842         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8843             pr "  const char *%s;\n" n
8844         | OptString n -> pr "  const char *%s;\n" n
8845         | StringList n | DeviceList n ->
8846             pr "  PyObject *py_%s;\n" n;
8847             pr "  char **%s;\n" n
8848         | Bool n -> pr "  int %s;\n" n
8849         | Int n -> pr "  int %s;\n" n
8850         | Int64 n -> pr "  long long %s;\n" n
8851       ) (snd style);
8852
8853       pr "\n";
8854
8855       (* Convert the parameters. *)
8856       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8857       List.iter (
8858         function
8859         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8860         | OptString _ -> pr "z"
8861         | StringList _ | DeviceList _ -> pr "O"
8862         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8863         | Int _ -> pr "i"
8864         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8865                              * emulate C's int/long/long long in Python?
8866                              *)
8867       ) (snd style);
8868       pr ":guestfs_%s\",\n" name;
8869       pr "                         &py_g";
8870       List.iter (
8871         function
8872         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8873         | OptString n -> pr ", &%s" n
8874         | StringList n | DeviceList n -> pr ", &py_%s" n
8875         | Bool n -> pr ", &%s" n
8876         | Int n -> pr ", &%s" n
8877         | Int64 n -> pr ", &%s" n
8878       ) (snd style);
8879
8880       pr "))\n";
8881       pr "    return NULL;\n";
8882
8883       pr "  g = get_handle (py_g);\n";
8884       List.iter (
8885         function
8886         | Pathname _ | Device _ | Dev_or_Path _ | String _
8887         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8888         | StringList n | DeviceList n ->
8889             pr "  %s = get_string_list (py_%s);\n" n n;
8890             pr "  if (!%s) return NULL;\n" n
8891       ) (snd style);
8892
8893       pr "\n";
8894
8895       pr "  r = guestfs_%s " name;
8896       generate_c_call_args ~handle:"g" style;
8897       pr ";\n";
8898
8899       List.iter (
8900         function
8901         | Pathname _ | Device _ | Dev_or_Path _ | String _
8902         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8903         | StringList n | DeviceList n ->
8904             pr "  free (%s);\n" n
8905       ) (snd style);
8906
8907       pr "  if (r == %s) {\n" error_code;
8908       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8909       pr "    return NULL;\n";
8910       pr "  }\n";
8911       pr "\n";
8912
8913       (match fst style with
8914        | RErr ->
8915            pr "  Py_INCREF (Py_None);\n";
8916            pr "  py_r = Py_None;\n"
8917        | RInt _
8918        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8919        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8920        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8921        | RConstOptString _ ->
8922            pr "  if (r)\n";
8923            pr "    py_r = PyString_FromString (r);\n";
8924            pr "  else {\n";
8925            pr "    Py_INCREF (Py_None);\n";
8926            pr "    py_r = Py_None;\n";
8927            pr "  }\n"
8928        | RString _ ->
8929            pr "  py_r = PyString_FromString (r);\n";
8930            pr "  free (r);\n"
8931        | RStringList _ ->
8932            pr "  py_r = put_string_list (r);\n";
8933            pr "  free_strings (r);\n"
8934        | RStruct (_, typ) ->
8935            pr "  py_r = put_%s (r);\n" typ;
8936            pr "  guestfs_free_%s (r);\n" typ
8937        | RStructList (_, typ) ->
8938            pr "  py_r = put_%s_list (r);\n" typ;
8939            pr "  guestfs_free_%s_list (r);\n" typ
8940        | RHashtable n ->
8941            pr "  py_r = put_table (r);\n";
8942            pr "  free_strings (r);\n"
8943        | RBufferOut _ ->
8944            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8945            pr "  free (r);\n"
8946       );
8947
8948       pr "  return py_r;\n";
8949       pr "}\n";
8950       pr "\n"
8951   ) all_functions;
8952
8953   (* Table of functions. *)
8954   pr "static PyMethodDef methods[] = {\n";
8955   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8956   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8957   List.iter (
8958     fun (name, _, _, _, _, _, _) ->
8959       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8960         name name
8961   ) all_functions;
8962   pr "  { NULL, NULL, 0, NULL }\n";
8963   pr "};\n";
8964   pr "\n";
8965
8966   (* Init function. *)
8967   pr "\
8968 void
8969 initlibguestfsmod (void)
8970 {
8971   static int initialized = 0;
8972
8973   if (initialized) return;
8974   Py_InitModule ((char *) \"libguestfsmod\", methods);
8975   initialized = 1;
8976 }
8977 "
8978
8979 (* Generate Python module. *)
8980 and generate_python_py () =
8981   generate_header HashStyle LGPLv2plus;
8982
8983   pr "\
8984 u\"\"\"Python bindings for libguestfs
8985
8986 import guestfs
8987 g = guestfs.GuestFS ()
8988 g.add_drive (\"guest.img\")
8989 g.launch ()
8990 parts = g.list_partitions ()
8991
8992 The guestfs module provides a Python binding to the libguestfs API
8993 for examining and modifying virtual machine disk images.
8994
8995 Amongst the things this is good for: making batch configuration
8996 changes to guests, getting disk used/free statistics (see also:
8997 virt-df), migrating between virtualization systems (see also:
8998 virt-p2v), performing partial backups, performing partial guest
8999 clones, cloning guests and changing registry/UUID/hostname info, and
9000 much else besides.
9001
9002 Libguestfs uses Linux kernel and qemu code, and can access any type of
9003 guest filesystem that Linux and qemu can, including but not limited
9004 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9005 schemes, qcow, qcow2, vmdk.
9006
9007 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9008 LVs, what filesystem is in each LV, etc.).  It can also run commands
9009 in the context of the guest.  Also you can access filesystems over
9010 FUSE.
9011
9012 Errors which happen while using the API are turned into Python
9013 RuntimeError exceptions.
9014
9015 To create a guestfs handle you usually have to perform the following
9016 sequence of calls:
9017
9018 # Create the handle, call add_drive at least once, and possibly
9019 # several times if the guest has multiple block devices:
9020 g = guestfs.GuestFS ()
9021 g.add_drive (\"guest.img\")
9022
9023 # Launch the qemu subprocess and wait for it to become ready:
9024 g.launch ()
9025
9026 # Now you can issue commands, for example:
9027 logvols = g.lvs ()
9028
9029 \"\"\"
9030
9031 import libguestfsmod
9032
9033 class GuestFS:
9034     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9035
9036     def __init__ (self):
9037         \"\"\"Create a new libguestfs handle.\"\"\"
9038         self._o = libguestfsmod.create ()
9039
9040     def __del__ (self):
9041         libguestfsmod.close (self._o)
9042
9043 ";
9044
9045   List.iter (
9046     fun (name, style, _, flags, _, _, longdesc) ->
9047       pr "    def %s " name;
9048       generate_py_call_args ~handle:"self" (snd style);
9049       pr ":\n";
9050
9051       if not (List.mem NotInDocs flags) then (
9052         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9053         let doc =
9054           match fst style with
9055           | RErr | RInt _ | RInt64 _ | RBool _
9056           | RConstOptString _ | RConstString _
9057           | RString _ | RBufferOut _ -> doc
9058           | RStringList _ ->
9059               doc ^ "\n\nThis function returns a list of strings."
9060           | RStruct (_, typ) ->
9061               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9062           | RStructList (_, typ) ->
9063               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9064           | RHashtable _ ->
9065               doc ^ "\n\nThis function returns a dictionary." in
9066         let doc =
9067           if List.mem ProtocolLimitWarning flags then
9068             doc ^ "\n\n" ^ protocol_limit_warning
9069           else doc in
9070         let doc =
9071           if List.mem DangerWillRobinson flags then
9072             doc ^ "\n\n" ^ danger_will_robinson
9073           else doc in
9074         let doc =
9075           match deprecation_notice flags with
9076           | None -> doc
9077           | Some txt -> doc ^ "\n\n" ^ txt in
9078         let doc = pod2text ~width:60 name doc in
9079         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9080         let doc = String.concat "\n        " doc in
9081         pr "        u\"\"\"%s\"\"\"\n" doc;
9082       );
9083       pr "        return libguestfsmod.%s " name;
9084       generate_py_call_args ~handle:"self._o" (snd style);
9085       pr "\n";
9086       pr "\n";
9087   ) all_functions
9088
9089 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9090 and generate_py_call_args ~handle args =
9091   pr "(%s" handle;
9092   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9093   pr ")"
9094
9095 (* Useful if you need the longdesc POD text as plain text.  Returns a
9096  * list of lines.
9097  *
9098  * Because this is very slow (the slowest part of autogeneration),
9099  * we memoize the results.
9100  *)
9101 and pod2text ~width name longdesc =
9102   let key = width, name, longdesc in
9103   try Hashtbl.find pod2text_memo key
9104   with Not_found ->
9105     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9106     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9107     close_out chan;
9108     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9109     let chan = open_process_in cmd in
9110     let lines = ref [] in
9111     let rec loop i =
9112       let line = input_line chan in
9113       if i = 1 then             (* discard the first line of output *)
9114         loop (i+1)
9115       else (
9116         let line = triml line in
9117         lines := line :: !lines;
9118         loop (i+1)
9119       ) in
9120     let lines = try loop 1 with End_of_file -> List.rev !lines in
9121     unlink filename;
9122     (match close_process_in chan with
9123      | WEXITED 0 -> ()
9124      | WEXITED i ->
9125          failwithf "pod2text: process exited with non-zero status (%d)" i
9126      | WSIGNALED i | WSTOPPED i ->
9127          failwithf "pod2text: process signalled or stopped by signal %d" i
9128     );
9129     Hashtbl.add pod2text_memo key lines;
9130     pod2text_memo_updated ();
9131     lines
9132
9133 (* Generate ruby bindings. *)
9134 and generate_ruby_c () =
9135   generate_header CStyle LGPLv2plus;
9136
9137   pr "\
9138 #include <stdio.h>
9139 #include <stdlib.h>
9140
9141 #include <ruby.h>
9142
9143 #include \"guestfs.h\"
9144
9145 #include \"extconf.h\"
9146
9147 /* For Ruby < 1.9 */
9148 #ifndef RARRAY_LEN
9149 #define RARRAY_LEN(r) (RARRAY((r))->len)
9150 #endif
9151
9152 static VALUE m_guestfs;                 /* guestfs module */
9153 static VALUE c_guestfs;                 /* guestfs_h handle */
9154 static VALUE e_Error;                   /* used for all errors */
9155
9156 static void ruby_guestfs_free (void *p)
9157 {
9158   if (!p) return;
9159   guestfs_close ((guestfs_h *) p);
9160 }
9161
9162 static VALUE ruby_guestfs_create (VALUE m)
9163 {
9164   guestfs_h *g;
9165
9166   g = guestfs_create ();
9167   if (!g)
9168     rb_raise (e_Error, \"failed to create guestfs handle\");
9169
9170   /* Don't print error messages to stderr by default. */
9171   guestfs_set_error_handler (g, NULL, NULL);
9172
9173   /* Wrap it, and make sure the close function is called when the
9174    * handle goes away.
9175    */
9176   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9177 }
9178
9179 static VALUE ruby_guestfs_close (VALUE gv)
9180 {
9181   guestfs_h *g;
9182   Data_Get_Struct (gv, guestfs_h, g);
9183
9184   ruby_guestfs_free (g);
9185   DATA_PTR (gv) = NULL;
9186
9187   return Qnil;
9188 }
9189
9190 ";
9191
9192   List.iter (
9193     fun (name, style, _, _, _, _, _) ->
9194       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9195       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9196       pr ")\n";
9197       pr "{\n";
9198       pr "  guestfs_h *g;\n";
9199       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9200       pr "  if (!g)\n";
9201       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9202         name;
9203       pr "\n";
9204
9205       List.iter (
9206         function
9207         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9208             pr "  Check_Type (%sv, T_STRING);\n" n;
9209             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9210             pr "  if (!%s)\n" n;
9211             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9212             pr "              \"%s\", \"%s\");\n" n name
9213         | OptString n ->
9214             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9215         | StringList n | DeviceList n ->
9216             pr "  char **%s;\n" n;
9217             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9218             pr "  {\n";
9219             pr "    int i, len;\n";
9220             pr "    len = RARRAY_LEN (%sv);\n" n;
9221             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9222               n;
9223             pr "    for (i = 0; i < len; ++i) {\n";
9224             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9225             pr "      %s[i] = StringValueCStr (v);\n" n;
9226             pr "    }\n";
9227             pr "    %s[len] = NULL;\n" n;
9228             pr "  }\n";
9229         | Bool n ->
9230             pr "  int %s = RTEST (%sv);\n" n n
9231         | Int n ->
9232             pr "  int %s = NUM2INT (%sv);\n" n n
9233         | Int64 n ->
9234             pr "  long long %s = NUM2LL (%sv);\n" n n
9235       ) (snd style);
9236       pr "\n";
9237
9238       let error_code =
9239         match fst style with
9240         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9241         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9242         | RConstString _ | RConstOptString _ ->
9243             pr "  const char *r;\n"; "NULL"
9244         | RString _ -> pr "  char *r;\n"; "NULL"
9245         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9246         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9247         | RStructList (_, typ) ->
9248             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9249         | RBufferOut _ ->
9250             pr "  char *r;\n";
9251             pr "  size_t size;\n";
9252             "NULL" in
9253       pr "\n";
9254
9255       pr "  r = guestfs_%s " name;
9256       generate_c_call_args ~handle:"g" style;
9257       pr ";\n";
9258
9259       List.iter (
9260         function
9261         | Pathname _ | Device _ | Dev_or_Path _ | String _
9262         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9263         | StringList n | DeviceList n ->
9264             pr "  free (%s);\n" n
9265       ) (snd style);
9266
9267       pr "  if (r == %s)\n" error_code;
9268       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9269       pr "\n";
9270
9271       (match fst style with
9272        | RErr ->
9273            pr "  return Qnil;\n"
9274        | RInt _ | RBool _ ->
9275            pr "  return INT2NUM (r);\n"
9276        | RInt64 _ ->
9277            pr "  return ULL2NUM (r);\n"
9278        | RConstString _ ->
9279            pr "  return rb_str_new2 (r);\n";
9280        | RConstOptString _ ->
9281            pr "  if (r)\n";
9282            pr "    return rb_str_new2 (r);\n";
9283            pr "  else\n";
9284            pr "    return Qnil;\n";
9285        | RString _ ->
9286            pr "  VALUE rv = rb_str_new2 (r);\n";
9287            pr "  free (r);\n";
9288            pr "  return rv;\n";
9289        | RStringList _ ->
9290            pr "  int i, len = 0;\n";
9291            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9292            pr "  VALUE rv = rb_ary_new2 (len);\n";
9293            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9294            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9295            pr "    free (r[i]);\n";
9296            pr "  }\n";
9297            pr "  free (r);\n";
9298            pr "  return rv;\n"
9299        | RStruct (_, typ) ->
9300            let cols = cols_of_struct typ in
9301            generate_ruby_struct_code typ cols
9302        | RStructList (_, typ) ->
9303            let cols = cols_of_struct typ in
9304            generate_ruby_struct_list_code typ cols
9305        | RHashtable _ ->
9306            pr "  VALUE rv = rb_hash_new ();\n";
9307            pr "  int i;\n";
9308            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9309            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9310            pr "    free (r[i]);\n";
9311            pr "    free (r[i+1]);\n";
9312            pr "  }\n";
9313            pr "  free (r);\n";
9314            pr "  return rv;\n"
9315        | RBufferOut _ ->
9316            pr "  VALUE rv = rb_str_new (r, size);\n";
9317            pr "  free (r);\n";
9318            pr "  return rv;\n";
9319       );
9320
9321       pr "}\n";
9322       pr "\n"
9323   ) all_functions;
9324
9325   pr "\
9326 /* Initialize the module. */
9327 void Init__guestfs ()
9328 {
9329   m_guestfs = rb_define_module (\"Guestfs\");
9330   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9331   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9332
9333   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9334   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9335
9336 ";
9337   (* Define the rest of the methods. *)
9338   List.iter (
9339     fun (name, style, _, _, _, _, _) ->
9340       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9341       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9342   ) all_functions;
9343
9344   pr "}\n"
9345
9346 (* Ruby code to return a struct. *)
9347 and generate_ruby_struct_code typ cols =
9348   pr "  VALUE rv = rb_hash_new ();\n";
9349   List.iter (
9350     function
9351     | name, FString ->
9352         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9353     | name, FBuffer ->
9354         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9355     | name, FUUID ->
9356         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9357     | name, (FBytes|FUInt64) ->
9358         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9359     | name, FInt64 ->
9360         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9361     | name, FUInt32 ->
9362         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9363     | name, FInt32 ->
9364         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9365     | name, FOptPercent ->
9366         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9367     | name, FChar -> (* XXX wrong? *)
9368         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9369   ) cols;
9370   pr "  guestfs_free_%s (r);\n" typ;
9371   pr "  return rv;\n"
9372
9373 (* Ruby code to return a struct list. *)
9374 and generate_ruby_struct_list_code typ cols =
9375   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9376   pr "  int i;\n";
9377   pr "  for (i = 0; i < r->len; ++i) {\n";
9378   pr "    VALUE hv = rb_hash_new ();\n";
9379   List.iter (
9380     function
9381     | name, FString ->
9382         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9383     | name, FBuffer ->
9384         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
9385     | name, FUUID ->
9386         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9387     | name, (FBytes|FUInt64) ->
9388         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9389     | name, FInt64 ->
9390         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9391     | name, FUInt32 ->
9392         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9393     | name, FInt32 ->
9394         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9395     | name, FOptPercent ->
9396         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9397     | name, FChar -> (* XXX wrong? *)
9398         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9399   ) cols;
9400   pr "    rb_ary_push (rv, hv);\n";
9401   pr "  }\n";
9402   pr "  guestfs_free_%s_list (r);\n" typ;
9403   pr "  return rv;\n"
9404
9405 (* Generate Java bindings GuestFS.java file. *)
9406 and generate_java_java () =
9407   generate_header CStyle LGPLv2plus;
9408
9409   pr "\
9410 package com.redhat.et.libguestfs;
9411
9412 import java.util.HashMap;
9413 import com.redhat.et.libguestfs.LibGuestFSException;
9414 import com.redhat.et.libguestfs.PV;
9415 import com.redhat.et.libguestfs.VG;
9416 import com.redhat.et.libguestfs.LV;
9417 import com.redhat.et.libguestfs.Stat;
9418 import com.redhat.et.libguestfs.StatVFS;
9419 import com.redhat.et.libguestfs.IntBool;
9420 import com.redhat.et.libguestfs.Dirent;
9421
9422 /**
9423  * The GuestFS object is a libguestfs handle.
9424  *
9425  * @author rjones
9426  */
9427 public class GuestFS {
9428   // Load the native code.
9429   static {
9430     System.loadLibrary (\"guestfs_jni\");
9431   }
9432
9433   /**
9434    * The native guestfs_h pointer.
9435    */
9436   long g;
9437
9438   /**
9439    * Create a libguestfs handle.
9440    *
9441    * @throws LibGuestFSException
9442    */
9443   public GuestFS () throws LibGuestFSException
9444   {
9445     g = _create ();
9446   }
9447   private native long _create () throws LibGuestFSException;
9448
9449   /**
9450    * Close a libguestfs handle.
9451    *
9452    * You can also leave handles to be collected by the garbage
9453    * collector, but this method ensures that the resources used
9454    * by the handle are freed up immediately.  If you call any
9455    * other methods after closing the handle, you will get an
9456    * exception.
9457    *
9458    * @throws LibGuestFSException
9459    */
9460   public void close () throws LibGuestFSException
9461   {
9462     if (g != 0)
9463       _close (g);
9464     g = 0;
9465   }
9466   private native void _close (long g) throws LibGuestFSException;
9467
9468   public void finalize () throws LibGuestFSException
9469   {
9470     close ();
9471   }
9472
9473 ";
9474
9475   List.iter (
9476     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9477       if not (List.mem NotInDocs flags); then (
9478         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9479         let doc =
9480           if List.mem ProtocolLimitWarning flags then
9481             doc ^ "\n\n" ^ protocol_limit_warning
9482           else doc in
9483         let doc =
9484           if List.mem DangerWillRobinson flags then
9485             doc ^ "\n\n" ^ danger_will_robinson
9486           else doc in
9487         let doc =
9488           match deprecation_notice flags with
9489           | None -> doc
9490           | Some txt -> doc ^ "\n\n" ^ txt in
9491         let doc = pod2text ~width:60 name doc in
9492         let doc = List.map (            (* RHBZ#501883 *)
9493           function
9494           | "" -> "<p>"
9495           | nonempty -> nonempty
9496         ) doc in
9497         let doc = String.concat "\n   * " doc in
9498
9499         pr "  /**\n";
9500         pr "   * %s\n" shortdesc;
9501         pr "   * <p>\n";
9502         pr "   * %s\n" doc;
9503         pr "   * @throws LibGuestFSException\n";
9504         pr "   */\n";
9505         pr "  ";
9506       );
9507       generate_java_prototype ~public:true ~semicolon:false name style;
9508       pr "\n";
9509       pr "  {\n";
9510       pr "    if (g == 0)\n";
9511       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9512         name;
9513       pr "    ";
9514       if fst style <> RErr then pr "return ";
9515       pr "_%s " name;
9516       generate_java_call_args ~handle:"g" (snd style);
9517       pr ";\n";
9518       pr "  }\n";
9519       pr "  ";
9520       generate_java_prototype ~privat:true ~native:true name style;
9521       pr "\n";
9522       pr "\n";
9523   ) all_functions;
9524
9525   pr "}\n"
9526
9527 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9528 and generate_java_call_args ~handle args =
9529   pr "(%s" handle;
9530   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9531   pr ")"
9532
9533 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9534     ?(semicolon=true) name style =
9535   if privat then pr "private ";
9536   if public then pr "public ";
9537   if native then pr "native ";
9538
9539   (* return type *)
9540   (match fst style with
9541    | RErr -> pr "void ";
9542    | RInt _ -> pr "int ";
9543    | RInt64 _ -> pr "long ";
9544    | RBool _ -> pr "boolean ";
9545    | RConstString _ | RConstOptString _ | RString _
9546    | RBufferOut _ -> pr "String ";
9547    | RStringList _ -> pr "String[] ";
9548    | RStruct (_, typ) ->
9549        let name = java_name_of_struct typ in
9550        pr "%s " name;
9551    | RStructList (_, typ) ->
9552        let name = java_name_of_struct typ in
9553        pr "%s[] " name;
9554    | RHashtable _ -> pr "HashMap<String,String> ";
9555   );
9556
9557   if native then pr "_%s " name else pr "%s " name;
9558   pr "(";
9559   let needs_comma = ref false in
9560   if native then (
9561     pr "long g";
9562     needs_comma := true
9563   );
9564
9565   (* args *)
9566   List.iter (
9567     fun arg ->
9568       if !needs_comma then pr ", ";
9569       needs_comma := true;
9570
9571       match arg with
9572       | Pathname n
9573       | Device n | Dev_or_Path n
9574       | String n
9575       | OptString n
9576       | FileIn n
9577       | FileOut n ->
9578           pr "String %s" n
9579       | StringList n | DeviceList n ->
9580           pr "String[] %s" n
9581       | Bool n ->
9582           pr "boolean %s" n
9583       | Int n ->
9584           pr "int %s" n
9585       | Int64 n ->
9586           pr "long %s" n
9587   ) (snd style);
9588
9589   pr ")\n";
9590   pr "    throws LibGuestFSException";
9591   if semicolon then pr ";"
9592
9593 and generate_java_struct jtyp cols () =
9594   generate_header CStyle LGPLv2plus;
9595
9596   pr "\
9597 package com.redhat.et.libguestfs;
9598
9599 /**
9600  * Libguestfs %s structure.
9601  *
9602  * @author rjones
9603  * @see GuestFS
9604  */
9605 public class %s {
9606 " jtyp jtyp;
9607
9608   List.iter (
9609     function
9610     | name, FString
9611     | name, FUUID
9612     | name, FBuffer -> pr "  public String %s;\n" name
9613     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9614     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9615     | name, FChar -> pr "  public char %s;\n" name
9616     | name, FOptPercent ->
9617         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9618         pr "  public float %s;\n" name
9619   ) cols;
9620
9621   pr "}\n"
9622
9623 and generate_java_c () =
9624   generate_header CStyle LGPLv2plus;
9625
9626   pr "\
9627 #include <stdio.h>
9628 #include <stdlib.h>
9629 #include <string.h>
9630
9631 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9632 #include \"guestfs.h\"
9633
9634 /* Note that this function returns.  The exception is not thrown
9635  * until after the wrapper function returns.
9636  */
9637 static void
9638 throw_exception (JNIEnv *env, const char *msg)
9639 {
9640   jclass cl;
9641   cl = (*env)->FindClass (env,
9642                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9643   (*env)->ThrowNew (env, cl, msg);
9644 }
9645
9646 JNIEXPORT jlong JNICALL
9647 Java_com_redhat_et_libguestfs_GuestFS__1create
9648   (JNIEnv *env, jobject obj)
9649 {
9650   guestfs_h *g;
9651
9652   g = guestfs_create ();
9653   if (g == NULL) {
9654     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9655     return 0;
9656   }
9657   guestfs_set_error_handler (g, NULL, NULL);
9658   return (jlong) (long) g;
9659 }
9660
9661 JNIEXPORT void JNICALL
9662 Java_com_redhat_et_libguestfs_GuestFS__1close
9663   (JNIEnv *env, jobject obj, jlong jg)
9664 {
9665   guestfs_h *g = (guestfs_h *) (long) jg;
9666   guestfs_close (g);
9667 }
9668
9669 ";
9670
9671   List.iter (
9672     fun (name, style, _, _, _, _, _) ->
9673       pr "JNIEXPORT ";
9674       (match fst style with
9675        | RErr -> pr "void ";
9676        | RInt _ -> pr "jint ";
9677        | RInt64 _ -> pr "jlong ";
9678        | RBool _ -> pr "jboolean ";
9679        | RConstString _ | RConstOptString _ | RString _
9680        | RBufferOut _ -> pr "jstring ";
9681        | RStruct _ | RHashtable _ ->
9682            pr "jobject ";
9683        | RStringList _ | RStructList _ ->
9684            pr "jobjectArray ";
9685       );
9686       pr "JNICALL\n";
9687       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9688       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9689       pr "\n";
9690       pr "  (JNIEnv *env, jobject obj, jlong jg";
9691       List.iter (
9692         function
9693         | Pathname n
9694         | Device n | Dev_or_Path n
9695         | String n
9696         | OptString n
9697         | FileIn n
9698         | FileOut n ->
9699             pr ", jstring j%s" n
9700         | StringList n | DeviceList n ->
9701             pr ", jobjectArray j%s" n
9702         | Bool n ->
9703             pr ", jboolean j%s" n
9704         | Int n ->
9705             pr ", jint j%s" n
9706         | Int64 n ->
9707             pr ", jlong j%s" n
9708       ) (snd style);
9709       pr ")\n";
9710       pr "{\n";
9711       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9712       let error_code, no_ret =
9713         match fst style with
9714         | RErr -> pr "  int r;\n"; "-1", ""
9715         | RBool _
9716         | RInt _ -> pr "  int r;\n"; "-1", "0"
9717         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9718         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9719         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9720         | RString _ ->
9721             pr "  jstring jr;\n";
9722             pr "  char *r;\n"; "NULL", "NULL"
9723         | RStringList _ ->
9724             pr "  jobjectArray jr;\n";
9725             pr "  int r_len;\n";
9726             pr "  jclass cl;\n";
9727             pr "  jstring jstr;\n";
9728             pr "  char **r;\n"; "NULL", "NULL"
9729         | RStruct (_, typ) ->
9730             pr "  jobject jr;\n";
9731             pr "  jclass cl;\n";
9732             pr "  jfieldID fl;\n";
9733             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9734         | RStructList (_, typ) ->
9735             pr "  jobjectArray jr;\n";
9736             pr "  jclass cl;\n";
9737             pr "  jfieldID fl;\n";
9738             pr "  jobject jfl;\n";
9739             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9740         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9741         | RBufferOut _ ->
9742             pr "  jstring jr;\n";
9743             pr "  char *r;\n";
9744             pr "  size_t size;\n";
9745             "NULL", "NULL" in
9746       List.iter (
9747         function
9748         | Pathname n
9749         | Device n | Dev_or_Path n
9750         | String n
9751         | OptString n
9752         | FileIn n
9753         | FileOut n ->
9754             pr "  const char *%s;\n" n
9755         | StringList n | DeviceList n ->
9756             pr "  int %s_len;\n" n;
9757             pr "  const char **%s;\n" n
9758         | Bool n
9759         | Int n ->
9760             pr "  int %s;\n" n
9761         | Int64 n ->
9762             pr "  int64_t %s;\n" n
9763       ) (snd style);
9764
9765       let needs_i =
9766         (match fst style with
9767          | RStringList _ | RStructList _ -> true
9768          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9769          | RConstOptString _
9770          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9771           List.exists (function
9772                        | StringList _ -> true
9773                        | DeviceList _ -> true
9774                        | _ -> false) (snd style) in
9775       if needs_i then
9776         pr "  int i;\n";
9777
9778       pr "\n";
9779
9780       (* Get the parameters. *)
9781       List.iter (
9782         function
9783         | Pathname n
9784         | Device n | Dev_or_Path n
9785         | String n
9786         | FileIn n
9787         | FileOut n ->
9788             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9789         | OptString n ->
9790             (* This is completely undocumented, but Java null becomes
9791              * a NULL parameter.
9792              *)
9793             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9794         | StringList n | DeviceList n ->
9795             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9796             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9797             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9798             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9799               n;
9800             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9801             pr "  }\n";
9802             pr "  %s[%s_len] = NULL;\n" n n;
9803         | Bool n
9804         | Int n
9805         | Int64 n ->
9806             pr "  %s = j%s;\n" n n
9807       ) (snd style);
9808
9809       (* Make the call. *)
9810       pr "  r = guestfs_%s " name;
9811       generate_c_call_args ~handle:"g" style;
9812       pr ";\n";
9813
9814       (* Release the parameters. *)
9815       List.iter (
9816         function
9817         | Pathname n
9818         | Device n | Dev_or_Path n
9819         | String n
9820         | FileIn n
9821         | FileOut n ->
9822             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9823         | OptString n ->
9824             pr "  if (j%s)\n" n;
9825             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9826         | StringList n | DeviceList n ->
9827             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9828             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9829               n;
9830             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9831             pr "  }\n";
9832             pr "  free (%s);\n" n
9833         | Bool n
9834         | Int n
9835         | Int64 n -> ()
9836       ) (snd style);
9837
9838       (* Check for errors. *)
9839       pr "  if (r == %s) {\n" error_code;
9840       pr "    throw_exception (env, guestfs_last_error (g));\n";
9841       pr "    return %s;\n" no_ret;
9842       pr "  }\n";
9843
9844       (* Return value. *)
9845       (match fst style with
9846        | RErr -> ()
9847        | RInt _ -> pr "  return (jint) r;\n"
9848        | RBool _ -> pr "  return (jboolean) r;\n"
9849        | RInt64 _ -> pr "  return (jlong) r;\n"
9850        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9851        | RConstOptString _ ->
9852            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9853        | RString _ ->
9854            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9855            pr "  free (r);\n";
9856            pr "  return jr;\n"
9857        | RStringList _ ->
9858            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9859            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9860            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9861            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9862            pr "  for (i = 0; i < r_len; ++i) {\n";
9863            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9864            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9865            pr "    free (r[i]);\n";
9866            pr "  }\n";
9867            pr "  free (r);\n";
9868            pr "  return jr;\n"
9869        | RStruct (_, typ) ->
9870            let jtyp = java_name_of_struct typ in
9871            let cols = cols_of_struct typ in
9872            generate_java_struct_return typ jtyp cols
9873        | RStructList (_, typ) ->
9874            let jtyp = java_name_of_struct typ in
9875            let cols = cols_of_struct typ in
9876            generate_java_struct_list_return typ jtyp cols
9877        | RHashtable _ ->
9878            (* XXX *)
9879            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9880            pr "  return NULL;\n"
9881        | RBufferOut _ ->
9882            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9883            pr "  free (r);\n";
9884            pr "  return jr;\n"
9885       );
9886
9887       pr "}\n";
9888       pr "\n"
9889   ) all_functions
9890
9891 and generate_java_struct_return typ jtyp cols =
9892   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9893   pr "  jr = (*env)->AllocObject (env, cl);\n";
9894   List.iter (
9895     function
9896     | name, FString ->
9897         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9898         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9899     | name, FUUID ->
9900         pr "  {\n";
9901         pr "    char s[33];\n";
9902         pr "    memcpy (s, r->%s, 32);\n" name;
9903         pr "    s[32] = 0;\n";
9904         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9905         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9906         pr "  }\n";
9907     | name, FBuffer ->
9908         pr "  {\n";
9909         pr "    int len = r->%s_len;\n" name;
9910         pr "    char s[len+1];\n";
9911         pr "    memcpy (s, r->%s, len);\n" name;
9912         pr "    s[len] = 0;\n";
9913         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9914         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9915         pr "  }\n";
9916     | name, (FBytes|FUInt64|FInt64) ->
9917         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9918         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9919     | name, (FUInt32|FInt32) ->
9920         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9921         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9922     | name, FOptPercent ->
9923         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9924         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9925     | name, FChar ->
9926         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9927         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9928   ) cols;
9929   pr "  free (r);\n";
9930   pr "  return jr;\n"
9931
9932 and generate_java_struct_list_return typ jtyp cols =
9933   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9934   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9935   pr "  for (i = 0; i < r->len; ++i) {\n";
9936   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9937   List.iter (
9938     function
9939     | name, FString ->
9940         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9941         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9942     | name, FUUID ->
9943         pr "    {\n";
9944         pr "      char s[33];\n";
9945         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9946         pr "      s[32] = 0;\n";
9947         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9948         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9949         pr "    }\n";
9950     | name, FBuffer ->
9951         pr "    {\n";
9952         pr "      int len = r->val[i].%s_len;\n" name;
9953         pr "      char s[len+1];\n";
9954         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9955         pr "      s[len] = 0;\n";
9956         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9957         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9958         pr "    }\n";
9959     | name, (FBytes|FUInt64|FInt64) ->
9960         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9961         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9962     | name, (FUInt32|FInt32) ->
9963         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9964         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9965     | name, FOptPercent ->
9966         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9967         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9968     | name, FChar ->
9969         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9970         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9971   ) cols;
9972   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9973   pr "  }\n";
9974   pr "  guestfs_free_%s_list (r);\n" typ;
9975   pr "  return jr;\n"
9976
9977 and generate_java_makefile_inc () =
9978   generate_header HashStyle GPLv2plus;
9979
9980   pr "java_built_sources = \\\n";
9981   List.iter (
9982     fun (typ, jtyp) ->
9983         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9984   ) java_structs;
9985   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9986
9987 and generate_haskell_hs () =
9988   generate_header HaskellStyle LGPLv2plus;
9989
9990   (* XXX We only know how to generate partial FFI for Haskell
9991    * at the moment.  Please help out!
9992    *)
9993   let can_generate style =
9994     match style with
9995     | RErr, _
9996     | RInt _, _
9997     | RInt64 _, _ -> true
9998     | RBool _, _
9999     | RConstString _, _
10000     | RConstOptString _, _
10001     | RString _, _
10002     | RStringList _, _
10003     | RStruct _, _
10004     | RStructList _, _
10005     | RHashtable _, _
10006     | RBufferOut _, _ -> false in
10007
10008   pr "\
10009 {-# INCLUDE <guestfs.h> #-}
10010 {-# LANGUAGE ForeignFunctionInterface #-}
10011
10012 module Guestfs (
10013   create";
10014
10015   (* List out the names of the actions we want to export. *)
10016   List.iter (
10017     fun (name, style, _, _, _, _, _) ->
10018       if can_generate style then pr ",\n  %s" name
10019   ) all_functions;
10020
10021   pr "
10022   ) where
10023
10024 -- Unfortunately some symbols duplicate ones already present
10025 -- in Prelude.  We don't know which, so we hard-code a list
10026 -- here.
10027 import Prelude hiding (truncate)
10028
10029 import Foreign
10030 import Foreign.C
10031 import Foreign.C.Types
10032 import IO
10033 import Control.Exception
10034 import Data.Typeable
10035
10036 data GuestfsS = GuestfsS            -- represents the opaque C struct
10037 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10038 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10039
10040 -- XXX define properly later XXX
10041 data PV = PV
10042 data VG = VG
10043 data LV = LV
10044 data IntBool = IntBool
10045 data Stat = Stat
10046 data StatVFS = StatVFS
10047 data Hashtable = Hashtable
10048
10049 foreign import ccall unsafe \"guestfs_create\" c_create
10050   :: IO GuestfsP
10051 foreign import ccall unsafe \"&guestfs_close\" c_close
10052   :: FunPtr (GuestfsP -> IO ())
10053 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10054   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10055
10056 create :: IO GuestfsH
10057 create = do
10058   p <- c_create
10059   c_set_error_handler p nullPtr nullPtr
10060   h <- newForeignPtr c_close p
10061   return h
10062
10063 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10064   :: GuestfsP -> IO CString
10065
10066 -- last_error :: GuestfsH -> IO (Maybe String)
10067 -- last_error h = do
10068 --   str <- withForeignPtr h (\\p -> c_last_error p)
10069 --   maybePeek peekCString str
10070
10071 last_error :: GuestfsH -> IO (String)
10072 last_error h = do
10073   str <- withForeignPtr h (\\p -> c_last_error p)
10074   if (str == nullPtr)
10075     then return \"no error\"
10076     else peekCString str
10077
10078 ";
10079
10080   (* Generate wrappers for each foreign function. *)
10081   List.iter (
10082     fun (name, style, _, _, _, _, _) ->
10083       if can_generate style then (
10084         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10085         pr "  :: ";
10086         generate_haskell_prototype ~handle:"GuestfsP" style;
10087         pr "\n";
10088         pr "\n";
10089         pr "%s :: " name;
10090         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10091         pr "\n";
10092         pr "%s %s = do\n" name
10093           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10094         pr "  r <- ";
10095         (* Convert pointer arguments using with* functions. *)
10096         List.iter (
10097           function
10098           | FileIn n
10099           | FileOut n
10100           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10101           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10102           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10103           | Bool _ | Int _ | Int64 _ -> ()
10104         ) (snd style);
10105         (* Convert integer arguments. *)
10106         let args =
10107           List.map (
10108             function
10109             | Bool n -> sprintf "(fromBool %s)" n
10110             | Int n -> sprintf "(fromIntegral %s)" n
10111             | Int64 n -> sprintf "(fromIntegral %s)" n
10112             | FileIn n | FileOut n
10113             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10114           ) (snd style) in
10115         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10116           (String.concat " " ("p" :: args));
10117         (match fst style with
10118          | RErr | RInt _ | RInt64 _ | RBool _ ->
10119              pr "  if (r == -1)\n";
10120              pr "    then do\n";
10121              pr "      err <- last_error h\n";
10122              pr "      fail err\n";
10123          | RConstString _ | RConstOptString _ | RString _
10124          | RStringList _ | RStruct _
10125          | RStructList _ | RHashtable _ | RBufferOut _ ->
10126              pr "  if (r == nullPtr)\n";
10127              pr "    then do\n";
10128              pr "      err <- last_error h\n";
10129              pr "      fail err\n";
10130         );
10131         (match fst style with
10132          | RErr ->
10133              pr "    else return ()\n"
10134          | RInt _ ->
10135              pr "    else return (fromIntegral r)\n"
10136          | RInt64 _ ->
10137              pr "    else return (fromIntegral r)\n"
10138          | RBool _ ->
10139              pr "    else return (toBool r)\n"
10140          | RConstString _
10141          | RConstOptString _
10142          | RString _
10143          | RStringList _
10144          | RStruct _
10145          | RStructList _
10146          | RHashtable _
10147          | RBufferOut _ ->
10148              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10149         );
10150         pr "\n";
10151       )
10152   ) all_functions
10153
10154 and generate_haskell_prototype ~handle ?(hs = false) style =
10155   pr "%s -> " handle;
10156   let string = if hs then "String" else "CString" in
10157   let int = if hs then "Int" else "CInt" in
10158   let bool = if hs then "Bool" else "CInt" in
10159   let int64 = if hs then "Integer" else "Int64" in
10160   List.iter (
10161     fun arg ->
10162       (match arg with
10163        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10164        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10165        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10166        | Bool _ -> pr "%s" bool
10167        | Int _ -> pr "%s" int
10168        | Int64 _ -> pr "%s" int
10169        | FileIn _ -> pr "%s" string
10170        | FileOut _ -> pr "%s" string
10171       );
10172       pr " -> ";
10173   ) (snd style);
10174   pr "IO (";
10175   (match fst style with
10176    | RErr -> if not hs then pr "CInt"
10177    | RInt _ -> pr "%s" int
10178    | RInt64 _ -> pr "%s" int64
10179    | RBool _ -> pr "%s" bool
10180    | RConstString _ -> pr "%s" string
10181    | RConstOptString _ -> pr "Maybe %s" string
10182    | RString _ -> pr "%s" string
10183    | RStringList _ -> pr "[%s]" string
10184    | RStruct (_, typ) ->
10185        let name = java_name_of_struct typ in
10186        pr "%s" name
10187    | RStructList (_, typ) ->
10188        let name = java_name_of_struct typ in
10189        pr "[%s]" name
10190    | RHashtable _ -> pr "Hashtable"
10191    | RBufferOut _ -> pr "%s" string
10192   );
10193   pr ")"
10194
10195 and generate_csharp () =
10196   generate_header CPlusPlusStyle LGPLv2plus;
10197
10198   (* XXX Make this configurable by the C# assembly users. *)
10199   let library = "libguestfs.so.0" in
10200
10201   pr "\
10202 // These C# bindings are highly experimental at present.
10203 //
10204 // Firstly they only work on Linux (ie. Mono).  In order to get them
10205 // to work on Windows (ie. .Net) you would need to port the library
10206 // itself to Windows first.
10207 //
10208 // The second issue is that some calls are known to be incorrect and
10209 // can cause Mono to segfault.  Particularly: calls which pass or
10210 // return string[], or return any structure value.  This is because
10211 // we haven't worked out the correct way to do this from C#.
10212 //
10213 // The third issue is that when compiling you get a lot of warnings.
10214 // We are not sure whether the warnings are important or not.
10215 //
10216 // Fourthly we do not routinely build or test these bindings as part
10217 // of the make && make check cycle, which means that regressions might
10218 // go unnoticed.
10219 //
10220 // Suggestions and patches are welcome.
10221
10222 // To compile:
10223 //
10224 // gmcs Libguestfs.cs
10225 // mono Libguestfs.exe
10226 //
10227 // (You'll probably want to add a Test class / static main function
10228 // otherwise this won't do anything useful).
10229
10230 using System;
10231 using System.IO;
10232 using System.Runtime.InteropServices;
10233 using System.Runtime.Serialization;
10234 using System.Collections;
10235
10236 namespace Guestfs
10237 {
10238   class Error : System.ApplicationException
10239   {
10240     public Error (string message) : base (message) {}
10241     protected Error (SerializationInfo info, StreamingContext context) {}
10242   }
10243
10244   class Guestfs
10245   {
10246     IntPtr _handle;
10247
10248     [DllImport (\"%s\")]
10249     static extern IntPtr guestfs_create ();
10250
10251     public Guestfs ()
10252     {
10253       _handle = guestfs_create ();
10254       if (_handle == IntPtr.Zero)
10255         throw new Error (\"could not create guestfs handle\");
10256     }
10257
10258     [DllImport (\"%s\")]
10259     static extern void guestfs_close (IntPtr h);
10260
10261     ~Guestfs ()
10262     {
10263       guestfs_close (_handle);
10264     }
10265
10266     [DllImport (\"%s\")]
10267     static extern string guestfs_last_error (IntPtr h);
10268
10269 " library library library;
10270
10271   (* Generate C# structure bindings.  We prefix struct names with
10272    * underscore because C# cannot have conflicting struct names and
10273    * method names (eg. "class stat" and "stat").
10274    *)
10275   List.iter (
10276     fun (typ, cols) ->
10277       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10278       pr "    public class _%s {\n" typ;
10279       List.iter (
10280         function
10281         | name, FChar -> pr "      char %s;\n" name
10282         | name, FString -> pr "      string %s;\n" name
10283         | name, FBuffer ->
10284             pr "      uint %s_len;\n" name;
10285             pr "      string %s;\n" name
10286         | name, FUUID ->
10287             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10288             pr "      string %s;\n" name
10289         | name, FUInt32 -> pr "      uint %s;\n" name
10290         | name, FInt32 -> pr "      int %s;\n" name
10291         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10292         | name, FInt64 -> pr "      long %s;\n" name
10293         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10294       ) cols;
10295       pr "    }\n";
10296       pr "\n"
10297   ) structs;
10298
10299   (* Generate C# function bindings. *)
10300   List.iter (
10301     fun (name, style, _, _, _, shortdesc, _) ->
10302       let rec csharp_return_type () =
10303         match fst style with
10304         | RErr -> "void"
10305         | RBool n -> "bool"
10306         | RInt n -> "int"
10307         | RInt64 n -> "long"
10308         | RConstString n
10309         | RConstOptString n
10310         | RString n
10311         | RBufferOut n -> "string"
10312         | RStruct (_,n) -> "_" ^ n
10313         | RHashtable n -> "Hashtable"
10314         | RStringList n -> "string[]"
10315         | RStructList (_,n) -> sprintf "_%s[]" n
10316
10317       and c_return_type () =
10318         match fst style with
10319         | RErr
10320         | RBool _
10321         | RInt _ -> "int"
10322         | RInt64 _ -> "long"
10323         | RConstString _
10324         | RConstOptString _
10325         | RString _
10326         | RBufferOut _ -> "string"
10327         | RStruct (_,n) -> "_" ^ n
10328         | RHashtable _
10329         | RStringList _ -> "string[]"
10330         | RStructList (_,n) -> sprintf "_%s[]" n
10331
10332       and c_error_comparison () =
10333         match fst style with
10334         | RErr
10335         | RBool _
10336         | RInt _
10337         | RInt64 _ -> "== -1"
10338         | RConstString _
10339         | RConstOptString _
10340         | RString _
10341         | RBufferOut _
10342         | RStruct (_,_)
10343         | RHashtable _
10344         | RStringList _
10345         | RStructList (_,_) -> "== null"
10346
10347       and generate_extern_prototype () =
10348         pr "    static extern %s guestfs_%s (IntPtr h"
10349           (c_return_type ()) name;
10350         List.iter (
10351           function
10352           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10353           | FileIn n | FileOut n ->
10354               pr ", [In] string %s" n
10355           | StringList n | DeviceList n ->
10356               pr ", [In] string[] %s" n
10357           | Bool n ->
10358               pr ", bool %s" n
10359           | Int n ->
10360               pr ", int %s" n
10361           | Int64 n ->
10362               pr ", long %s" n
10363         ) (snd style);
10364         pr ");\n"
10365
10366       and generate_public_prototype () =
10367         pr "    public %s %s (" (csharp_return_type ()) name;
10368         let comma = ref false in
10369         let next () =
10370           if !comma then pr ", ";
10371           comma := true
10372         in
10373         List.iter (
10374           function
10375           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10376           | FileIn n | FileOut n ->
10377               next (); pr "string %s" n
10378           | StringList n | DeviceList n ->
10379               next (); pr "string[] %s" n
10380           | Bool n ->
10381               next (); pr "bool %s" n
10382           | Int n ->
10383               next (); pr "int %s" n
10384           | Int64 n ->
10385               next (); pr "long %s" n
10386         ) (snd style);
10387         pr ")\n"
10388
10389       and generate_call () =
10390         pr "guestfs_%s (_handle" name;
10391         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10392         pr ");\n";
10393       in
10394
10395       pr "    [DllImport (\"%s\")]\n" library;
10396       generate_extern_prototype ();
10397       pr "\n";
10398       pr "    /// <summary>\n";
10399       pr "    /// %s\n" shortdesc;
10400       pr "    /// </summary>\n";
10401       generate_public_prototype ();
10402       pr "    {\n";
10403       pr "      %s r;\n" (c_return_type ());
10404       pr "      r = ";
10405       generate_call ();
10406       pr "      if (r %s)\n" (c_error_comparison ());
10407       pr "        throw new Error (guestfs_last_error (_handle));\n";
10408       (match fst style with
10409        | RErr -> ()
10410        | RBool _ ->
10411            pr "      return r != 0 ? true : false;\n"
10412        | RHashtable _ ->
10413            pr "      Hashtable rr = new Hashtable ();\n";
10414            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10415            pr "        rr.Add (r[i], r[i+1]);\n";
10416            pr "      return rr;\n"
10417        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10418        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10419        | RStructList _ ->
10420            pr "      return r;\n"
10421       );
10422       pr "    }\n";
10423       pr "\n";
10424   ) all_functions_sorted;
10425
10426   pr "  }
10427 }
10428 "
10429
10430 and generate_bindtests () =
10431   generate_header CStyle LGPLv2plus;
10432
10433   pr "\
10434 #include <stdio.h>
10435 #include <stdlib.h>
10436 #include <inttypes.h>
10437 #include <string.h>
10438
10439 #include \"guestfs.h\"
10440 #include \"guestfs-internal.h\"
10441 #include \"guestfs-internal-actions.h\"
10442 #include \"guestfs_protocol.h\"
10443
10444 #define error guestfs_error
10445 #define safe_calloc guestfs_safe_calloc
10446 #define safe_malloc guestfs_safe_malloc
10447
10448 static void
10449 print_strings (char *const *argv)
10450 {
10451   int argc;
10452
10453   printf (\"[\");
10454   for (argc = 0; argv[argc] != NULL; ++argc) {
10455     if (argc > 0) printf (\", \");
10456     printf (\"\\\"%%s\\\"\", argv[argc]);
10457   }
10458   printf (\"]\\n\");
10459 }
10460
10461 /* The test0 function prints its parameters to stdout. */
10462 ";
10463
10464   let test0, tests =
10465     match test_functions with
10466     | [] -> assert false
10467     | test0 :: tests -> test0, tests in
10468
10469   let () =
10470     let (name, style, _, _, _, _, _) = test0 in
10471     generate_prototype ~extern:false ~semicolon:false ~newline:true
10472       ~handle:"g" ~prefix:"guestfs__" name style;
10473     pr "{\n";
10474     List.iter (
10475       function
10476       | Pathname n
10477       | Device n | Dev_or_Path n
10478       | String n
10479       | FileIn n
10480       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10481       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10482       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10483       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10484       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10485       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10486     ) (snd style);
10487     pr "  /* Java changes stdout line buffering so we need this: */\n";
10488     pr "  fflush (stdout);\n";
10489     pr "  return 0;\n";
10490     pr "}\n";
10491     pr "\n" in
10492
10493   List.iter (
10494     fun (name, style, _, _, _, _, _) ->
10495       if String.sub name (String.length name - 3) 3 <> "err" then (
10496         pr "/* Test normal return. */\n";
10497         generate_prototype ~extern:false ~semicolon:false ~newline:true
10498           ~handle:"g" ~prefix:"guestfs__" name style;
10499         pr "{\n";
10500         (match fst style with
10501          | RErr ->
10502              pr "  return 0;\n"
10503          | RInt _ ->
10504              pr "  int r;\n";
10505              pr "  sscanf (val, \"%%d\", &r);\n";
10506              pr "  return r;\n"
10507          | RInt64 _ ->
10508              pr "  int64_t r;\n";
10509              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10510              pr "  return r;\n"
10511          | RBool _ ->
10512              pr "  return STREQ (val, \"true\");\n"
10513          | RConstString _
10514          | RConstOptString _ ->
10515              (* Can't return the input string here.  Return a static
10516               * string so we ensure we get a segfault if the caller
10517               * tries to free it.
10518               *)
10519              pr "  return \"static string\";\n"
10520          | RString _ ->
10521              pr "  return strdup (val);\n"
10522          | RStringList _ ->
10523              pr "  char **strs;\n";
10524              pr "  int n, i;\n";
10525              pr "  sscanf (val, \"%%d\", &n);\n";
10526              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10527              pr "  for (i = 0; i < n; ++i) {\n";
10528              pr "    strs[i] = safe_malloc (g, 16);\n";
10529              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10530              pr "  }\n";
10531              pr "  strs[n] = NULL;\n";
10532              pr "  return strs;\n"
10533          | RStruct (_, typ) ->
10534              pr "  struct guestfs_%s *r;\n" typ;
10535              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10536              pr "  return r;\n"
10537          | RStructList (_, typ) ->
10538              pr "  struct guestfs_%s_list *r;\n" typ;
10539              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10540              pr "  sscanf (val, \"%%d\", &r->len);\n";
10541              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10542              pr "  return r;\n"
10543          | RHashtable _ ->
10544              pr "  char **strs;\n";
10545              pr "  int n, i;\n";
10546              pr "  sscanf (val, \"%%d\", &n);\n";
10547              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10548              pr "  for (i = 0; i < n; ++i) {\n";
10549              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10550              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10551              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10552              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10553              pr "  }\n";
10554              pr "  strs[n*2] = NULL;\n";
10555              pr "  return strs;\n"
10556          | RBufferOut _ ->
10557              pr "  return strdup (val);\n"
10558         );
10559         pr "}\n";
10560         pr "\n"
10561       ) else (
10562         pr "/* Test error return. */\n";
10563         generate_prototype ~extern:false ~semicolon:false ~newline:true
10564           ~handle:"g" ~prefix:"guestfs__" name style;
10565         pr "{\n";
10566         pr "  error (g, \"error\");\n";
10567         (match fst style with
10568          | RErr | RInt _ | RInt64 _ | RBool _ ->
10569              pr "  return -1;\n"
10570          | RConstString _ | RConstOptString _
10571          | RString _ | RStringList _ | RStruct _
10572          | RStructList _
10573          | RHashtable _
10574          | RBufferOut _ ->
10575              pr "  return NULL;\n"
10576         );
10577         pr "}\n";
10578         pr "\n"
10579       )
10580   ) tests
10581
10582 and generate_ocaml_bindtests () =
10583   generate_header OCamlStyle GPLv2plus;
10584
10585   pr "\
10586 let () =
10587   let g = Guestfs.create () in
10588 ";
10589
10590   let mkargs args =
10591     String.concat " " (
10592       List.map (
10593         function
10594         | CallString s -> "\"" ^ s ^ "\""
10595         | CallOptString None -> "None"
10596         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10597         | CallStringList xs ->
10598             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10599         | CallInt i when i >= 0 -> string_of_int i
10600         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10601         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10602         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10603         | CallBool b -> string_of_bool b
10604       ) args
10605     )
10606   in
10607
10608   generate_lang_bindtests (
10609     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10610   );
10611
10612   pr "print_endline \"EOF\"\n"
10613
10614 and generate_perl_bindtests () =
10615   pr "#!/usr/bin/perl -w\n";
10616   generate_header HashStyle GPLv2plus;
10617
10618   pr "\
10619 use strict;
10620
10621 use Sys::Guestfs;
10622
10623 my $g = Sys::Guestfs->new ();
10624 ";
10625
10626   let mkargs args =
10627     String.concat ", " (
10628       List.map (
10629         function
10630         | CallString s -> "\"" ^ s ^ "\""
10631         | CallOptString None -> "undef"
10632         | CallOptString (Some s) -> sprintf "\"%s\"" s
10633         | CallStringList xs ->
10634             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10635         | CallInt i -> string_of_int i
10636         | CallInt64 i -> Int64.to_string i
10637         | CallBool b -> if b then "1" else "0"
10638       ) args
10639     )
10640   in
10641
10642   generate_lang_bindtests (
10643     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10644   );
10645
10646   pr "print \"EOF\\n\"\n"
10647
10648 and generate_python_bindtests () =
10649   generate_header HashStyle GPLv2plus;
10650
10651   pr "\
10652 import guestfs
10653
10654 g = guestfs.GuestFS ()
10655 ";
10656
10657   let mkargs args =
10658     String.concat ", " (
10659       List.map (
10660         function
10661         | CallString s -> "\"" ^ s ^ "\""
10662         | CallOptString None -> "None"
10663         | CallOptString (Some s) -> sprintf "\"%s\"" s
10664         | CallStringList xs ->
10665             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10666         | CallInt i -> string_of_int i
10667         | CallInt64 i -> Int64.to_string i
10668         | CallBool b -> if b then "1" else "0"
10669       ) args
10670     )
10671   in
10672
10673   generate_lang_bindtests (
10674     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10675   );
10676
10677   pr "print \"EOF\"\n"
10678
10679 and generate_ruby_bindtests () =
10680   generate_header HashStyle GPLv2plus;
10681
10682   pr "\
10683 require 'guestfs'
10684
10685 g = Guestfs::create()
10686 ";
10687
10688   let mkargs args =
10689     String.concat ", " (
10690       List.map (
10691         function
10692         | CallString s -> "\"" ^ s ^ "\""
10693         | CallOptString None -> "nil"
10694         | CallOptString (Some s) -> sprintf "\"%s\"" s
10695         | CallStringList xs ->
10696             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10697         | CallInt i -> string_of_int i
10698         | CallInt64 i -> Int64.to_string i
10699         | CallBool b -> string_of_bool b
10700       ) args
10701     )
10702   in
10703
10704   generate_lang_bindtests (
10705     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10706   );
10707
10708   pr "print \"EOF\\n\"\n"
10709
10710 and generate_java_bindtests () =
10711   generate_header CStyle GPLv2plus;
10712
10713   pr "\
10714 import com.redhat.et.libguestfs.*;
10715
10716 public class Bindtests {
10717     public static void main (String[] argv)
10718     {
10719         try {
10720             GuestFS g = new GuestFS ();
10721 ";
10722
10723   let mkargs args =
10724     String.concat ", " (
10725       List.map (
10726         function
10727         | CallString s -> "\"" ^ s ^ "\""
10728         | CallOptString None -> "null"
10729         | CallOptString (Some s) -> sprintf "\"%s\"" s
10730         | CallStringList xs ->
10731             "new String[]{" ^
10732               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10733         | CallInt i -> string_of_int i
10734         | CallInt64 i -> Int64.to_string i
10735         | CallBool b -> string_of_bool b
10736       ) args
10737     )
10738   in
10739
10740   generate_lang_bindtests (
10741     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10742   );
10743
10744   pr "
10745             System.out.println (\"EOF\");
10746         }
10747         catch (Exception exn) {
10748             System.err.println (exn);
10749             System.exit (1);
10750         }
10751     }
10752 }
10753 "
10754
10755 and generate_haskell_bindtests () =
10756   generate_header HaskellStyle GPLv2plus;
10757
10758   pr "\
10759 module Bindtests where
10760 import qualified Guestfs
10761
10762 main = do
10763   g <- Guestfs.create
10764 ";
10765
10766   let mkargs args =
10767     String.concat " " (
10768       List.map (
10769         function
10770         | CallString s -> "\"" ^ s ^ "\""
10771         | CallOptString None -> "Nothing"
10772         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10773         | CallStringList xs ->
10774             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10775         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10776         | CallInt i -> string_of_int i
10777         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10778         | CallInt64 i -> Int64.to_string i
10779         | CallBool true -> "True"
10780         | CallBool false -> "False"
10781       ) args
10782     )
10783   in
10784
10785   generate_lang_bindtests (
10786     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10787   );
10788
10789   pr "  putStrLn \"EOF\"\n"
10790
10791 (* Language-independent bindings tests - we do it this way to
10792  * ensure there is parity in testing bindings across all languages.
10793  *)
10794 and generate_lang_bindtests call =
10795   call "test0" [CallString "abc"; CallOptString (Some "def");
10796                 CallStringList []; CallBool false;
10797                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10798   call "test0" [CallString "abc"; CallOptString None;
10799                 CallStringList []; CallBool false;
10800                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10801   call "test0" [CallString ""; CallOptString (Some "def");
10802                 CallStringList []; CallBool false;
10803                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10804   call "test0" [CallString ""; CallOptString (Some "");
10805                 CallStringList []; CallBool false;
10806                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10807   call "test0" [CallString "abc"; CallOptString (Some "def");
10808                 CallStringList ["1"]; CallBool false;
10809                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10810   call "test0" [CallString "abc"; CallOptString (Some "def");
10811                 CallStringList ["1"; "2"]; CallBool false;
10812                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10813   call "test0" [CallString "abc"; CallOptString (Some "def");
10814                 CallStringList ["1"]; CallBool true;
10815                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10816   call "test0" [CallString "abc"; CallOptString (Some "def");
10817                 CallStringList ["1"]; CallBool false;
10818                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10819   call "test0" [CallString "abc"; CallOptString (Some "def");
10820                 CallStringList ["1"]; CallBool false;
10821                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10822   call "test0" [CallString "abc"; CallOptString (Some "def");
10823                 CallStringList ["1"]; CallBool false;
10824                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10825   call "test0" [CallString "abc"; CallOptString (Some "def");
10826                 CallStringList ["1"]; CallBool false;
10827                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10828   call "test0" [CallString "abc"; CallOptString (Some "def");
10829                 CallStringList ["1"]; CallBool false;
10830                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10831   call "test0" [CallString "abc"; CallOptString (Some "def");
10832                 CallStringList ["1"]; CallBool false;
10833                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10834
10835 (* XXX Add here tests of the return and error functions. *)
10836
10837 (* Code to generator bindings for virt-inspector.  Currently only
10838  * implemented for OCaml code (for virt-p2v 2.0).
10839  *)
10840 let rng_input = "inspector/virt-inspector.rng"
10841
10842 (* Read the input file and parse it into internal structures.  This is
10843  * by no means a complete RELAX NG parser, but is just enough to be
10844  * able to parse the specific input file.
10845  *)
10846 type rng =
10847   | Element of string * rng list        (* <element name=name/> *)
10848   | Attribute of string * rng list        (* <attribute name=name/> *)
10849   | Interleave of rng list                (* <interleave/> *)
10850   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10851   | OneOrMore of rng                        (* <oneOrMore/> *)
10852   | Optional of rng                        (* <optional/> *)
10853   | Choice of string list                (* <choice><value/>*</choice> *)
10854   | Value of string                        (* <value>str</value> *)
10855   | Text                                (* <text/> *)
10856
10857 let rec string_of_rng = function
10858   | Element (name, xs) ->
10859       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10860   | Attribute (name, xs) ->
10861       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10862   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10863   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10864   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10865   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10866   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10867   | Value value -> "Value \"" ^ value ^ "\""
10868   | Text -> "Text"
10869
10870 and string_of_rng_list xs =
10871   String.concat ", " (List.map string_of_rng xs)
10872
10873 let rec parse_rng ?defines context = function
10874   | [] -> []
10875   | Xml.Element ("element", ["name", name], children) :: rest ->
10876       Element (name, parse_rng ?defines context children)
10877       :: parse_rng ?defines context rest
10878   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10879       Attribute (name, parse_rng ?defines context children)
10880       :: parse_rng ?defines context rest
10881   | Xml.Element ("interleave", [], children) :: rest ->
10882       Interleave (parse_rng ?defines context children)
10883       :: parse_rng ?defines context rest
10884   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10885       let rng = parse_rng ?defines context [child] in
10886       (match rng with
10887        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10888        | _ ->
10889            failwithf "%s: <zeroOrMore> contains more than one child element"
10890              context
10891       )
10892   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10893       let rng = parse_rng ?defines context [child] in
10894       (match rng with
10895        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10896        | _ ->
10897            failwithf "%s: <oneOrMore> contains more than one child element"
10898              context
10899       )
10900   | Xml.Element ("optional", [], [child]) :: rest ->
10901       let rng = parse_rng ?defines context [child] in
10902       (match rng with
10903        | [child] -> Optional child :: parse_rng ?defines context rest
10904        | _ ->
10905            failwithf "%s: <optional> contains more than one child element"
10906              context
10907       )
10908   | Xml.Element ("choice", [], children) :: rest ->
10909       let values = List.map (
10910         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10911         | _ ->
10912             failwithf "%s: can't handle anything except <value> in <choice>"
10913               context
10914       ) children in
10915       Choice values
10916       :: parse_rng ?defines context rest
10917   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10918       Value value :: parse_rng ?defines context rest
10919   | Xml.Element ("text", [], []) :: rest ->
10920       Text :: parse_rng ?defines context rest
10921   | Xml.Element ("ref", ["name", name], []) :: rest ->
10922       (* Look up the reference.  Because of limitations in this parser,
10923        * we can't handle arbitrarily nested <ref> yet.  You can only
10924        * use <ref> from inside <start>.
10925        *)
10926       (match defines with
10927        | None ->
10928            failwithf "%s: contains <ref>, but no refs are defined yet" context
10929        | Some map ->
10930            let rng = StringMap.find name map in
10931            rng @ parse_rng ?defines context rest
10932       )
10933   | x :: _ ->
10934       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10935
10936 let grammar =
10937   let xml = Xml.parse_file rng_input in
10938   match xml with
10939   | Xml.Element ("grammar", _,
10940                  Xml.Element ("start", _, gram) :: defines) ->
10941       (* The <define/> elements are referenced in the <start> section,
10942        * so build a map of those first.
10943        *)
10944       let defines = List.fold_left (
10945         fun map ->
10946           function Xml.Element ("define", ["name", name], defn) ->
10947             StringMap.add name defn map
10948           | _ ->
10949               failwithf "%s: expected <define name=name/>" rng_input
10950       ) StringMap.empty defines in
10951       let defines = StringMap.mapi parse_rng defines in
10952
10953       (* Parse the <start> clause, passing the defines. *)
10954       parse_rng ~defines "<start>" gram
10955   | _ ->
10956       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10957         rng_input
10958
10959 let name_of_field = function
10960   | Element (name, _) | Attribute (name, _)
10961   | ZeroOrMore (Element (name, _))
10962   | OneOrMore (Element (name, _))
10963   | Optional (Element (name, _)) -> name
10964   | Optional (Attribute (name, _)) -> name
10965   | Text -> (* an unnamed field in an element *)
10966       "data"
10967   | rng ->
10968       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10969
10970 (* At the moment this function only generates OCaml types.  However we
10971  * should parameterize it later so it can generate types/structs in a
10972  * variety of languages.
10973  *)
10974 let generate_types xs =
10975   (* A simple type is one that can be printed out directly, eg.
10976    * "string option".  A complex type is one which has a name and has
10977    * to be defined via another toplevel definition, eg. a struct.
10978    *
10979    * generate_type generates code for either simple or complex types.
10980    * In the simple case, it returns the string ("string option").  In
10981    * the complex case, it returns the name ("mountpoint").  In the
10982    * complex case it has to print out the definition before returning,
10983    * so it should only be called when we are at the beginning of a
10984    * new line (BOL context).
10985    *)
10986   let rec generate_type = function
10987     | Text ->                                (* string *)
10988         "string", true
10989     | Choice values ->                        (* [`val1|`val2|...] *)
10990         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10991     | ZeroOrMore rng ->                        (* <rng> list *)
10992         let t, is_simple = generate_type rng in
10993         t ^ " list (* 0 or more *)", is_simple
10994     | OneOrMore rng ->                        (* <rng> list *)
10995         let t, is_simple = generate_type rng in
10996         t ^ " list (* 1 or more *)", is_simple
10997                                         (* virt-inspector hack: bool *)
10998     | Optional (Attribute (name, [Value "1"])) ->
10999         "bool", true
11000     | Optional rng ->                        (* <rng> list *)
11001         let t, is_simple = generate_type rng in
11002         t ^ " option", is_simple
11003                                         (* type name = { fields ... } *)
11004     | Element (name, fields) when is_attrs_interleave fields ->
11005         generate_type_struct name (get_attrs_interleave fields)
11006     | Element (name, [field])                (* type name = field *)
11007     | Attribute (name, [field]) ->
11008         let t, is_simple = generate_type field in
11009         if is_simple then (t, true)
11010         else (
11011           pr "type %s = %s\n" name t;
11012           name, false
11013         )
11014     | Element (name, fields) ->              (* type name = { fields ... } *)
11015         generate_type_struct name fields
11016     | rng ->
11017         failwithf "generate_type failed at: %s" (string_of_rng rng)
11018
11019   and is_attrs_interleave = function
11020     | [Interleave _] -> true
11021     | Attribute _ :: fields -> is_attrs_interleave fields
11022     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11023     | _ -> false
11024
11025   and get_attrs_interleave = function
11026     | [Interleave fields] -> fields
11027     | ((Attribute _) as field) :: fields
11028     | ((Optional (Attribute _)) as field) :: fields ->
11029         field :: get_attrs_interleave fields
11030     | _ -> assert false
11031
11032   and generate_types xs =
11033     List.iter (fun x -> ignore (generate_type x)) xs
11034
11035   and generate_type_struct name fields =
11036     (* Calculate the types of the fields first.  We have to do this
11037      * before printing anything so we are still in BOL context.
11038      *)
11039     let types = List.map fst (List.map generate_type fields) in
11040
11041     (* Special case of a struct containing just a string and another
11042      * field.  Turn it into an assoc list.
11043      *)
11044     match types with
11045     | ["string"; other] ->
11046         let fname1, fname2 =
11047           match fields with
11048           | [f1; f2] -> name_of_field f1, name_of_field f2
11049           | _ -> assert false in
11050         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11051         name, false
11052
11053     | types ->
11054         pr "type %s = {\n" name;
11055         List.iter (
11056           fun (field, ftype) ->
11057             let fname = name_of_field field in
11058             pr "  %s_%s : %s;\n" name fname ftype
11059         ) (List.combine fields types);
11060         pr "}\n";
11061         (* Return the name of this type, and
11062          * false because it's not a simple type.
11063          *)
11064         name, false
11065   in
11066
11067   generate_types xs
11068
11069 let generate_parsers xs =
11070   (* As for generate_type above, generate_parser makes a parser for
11071    * some type, and returns the name of the parser it has generated.
11072    * Because it (may) need to print something, it should always be
11073    * called in BOL context.
11074    *)
11075   let rec generate_parser = function
11076     | Text ->                                (* string *)
11077         "string_child_or_empty"
11078     | Choice values ->                        (* [`val1|`val2|...] *)
11079         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11080           (String.concat "|"
11081              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11082     | ZeroOrMore rng ->                        (* <rng> list *)
11083         let pa = generate_parser rng in
11084         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11085     | OneOrMore rng ->                        (* <rng> list *)
11086         let pa = generate_parser rng in
11087         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11088                                         (* virt-inspector hack: bool *)
11089     | Optional (Attribute (name, [Value "1"])) ->
11090         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11091     | Optional rng ->                        (* <rng> list *)
11092         let pa = generate_parser rng in
11093         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11094                                         (* type name = { fields ... } *)
11095     | Element (name, fields) when is_attrs_interleave fields ->
11096         generate_parser_struct name (get_attrs_interleave fields)
11097     | Element (name, [field]) ->        (* type name = field *)
11098         let pa = generate_parser field in
11099         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11100         pr "let %s =\n" parser_name;
11101         pr "  %s\n" pa;
11102         pr "let parse_%s = %s\n" name parser_name;
11103         parser_name
11104     | Attribute (name, [field]) ->
11105         let pa = generate_parser field in
11106         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11107         pr "let %s =\n" parser_name;
11108         pr "  %s\n" pa;
11109         pr "let parse_%s = %s\n" name parser_name;
11110         parser_name
11111     | Element (name, fields) ->              (* type name = { fields ... } *)
11112         generate_parser_struct name ([], fields)
11113     | rng ->
11114         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11115
11116   and is_attrs_interleave = function
11117     | [Interleave _] -> true
11118     | Attribute _ :: fields -> is_attrs_interleave fields
11119     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11120     | _ -> false
11121
11122   and get_attrs_interleave = function
11123     | [Interleave fields] -> [], fields
11124     | ((Attribute _) as field) :: fields
11125     | ((Optional (Attribute _)) as field) :: fields ->
11126         let attrs, interleaves = get_attrs_interleave fields in
11127         (field :: attrs), interleaves
11128     | _ -> assert false
11129
11130   and generate_parsers xs =
11131     List.iter (fun x -> ignore (generate_parser x)) xs
11132
11133   and generate_parser_struct name (attrs, interleaves) =
11134     (* Generate parsers for the fields first.  We have to do this
11135      * before printing anything so we are still in BOL context.
11136      *)
11137     let fields = attrs @ interleaves in
11138     let pas = List.map generate_parser fields in
11139
11140     (* Generate an intermediate tuple from all the fields first.
11141      * If the type is just a string + another field, then we will
11142      * return this directly, otherwise it is turned into a record.
11143      *
11144      * RELAX NG note: This code treats <interleave> and plain lists of
11145      * fields the same.  In other words, it doesn't bother enforcing
11146      * any ordering of fields in the XML.
11147      *)
11148     pr "let parse_%s x =\n" name;
11149     pr "  let t = (\n    ";
11150     let comma = ref false in
11151     List.iter (
11152       fun x ->
11153         if !comma then pr ",\n    ";
11154         comma := true;
11155         match x with
11156         | Optional (Attribute (fname, [field])), pa ->
11157             pr "%s x" pa
11158         | Optional (Element (fname, [field])), pa ->
11159             pr "%s (optional_child %S x)" pa fname
11160         | Attribute (fname, [Text]), _ ->
11161             pr "attribute %S x" fname
11162         | (ZeroOrMore _ | OneOrMore _), pa ->
11163             pr "%s x" pa
11164         | Text, pa ->
11165             pr "%s x" pa
11166         | (field, pa) ->
11167             let fname = name_of_field field in
11168             pr "%s (child %S x)" pa fname
11169     ) (List.combine fields pas);
11170     pr "\n  ) in\n";
11171
11172     (match fields with
11173      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11174          pr "  t\n"
11175
11176      | _ ->
11177          pr "  (Obj.magic t : %s)\n" name
11178 (*
11179          List.iter (
11180            function
11181            | (Optional (Attribute (fname, [field])), pa) ->
11182                pr "  %s_%s =\n" name fname;
11183                pr "    %s x;\n" pa
11184            | (Optional (Element (fname, [field])), pa) ->
11185                pr "  %s_%s =\n" name fname;
11186                pr "    (let x = optional_child %S x in\n" fname;
11187                pr "     %s x);\n" pa
11188            | (field, pa) ->
11189                let fname = name_of_field field in
11190                pr "  %s_%s =\n" name fname;
11191                pr "    (let x = child %S x in\n" fname;
11192                pr "     %s x);\n" pa
11193          ) (List.combine fields pas);
11194          pr "}\n"
11195 *)
11196     );
11197     sprintf "parse_%s" name
11198   in
11199
11200   generate_parsers xs
11201
11202 (* Generate ocaml/guestfs_inspector.mli. *)
11203 let generate_ocaml_inspector_mli () =
11204   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11205
11206   pr "\
11207 (** This is an OCaml language binding to the external [virt-inspector]
11208     program.
11209
11210     For more information, please read the man page [virt-inspector(1)].
11211 *)
11212
11213 ";
11214
11215   generate_types grammar;
11216   pr "(** The nested information returned from the {!inspect} function. *)\n";
11217   pr "\n";
11218
11219   pr "\
11220 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11221 (** To inspect a libvirt domain called [name], pass a singleton
11222     list: [inspect [name]].  When using libvirt only, you may
11223     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11224
11225     To inspect a disk image or images, pass a list of the filenames
11226     of the disk images: [inspect filenames]
11227
11228     This function inspects the given guest or disk images and
11229     returns a list of operating system(s) found and a large amount
11230     of information about them.  In the vast majority of cases,
11231     a virtual machine only contains a single operating system.
11232
11233     If the optional [~xml] parameter is given, then this function
11234     skips running the external virt-inspector program and just
11235     parses the given XML directly (which is expected to be XML
11236     produced from a previous run of virt-inspector).  The list of
11237     names and connect URI are ignored in this case.
11238
11239     This function can throw a wide variety of exceptions, for example
11240     if the external virt-inspector program cannot be found, or if
11241     it doesn't generate valid XML.
11242 *)
11243 "
11244
11245 (* Generate ocaml/guestfs_inspector.ml. *)
11246 let generate_ocaml_inspector_ml () =
11247   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11248
11249   pr "open Unix\n";
11250   pr "\n";
11251
11252   generate_types grammar;
11253   pr "\n";
11254
11255   pr "\
11256 (* Misc functions which are used by the parser code below. *)
11257 let first_child = function
11258   | Xml.Element (_, _, c::_) -> c
11259   | Xml.Element (name, _, []) ->
11260       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11261   | Xml.PCData str ->
11262       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11263
11264 let string_child_or_empty = function
11265   | Xml.Element (_, _, [Xml.PCData s]) -> s
11266   | Xml.Element (_, _, []) -> \"\"
11267   | Xml.Element (x, _, _) ->
11268       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11269                 x ^ \" instead\")
11270   | Xml.PCData str ->
11271       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11272
11273 let optional_child name xml =
11274   let children = Xml.children xml in
11275   try
11276     Some (List.find (function
11277                      | Xml.Element (n, _, _) when n = name -> true
11278                      | _ -> false) children)
11279   with
11280     Not_found -> None
11281
11282 let child name xml =
11283   match optional_child name xml with
11284   | Some c -> c
11285   | None ->
11286       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11287
11288 let attribute name xml =
11289   try Xml.attrib xml name
11290   with Xml.No_attribute _ ->
11291     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11292
11293 ";
11294
11295   generate_parsers grammar;
11296   pr "\n";
11297
11298   pr "\
11299 (* Run external virt-inspector, then use parser to parse the XML. *)
11300 let inspect ?connect ?xml names =
11301   let xml =
11302     match xml with
11303     | None ->
11304         if names = [] then invalid_arg \"inspect: no names given\";
11305         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11306           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11307           names in
11308         let cmd = List.map Filename.quote cmd in
11309         let cmd = String.concat \" \" cmd in
11310         let chan = open_process_in cmd in
11311         let xml = Xml.parse_in chan in
11312         (match close_process_in chan with
11313          | WEXITED 0 -> ()
11314          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11315          | WSIGNALED i | WSTOPPED i ->
11316              failwith (\"external virt-inspector command died or stopped on sig \" ^
11317                        string_of_int i)
11318         );
11319         xml
11320     | Some doc ->
11321         Xml.parse_string doc in
11322   parse_operatingsystems xml
11323 "
11324
11325 (* This is used to generate the src/MAX_PROC_NR file which
11326  * contains the maximum procedure number, a surrogate for the
11327  * ABI version number.  See src/Makefile.am for the details.
11328  *)
11329 and generate_max_proc_nr () =
11330   let proc_nrs = List.map (
11331     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11332   ) daemon_functions in
11333
11334   let max_proc_nr = List.fold_left max 0 proc_nrs in
11335
11336   pr "%d\n" max_proc_nr
11337
11338 let output_to filename k =
11339   let filename_new = filename ^ ".new" in
11340   chan := open_out filename_new;
11341   k ();
11342   close_out !chan;
11343   chan := Pervasives.stdout;
11344
11345   (* Is the new file different from the current file? *)
11346   if Sys.file_exists filename && files_equal filename filename_new then
11347     unlink filename_new                 (* same, so skip it *)
11348   else (
11349     (* different, overwrite old one *)
11350     (try chmod filename 0o644 with Unix_error _ -> ());
11351     rename filename_new filename;
11352     chmod filename 0o444;
11353     printf "written %s\n%!" filename;
11354   )
11355
11356 let perror msg = function
11357   | Unix_error (err, _, _) ->
11358       eprintf "%s: %s\n" msg (error_message err)
11359   | exn ->
11360       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11361
11362 (* Main program. *)
11363 let () =
11364   let lock_fd =
11365     try openfile "HACKING" [O_RDWR] 0
11366     with
11367     | Unix_error (ENOENT, _, _) ->
11368         eprintf "\
11369 You are probably running this from the wrong directory.
11370 Run it from the top source directory using the command
11371   src/generator.ml
11372 ";
11373         exit 1
11374     | exn ->
11375         perror "open: HACKING" exn;
11376         exit 1 in
11377
11378   (* Acquire a lock so parallel builds won't try to run the generator
11379    * twice at the same time.  Subsequent builds will wait for the first
11380    * one to finish.  Note the lock is released implicitly when the
11381    * program exits.
11382    *)
11383   (try lockf lock_fd F_LOCK 1
11384    with exn ->
11385      perror "lock: HACKING" exn;
11386      exit 1);
11387
11388   check_functions ();
11389
11390   output_to "src/guestfs_protocol.x" generate_xdr;
11391   output_to "src/guestfs-structs.h" generate_structs_h;
11392   output_to "src/guestfs-actions.h" generate_actions_h;
11393   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11394   output_to "src/guestfs-actions.c" generate_client_actions;
11395   output_to "src/guestfs-bindtests.c" generate_bindtests;
11396   output_to "src/guestfs-structs.pod" generate_structs_pod;
11397   output_to "src/guestfs-actions.pod" generate_actions_pod;
11398   output_to "src/guestfs-availability.pod" generate_availability_pod;
11399   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11400   output_to "src/libguestfs.syms" generate_linker_script;
11401   output_to "daemon/actions.h" generate_daemon_actions_h;
11402   output_to "daemon/stubs.c" generate_daemon_actions;
11403   output_to "daemon/names.c" generate_daemon_names;
11404   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11405   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11406   output_to "capitests/tests.c" generate_tests;
11407   output_to "fish/cmds.c" generate_fish_cmds;
11408   output_to "fish/completion.c" generate_fish_completion;
11409   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11410   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11411   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11412   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11413   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11414   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11415   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11416   output_to "perl/Guestfs.xs" generate_perl_xs;
11417   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11418   output_to "perl/bindtests.pl" generate_perl_bindtests;
11419   output_to "python/guestfs-py.c" generate_python_c;
11420   output_to "python/guestfs.py" generate_python_py;
11421   output_to "python/bindtests.py" generate_python_bindtests;
11422   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11423   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11424   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11425
11426   List.iter (
11427     fun (typ, jtyp) ->
11428       let cols = cols_of_struct typ in
11429       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11430       output_to filename (generate_java_struct jtyp cols);
11431   ) java_structs;
11432
11433   output_to "java/Makefile.inc" generate_java_makefile_inc;
11434   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11435   output_to "java/Bindtests.java" generate_java_bindtests;
11436   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11437   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11438   output_to "csharp/Libguestfs.cs" generate_csharp;
11439
11440   (* Always generate this file last, and unconditionally.  It's used
11441    * by the Makefile to know when we must re-run the generator.
11442    *)
11443   let chan = open_out "src/stamp-generator" in
11444   fprintf chan "1\n";
11445   close_out chan;
11446
11447   printf "generated %d lines of code\n" !lines