1e6d3c0da853b753968e3dbeef00b126dfeb27b1
[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   | FishOutput of fish_output_t (* how to display output in guestfish *)
186   | NotInFish             (* do not export via guestfish *)
187   | NotInDocs             (* do not add this function to documentation *)
188   | DeprecatedBy of string (* function is deprecated, use .. instead *)
189   | Optional of string    (* function is part of an optional group *)
190
191 and fish_output_t =
192   | FishOutputOctal       (* for int return, print in octal *)
193   | FishOutputHexadecimal (* for int return, print in hex *)
194
195 (* You can supply zero or as many tests as you want per API call.
196  *
197  * Note that the test environment has 3 block devices, of size 500MB,
198  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
199  * a fourth ISO block device with some known files on it (/dev/sdd).
200  *
201  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
202  * Number of cylinders was 63 for IDE emulated disks with precisely
203  * the same size.  How exactly this is calculated is a mystery.
204  *
205  * The ISO block device (/dev/sdd) comes from images/test.iso.
206  *
207  * To be able to run the tests in a reasonable amount of time,
208  * the virtual machine and block devices are reused between tests.
209  * So don't try testing kill_subprocess :-x
210  *
211  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
212  *
213  * Don't assume anything about the previous contents of the block
214  * devices.  Use 'Init*' to create some initial scenarios.
215  *
216  * You can add a prerequisite clause to any individual test.  This
217  * is a run-time check, which, if it fails, causes the test to be
218  * skipped.  Useful if testing a command which might not work on
219  * all variations of libguestfs builds.  A test that has prerequisite
220  * of 'Always' is run unconditionally.
221  *
222  * In addition, packagers can skip individual tests by setting the
223  * environment variables:     eg:
224  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
225  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
226  *)
227 type tests = (test_init * test_prereq * test) list
228 and test =
229     (* Run the command sequence and just expect nothing to fail. *)
230   | TestRun of seq
231
232     (* Run the command sequence and expect the output of the final
233      * command to be the string.
234      *)
235   | TestOutput of seq * string
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the list of strings.
239      *)
240   | TestOutputList of seq * string list
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of block devices (could be either
244      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
245      * character of each string).
246      *)
247   | TestOutputListOfDevices of seq * string list
248
249     (* Run the command sequence and expect the output of the final
250      * command to be the integer.
251      *)
252   | TestOutputInt of seq * int
253
254     (* Run the command sequence and expect the output of the final
255      * command to be <op> <int>, eg. ">=", "1".
256      *)
257   | TestOutputIntOp of seq * string * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be a true value (!= 0 or != NULL).
261      *)
262   | TestOutputTrue of seq
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a false value (== 0 or == NULL, but not an error).
266      *)
267   | TestOutputFalse of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a list of the given length (but don't care about
271      * content).
272      *)
273   | TestOutputLength of seq * int
274
275     (* Run the command sequence and expect the output of the final
276      * command to be a buffer (RBufferOut), ie. string + size.
277      *)
278   | TestOutputBuffer of seq * string
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a structure.
282      *)
283   | TestOutputStruct of seq * test_field_compare list
284
285     (* Run the command sequence and expect the final command (only)
286      * to fail.
287      *)
288   | TestLastFail of seq
289
290 and test_field_compare =
291   | CompareWithInt of string * int
292   | CompareWithIntOp of string * string * int
293   | CompareWithString of string * string
294   | CompareFieldsIntEq of string * string
295   | CompareFieldsStrEq of string * string
296
297 (* Test prerequisites. *)
298 and test_prereq =
299     (* Test always runs. *)
300   | Always
301
302     (* Test is currently disabled - eg. it fails, or it tests some
303      * unimplemented feature.
304      *)
305   | Disabled
306
307     (* 'string' is some C code (a function body) that should return
308      * true or false.  The test will run if the code returns true.
309      *)
310   | If of string
311
312     (* As for 'If' but the test runs _unless_ the code returns true. *)
313   | Unless of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388 ]
389
390 let test_all_rets = [
391   (* except for RErr, which is tested thoroughly elsewhere *)
392   "test0rint",         RInt "valout";
393   "test0rint64",       RInt64 "valout";
394   "test0rbool",        RBool "valout";
395   "test0rconststring", RConstString "valout";
396   "test0rconstoptstring", RConstOptString "valout";
397   "test0rstring",      RString "valout";
398   "test0rstringlist",  RStringList "valout";
399   "test0rstruct",      RStruct ("valout", "lvm_pv");
400   "test0rstructlist",  RStructList ("valout", "lvm_pv");
401   "test0rhashtable",   RHashtable "valout";
402 ]
403
404 let test_functions = [
405   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
406    [],
407    "internal test function - do not use",
408    "\
409 This is an internal test function which is used to test whether
410 the automatically generated bindings can handle every possible
411 parameter type correctly.
412
413 It echos the contents of each parameter to stdout.
414
415 You probably don't want to call this function.");
416 ] @ List.flatten (
417   List.map (
418     fun (name, ret) ->
419       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
420         [],
421         "internal test function - do not use",
422         "\
423 This is an internal test function which is used to test whether
424 the automatically generated bindings can handle every possible
425 return type correctly.
426
427 It converts string C<val> to the return type.
428
429 You probably don't want to call this function.");
430        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
431         [],
432         "internal test function - do not use",
433         "\
434 This is an internal test function which is used to test whether
435 the automatically generated bindings can handle every possible
436 return type correctly.
437
438 This function always returns an error.
439
440 You probably don't want to call this function.")]
441   ) test_all_rets
442 )
443
444 (* non_daemon_functions are any functions which don't get processed
445  * in the daemon, eg. functions for setting and getting local
446  * configuration values.
447  *)
448
449 let non_daemon_functions = test_functions @ [
450   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
451    [],
452    "launch the qemu subprocess",
453    "\
454 Internally libguestfs is implemented by running a virtual machine
455 using L<qemu(1)>.
456
457 You should call this after configuring the handle
458 (eg. adding drives) but before performing any actions.");
459
460   ("wait_ready", (RErr, []), -1, [NotInFish],
461    [],
462    "wait until the qemu subprocess launches (no op)",
463    "\
464 This function is a no op.
465
466 In versions of the API E<lt> 1.0.71 you had to call this function
467 just after calling C<guestfs_launch> to wait for the launch
468 to complete.  However this is no longer necessary because
469 C<guestfs_launch> now does the waiting.
470
471 If you see any calls to this function in code then you can just
472 remove them, unless you want to retain compatibility with older
473 versions of the API.");
474
475   ("kill_subprocess", (RErr, []), -1, [],
476    [],
477    "kill the qemu subprocess",
478    "\
479 This kills the qemu subprocess.  You should never need to call this.");
480
481   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
482    [],
483    "add an image to examine or modify",
484    "\
485 This function adds a virtual machine disk image C<filename> to the
486 guest.  The first time you call this function, the disk appears as IDE
487 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
488 so on.
489
490 You don't necessarily need to be root when using libguestfs.  However
491 you obviously do need sufficient permissions to access the filename
492 for whatever operations you want to perform (ie. read access if you
493 just want to read the image or write access if you want to modify the
494 image).
495
496 This is equivalent to the qemu parameter
497 C<-drive file=filename,cache=off,if=...>.
498
499 C<cache=off> is omitted in cases where it is not supported by
500 the underlying filesystem.
501
502 C<if=...> is set at compile time by the configuration option
503 C<./configure --with-drive-if=...>.  In the rare case where you
504 might need to change this at run time, use C<guestfs_add_drive_with_if>
505 or C<guestfs_add_drive_ro_with_if>.
506
507 Note that this call checks for the existence of C<filename>.  This
508 stops you from specifying other types of drive which are supported
509 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
510 the general C<guestfs_config> call instead.");
511
512   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
513    [],
514    "add a CD-ROM disk image to examine",
515    "\
516 This function adds a virtual CD-ROM disk image to the guest.
517
518 This is equivalent to the qemu parameter C<-cdrom filename>.
519
520 Notes:
521
522 =over 4
523
524 =item *
525
526 This call checks for the existence of C<filename>.  This
527 stops you from specifying other types of drive which are supported
528 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
529 the general C<guestfs_config> call instead.
530
531 =item *
532
533 If you just want to add an ISO file (often you use this as an
534 efficient way to transfer large files into the guest), then you
535 should probably use C<guestfs_add_drive_ro> instead.
536
537 =back");
538
539   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
540    [],
541    "add a drive in snapshot mode (read-only)",
542    "\
543 This adds a drive in snapshot mode, making it effectively
544 read-only.
545
546 Note that writes to the device are allowed, and will be seen for
547 the duration of the guestfs handle, but they are written
548 to a temporary file which is discarded as soon as the guestfs
549 handle is closed.  We don't currently have any method to enable
550 changes to be committed, although qemu can support this.
551
552 This is equivalent to the qemu parameter
553 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
554
555 C<if=...> is set at compile time by the configuration option
556 C<./configure --with-drive-if=...>.  In the rare case where you
557 might need to change this at run time, use C<guestfs_add_drive_with_if>
558 or C<guestfs_add_drive_ro_with_if>.
559
560 C<readonly=on> is only added where qemu supports this option.
561
562 Note that this call checks for the existence of C<filename>.  This
563 stops you from specifying other types of drive which are supported
564 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
565 the general C<guestfs_config> call instead.");
566
567   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
568    [],
569    "add qemu parameters",
570    "\
571 This can be used to add arbitrary qemu command line parameters
572 of the form C<-param value>.  Actually it's not quite arbitrary - we
573 prevent you from setting some parameters which would interfere with
574 parameters that we use.
575
576 The first character of C<param> string must be a C<-> (dash).
577
578 C<value> can be NULL.");
579
580   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
581    [],
582    "set the qemu binary",
583    "\
584 Set the qemu binary that we will use.
585
586 The default is chosen when the library was compiled by the
587 configure script.
588
589 You can also override this by setting the C<LIBGUESTFS_QEMU>
590 environment variable.
591
592 Setting C<qemu> to C<NULL> restores the default qemu binary.
593
594 Note that you should call this function as early as possible
595 after creating the handle.  This is because some pre-launch
596 operations depend on testing qemu features (by running C<qemu -help>).
597 If the qemu binary changes, we don't retest features, and
598 so you might see inconsistent results.  Using the environment
599 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
600 the qemu binary at the same time as the handle is created.");
601
602   ("get_qemu", (RConstString "qemu", []), -1, [],
603    [InitNone, Always, TestRun (
604       [["get_qemu"]])],
605    "get the qemu binary",
606    "\
607 Return the current qemu binary.
608
609 This is always non-NULL.  If it wasn't set already, then this will
610 return the default qemu binary name.");
611
612   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
613    [],
614    "set the search path",
615    "\
616 Set the path that libguestfs searches for kernel and initrd.img.
617
618 The default is C<$libdir/guestfs> unless overridden by setting
619 C<LIBGUESTFS_PATH> environment variable.
620
621 Setting C<path> to C<NULL> restores the default path.");
622
623   ("get_path", (RConstString "path", []), -1, [],
624    [InitNone, Always, TestRun (
625       [["get_path"]])],
626    "get the search path",
627    "\
628 Return the current search path.
629
630 This is always non-NULL.  If it wasn't set already, then this will
631 return the default path.");
632
633   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
634    [],
635    "add options to kernel command line",
636    "\
637 This function is used to add additional options to the
638 guest kernel command line.
639
640 The default is C<NULL> unless overridden by setting
641 C<LIBGUESTFS_APPEND> environment variable.
642
643 Setting C<append> to C<NULL> means I<no> additional options
644 are passed (libguestfs always adds a few of its own).");
645
646   ("get_append", (RConstOptString "append", []), -1, [],
647    (* This cannot be tested with the current framework.  The
648     * function can return NULL in normal operations, which the
649     * test framework interprets as an error.
650     *)
651    [],
652    "get the additional kernel options",
653    "\
654 Return the additional kernel options which are added to the
655 guest kernel command line.
656
657 If C<NULL> then no options are added.");
658
659   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
660    [],
661    "set autosync mode",
662    "\
663 If C<autosync> is true, this enables autosync.  Libguestfs will make a
664 best effort attempt to run C<guestfs_umount_all> followed by
665 C<guestfs_sync> when the handle is closed
666 (also if the program exits without closing handles).
667
668 This is disabled by default (except in guestfish where it is
669 enabled by default).");
670
671   ("get_autosync", (RBool "autosync", []), -1, [],
672    [InitNone, Always, TestRun (
673       [["get_autosync"]])],
674    "get autosync mode",
675    "\
676 Get the autosync flag.");
677
678   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
679    [],
680    "set verbose mode",
681    "\
682 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
683
684 Verbose messages are disabled unless the environment variable
685 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
686
687   ("get_verbose", (RBool "verbose", []), -1, [],
688    [],
689    "get verbose mode",
690    "\
691 This returns the verbose messages flag.");
692
693   ("is_ready", (RBool "ready", []), -1, [],
694    [InitNone, Always, TestOutputTrue (
695       [["is_ready"]])],
696    "is ready to accept commands",
697    "\
698 This returns true iff this handle is ready to accept commands
699 (in the C<READY> state).
700
701 For more information on states, see L<guestfs(3)>.");
702
703   ("is_config", (RBool "config", []), -1, [],
704    [InitNone, Always, TestOutputFalse (
705       [["is_config"]])],
706    "is in configuration state",
707    "\
708 This returns true iff this handle is being configured
709 (in the C<CONFIG> state).
710
711 For more information on states, see L<guestfs(3)>.");
712
713   ("is_launching", (RBool "launching", []), -1, [],
714    [InitNone, Always, TestOutputFalse (
715       [["is_launching"]])],
716    "is launching subprocess",
717    "\
718 This returns true iff this handle is launching the subprocess
719 (in the C<LAUNCHING> state).
720
721 For more information on states, see L<guestfs(3)>.");
722
723   ("is_busy", (RBool "busy", []), -1, [],
724    [InitNone, Always, TestOutputFalse (
725       [["is_busy"]])],
726    "is busy processing a command",
727    "\
728 This returns true iff this handle is busy processing a command
729 (in the C<BUSY> state).
730
731 For more information on states, see L<guestfs(3)>.");
732
733   ("get_state", (RInt "state", []), -1, [],
734    [],
735    "get the current state",
736    "\
737 This returns the current state as an opaque integer.  This is
738 only useful for printing debug and internal error messages.
739
740 For more information on states, see L<guestfs(3)>.");
741
742   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
743    [InitNone, Always, TestOutputInt (
744       [["set_memsize"; "500"];
745        ["get_memsize"]], 500)],
746    "set memory allocated to the qemu subprocess",
747    "\
748 This sets the memory size in megabytes allocated to the
749 qemu subprocess.  This only has any effect if called before
750 C<guestfs_launch>.
751
752 You can also change this by setting the environment
753 variable C<LIBGUESTFS_MEMSIZE> before the handle is
754 created.
755
756 For more information on the architecture of libguestfs,
757 see L<guestfs(3)>.");
758
759   ("get_memsize", (RInt "memsize", []), -1, [],
760    [InitNone, Always, TestOutputIntOp (
761       [["get_memsize"]], ">=", 256)],
762    "get memory allocated to the qemu subprocess",
763    "\
764 This gets the memory size in megabytes allocated to the
765 qemu subprocess.
766
767 If C<guestfs_set_memsize> was not called
768 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
769 then this returns the compiled-in default value for memsize.
770
771 For more information on the architecture of libguestfs,
772 see L<guestfs(3)>.");
773
774   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
775    [InitNone, Always, TestOutputIntOp (
776       [["get_pid"]], ">=", 1)],
777    "get PID of qemu subprocess",
778    "\
779 Return the process ID of the qemu subprocess.  If there is no
780 qemu subprocess, then this will return an error.
781
782 This is an internal call used for debugging and testing.");
783
784   ("version", (RStruct ("version", "version"), []), -1, [],
785    [InitNone, Always, TestOutputStruct (
786       [["version"]], [CompareWithInt ("major", 1)])],
787    "get the library version number",
788    "\
789 Return the libguestfs version number that the program is linked
790 against.
791
792 Note that because of dynamic linking this is not necessarily
793 the version of libguestfs that you compiled against.  You can
794 compile the program, and then at runtime dynamically link
795 against a completely different C<libguestfs.so> library.
796
797 This call was added in version C<1.0.58>.  In previous
798 versions of libguestfs there was no way to get the version
799 number.  From C code you can use ELF weak linking tricks to find out if
800 this symbol exists (if it doesn't, then it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 I<Note:> Don't use this call to test for availability
812 of features.  Distro backports makes this unreliable.  Use
813 C<guestfs_available> instead.");
814
815   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
816    [InitNone, Always, TestOutputTrue (
817       [["set_selinux"; "true"];
818        ["get_selinux"]])],
819    "set SELinux enabled or disabled at appliance boot",
820    "\
821 This sets the selinux flag that is passed to the appliance
822 at boot time.  The default is C<selinux=0> (disabled).
823
824 Note that if SELinux is enabled, it is always in
825 Permissive mode (C<enforcing=0>).
826
827 For more information on the architecture of libguestfs,
828 see L<guestfs(3)>.");
829
830   ("get_selinux", (RBool "selinux", []), -1, [],
831    [],
832    "get SELinux enabled flag",
833    "\
834 This returns the current setting of the selinux flag which
835 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
836
837 For more information on the architecture of libguestfs,
838 see L<guestfs(3)>.");
839
840   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
841    [InitNone, Always, TestOutputFalse (
842       [["set_trace"; "false"];
843        ["get_trace"]])],
844    "enable or disable command traces",
845    "\
846 If the command trace flag is set to 1, then commands are
847 printed on stdout before they are executed in a format
848 which is very similar to the one used by guestfish.  In
849 other words, you can run a program with this enabled, and
850 you will get out a script which you can feed to guestfish
851 to perform the same set of actions.
852
853 If you want to trace C API calls into libguestfs (and
854 other libraries) then possibly a better way is to use
855 the external ltrace(1) command.
856
857 Command traces are disabled unless the environment variable
858 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
859
860   ("get_trace", (RBool "trace", []), -1, [],
861    [],
862    "get command trace enabled flag",
863    "\
864 Return the command trace flag.");
865
866   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
867    [InitNone, Always, TestOutputFalse (
868       [["set_direct"; "false"];
869        ["get_direct"]])],
870    "enable or disable direct appliance mode",
871    "\
872 If the direct appliance mode flag is enabled, then stdin and
873 stdout are passed directly through to the appliance once it
874 is launched.
875
876 One consequence of this is that log messages aren't caught
877 by the library and handled by C<guestfs_set_log_message_callback>,
878 but go straight to stdout.
879
880 You probably don't want to use this unless you know what you
881 are doing.
882
883 The default is disabled.");
884
885   ("get_direct", (RBool "direct", []), -1, [],
886    [],
887    "get direct appliance mode flag",
888    "\
889 Return the direct appliance mode flag.");
890
891   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
892    [InitNone, Always, TestOutputTrue (
893       [["set_recovery_proc"; "true"];
894        ["get_recovery_proc"]])],
895    "enable or disable the recovery process",
896    "\
897 If this is called with the parameter C<false> then
898 C<guestfs_launch> does not create a recovery process.  The
899 purpose of the recovery process is to stop runaway qemu
900 processes in the case where the main program aborts abruptly.
901
902 This only has any effect if called before C<guestfs_launch>,
903 and the default is true.
904
905 About the only time when you would want to disable this is
906 if the main process will fork itself into the background
907 (\"daemonize\" itself).  In this case the recovery process
908 thinks that the main program has disappeared and so kills
909 qemu, which is not very helpful.");
910
911   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
912    [],
913    "get recovery process enabled flag",
914    "\
915 Return the recovery process enabled flag.");
916
917   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
918    [],
919    "add a drive specifying the QEMU block emulation to use",
920    "\
921 This is the same as C<guestfs_add_drive> but it allows you
922 to specify the QEMU interface emulation to use at run time.");
923
924   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
925    [],
926    "add a drive read-only specifying the QEMU block emulation to use",
927    "\
928 This is the same as C<guestfs_add_drive_ro> but it allows you
929 to specify the QEMU interface emulation to use at run time.");
930
931 ]
932
933 (* daemon_functions are any functions which cause some action
934  * to take place in the daemon.
935  *)
936
937 let daemon_functions = [
938   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
939    [InitEmpty, Always, TestOutput (
940       [["part_disk"; "/dev/sda"; "mbr"];
941        ["mkfs"; "ext2"; "/dev/sda1"];
942        ["mount"; "/dev/sda1"; "/"];
943        ["write_file"; "/new"; "new file contents"; "0"];
944        ["cat"; "/new"]], "new file contents")],
945    "mount a guest disk at a position in the filesystem",
946    "\
947 Mount a guest disk at a position in the filesystem.  Block devices
948 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
949 the guest.  If those block devices contain partitions, they will have
950 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
951 names can be used.
952
953 The rules are the same as for L<mount(2)>:  A filesystem must
954 first be mounted on C</> before others can be mounted.  Other
955 filesystems can only be mounted on directories which already
956 exist.
957
958 The mounted filesystem is writable, if we have sufficient permissions
959 on the underlying device.
960
961 B<Important note:>
962 When you use this call, the filesystem options C<sync> and C<noatime>
963 are set implicitly.  This was originally done because we thought it
964 would improve reliability, but it turns out that I<-o sync> has a
965 very large negative performance impact and negligible effect on
966 reliability.  Therefore we recommend that you avoid using
967 C<guestfs_mount> in any code that needs performance, and instead
968 use C<guestfs_mount_options> (use an empty string for the first
969 parameter if you don't want any options).");
970
971   ("sync", (RErr, []), 2, [],
972    [ InitEmpty, Always, TestRun [["sync"]]],
973    "sync disks, writes are flushed through to the disk image",
974    "\
975 This syncs the disk, so that any writes are flushed through to the
976 underlying disk image.
977
978 You should always call this if you have modified a disk image, before
979 closing the handle.");
980
981   ("touch", (RErr, [Pathname "path"]), 3, [],
982    [InitBasicFS, Always, TestOutputTrue (
983       [["touch"; "/new"];
984        ["exists"; "/new"]])],
985    "update file timestamps or create a new file",
986    "\
987 Touch acts like the L<touch(1)> command.  It can be used to
988 update the timestamps on a file, or, if the file does not exist,
989 to create a new zero-length file.");
990
991   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
992    [InitISOFS, Always, TestOutput (
993       [["cat"; "/known-2"]], "abcdef\n")],
994    "list the contents of a file",
995    "\
996 Return the contents of the file named C<path>.
997
998 Note that this function cannot correctly handle binary files
999 (specifically, files containing C<\\0> character which is treated
1000 as end of string).  For those you need to use the C<guestfs_read_file>
1001 or C<guestfs_download> functions which have a more complex interface.");
1002
1003   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1004    [], (* XXX Tricky to test because it depends on the exact format
1005         * of the 'ls -l' command, which changes between F10 and F11.
1006         *)
1007    "list the files in a directory (long format)",
1008    "\
1009 List the files in C<directory> (relative to the root directory,
1010 there is no cwd) in the format of 'ls -la'.
1011
1012 This command is mostly useful for interactive sessions.  It
1013 is I<not> intended that you try to parse the output string.");
1014
1015   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1016    [InitBasicFS, Always, TestOutputList (
1017       [["touch"; "/new"];
1018        ["touch"; "/newer"];
1019        ["touch"; "/newest"];
1020        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1021    "list the files in a directory",
1022    "\
1023 List the files in C<directory> (relative to the root directory,
1024 there is no cwd).  The '.' and '..' entries are not returned, but
1025 hidden files are shown.
1026
1027 This command is mostly useful for interactive sessions.  Programs
1028 should probably use C<guestfs_readdir> instead.");
1029
1030   ("list_devices", (RStringList "devices", []), 7, [],
1031    [InitEmpty, Always, TestOutputListOfDevices (
1032       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1033    "list the block devices",
1034    "\
1035 List all the block devices.
1036
1037 The full block device names are returned, eg. C</dev/sda>");
1038
1039   ("list_partitions", (RStringList "partitions", []), 8, [],
1040    [InitBasicFS, Always, TestOutputListOfDevices (
1041       [["list_partitions"]], ["/dev/sda1"]);
1042     InitEmpty, Always, TestOutputListOfDevices (
1043       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1044        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1045    "list the partitions",
1046    "\
1047 List all the partitions detected on all block devices.
1048
1049 The full partition device names are returned, eg. C</dev/sda1>
1050
1051 This does not return logical volumes.  For that you will need to
1052 call C<guestfs_lvs>.");
1053
1054   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1055    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1056       [["pvs"]], ["/dev/sda1"]);
1057     InitEmpty, Always, TestOutputListOfDevices (
1058       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1059        ["pvcreate"; "/dev/sda1"];
1060        ["pvcreate"; "/dev/sda2"];
1061        ["pvcreate"; "/dev/sda3"];
1062        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1063    "list the LVM physical volumes (PVs)",
1064    "\
1065 List all the physical volumes detected.  This is the equivalent
1066 of the L<pvs(8)> command.
1067
1068 This returns a list of just the device names that contain
1069 PVs (eg. C</dev/sda2>).
1070
1071 See also C<guestfs_pvs_full>.");
1072
1073   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1074    [InitBasicFSonLVM, Always, TestOutputList (
1075       [["vgs"]], ["VG"]);
1076     InitEmpty, Always, TestOutputList (
1077       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1078        ["pvcreate"; "/dev/sda1"];
1079        ["pvcreate"; "/dev/sda2"];
1080        ["pvcreate"; "/dev/sda3"];
1081        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1082        ["vgcreate"; "VG2"; "/dev/sda3"];
1083        ["vgs"]], ["VG1"; "VG2"])],
1084    "list the LVM volume groups (VGs)",
1085    "\
1086 List all the volumes groups detected.  This is the equivalent
1087 of the L<vgs(8)> command.
1088
1089 This returns a list of just the volume group names that were
1090 detected (eg. C<VolGroup00>).
1091
1092 See also C<guestfs_vgs_full>.");
1093
1094   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1095    [InitBasicFSonLVM, Always, TestOutputList (
1096       [["lvs"]], ["/dev/VG/LV"]);
1097     InitEmpty, Always, TestOutputList (
1098       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1099        ["pvcreate"; "/dev/sda1"];
1100        ["pvcreate"; "/dev/sda2"];
1101        ["pvcreate"; "/dev/sda3"];
1102        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1103        ["vgcreate"; "VG2"; "/dev/sda3"];
1104        ["lvcreate"; "LV1"; "VG1"; "50"];
1105        ["lvcreate"; "LV2"; "VG1"; "50"];
1106        ["lvcreate"; "LV3"; "VG2"; "50"];
1107        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1108    "list the LVM logical volumes (LVs)",
1109    "\
1110 List all the logical volumes detected.  This is the equivalent
1111 of the L<lvs(8)> command.
1112
1113 This returns a list of the logical volume device names
1114 (eg. C</dev/VolGroup00/LogVol00>).
1115
1116 See also C<guestfs_lvs_full>.");
1117
1118   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM physical volumes (PVs)",
1121    "\
1122 List all the physical volumes detected.  This is the equivalent
1123 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM volume groups (VGs)",
1128    "\
1129 List all the volumes groups detected.  This is the equivalent
1130 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM logical volumes (LVs)",
1135    "\
1136 List all the logical volumes detected.  This is the equivalent
1137 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1140    [InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1142     InitISOFS, Always, TestOutputList (
1143       [["read_lines"; "/empty"]], [])],
1144    "read file as lines",
1145    "\
1146 Return the contents of the file named C<path>.
1147
1148 The file contents are returned as a list of lines.  Trailing
1149 C<LF> and C<CRLF> character sequences are I<not> returned.
1150
1151 Note that this function cannot correctly handle binary files
1152 (specifically, files containing C<\\0> character which is treated
1153 as end of line).  For those you need to use the C<guestfs_read_file>
1154 function which has a more complex interface.");
1155
1156   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1157    [], (* XXX Augeas code needs tests. *)
1158    "create a new Augeas handle",
1159    "\
1160 Create a new Augeas handle for editing configuration files.
1161 If there was any previous Augeas handle associated with this
1162 guestfs session, then it is closed.
1163
1164 You must call this before using any other C<guestfs_aug_*>
1165 commands.
1166
1167 C<root> is the filesystem root.  C<root> must not be NULL,
1168 use C</> instead.
1169
1170 The flags are the same as the flags defined in
1171 E<lt>augeas.hE<gt>, the logical I<or> of the following
1172 integers:
1173
1174 =over 4
1175
1176 =item C<AUG_SAVE_BACKUP> = 1
1177
1178 Keep the original file with a C<.augsave> extension.
1179
1180 =item C<AUG_SAVE_NEWFILE> = 2
1181
1182 Save changes into a file with extension C<.augnew>, and
1183 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1184
1185 =item C<AUG_TYPE_CHECK> = 4
1186
1187 Typecheck lenses (can be expensive).
1188
1189 =item C<AUG_NO_STDINC> = 8
1190
1191 Do not use standard load path for modules.
1192
1193 =item C<AUG_SAVE_NOOP> = 16
1194
1195 Make save a no-op, just record what would have been changed.
1196
1197 =item C<AUG_NO_LOAD> = 32
1198
1199 Do not load the tree in C<guestfs_aug_init>.
1200
1201 =back
1202
1203 To close the handle, you can call C<guestfs_aug_close>.
1204
1205 To find out more about Augeas, see L<http://augeas.net/>.");
1206
1207   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1208    [], (* XXX Augeas code needs tests. *)
1209    "close the current Augeas handle",
1210    "\
1211 Close the current Augeas handle and free up any resources
1212 used by it.  After calling this, you have to call
1213 C<guestfs_aug_init> again before you can use any other
1214 Augeas functions.");
1215
1216   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "define an Augeas variable",
1219    "\
1220 Defines an Augeas variable C<name> whose value is the result
1221 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1222 undefined.
1223
1224 On success this returns the number of nodes in C<expr>, or
1225 C<0> if C<expr> evaluates to something which is not a nodeset.");
1226
1227   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1228    [], (* XXX Augeas code needs tests. *)
1229    "define an Augeas node",
1230    "\
1231 Defines a variable C<name> whose value is the result of
1232 evaluating C<expr>.
1233
1234 If C<expr> evaluates to an empty nodeset, a node is created,
1235 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1236 C<name> will be the nodeset containing that single node.
1237
1238 On success this returns a pair containing the
1239 number of nodes in the nodeset, and a boolean flag
1240 if a node was created.");
1241
1242   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "look up the value of an Augeas path",
1245    "\
1246 Look up the value associated with C<path>.  If C<path>
1247 matches exactly one node, the C<value> is returned.");
1248
1249   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "set Augeas path to value",
1252    "\
1253 Set the value associated with C<path> to C<val>.
1254
1255 In the Augeas API, it is possible to clear a node by setting
1256 the value to NULL.  Due to an oversight in the libguestfs API
1257 you cannot do that with this call.  Instead you must use the
1258 C<guestfs_aug_clear> call.");
1259
1260   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1261    [], (* XXX Augeas code needs tests. *)
1262    "insert a sibling Augeas node",
1263    "\
1264 Create a new sibling C<label> for C<path>, inserting it into
1265 the tree before or after C<path> (depending on the boolean
1266 flag C<before>).
1267
1268 C<path> must match exactly one existing node in the tree, and
1269 C<label> must be a label, ie. not contain C</>, C<*> or end
1270 with a bracketed index C<[N]>.");
1271
1272   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1273    [], (* XXX Augeas code needs tests. *)
1274    "remove an Augeas path",
1275    "\
1276 Remove C<path> and all of its children.
1277
1278 On success this returns the number of entries which were removed.");
1279
1280   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "move Augeas node",
1283    "\
1284 Move the node C<src> to C<dest>.  C<src> must match exactly
1285 one node.  C<dest> is overwritten if it exists.");
1286
1287   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "return Augeas nodes which match augpath",
1290    "\
1291 Returns a list of paths which match the path expression C<path>.
1292 The returned paths are sufficiently qualified so that they match
1293 exactly one node in the current tree.");
1294
1295   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1296    [], (* XXX Augeas code needs tests. *)
1297    "write all pending Augeas changes to disk",
1298    "\
1299 This writes all pending changes to disk.
1300
1301 The flags which were passed to C<guestfs_aug_init> affect exactly
1302 how files are saved.");
1303
1304   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "load files into the tree",
1307    "\
1308 Load files into the tree.
1309
1310 See C<aug_load> in the Augeas documentation for the full gory
1311 details.");
1312
1313   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1314    [], (* XXX Augeas code needs tests. *)
1315    "list Augeas nodes under augpath",
1316    "\
1317 This is just a shortcut for listing C<guestfs_aug_match>
1318 C<path/*> and sorting the resulting nodes into alphabetical order.");
1319
1320   ("rm", (RErr, [Pathname "path"]), 29, [],
1321    [InitBasicFS, Always, TestRun
1322       [["touch"; "/new"];
1323        ["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["rm"; "/new"]];
1326     InitBasicFS, Always, TestLastFail
1327       [["mkdir"; "/new"];
1328        ["rm"; "/new"]]],
1329    "remove a file",
1330    "\
1331 Remove the single file C<path>.");
1332
1333   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1334    [InitBasicFS, Always, TestRun
1335       [["mkdir"; "/new"];
1336        ["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["rmdir"; "/new"]];
1339     InitBasicFS, Always, TestLastFail
1340       [["touch"; "/new"];
1341        ["rmdir"; "/new"]]],
1342    "remove a directory",
1343    "\
1344 Remove the single directory C<path>.");
1345
1346   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1347    [InitBasicFS, Always, TestOutputFalse
1348       [["mkdir"; "/new"];
1349        ["mkdir"; "/new/foo"];
1350        ["touch"; "/new/foo/bar"];
1351        ["rm_rf"; "/new"];
1352        ["exists"; "/new"]]],
1353    "remove a file or directory recursively",
1354    "\
1355 Remove the file or directory C<path>, recursively removing the
1356 contents if its a directory.  This is like the C<rm -rf> shell
1357 command.");
1358
1359   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1360    [InitBasicFS, Always, TestOutputTrue
1361       [["mkdir"; "/new"];
1362        ["is_dir"; "/new"]];
1363     InitBasicFS, Always, TestLastFail
1364       [["mkdir"; "/new/foo/bar"]]],
1365    "create a directory",
1366    "\
1367 Create a directory named C<path>.");
1368
1369   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1370    [InitBasicFS, Always, TestOutputTrue
1371       [["mkdir_p"; "/new/foo/bar"];
1372        ["is_dir"; "/new/foo/bar"]];
1373     InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new"]];
1379     (* Regression tests for RHBZ#503133: *)
1380     InitBasicFS, Always, TestRun
1381       [["mkdir"; "/new"];
1382        ["mkdir_p"; "/new"]];
1383     InitBasicFS, Always, TestLastFail
1384       [["touch"; "/new"];
1385        ["mkdir_p"; "/new"]]],
1386    "create a directory and parents",
1387    "\
1388 Create a directory named C<path>, creating any parent directories
1389 as necessary.  This is like the C<mkdir -p> shell command.");
1390
1391   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1392    [], (* XXX Need stat command to test *)
1393    "change file mode",
1394    "\
1395 Change the mode (permissions) of C<path> to C<mode>.  Only
1396 numeric modes are supported.
1397
1398 I<Note>: When using this command from guestfish, C<mode>
1399 by default would be decimal, unless you prefix it with
1400 C<0> to get octal, ie. use C<0700> not C<700>.
1401
1402 The mode actually set is affected by the umask.");
1403
1404   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1405    [], (* XXX Need stat command to test *)
1406    "change file owner and group",
1407    "\
1408 Change the file owner to C<owner> and group to C<group>.
1409
1410 Only numeric uid and gid are supported.  If you want to use
1411 names, you will need to locate and parse the password file
1412 yourself (Augeas support makes this relatively easy).");
1413
1414   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1415    [InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/empty"]]);
1417     InitISOFS, Always, TestOutputTrue (
1418       [["exists"; "/directory"]])],
1419    "test if file or directory exists",
1420    "\
1421 This returns C<true> if and only if there is a file, directory
1422 (or anything) with the given C<path> name.
1423
1424 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1425
1426   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1427    [InitISOFS, Always, TestOutputTrue (
1428       [["is_file"; "/known-1"]]);
1429     InitISOFS, Always, TestOutputFalse (
1430       [["is_file"; "/directory"]])],
1431    "test if file exists",
1432    "\
1433 This returns C<true> if and only if there is a file
1434 with the given C<path> name.  Note that it returns false for
1435 other objects like directories.
1436
1437 See also C<guestfs_stat>.");
1438
1439   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1440    [InitISOFS, Always, TestOutputFalse (
1441       [["is_dir"; "/known-3"]]);
1442     InitISOFS, Always, TestOutputTrue (
1443       [["is_dir"; "/directory"]])],
1444    "test if file exists",
1445    "\
1446 This returns C<true> if and only if there is a directory
1447 with the given C<path> name.  Note that it returns false for
1448 other objects like files.
1449
1450 See also C<guestfs_stat>.");
1451
1452   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1453    [InitEmpty, Always, TestOutputListOfDevices (
1454       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1455        ["pvcreate"; "/dev/sda1"];
1456        ["pvcreate"; "/dev/sda2"];
1457        ["pvcreate"; "/dev/sda3"];
1458        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1459    "create an LVM physical volume",
1460    "\
1461 This creates an LVM physical volume on the named C<device>,
1462 where C<device> should usually be a partition name such
1463 as C</dev/sda1>.");
1464
1465   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1466    [InitEmpty, Always, TestOutputList (
1467       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1468        ["pvcreate"; "/dev/sda1"];
1469        ["pvcreate"; "/dev/sda2"];
1470        ["pvcreate"; "/dev/sda3"];
1471        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1472        ["vgcreate"; "VG2"; "/dev/sda3"];
1473        ["vgs"]], ["VG1"; "VG2"])],
1474    "create an LVM volume group",
1475    "\
1476 This creates an LVM volume group called C<volgroup>
1477 from the non-empty list of physical volumes C<physvols>.");
1478
1479   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1480    [InitEmpty, Always, TestOutputList (
1481       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1482        ["pvcreate"; "/dev/sda1"];
1483        ["pvcreate"; "/dev/sda2"];
1484        ["pvcreate"; "/dev/sda3"];
1485        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1486        ["vgcreate"; "VG2"; "/dev/sda3"];
1487        ["lvcreate"; "LV1"; "VG1"; "50"];
1488        ["lvcreate"; "LV2"; "VG1"; "50"];
1489        ["lvcreate"; "LV3"; "VG2"; "50"];
1490        ["lvcreate"; "LV4"; "VG2"; "50"];
1491        ["lvcreate"; "LV5"; "VG2"; "50"];
1492        ["lvs"]],
1493       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1494        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1495    "create an LVM logical volume",
1496    "\
1497 This creates an LVM logical volume called C<logvol>
1498 on the volume group C<volgroup>, with C<size> megabytes.");
1499
1500   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1501    [InitEmpty, Always, TestOutput (
1502       [["part_disk"; "/dev/sda"; "mbr"];
1503        ["mkfs"; "ext2"; "/dev/sda1"];
1504        ["mount_options"; ""; "/dev/sda1"; "/"];
1505        ["write_file"; "/new"; "new file contents"; "0"];
1506        ["cat"; "/new"]], "new file contents")],
1507    "make a filesystem",
1508    "\
1509 This creates a filesystem on C<device> (usually a partition
1510 or LVM logical volume).  The filesystem type is C<fstype>, for
1511 example C<ext3>.");
1512
1513   ("sfdisk", (RErr, [Device "device";
1514                      Int "cyls"; Int "heads"; Int "sectors";
1515                      StringList "lines"]), 43, [DangerWillRobinson],
1516    [],
1517    "create partitions on a block device",
1518    "\
1519 This is a direct interface to the L<sfdisk(8)> program for creating
1520 partitions on block devices.
1521
1522 C<device> should be a block device, for example C</dev/sda>.
1523
1524 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1525 and sectors on the device, which are passed directly to sfdisk as
1526 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1527 of these, then the corresponding parameter is omitted.  Usually for
1528 'large' disks, you can just pass C<0> for these, but for small
1529 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1530 out the right geometry and you will need to tell it.
1531
1532 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1533 information refer to the L<sfdisk(8)> manpage.
1534
1535 To create a single partition occupying the whole disk, you would
1536 pass C<lines> as a single element list, when the single element being
1537 the string C<,> (comma).
1538
1539 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1540 C<guestfs_part_init>");
1541
1542   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1543    [InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; "new file contents"; "0"];
1545        ["cat"; "/new"]], "new file contents");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1548        ["cat"; "/new"]], "\nnew file contents\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n\n"; "0"];
1551        ["cat"; "/new"]], "\n\n");
1552     InitBasicFS, Always, TestOutput (
1553       [["write_file"; "/new"; ""; "0"];
1554        ["cat"; "/new"]], "");
1555     InitBasicFS, Always, TestOutput (
1556       [["write_file"; "/new"; "\n\n\n"; "0"];
1557        ["cat"; "/new"]], "\n\n\n");
1558     InitBasicFS, Always, TestOutput (
1559       [["write_file"; "/new"; "\n"; "0"];
1560        ["cat"; "/new"]], "\n")],
1561    "create a file",
1562    "\
1563 This call creates a file called C<path>.  The contents of the
1564 file is the string C<content> (which can contain any 8 bit data),
1565 with length C<size>.
1566
1567 As a special case, if C<size> is C<0>
1568 then the length is calculated using C<strlen> (so in this case
1569 the content cannot contain embedded ASCII NULs).
1570
1571 I<NB.> Owing to a bug, writing content containing ASCII NUL
1572 characters does I<not> work, even if the length is specified.
1573 We hope to resolve this bug in a future version.  In the meantime
1574 use C<guestfs_upload>.");
1575
1576   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1577    [InitEmpty, Always, TestOutputListOfDevices (
1578       [["part_disk"; "/dev/sda"; "mbr"];
1579        ["mkfs"; "ext2"; "/dev/sda1"];
1580        ["mount_options"; ""; "/dev/sda1"; "/"];
1581        ["mounts"]], ["/dev/sda1"]);
1582     InitEmpty, Always, TestOutputList (
1583       [["part_disk"; "/dev/sda"; "mbr"];
1584        ["mkfs"; "ext2"; "/dev/sda1"];
1585        ["mount_options"; ""; "/dev/sda1"; "/"];
1586        ["umount"; "/"];
1587        ["mounts"]], [])],
1588    "unmount a filesystem",
1589    "\
1590 This unmounts the given filesystem.  The filesystem may be
1591 specified either by its mountpoint (path) or the device which
1592 contains the filesystem.");
1593
1594   ("mounts", (RStringList "devices", []), 46, [],
1595    [InitBasicFS, Always, TestOutputListOfDevices (
1596       [["mounts"]], ["/dev/sda1"])],
1597    "show mounted filesystems",
1598    "\
1599 This returns the list of currently mounted filesystems.  It returns
1600 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1601
1602 Some internal mounts are not shown.
1603
1604 See also: C<guestfs_mountpoints>");
1605
1606   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1607    [InitBasicFS, Always, TestOutputList (
1608       [["umount_all"];
1609        ["mounts"]], []);
1610     (* check that umount_all can unmount nested mounts correctly: *)
1611     InitEmpty, Always, TestOutputList (
1612       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1613        ["mkfs"; "ext2"; "/dev/sda1"];
1614        ["mkfs"; "ext2"; "/dev/sda2"];
1615        ["mkfs"; "ext2"; "/dev/sda3"];
1616        ["mount_options"; ""; "/dev/sda1"; "/"];
1617        ["mkdir"; "/mp1"];
1618        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1619        ["mkdir"; "/mp1/mp2"];
1620        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1621        ["mkdir"; "/mp1/mp2/mp3"];
1622        ["umount_all"];
1623        ["mounts"]], [])],
1624    "unmount all filesystems",
1625    "\
1626 This unmounts all mounted filesystems.
1627
1628 Some internal mounts are not unmounted by this call.");
1629
1630   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1631    [],
1632    "remove all LVM LVs, VGs and PVs",
1633    "\
1634 This command removes all LVM logical volumes, volume groups
1635 and physical volumes.");
1636
1637   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1638    [InitISOFS, Always, TestOutput (
1639       [["file"; "/empty"]], "empty");
1640     InitISOFS, Always, TestOutput (
1641       [["file"; "/known-1"]], "ASCII text");
1642     InitISOFS, Always, TestLastFail (
1643       [["file"; "/notexists"]])],
1644    "determine file type",
1645    "\
1646 This call uses the standard L<file(1)> command to determine
1647 the type or contents of the file.  This also works on devices,
1648 for example to find out whether a partition contains a filesystem.
1649
1650 This call will also transparently look inside various types
1651 of compressed file.
1652
1653 The exact command which runs is C<file -zbsL path>.  Note in
1654 particular that the filename is not prepended to the output
1655 (the C<-b> option).");
1656
1657   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1658    [InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 1"]], "Result1");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 2"]], "Result2\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 3"]], "\nResult3");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 4"]], "\nResult4\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 5"]], "\nResult5\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 7"]], "");
1686     InitBasicFS, Always, TestOutput (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command 8"]], "\n");
1690     InitBasicFS, Always, TestOutput (
1691       [["upload"; "test-command"; "/test-command"];
1692        ["chmod"; "0o755"; "/test-command"];
1693        ["command"; "/test-command 9"]], "\n\n");
1694     InitBasicFS, Always, TestOutput (
1695       [["upload"; "test-command"; "/test-command"];
1696        ["chmod"; "0o755"; "/test-command"];
1697        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1698     InitBasicFS, Always, TestOutput (
1699       [["upload"; "test-command"; "/test-command"];
1700        ["chmod"; "0o755"; "/test-command"];
1701        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1702     InitBasicFS, Always, TestLastFail (
1703       [["upload"; "test-command"; "/test-command"];
1704        ["chmod"; "0o755"; "/test-command"];
1705        ["command"; "/test-command"]])],
1706    "run a command from the guest filesystem",
1707    "\
1708 This call runs a command from the guest filesystem.  The
1709 filesystem must be mounted, and must contain a compatible
1710 operating system (ie. something Linux, with the same
1711 or compatible processor architecture).
1712
1713 The single parameter is an argv-style list of arguments.
1714 The first element is the name of the program to run.
1715 Subsequent elements are parameters.  The list must be
1716 non-empty (ie. must contain a program name).  Note that
1717 the command runs directly, and is I<not> invoked via
1718 the shell (see C<guestfs_sh>).
1719
1720 The return value is anything printed to I<stdout> by
1721 the command.
1722
1723 If the command returns a non-zero exit status, then
1724 this function returns an error message.  The error message
1725 string is the content of I<stderr> from the command.
1726
1727 The C<$PATH> environment variable will contain at least
1728 C</usr/bin> and C</bin>.  If you require a program from
1729 another location, you should provide the full path in the
1730 first parameter.
1731
1732 Shared libraries and data files required by the program
1733 must be available on filesystems which are mounted in the
1734 correct places.  It is the caller's responsibility to ensure
1735 all filesystems that are needed are mounted at the right
1736 locations.");
1737
1738   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1739    [InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 1"]], ["Result1"]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 2"]], ["Result2"]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 7"]], []);
1767     InitBasicFS, Always, TestOutputList (
1768       [["upload"; "test-command"; "/test-command"];
1769        ["chmod"; "0o755"; "/test-command"];
1770        ["command_lines"; "/test-command 8"]], [""]);
1771     InitBasicFS, Always, TestOutputList (
1772       [["upload"; "test-command"; "/test-command"];
1773        ["chmod"; "0o755"; "/test-command"];
1774        ["command_lines"; "/test-command 9"]], ["";""]);
1775     InitBasicFS, Always, TestOutputList (
1776       [["upload"; "test-command"; "/test-command"];
1777        ["chmod"; "0o755"; "/test-command"];
1778        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1779     InitBasicFS, Always, TestOutputList (
1780       [["upload"; "test-command"; "/test-command"];
1781        ["chmod"; "0o755"; "/test-command"];
1782        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1783    "run a command, returning lines",
1784    "\
1785 This is the same as C<guestfs_command>, but splits the
1786 result into a list of lines.
1787
1788 See also: C<guestfs_sh_lines>");
1789
1790   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as the C<stat(2)> system call.");
1798
1799   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1800    [InitISOFS, Always, TestOutputStruct (
1801       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1802    "get file information for a symbolic link",
1803    "\
1804 Returns file information for the given C<path>.
1805
1806 This is the same as C<guestfs_stat> except that if C<path>
1807 is a symbolic link, then the link is stat-ed, not the file it
1808 refers to.
1809
1810 This is the same as the C<lstat(2)> system call.");
1811
1812   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1813    [InitISOFS, Always, TestOutputStruct (
1814       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1815    "get file system statistics",
1816    "\
1817 Returns file system statistics for any mounted file system.
1818 C<path> should be a file or directory in the mounted file system
1819 (typically it is the mount point itself, but it doesn't need to be).
1820
1821 This is the same as the C<statvfs(2)> system call.");
1822
1823   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1824    [], (* XXX test *)
1825    "get ext2/ext3/ext4 superblock details",
1826    "\
1827 This returns the contents of the ext2, ext3 or ext4 filesystem
1828 superblock on C<device>.
1829
1830 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1831 manpage for more details.  The list of fields returned isn't
1832 clearly defined, and depends on both the version of C<tune2fs>
1833 that libguestfs was built against, and the filesystem itself.");
1834
1835   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "set block device to read-only",
1840    "\
1841 Sets the block device named C<device> to read-only.
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1846    [InitEmpty, Always, TestOutputFalse (
1847       [["blockdev_setrw"; "/dev/sda"];
1848        ["blockdev_getro"; "/dev/sda"]])],
1849    "set block device to read-write",
1850    "\
1851 Sets the block device named C<device> to read-write.
1852
1853 This uses the L<blockdev(8)> command.");
1854
1855   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1856    [InitEmpty, Always, TestOutputTrue (
1857       [["blockdev_setro"; "/dev/sda"];
1858        ["blockdev_getro"; "/dev/sda"]])],
1859    "is block device set to read-only",
1860    "\
1861 Returns a boolean indicating if the block device is read-only
1862 (true if read-only, false if not).
1863
1864 This uses the L<blockdev(8)> command.");
1865
1866   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1867    [InitEmpty, Always, TestOutputInt (
1868       [["blockdev_getss"; "/dev/sda"]], 512)],
1869    "get sectorsize of block device",
1870    "\
1871 This returns the size of sectors on a block device.
1872 Usually 512, but can be larger for modern devices.
1873
1874 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1875 for that).
1876
1877 This uses the L<blockdev(8)> command.");
1878
1879   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1880    [InitEmpty, Always, TestOutputInt (
1881       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1882    "get blocksize of block device",
1883    "\
1884 This returns the block size of a device.
1885
1886 (Note this is different from both I<size in blocks> and
1887 I<filesystem block size>).
1888
1889 This uses the L<blockdev(8)> command.");
1890
1891   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1892    [], (* XXX test *)
1893    "set blocksize of block device",
1894    "\
1895 This sets the block size of a device.
1896
1897 (Note this is different from both I<size in blocks> and
1898 I<filesystem block size>).
1899
1900 This uses the L<blockdev(8)> command.");
1901
1902   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1903    [InitEmpty, Always, TestOutputInt (
1904       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1905    "get total size of device in 512-byte sectors",
1906    "\
1907 This returns the size of the device in units of 512-byte sectors
1908 (even if the sectorsize isn't 512 bytes ... weird).
1909
1910 See also C<guestfs_blockdev_getss> for the real sector size of
1911 the device, and C<guestfs_blockdev_getsize64> for the more
1912 useful I<size in bytes>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1917    [InitEmpty, Always, TestOutputInt (
1918       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1919    "get total size of device in bytes",
1920    "\
1921 This returns the size of the device in bytes.
1922
1923 See also C<guestfs_blockdev_getsz>.
1924
1925 This uses the L<blockdev(8)> command.");
1926
1927   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1928    [InitEmpty, Always, TestRun
1929       [["blockdev_flushbufs"; "/dev/sda"]]],
1930    "flush device buffers",
1931    "\
1932 This tells the kernel to flush internal buffers associated
1933 with C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1938    [InitEmpty, Always, TestRun
1939       [["blockdev_rereadpt"; "/dev/sda"]]],
1940    "reread partition table",
1941    "\
1942 Reread the partition table on C<device>.
1943
1944 This uses the L<blockdev(8)> command.");
1945
1946   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1947    [InitBasicFS, Always, TestOutput (
1948       (* Pick a file from cwd which isn't likely to change. *)
1949       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1950        ["checksum"; "md5"; "/COPYING.LIB"]],
1951       Digest.to_hex (Digest.file "COPYING.LIB"))],
1952    "upload a file from the local machine",
1953    "\
1954 Upload local file C<filename> to C<remotefilename> on the
1955 filesystem.
1956
1957 C<filename> can also be a named pipe.
1958
1959 See also C<guestfs_download>.");
1960
1961   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1962    [InitBasicFS, Always, TestOutput (
1963       (* Pick a file from cwd which isn't likely to change. *)
1964       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1965        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1966        ["upload"; "testdownload.tmp"; "/upload"];
1967        ["checksum"; "md5"; "/upload"]],
1968       Digest.to_hex (Digest.file "COPYING.LIB"))],
1969    "download a file to the local machine",
1970    "\
1971 Download file C<remotefilename> and save it as C<filename>
1972 on the local machine.
1973
1974 C<filename> can also be a named pipe.
1975
1976 See also C<guestfs_upload>, C<guestfs_cat>.");
1977
1978   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1979    [InitISOFS, Always, TestOutput (
1980       [["checksum"; "crc"; "/known-3"]], "2891671662");
1981     InitISOFS, Always, TestLastFail (
1982       [["checksum"; "crc"; "/notexists"]]);
1983     InitISOFS, Always, TestOutput (
1984       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1985     InitISOFS, Always, TestOutput (
1986       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1987     InitISOFS, Always, TestOutput (
1988       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1989     InitISOFS, Always, TestOutput (
1990       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1991     InitISOFS, Always, TestOutput (
1992       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1993     InitISOFS, Always, TestOutput (
1994       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1995     (* Test for RHBZ#579608, absolute symbolic links. *)
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1998    "compute MD5, SHAx or CRC checksum of file",
1999    "\
2000 This call computes the MD5, SHAx or CRC checksum of the
2001 file named C<path>.
2002
2003 The type of checksum to compute is given by the C<csumtype>
2004 parameter which must have one of the following values:
2005
2006 =over 4
2007
2008 =item C<crc>
2009
2010 Compute the cyclic redundancy check (CRC) specified by POSIX
2011 for the C<cksum> command.
2012
2013 =item C<md5>
2014
2015 Compute the MD5 hash (using the C<md5sum> program).
2016
2017 =item C<sha1>
2018
2019 Compute the SHA1 hash (using the C<sha1sum> program).
2020
2021 =item C<sha224>
2022
2023 Compute the SHA224 hash (using the C<sha224sum> program).
2024
2025 =item C<sha256>
2026
2027 Compute the SHA256 hash (using the C<sha256sum> program).
2028
2029 =item C<sha384>
2030
2031 Compute the SHA384 hash (using the C<sha384sum> program).
2032
2033 =item C<sha512>
2034
2035 Compute the SHA512 hash (using the C<sha512sum> program).
2036
2037 =back
2038
2039 The checksum is returned as a printable string.
2040
2041 To get the checksum for a device, use C<guestfs_checksum_device>.
2042
2043 To get the checksums for many files, use C<guestfs_checksums_out>.");
2044
2045   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2046    [InitBasicFS, Always, TestOutput (
2047       [["tar_in"; "../images/helloworld.tar"; "/"];
2048        ["cat"; "/hello"]], "hello\n")],
2049    "unpack tarfile to directory",
2050    "\
2051 This command uploads and unpacks local file C<tarfile> (an
2052 I<uncompressed> tar file) into C<directory>.
2053
2054 To upload a compressed tarball, use C<guestfs_tgz_in>
2055 or C<guestfs_txz_in>.");
2056
2057   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2058    [],
2059    "pack directory into tarfile",
2060    "\
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarfile>.
2063
2064 To download a compressed tarball, use C<guestfs_tgz_out>
2065 or C<guestfs_txz_out>.");
2066
2067   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2068    [InitBasicFS, Always, TestOutput (
2069       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2070        ["cat"; "/hello"]], "hello\n")],
2071    "unpack compressed tarball to directory",
2072    "\
2073 This command uploads and unpacks local file C<tarball> (a
2074 I<gzip compressed> tar file) into C<directory>.
2075
2076 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2077
2078   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2079    [],
2080    "pack directory into compressed tarball",
2081    "\
2082 This command packs the contents of C<directory> and downloads
2083 it to local file C<tarball>.
2084
2085 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2086
2087   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2088    [InitBasicFS, Always, TestLastFail (
2089       [["umount"; "/"];
2090        ["mount_ro"; "/dev/sda1"; "/"];
2091        ["touch"; "/new"]]);
2092     InitBasicFS, Always, TestOutput (
2093       [["write_file"; "/new"; "data"; "0"];
2094        ["umount"; "/"];
2095        ["mount_ro"; "/dev/sda1"; "/"];
2096        ["cat"; "/new"]], "data")],
2097    "mount a guest disk, read-only",
2098    "\
2099 This is the same as the C<guestfs_mount> command, but it
2100 mounts the filesystem with the read-only (I<-o ro>) flag.");
2101
2102   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2103    [],
2104    "mount a guest disk with mount options",
2105    "\
2106 This is the same as the C<guestfs_mount> command, but it
2107 allows you to set the mount options as for the
2108 L<mount(8)> I<-o> flag.
2109
2110 If the C<options> parameter is an empty string, then
2111 no options are passed (all options default to whatever
2112 the filesystem uses).");
2113
2114   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2115    [],
2116    "mount a guest disk with mount options and vfstype",
2117    "\
2118 This is the same as the C<guestfs_mount> command, but it
2119 allows you to set both the mount options and the vfstype
2120 as for the L<mount(8)> I<-o> and I<-t> flags.");
2121
2122   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2123    [],
2124    "debugging and internals",
2125    "\
2126 The C<guestfs_debug> command exposes some internals of
2127 C<guestfsd> (the guestfs daemon) that runs inside the
2128 qemu subprocess.
2129
2130 There is no comprehensive help for this command.  You have
2131 to look at the file C<daemon/debug.c> in the libguestfs source
2132 to find out what you can do.");
2133
2134   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2135    [InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG/LV1"];
2142        ["lvs"]], ["/dev/VG/LV2"]);
2143     InitEmpty, Always, TestOutputList (
2144       [["part_disk"; "/dev/sda"; "mbr"];
2145        ["pvcreate"; "/dev/sda1"];
2146        ["vgcreate"; "VG"; "/dev/sda1"];
2147        ["lvcreate"; "LV1"; "VG"; "50"];
2148        ["lvcreate"; "LV2"; "VG"; "50"];
2149        ["lvremove"; "/dev/VG"];
2150        ["lvs"]], []);
2151     InitEmpty, Always, TestOutputList (
2152       [["part_disk"; "/dev/sda"; "mbr"];
2153        ["pvcreate"; "/dev/sda1"];
2154        ["vgcreate"; "VG"; "/dev/sda1"];
2155        ["lvcreate"; "LV1"; "VG"; "50"];
2156        ["lvcreate"; "LV2"; "VG"; "50"];
2157        ["lvremove"; "/dev/VG"];
2158        ["vgs"]], ["VG"])],
2159    "remove an LVM logical volume",
2160    "\
2161 Remove an LVM logical volume C<device>, where C<device> is
2162 the path to the LV, such as C</dev/VG/LV>.
2163
2164 You can also remove all LVs in a volume group by specifying
2165 the VG name, C</dev/VG>.");
2166
2167   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2168    [InitEmpty, Always, TestOutputList (
2169       [["part_disk"; "/dev/sda"; "mbr"];
2170        ["pvcreate"; "/dev/sda1"];
2171        ["vgcreate"; "VG"; "/dev/sda1"];
2172        ["lvcreate"; "LV1"; "VG"; "50"];
2173        ["lvcreate"; "LV2"; "VG"; "50"];
2174        ["vgremove"; "VG"];
2175        ["lvs"]], []);
2176     InitEmpty, Always, TestOutputList (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["vgs"]], [])],
2184    "remove an LVM volume group",
2185    "\
2186 Remove an LVM volume group C<vgname>, (for example C<VG>).
2187
2188 This also forcibly removes all logical volumes in the volume
2189 group (if any).");
2190
2191   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2192    [InitEmpty, Always, TestOutputListOfDevices (
2193       [["part_disk"; "/dev/sda"; "mbr"];
2194        ["pvcreate"; "/dev/sda1"];
2195        ["vgcreate"; "VG"; "/dev/sda1"];
2196        ["lvcreate"; "LV1"; "VG"; "50"];
2197        ["lvcreate"; "LV2"; "VG"; "50"];
2198        ["vgremove"; "VG"];
2199        ["pvremove"; "/dev/sda1"];
2200        ["lvs"]], []);
2201     InitEmpty, Always, TestOutputListOfDevices (
2202       [["part_disk"; "/dev/sda"; "mbr"];
2203        ["pvcreate"; "/dev/sda1"];
2204        ["vgcreate"; "VG"; "/dev/sda1"];
2205        ["lvcreate"; "LV1"; "VG"; "50"];
2206        ["lvcreate"; "LV2"; "VG"; "50"];
2207        ["vgremove"; "VG"];
2208        ["pvremove"; "/dev/sda1"];
2209        ["vgs"]], []);
2210     InitEmpty, Always, TestOutputListOfDevices (
2211       [["part_disk"; "/dev/sda"; "mbr"];
2212        ["pvcreate"; "/dev/sda1"];
2213        ["vgcreate"; "VG"; "/dev/sda1"];
2214        ["lvcreate"; "LV1"; "VG"; "50"];
2215        ["lvcreate"; "LV2"; "VG"; "50"];
2216        ["vgremove"; "VG"];
2217        ["pvremove"; "/dev/sda1"];
2218        ["pvs"]], [])],
2219    "remove an LVM physical volume",
2220    "\
2221 This wipes a physical volume C<device> so that LVM will no longer
2222 recognise it.
2223
2224 The implementation uses the C<pvremove> command which refuses to
2225 wipe physical volumes that contain any volume groups, so you have
2226 to remove those first.");
2227
2228   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2229    [InitBasicFS, Always, TestOutput (
2230       [["set_e2label"; "/dev/sda1"; "testlabel"];
2231        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2232    "set the ext2/3/4 filesystem label",
2233    "\
2234 This sets the ext2/3/4 filesystem label of the filesystem on
2235 C<device> to C<label>.  Filesystem labels are limited to
2236 16 characters.
2237
2238 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2239 to return the existing label on a filesystem.");
2240
2241   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2242    [],
2243    "get the ext2/3/4 filesystem label",
2244    "\
2245 This returns the ext2/3/4 filesystem label of the filesystem on
2246 C<device>.");
2247
2248   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2249    (let uuid = uuidgen () in
2250     [InitBasicFS, Always, TestOutput (
2251        [["set_e2uuid"; "/dev/sda1"; uuid];
2252         ["get_e2uuid"; "/dev/sda1"]], uuid);
2253      InitBasicFS, Always, TestOutput (
2254        [["set_e2uuid"; "/dev/sda1"; "clear"];
2255         ["get_e2uuid"; "/dev/sda1"]], "");
2256      (* We can't predict what UUIDs will be, so just check the commands run. *)
2257      InitBasicFS, Always, TestRun (
2258        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2259      InitBasicFS, Always, TestRun (
2260        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2261    "set the ext2/3/4 filesystem UUID",
2262    "\
2263 This sets the ext2/3/4 filesystem UUID of the filesystem on
2264 C<device> to C<uuid>.  The format of the UUID and alternatives
2265 such as C<clear>, C<random> and C<time> are described in the
2266 L<tune2fs(8)> manpage.
2267
2268 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2269 to return the existing UUID of a filesystem.");
2270
2271   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2272    [],
2273    "get the ext2/3/4 filesystem UUID",
2274    "\
2275 This returns the ext2/3/4 filesystem UUID of the filesystem on
2276 C<device>.");
2277
2278   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2279    [InitBasicFS, Always, TestOutputInt (
2280       [["umount"; "/dev/sda1"];
2281        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2282     InitBasicFS, Always, TestOutputInt (
2283       [["umount"; "/dev/sda1"];
2284        ["zero"; "/dev/sda1"];
2285        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2286    "run the filesystem checker",
2287    "\
2288 This runs the filesystem checker (fsck) on C<device> which
2289 should have filesystem type C<fstype>.
2290
2291 The returned integer is the status.  See L<fsck(8)> for the
2292 list of status codes from C<fsck>.
2293
2294 Notes:
2295
2296 =over 4
2297
2298 =item *
2299
2300 Multiple status codes can be summed together.
2301
2302 =item *
2303
2304 A non-zero return code can mean \"success\", for example if
2305 errors have been corrected on the filesystem.
2306
2307 =item *
2308
2309 Checking or repairing NTFS volumes is not supported
2310 (by linux-ntfs).
2311
2312 =back
2313
2314 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2315
2316   ("zero", (RErr, [Device "device"]), 85, [],
2317    [InitBasicFS, Always, TestOutput (
2318       [["umount"; "/dev/sda1"];
2319        ["zero"; "/dev/sda1"];
2320        ["file"; "/dev/sda1"]], "data")],
2321    "write zeroes to the device",
2322    "\
2323 This command writes zeroes over the first few blocks of C<device>.
2324
2325 How many blocks are zeroed isn't specified (but it's I<not> enough
2326 to securely wipe the device).  It should be sufficient to remove
2327 any partition tables, filesystem superblocks and so on.
2328
2329 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2330
2331   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2332    (* Test disabled because grub-install incompatible with virtio-blk driver.
2333     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2334     *)
2335    [InitBasicFS, Disabled, TestOutputTrue (
2336       [["grub_install"; "/"; "/dev/sda1"];
2337        ["is_dir"; "/boot"]])],
2338    "install GRUB",
2339    "\
2340 This command installs GRUB (the Grand Unified Bootloader) on
2341 C<device>, with the root directory being C<root>.");
2342
2343   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2344    [InitBasicFS, Always, TestOutput (
2345       [["write_file"; "/old"; "file content"; "0"];
2346        ["cp"; "/old"; "/new"];
2347        ["cat"; "/new"]], "file content");
2348     InitBasicFS, Always, TestOutputTrue (
2349       [["write_file"; "/old"; "file content"; "0"];
2350        ["cp"; "/old"; "/new"];
2351        ["is_file"; "/old"]]);
2352     InitBasicFS, Always, TestOutput (
2353       [["write_file"; "/old"; "file content"; "0"];
2354        ["mkdir"; "/dir"];
2355        ["cp"; "/old"; "/dir/new"];
2356        ["cat"; "/dir/new"]], "file content")],
2357    "copy a file",
2358    "\
2359 This copies a file from C<src> to C<dest> where C<dest> is
2360 either a destination filename or destination directory.");
2361
2362   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2363    [InitBasicFS, Always, TestOutput (
2364       [["mkdir"; "/olddir"];
2365        ["mkdir"; "/newdir"];
2366        ["write_file"; "/olddir/file"; "file content"; "0"];
2367        ["cp_a"; "/olddir"; "/newdir"];
2368        ["cat"; "/newdir/olddir/file"]], "file content")],
2369    "copy a file or directory recursively",
2370    "\
2371 This copies a file or directory from C<src> to C<dest>
2372 recursively using the C<cp -a> command.");
2373
2374   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2375    [InitBasicFS, Always, TestOutput (
2376       [["write_file"; "/old"; "file content"; "0"];
2377        ["mv"; "/old"; "/new"];
2378        ["cat"; "/new"]], "file content");
2379     InitBasicFS, Always, TestOutputFalse (
2380       [["write_file"; "/old"; "file content"; "0"];
2381        ["mv"; "/old"; "/new"];
2382        ["is_file"; "/old"]])],
2383    "move a file",
2384    "\
2385 This moves a file from C<src> to C<dest> where C<dest> is
2386 either a destination filename or destination directory.");
2387
2388   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2389    [InitEmpty, Always, TestRun (
2390       [["drop_caches"; "3"]])],
2391    "drop kernel page cache, dentries and inodes",
2392    "\
2393 This instructs the guest kernel to drop its page cache,
2394 and/or dentries and inode caches.  The parameter C<whattodrop>
2395 tells the kernel what precisely to drop, see
2396 L<http://linux-mm.org/Drop_Caches>
2397
2398 Setting C<whattodrop> to 3 should drop everything.
2399
2400 This automatically calls L<sync(2)> before the operation,
2401 so that the maximum guest memory is freed.");
2402
2403   ("dmesg", (RString "kmsgs", []), 91, [],
2404    [InitEmpty, Always, TestRun (
2405       [["dmesg"]])],
2406    "return kernel messages",
2407    "\
2408 This returns the kernel messages (C<dmesg> output) from
2409 the guest kernel.  This is sometimes useful for extended
2410 debugging of problems.
2411
2412 Another way to get the same information is to enable
2413 verbose messages with C<guestfs_set_verbose> or by setting
2414 the environment variable C<LIBGUESTFS_DEBUG=1> before
2415 running the program.");
2416
2417   ("ping_daemon", (RErr, []), 92, [],
2418    [InitEmpty, Always, TestRun (
2419       [["ping_daemon"]])],
2420    "ping the guest daemon",
2421    "\
2422 This is a test probe into the guestfs daemon running inside
2423 the qemu subprocess.  Calling this function checks that the
2424 daemon responds to the ping message, without affecting the daemon
2425 or attached block device(s) in any other way.");
2426
2427   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2428    [InitBasicFS, Always, TestOutputTrue (
2429       [["write_file"; "/file1"; "contents of a file"; "0"];
2430        ["cp"; "/file1"; "/file2"];
2431        ["equal"; "/file1"; "/file2"]]);
2432     InitBasicFS, Always, TestOutputFalse (
2433       [["write_file"; "/file1"; "contents of a file"; "0"];
2434        ["write_file"; "/file2"; "contents of another file"; "0"];
2435        ["equal"; "/file1"; "/file2"]]);
2436     InitBasicFS, Always, TestLastFail (
2437       [["equal"; "/file1"; "/file2"]])],
2438    "test if two files have equal contents",
2439    "\
2440 This compares the two files C<file1> and C<file2> and returns
2441 true if their content is exactly equal, or false otherwise.
2442
2443 The external L<cmp(1)> program is used for the comparison.");
2444
2445   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2446    [InitISOFS, Always, TestOutputList (
2447       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2448     InitISOFS, Always, TestOutputList (
2449       [["strings"; "/empty"]], []);
2450     (* Test for RHBZ#579608, absolute symbolic links. *)
2451     InitISOFS, Always, TestRun (
2452       [["strings"; "/abssymlink"]])],
2453    "print the printable strings in a file",
2454    "\
2455 This runs the L<strings(1)> command on a file and returns
2456 the list of printable strings found.");
2457
2458   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2459    [InitISOFS, Always, TestOutputList (
2460       [["strings_e"; "b"; "/known-5"]], []);
2461     InitBasicFS, Disabled, TestOutputList (
2462       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2463        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2464    "print the printable strings in a file",
2465    "\
2466 This is like the C<guestfs_strings> command, but allows you to
2467 specify the encoding.
2468
2469 See the L<strings(1)> manpage for the full list of encodings.
2470
2471 Commonly useful encodings are C<l> (lower case L) which will
2472 show strings inside Windows/x86 files.
2473
2474 The returned strings are transcoded to UTF-8.");
2475
2476   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2477    [InitISOFS, Always, TestOutput (
2478       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2479     (* Test for RHBZ#501888c2 regression which caused large hexdump
2480      * commands to segfault.
2481      *)
2482     InitISOFS, Always, TestRun (
2483       [["hexdump"; "/100krandom"]]);
2484     (* Test for RHBZ#579608, absolute symbolic links. *)
2485     InitISOFS, Always, TestRun (
2486       [["hexdump"; "/abssymlink"]])],
2487    "dump a file in hexadecimal",
2488    "\
2489 This runs C<hexdump -C> on the given C<path>.  The result is
2490 the human-readable, canonical hex dump of the file.");
2491
2492   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2493    [InitNone, Always, TestOutput (
2494       [["part_disk"; "/dev/sda"; "mbr"];
2495        ["mkfs"; "ext3"; "/dev/sda1"];
2496        ["mount_options"; ""; "/dev/sda1"; "/"];
2497        ["write_file"; "/new"; "test file"; "0"];
2498        ["umount"; "/dev/sda1"];
2499        ["zerofree"; "/dev/sda1"];
2500        ["mount_options"; ""; "/dev/sda1"; "/"];
2501        ["cat"; "/new"]], "test file")],
2502    "zero unused inodes and disk blocks on ext2/3 filesystem",
2503    "\
2504 This runs the I<zerofree> program on C<device>.  This program
2505 claims to zero unused inodes and disk blocks on an ext2/3
2506 filesystem, thus making it possible to compress the filesystem
2507 more effectively.
2508
2509 You should B<not> run this program if the filesystem is
2510 mounted.
2511
2512 It is possible that using this program can damage the filesystem
2513 or data on the filesystem.");
2514
2515   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2516    [],
2517    "resize an LVM physical volume",
2518    "\
2519 This resizes (expands or shrinks) an existing LVM physical
2520 volume to match the new size of the underlying device.");
2521
2522   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2523                        Int "cyls"; Int "heads"; Int "sectors";
2524                        String "line"]), 99, [DangerWillRobinson],
2525    [],
2526    "modify a single partition on a block device",
2527    "\
2528 This runs L<sfdisk(8)> option to modify just the single
2529 partition C<n> (note: C<n> counts from 1).
2530
2531 For other parameters, see C<guestfs_sfdisk>.  You should usually
2532 pass C<0> for the cyls/heads/sectors parameters.
2533
2534 See also: C<guestfs_part_add>");
2535
2536   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2537    [],
2538    "display the partition table",
2539    "\
2540 This displays the partition table on C<device>, in the
2541 human-readable output of the L<sfdisk(8)> command.  It is
2542 not intended to be parsed.
2543
2544 See also: C<guestfs_part_list>");
2545
2546   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2547    [],
2548    "display the kernel geometry",
2549    "\
2550 This displays the kernel's idea of the geometry of C<device>.
2551
2552 The result is in human-readable format, and not designed to
2553 be parsed.");
2554
2555   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2556    [],
2557    "display the disk geometry from the partition table",
2558    "\
2559 This displays the disk geometry of C<device> read from the
2560 partition table.  Especially in the case where the underlying
2561 block device has been resized, this can be different from the
2562 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2563
2564 The result is in human-readable format, and not designed to
2565 be parsed.");
2566
2567   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2568    [],
2569    "activate or deactivate all volume groups",
2570    "\
2571 This command activates or (if C<activate> is false) deactivates
2572 all logical volumes in all volume groups.
2573 If activated, then they are made known to the
2574 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2575 then those devices disappear.
2576
2577 This command is the same as running C<vgchange -a y|n>");
2578
2579   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2580    [],
2581    "activate or deactivate some volume groups",
2582    "\
2583 This command activates or (if C<activate> is false) deactivates
2584 all logical volumes in the listed volume groups C<volgroups>.
2585 If activated, then they are made known to the
2586 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2587 then those devices disappear.
2588
2589 This command is the same as running C<vgchange -a y|n volgroups...>
2590
2591 Note that if C<volgroups> is an empty list then B<all> volume groups
2592 are activated or deactivated.");
2593
2594   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2595    [InitNone, Always, TestOutput (
2596       [["part_disk"; "/dev/sda"; "mbr"];
2597        ["pvcreate"; "/dev/sda1"];
2598        ["vgcreate"; "VG"; "/dev/sda1"];
2599        ["lvcreate"; "LV"; "VG"; "10"];
2600        ["mkfs"; "ext2"; "/dev/VG/LV"];
2601        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2602        ["write_file"; "/new"; "test content"; "0"];
2603        ["umount"; "/"];
2604        ["lvresize"; "/dev/VG/LV"; "20"];
2605        ["e2fsck_f"; "/dev/VG/LV"];
2606        ["resize2fs"; "/dev/VG/LV"];
2607        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2608        ["cat"; "/new"]], "test content");
2609     InitNone, Always, TestRun (
2610       (* Make an LV smaller to test RHBZ#587484. *)
2611       [["part_disk"; "/dev/sda"; "mbr"];
2612        ["pvcreate"; "/dev/sda1"];
2613        ["vgcreate"; "VG"; "/dev/sda1"];
2614        ["lvcreate"; "LV"; "VG"; "20"];
2615        ["lvresize"; "/dev/VG/LV"; "10"]])],
2616    "resize an LVM logical volume",
2617    "\
2618 This resizes (expands or shrinks) an existing LVM logical
2619 volume to C<mbytes>.  When reducing, data in the reduced part
2620 is lost.");
2621
2622   ("resize2fs", (RErr, [Device "device"]), 106, [],
2623    [], (* lvresize tests this *)
2624    "resize an ext2/ext3 filesystem",
2625    "\
2626 This resizes an ext2 or ext3 filesystem to match the size of
2627 the underlying device.
2628
2629 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2630 on the C<device> before calling this command.  For unknown reasons
2631 C<resize2fs> sometimes gives an error about this and sometimes not.
2632 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2633 calling this function.");
2634
2635   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2636    [InitBasicFS, Always, TestOutputList (
2637       [["find"; "/"]], ["lost+found"]);
2638     InitBasicFS, Always, TestOutputList (
2639       [["touch"; "/a"];
2640        ["mkdir"; "/b"];
2641        ["touch"; "/b/c"];
2642        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2643     InitBasicFS, Always, TestOutputList (
2644       [["mkdir_p"; "/a/b/c"];
2645        ["touch"; "/a/b/c/d"];
2646        ["find"; "/a/b/"]], ["c"; "c/d"])],
2647    "find all files and directories",
2648    "\
2649 This command lists out all files and directories, recursively,
2650 starting at C<directory>.  It is essentially equivalent to
2651 running the shell command C<find directory -print> but some
2652 post-processing happens on the output, described below.
2653
2654 This returns a list of strings I<without any prefix>.  Thus
2655 if the directory structure was:
2656
2657  /tmp/a
2658  /tmp/b
2659  /tmp/c/d
2660
2661 then the returned list from C<guestfs_find> C</tmp> would be
2662 4 elements:
2663
2664  a
2665  b
2666  c
2667  c/d
2668
2669 If C<directory> is not a directory, then this command returns
2670 an error.
2671
2672 The returned list is sorted.
2673
2674 See also C<guestfs_find0>.");
2675
2676   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2677    [], (* lvresize tests this *)
2678    "check an ext2/ext3 filesystem",
2679    "\
2680 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2681 filesystem checker on C<device>, noninteractively (C<-p>),
2682 even if the filesystem appears to be clean (C<-f>).
2683
2684 This command is only needed because of C<guestfs_resize2fs>
2685 (q.v.).  Normally you should use C<guestfs_fsck>.");
2686
2687   ("sleep", (RErr, [Int "secs"]), 109, [],
2688    [InitNone, Always, TestRun (
2689       [["sleep"; "1"]])],
2690    "sleep for some seconds",
2691    "\
2692 Sleep for C<secs> seconds.");
2693
2694   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2695    [InitNone, Always, TestOutputInt (
2696       [["part_disk"; "/dev/sda"; "mbr"];
2697        ["mkfs"; "ntfs"; "/dev/sda1"];
2698        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2699     InitNone, Always, TestOutputInt (
2700       [["part_disk"; "/dev/sda"; "mbr"];
2701        ["mkfs"; "ext2"; "/dev/sda1"];
2702        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2703    "probe NTFS volume",
2704    "\
2705 This command runs the L<ntfs-3g.probe(8)> command which probes
2706 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2707 be mounted read-write, and some cannot be mounted at all).
2708
2709 C<rw> is a boolean flag.  Set it to true if you want to test
2710 if the volume can be mounted read-write.  Set it to false if
2711 you want to test if the volume can be mounted read-only.
2712
2713 The return value is an integer which C<0> if the operation
2714 would succeed, or some non-zero value documented in the
2715 L<ntfs-3g.probe(8)> manual page.");
2716
2717   ("sh", (RString "output", [String "command"]), 111, [],
2718    [], (* XXX needs tests *)
2719    "run a command via the shell",
2720    "\
2721 This call runs a command from the guest filesystem via the
2722 guest's C</bin/sh>.
2723
2724 This is like C<guestfs_command>, but passes the command to:
2725
2726  /bin/sh -c \"command\"
2727
2728 Depending on the guest's shell, this usually results in
2729 wildcards being expanded, shell expressions being interpolated
2730 and so on.
2731
2732 All the provisos about C<guestfs_command> apply to this call.");
2733
2734   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2735    [], (* XXX needs tests *)
2736    "run a command via the shell returning lines",
2737    "\
2738 This is the same as C<guestfs_sh>, but splits the result
2739 into a list of lines.
2740
2741 See also: C<guestfs_command_lines>");
2742
2743   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2744    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2745     * code in stubs.c, since all valid glob patterns must start with "/".
2746     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2747     *)
2748    [InitBasicFS, Always, TestOutputList (
2749       [["mkdir_p"; "/a/b/c"];
2750        ["touch"; "/a/b/c/d"];
2751        ["touch"; "/a/b/c/e"];
2752        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2753     InitBasicFS, Always, TestOutputList (
2754       [["mkdir_p"; "/a/b/c"];
2755        ["touch"; "/a/b/c/d"];
2756        ["touch"; "/a/b/c/e"];
2757        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2758     InitBasicFS, Always, TestOutputList (
2759       [["mkdir_p"; "/a/b/c"];
2760        ["touch"; "/a/b/c/d"];
2761        ["touch"; "/a/b/c/e"];
2762        ["glob_expand"; "/a/*/x/*"]], [])],
2763    "expand a wildcard path",
2764    "\
2765 This command searches for all the pathnames matching
2766 C<pattern> according to the wildcard expansion rules
2767 used by the shell.
2768
2769 If no paths match, then this returns an empty list
2770 (note: not an error).
2771
2772 It is just a wrapper around the C L<glob(3)> function
2773 with flags C<GLOB_MARK|GLOB_BRACE>.
2774 See that manual page for more details.");
2775
2776   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2777    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2778       [["scrub_device"; "/dev/sdc"]])],
2779    "scrub (securely wipe) a device",
2780    "\
2781 This command writes patterns over C<device> to make data retrieval
2782 more difficult.
2783
2784 It is an interface to the L<scrub(1)> program.  See that
2785 manual page for more details.");
2786
2787   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2788    [InitBasicFS, Always, TestRun (
2789       [["write_file"; "/file"; "content"; "0"];
2790        ["scrub_file"; "/file"]])],
2791    "scrub (securely wipe) a file",
2792    "\
2793 This command writes patterns over a file to make data retrieval
2794 more difficult.
2795
2796 The file is I<removed> after scrubbing.
2797
2798 It is an interface to the L<scrub(1)> program.  See that
2799 manual page for more details.");
2800
2801   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2802    [], (* XXX needs testing *)
2803    "scrub (securely wipe) free space",
2804    "\
2805 This command creates the directory C<dir> and then fills it
2806 with files until the filesystem is full, and scrubs the files
2807 as for C<guestfs_scrub_file>, and deletes them.
2808 The intention is to scrub any free space on the partition
2809 containing C<dir>.
2810
2811 It is an interface to the L<scrub(1)> program.  See that
2812 manual page for more details.");
2813
2814   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2815    [InitBasicFS, Always, TestRun (
2816       [["mkdir"; "/tmp"];
2817        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2818    "create a temporary directory",
2819    "\
2820 This command creates a temporary directory.  The
2821 C<template> parameter should be a full pathname for the
2822 temporary directory name with the final six characters being
2823 \"XXXXXX\".
2824
2825 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2826 the second one being suitable for Windows filesystems.
2827
2828 The name of the temporary directory that was created
2829 is returned.
2830
2831 The temporary directory is created with mode 0700
2832 and is owned by root.
2833
2834 The caller is responsible for deleting the temporary
2835 directory and its contents after use.
2836
2837 See also: L<mkdtemp(3)>");
2838
2839   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2840    [InitISOFS, Always, TestOutputInt (
2841       [["wc_l"; "/10klines"]], 10000);
2842     (* Test for RHBZ#579608, absolute symbolic links. *)
2843     InitISOFS, Always, TestOutputInt (
2844       [["wc_l"; "/abssymlink"]], 10000)],
2845    "count lines in a file",
2846    "\
2847 This command counts the lines in a file, using the
2848 C<wc -l> external command.");
2849
2850   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2851    [InitISOFS, Always, TestOutputInt (
2852       [["wc_w"; "/10klines"]], 10000)],
2853    "count words in a file",
2854    "\
2855 This command counts the words in a file, using the
2856 C<wc -w> external command.");
2857
2858   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2859    [InitISOFS, Always, TestOutputInt (
2860       [["wc_c"; "/100kallspaces"]], 102400)],
2861    "count characters in a file",
2862    "\
2863 This command counts the characters in a file, using the
2864 C<wc -c> external command.");
2865
2866   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2867    [InitISOFS, Always, TestOutputList (
2868       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2869     (* Test for RHBZ#579608, absolute symbolic links. *)
2870     InitISOFS, Always, TestOutputList (
2871       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2872    "return first 10 lines of a file",
2873    "\
2874 This command returns up to the first 10 lines of a file as
2875 a list of strings.");
2876
2877   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2878    [InitISOFS, Always, TestOutputList (
2879       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2880     InitISOFS, Always, TestOutputList (
2881       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2882     InitISOFS, Always, TestOutputList (
2883       [["head_n"; "0"; "/10klines"]], [])],
2884    "return first N lines of a file",
2885    "\
2886 If the parameter C<nrlines> is a positive number, this returns the first
2887 C<nrlines> lines of the file C<path>.
2888
2889 If the parameter C<nrlines> is a negative number, this returns lines
2890 from the file C<path>, excluding the last C<nrlines> lines.
2891
2892 If the parameter C<nrlines> is zero, this returns an empty list.");
2893
2894   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2895    [InitISOFS, Always, TestOutputList (
2896       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2897    "return last 10 lines of a file",
2898    "\
2899 This command returns up to the last 10 lines of a file as
2900 a list of strings.");
2901
2902   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2903    [InitISOFS, Always, TestOutputList (
2904       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2905     InitISOFS, Always, TestOutputList (
2906       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2907     InitISOFS, Always, TestOutputList (
2908       [["tail_n"; "0"; "/10klines"]], [])],
2909    "return last N lines of a file",
2910    "\
2911 If the parameter C<nrlines> is a positive number, this returns the last
2912 C<nrlines> lines of the file C<path>.
2913
2914 If the parameter C<nrlines> is a negative number, this returns lines
2915 from the file C<path>, starting with the C<-nrlines>th line.
2916
2917 If the parameter C<nrlines> is zero, this returns an empty list.");
2918
2919   ("df", (RString "output", []), 125, [],
2920    [], (* XXX Tricky to test because it depends on the exact format
2921         * of the 'df' command and other imponderables.
2922         *)
2923    "report file system disk space usage",
2924    "\
2925 This command runs the C<df> command to report disk space used.
2926
2927 This command is mostly useful for interactive sessions.  It
2928 is I<not> intended that you try to parse the output string.
2929 Use C<statvfs> from programs.");
2930
2931   ("df_h", (RString "output", []), 126, [],
2932    [], (* XXX Tricky to test because it depends on the exact format
2933         * of the 'df' command and other imponderables.
2934         *)
2935    "report file system disk space usage (human readable)",
2936    "\
2937 This command runs the C<df -h> command to report disk space used
2938 in human-readable format.
2939
2940 This command is mostly useful for interactive sessions.  It
2941 is I<not> intended that you try to parse the output string.
2942 Use C<statvfs> from programs.");
2943
2944   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2945    [InitISOFS, Always, TestOutputInt (
2946       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2947    "estimate file space usage",
2948    "\
2949 This command runs the C<du -s> command to estimate file space
2950 usage for C<path>.
2951
2952 C<path> can be a file or a directory.  If C<path> is a directory
2953 then the estimate includes the contents of the directory and all
2954 subdirectories (recursively).
2955
2956 The result is the estimated size in I<kilobytes>
2957 (ie. units of 1024 bytes).");
2958
2959   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2960    [InitISOFS, Always, TestOutputList (
2961       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2962    "list files in an initrd",
2963    "\
2964 This command lists out files contained in an initrd.
2965
2966 The files are listed without any initial C</> character.  The
2967 files are listed in the order they appear (not necessarily
2968 alphabetical).  Directory names are listed as separate items.
2969
2970 Old Linux kernels (2.4 and earlier) used a compressed ext2
2971 filesystem as initrd.  We I<only> support the newer initramfs
2972 format (compressed cpio files).");
2973
2974   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2975    [],
2976    "mount a file using the loop device",
2977    "\
2978 This command lets you mount C<file> (a filesystem image
2979 in a file) on a mount point.  It is entirely equivalent to
2980 the command C<mount -o loop file mountpoint>.");
2981
2982   ("mkswap", (RErr, [Device "device"]), 130, [],
2983    [InitEmpty, Always, TestRun (
2984       [["part_disk"; "/dev/sda"; "mbr"];
2985        ["mkswap"; "/dev/sda1"]])],
2986    "create a swap partition",
2987    "\
2988 Create a swap partition on C<device>.");
2989
2990   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2991    [InitEmpty, Always, TestRun (
2992       [["part_disk"; "/dev/sda"; "mbr"];
2993        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2994    "create a swap partition with a label",
2995    "\
2996 Create a swap partition on C<device> with label C<label>.
2997
2998 Note that you cannot attach a swap label to a block device
2999 (eg. C</dev/sda>), just to a partition.  This appears to be
3000 a limitation of the kernel or swap tools.");
3001
3002   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3003    (let uuid = uuidgen () in
3004     [InitEmpty, Always, TestRun (
3005        [["part_disk"; "/dev/sda"; "mbr"];
3006         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3007    "create a swap partition with an explicit UUID",
3008    "\
3009 Create a swap partition on C<device> with UUID C<uuid>.");
3010
3011   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3012    [InitBasicFS, Always, TestOutputStruct (
3013       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3014        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3015        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3016     InitBasicFS, Always, TestOutputStruct (
3017       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3018        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3019    "make block, character or FIFO devices",
3020    "\
3021 This call creates block or character special devices, or
3022 named pipes (FIFOs).
3023
3024 The C<mode> parameter should be the mode, using the standard
3025 constants.  C<devmajor> and C<devminor> are the
3026 device major and minor numbers, only used when creating block
3027 and character special devices.
3028
3029 Note that, just like L<mknod(2)>, the mode must be bitwise
3030 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3031 just creates a regular file).  These constants are
3032 available in the standard Linux header files, or you can use
3033 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3034 which are wrappers around this command which bitwise OR
3035 in the appropriate constant for you.
3036
3037 The mode actually set is affected by the umask.");
3038
3039   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3040    [InitBasicFS, Always, TestOutputStruct (
3041       [["mkfifo"; "0o777"; "/node"];
3042        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3043    "make FIFO (named pipe)",
3044    "\
3045 This call creates a FIFO (named pipe) called C<path> with
3046 mode C<mode>.  It is just a convenient wrapper around
3047 C<guestfs_mknod>.
3048
3049 The mode actually set is affected by the umask.");
3050
3051   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3052    [InitBasicFS, Always, TestOutputStruct (
3053       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3054        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3055    "make block device node",
3056    "\
3057 This call creates a block device node called C<path> with
3058 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3059 It is just a convenient wrapper around C<guestfs_mknod>.
3060
3061 The mode actually set is affected by the umask.");
3062
3063   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3064    [InitBasicFS, Always, TestOutputStruct (
3065       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3066        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3067    "make char device node",
3068    "\
3069 This call creates a char device node called C<path> with
3070 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3071 It is just a convenient wrapper around C<guestfs_mknod>.
3072
3073 The mode actually set is affected by the umask.");
3074
3075   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3076    [InitEmpty, Always, TestOutputInt (
3077       [["umask"; "0o22"]], 0o22)],
3078    "set file mode creation mask (umask)",
3079    "\
3080 This function sets the mask used for creating new files and
3081 device nodes to C<mask & 0777>.
3082
3083 Typical umask values would be C<022> which creates new files
3084 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3085 C<002> which creates new files with permissions like
3086 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3087
3088 The default umask is C<022>.  This is important because it
3089 means that directories and device nodes will be created with
3090 C<0644> or C<0755> mode even if you specify C<0777>.
3091
3092 See also C<guestfs_get_umask>,
3093 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3094
3095 This call returns the previous umask.");
3096
3097   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3098    [],
3099    "read directories entries",
3100    "\
3101 This returns the list of directory entries in directory C<dir>.
3102
3103 All entries in the directory are returned, including C<.> and
3104 C<..>.  The entries are I<not> sorted, but returned in the same
3105 order as the underlying filesystem.
3106
3107 Also this call returns basic file type information about each
3108 file.  The C<ftyp> field will contain one of the following characters:
3109
3110 =over 4
3111
3112 =item 'b'
3113
3114 Block special
3115
3116 =item 'c'
3117
3118 Char special
3119
3120 =item 'd'
3121
3122 Directory
3123
3124 =item 'f'
3125
3126 FIFO (named pipe)
3127
3128 =item 'l'
3129
3130 Symbolic link
3131
3132 =item 'r'
3133
3134 Regular file
3135
3136 =item 's'
3137
3138 Socket
3139
3140 =item 'u'
3141
3142 Unknown file type
3143
3144 =item '?'
3145
3146 The L<readdir(3)> returned a C<d_type> field with an
3147 unexpected value
3148
3149 =back
3150
3151 This function is primarily intended for use by programs.  To
3152 get a simple list of names, use C<guestfs_ls>.  To get a printable
3153 directory for human consumption, use C<guestfs_ll>.");
3154
3155   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3156    [],
3157    "create partitions on a block device",
3158    "\
3159 This is a simplified interface to the C<guestfs_sfdisk>
3160 command, where partition sizes are specified in megabytes
3161 only (rounded to the nearest cylinder) and you don't need
3162 to specify the cyls, heads and sectors parameters which
3163 were rarely if ever used anyway.
3164
3165 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3166 and C<guestfs_part_disk>");
3167
3168   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3169    [],
3170    "determine file type inside a compressed file",
3171    "\
3172 This command runs C<file> after first decompressing C<path>
3173 using C<method>.
3174
3175 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3176
3177 Since 1.0.63, use C<guestfs_file> instead which can now
3178 process compressed files.");
3179
3180   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3181    [],
3182    "list extended attributes of a file or directory",
3183    "\
3184 This call lists the extended attributes of the file or directory
3185 C<path>.
3186
3187 At the system call level, this is a combination of the
3188 L<listxattr(2)> and L<getxattr(2)> calls.
3189
3190 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3191
3192   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3193    [],
3194    "list extended attributes of a file or directory",
3195    "\
3196 This is the same as C<guestfs_getxattrs>, but if C<path>
3197 is a symbolic link, then it returns the extended attributes
3198 of the link itself.");
3199
3200   ("setxattr", (RErr, [String "xattr";
3201                        String "val"; Int "vallen"; (* will be BufferIn *)
3202                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3203    [],
3204    "set extended attribute of a file or directory",
3205    "\
3206 This call sets the extended attribute named C<xattr>
3207 of the file C<path> to the value C<val> (of length C<vallen>).
3208 The value is arbitrary 8 bit data.
3209
3210 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3211
3212   ("lsetxattr", (RErr, [String "xattr";
3213                         String "val"; Int "vallen"; (* will be BufferIn *)
3214                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3215    [],
3216    "set extended attribute of a file or directory",
3217    "\
3218 This is the same as C<guestfs_setxattr>, but if C<path>
3219 is a symbolic link, then it sets an extended attribute
3220 of the link itself.");
3221
3222   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3223    [],
3224    "remove extended attribute of a file or directory",
3225    "\
3226 This call removes the extended attribute named C<xattr>
3227 of the file C<path>.
3228
3229 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3230
3231   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3232    [],
3233    "remove extended attribute of a file or directory",
3234    "\
3235 This is the same as C<guestfs_removexattr>, but if C<path>
3236 is a symbolic link, then it removes an extended attribute
3237 of the link itself.");
3238
3239   ("mountpoints", (RHashtable "mps", []), 147, [],
3240    [],
3241    "show mountpoints",
3242    "\
3243 This call is similar to C<guestfs_mounts>.  That call returns
3244 a list of devices.  This one returns a hash table (map) of
3245 device name to directory where the device is mounted.");
3246
3247   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3248    (* This is a special case: while you would expect a parameter
3249     * of type "Pathname", that doesn't work, because it implies
3250     * NEED_ROOT in the generated calling code in stubs.c, and
3251     * this function cannot use NEED_ROOT.
3252     *)
3253    [],
3254    "create a mountpoint",
3255    "\
3256 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3257 specialized calls that can be used to create extra mountpoints
3258 before mounting the first filesystem.
3259
3260 These calls are I<only> necessary in some very limited circumstances,
3261 mainly the case where you want to mount a mix of unrelated and/or
3262 read-only filesystems together.
3263
3264 For example, live CDs often contain a \"Russian doll\" nest of
3265 filesystems, an ISO outer layer, with a squashfs image inside, with
3266 an ext2/3 image inside that.  You can unpack this as follows
3267 in guestfish:
3268
3269  add-ro Fedora-11-i686-Live.iso
3270  run
3271  mkmountpoint /cd
3272  mkmountpoint /squash
3273  mkmountpoint /ext3
3274  mount /dev/sda /cd
3275  mount-loop /cd/LiveOS/squashfs.img /squash
3276  mount-loop /squash/LiveOS/ext3fs.img /ext3
3277
3278 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3279
3280   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3281    [],
3282    "remove a mountpoint",
3283    "\
3284 This calls removes a mountpoint that was previously created
3285 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3286 for full details.");
3287
3288   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3289    [InitISOFS, Always, TestOutputBuffer (
3290       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3291    "read a file",
3292    "\
3293 This calls returns the contents of the file C<path> as a
3294 buffer.
3295
3296 Unlike C<guestfs_cat>, this function can correctly
3297 handle files that contain embedded ASCII NUL characters.
3298 However unlike C<guestfs_download>, this function is limited
3299 in the total size of file that can be handled.");
3300
3301   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3302    [InitISOFS, Always, TestOutputList (
3303       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3304     InitISOFS, Always, TestOutputList (
3305       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3306     (* Test for RHBZ#579608, absolute symbolic links. *)
3307     InitISOFS, Always, TestOutputList (
3308       [["grep"; "nomatch"; "/abssymlink"]], [])],
3309    "return lines matching a pattern",
3310    "\
3311 This calls the external C<grep> program and returns the
3312 matching lines.");
3313
3314   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3315    [InitISOFS, Always, TestOutputList (
3316       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3317    "return lines matching a pattern",
3318    "\
3319 This calls the external C<egrep> program and returns the
3320 matching lines.");
3321
3322   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3323    [InitISOFS, Always, TestOutputList (
3324       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3325    "return lines matching a pattern",
3326    "\
3327 This calls the external C<fgrep> program and returns the
3328 matching lines.");
3329
3330   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3331    [InitISOFS, Always, TestOutputList (
3332       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3333    "return lines matching a pattern",
3334    "\
3335 This calls the external C<grep -i> program and returns the
3336 matching lines.");
3337
3338   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3339    [InitISOFS, Always, TestOutputList (
3340       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3341    "return lines matching a pattern",
3342    "\
3343 This calls the external C<egrep -i> program and returns the
3344 matching lines.");
3345
3346   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3347    [InitISOFS, Always, TestOutputList (
3348       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3349    "return lines matching a pattern",
3350    "\
3351 This calls the external C<fgrep -i> program and returns the
3352 matching lines.");
3353
3354   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3355    [InitISOFS, Always, TestOutputList (
3356       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3357    "return lines matching a pattern",
3358    "\
3359 This calls the external C<zgrep> program and returns the
3360 matching lines.");
3361
3362   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3363    [InitISOFS, Always, TestOutputList (
3364       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3365    "return lines matching a pattern",
3366    "\
3367 This calls the external C<zegrep> program and returns the
3368 matching lines.");
3369
3370   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3371    [InitISOFS, Always, TestOutputList (
3372       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3373    "return lines matching a pattern",
3374    "\
3375 This calls the external C<zfgrep> program and returns the
3376 matching lines.");
3377
3378   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3379    [InitISOFS, Always, TestOutputList (
3380       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<zgrep -i> program and returns the
3384 matching lines.");
3385
3386   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<zegrep -i> program and returns the
3392 matching lines.");
3393
3394   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<zfgrep -i> program and returns the
3400 matching lines.");
3401
3402   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3403    [InitISOFS, Always, TestOutput (
3404       [["realpath"; "/../directory"]], "/directory")],
3405    "canonicalized absolute pathname",
3406    "\
3407 Return the canonicalized absolute pathname of C<path>.  The
3408 returned path has no C<.>, C<..> or symbolic link path elements.");
3409
3410   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3411    [InitBasicFS, Always, TestOutputStruct (
3412       [["touch"; "/a"];
3413        ["ln"; "/a"; "/b"];
3414        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3415    "create a hard link",
3416    "\
3417 This command creates a hard link using the C<ln> command.");
3418
3419   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3420    [InitBasicFS, Always, TestOutputStruct (
3421       [["touch"; "/a"];
3422        ["touch"; "/b"];
3423        ["ln_f"; "/a"; "/b"];
3424        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3425    "create a hard link",
3426    "\
3427 This command creates a hard link using the C<ln -f> command.
3428 The C<-f> option removes the link (C<linkname>) if it exists already.");
3429
3430   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3431    [InitBasicFS, Always, TestOutputStruct (
3432       [["touch"; "/a"];
3433        ["ln_s"; "a"; "/b"];
3434        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3435    "create a symbolic link",
3436    "\
3437 This command creates a symbolic link using the C<ln -s> command.");
3438
3439   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3440    [InitBasicFS, Always, TestOutput (
3441       [["mkdir_p"; "/a/b"];
3442        ["touch"; "/a/b/c"];
3443        ["ln_sf"; "../d"; "/a/b/c"];
3444        ["readlink"; "/a/b/c"]], "../d")],
3445    "create a symbolic link",
3446    "\
3447 This command creates a symbolic link using the C<ln -sf> command,
3448 The C<-f> option removes the link (C<linkname>) if it exists already.");
3449
3450   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3451    [] (* XXX tested above *),
3452    "read the target of a symbolic link",
3453    "\
3454 This command reads the target of a symbolic link.");
3455
3456   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3457    [InitBasicFS, Always, TestOutputStruct (
3458       [["fallocate"; "/a"; "1000000"];
3459        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3460    "preallocate a file in the guest filesystem",
3461    "\
3462 This command preallocates a file (containing zero bytes) named
3463 C<path> of size C<len> bytes.  If the file exists already, it
3464 is overwritten.
3465
3466 Do not confuse this with the guestfish-specific
3467 C<alloc> command which allocates a file in the host and
3468 attaches it as a device.");
3469
3470   ("swapon_device", (RErr, [Device "device"]), 170, [],
3471    [InitPartition, Always, TestRun (
3472       [["mkswap"; "/dev/sda1"];
3473        ["swapon_device"; "/dev/sda1"];
3474        ["swapoff_device"; "/dev/sda1"]])],
3475    "enable swap on device",
3476    "\
3477 This command enables the libguestfs appliance to use the
3478 swap device or partition named C<device>.  The increased
3479 memory is made available for all commands, for example
3480 those run using C<guestfs_command> or C<guestfs_sh>.
3481
3482 Note that you should not swap to existing guest swap
3483 partitions unless you know what you are doing.  They may
3484 contain hibernation information, or other information that
3485 the guest doesn't want you to trash.  You also risk leaking
3486 information about the host to the guest this way.  Instead,
3487 attach a new host device to the guest and swap on that.");
3488
3489   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3490    [], (* XXX tested by swapon_device *)
3491    "disable swap on device",
3492    "\
3493 This command disables the libguestfs appliance swap
3494 device or partition named C<device>.
3495 See C<guestfs_swapon_device>.");
3496
3497   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3498    [InitBasicFS, Always, TestRun (
3499       [["fallocate"; "/swap"; "8388608"];
3500        ["mkswap_file"; "/swap"];
3501        ["swapon_file"; "/swap"];
3502        ["swapoff_file"; "/swap"]])],
3503    "enable swap on file",
3504    "\
3505 This command enables swap to a file.
3506 See C<guestfs_swapon_device> for other notes.");
3507
3508   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3509    [], (* XXX tested by swapon_file *)
3510    "disable swap on file",
3511    "\
3512 This command disables the libguestfs appliance swap on file.");
3513
3514   ("swapon_label", (RErr, [String "label"]), 174, [],
3515    [InitEmpty, Always, TestRun (
3516       [["part_disk"; "/dev/sdb"; "mbr"];
3517        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3518        ["swapon_label"; "swapit"];
3519        ["swapoff_label"; "swapit"];
3520        ["zero"; "/dev/sdb"];
3521        ["blockdev_rereadpt"; "/dev/sdb"]])],
3522    "enable swap on labeled swap partition",
3523    "\
3524 This command enables swap to a labeled swap partition.
3525 See C<guestfs_swapon_device> for other notes.");
3526
3527   ("swapoff_label", (RErr, [String "label"]), 175, [],
3528    [], (* XXX tested by swapon_label *)
3529    "disable swap on labeled swap partition",
3530    "\
3531 This command disables the libguestfs appliance swap on
3532 labeled swap partition.");
3533
3534   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3535    (let uuid = uuidgen () in
3536     [InitEmpty, Always, TestRun (
3537        [["mkswap_U"; uuid; "/dev/sdb"];
3538         ["swapon_uuid"; uuid];
3539         ["swapoff_uuid"; uuid]])]),
3540    "enable swap on swap partition by UUID",
3541    "\
3542 This command enables swap to a swap partition with the given UUID.
3543 See C<guestfs_swapon_device> for other notes.");
3544
3545   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3546    [], (* XXX tested by swapon_uuid *)
3547    "disable swap on swap partition by UUID",
3548    "\
3549 This command disables the libguestfs appliance swap partition
3550 with the given UUID.");
3551
3552   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3553    [InitBasicFS, Always, TestRun (
3554       [["fallocate"; "/swap"; "8388608"];
3555        ["mkswap_file"; "/swap"]])],
3556    "create a swap file",
3557    "\
3558 Create a swap file.
3559
3560 This command just writes a swap file signature to an existing
3561 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3562
3563   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3564    [InitISOFS, Always, TestRun (
3565       [["inotify_init"; "0"]])],
3566    "create an inotify handle",
3567    "\
3568 This command creates a new inotify handle.
3569 The inotify subsystem can be used to notify events which happen to
3570 objects in the guest filesystem.
3571
3572 C<maxevents> is the maximum number of events which will be
3573 queued up between calls to C<guestfs_inotify_read> or
3574 C<guestfs_inotify_files>.
3575 If this is passed as C<0>, then the kernel (or previously set)
3576 default is used.  For Linux 2.6.29 the default was 16384 events.
3577 Beyond this limit, the kernel throws away events, but records
3578 the fact that it threw them away by setting a flag
3579 C<IN_Q_OVERFLOW> in the returned structure list (see
3580 C<guestfs_inotify_read>).
3581
3582 Before any events are generated, you have to add some
3583 watches to the internal watch list.  See:
3584 C<guestfs_inotify_add_watch>,
3585 C<guestfs_inotify_rm_watch> and
3586 C<guestfs_inotify_watch_all>.
3587
3588 Queued up events should be read periodically by calling
3589 C<guestfs_inotify_read>
3590 (or C<guestfs_inotify_files> which is just a helpful
3591 wrapper around C<guestfs_inotify_read>).  If you don't
3592 read the events out often enough then you risk the internal
3593 queue overflowing.
3594
3595 The handle should be closed after use by calling
3596 C<guestfs_inotify_close>.  This also removes any
3597 watches automatically.
3598
3599 See also L<inotify(7)> for an overview of the inotify interface
3600 as exposed by the Linux kernel, which is roughly what we expose
3601 via libguestfs.  Note that there is one global inotify handle
3602 per libguestfs instance.");
3603
3604   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3605    [InitBasicFS, Always, TestOutputList (
3606       [["inotify_init"; "0"];
3607        ["inotify_add_watch"; "/"; "1073741823"];
3608        ["touch"; "/a"];
3609        ["touch"; "/b"];
3610        ["inotify_files"]], ["a"; "b"])],
3611    "add an inotify watch",
3612    "\
3613 Watch C<path> for the events listed in C<mask>.
3614
3615 Note that if C<path> is a directory then events within that
3616 directory are watched, but this does I<not> happen recursively
3617 (in subdirectories).
3618
3619 Note for non-C or non-Linux callers: the inotify events are
3620 defined by the Linux kernel ABI and are listed in
3621 C</usr/include/sys/inotify.h>.");
3622
3623   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3624    [],
3625    "remove an inotify watch",
3626    "\
3627 Remove a previously defined inotify watch.
3628 See C<guestfs_inotify_add_watch>.");
3629
3630   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3631    [],
3632    "return list of inotify events",
3633    "\
3634 Return the complete queue of events that have happened
3635 since the previous read call.
3636
3637 If no events have happened, this returns an empty list.
3638
3639 I<Note>: In order to make sure that all events have been
3640 read, you must call this function repeatedly until it
3641 returns an empty list.  The reason is that the call will
3642 read events up to the maximum appliance-to-host message
3643 size and leave remaining events in the queue.");
3644
3645   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3646    [],
3647    "return list of watched files that had events",
3648    "\
3649 This function is a helpful wrapper around C<guestfs_inotify_read>
3650 which just returns a list of pathnames of objects that were
3651 touched.  The returned pathnames are sorted and deduplicated.");
3652
3653   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3654    [],
3655    "close the inotify handle",
3656    "\
3657 This closes the inotify handle which was previously
3658 opened by inotify_init.  It removes all watches, throws
3659 away any pending events, and deallocates all resources.");
3660
3661   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3662    [],
3663    "set SELinux security context",
3664    "\
3665 This sets the SELinux security context of the daemon
3666 to the string C<context>.
3667
3668 See the documentation about SELINUX in L<guestfs(3)>.");
3669
3670   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3671    [],
3672    "get SELinux security context",
3673    "\
3674 This gets the SELinux security context of the daemon.
3675
3676 See the documentation about SELINUX in L<guestfs(3)>,
3677 and C<guestfs_setcon>");
3678
3679   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3680    [InitEmpty, Always, TestOutput (
3681       [["part_disk"; "/dev/sda"; "mbr"];
3682        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3683        ["mount_options"; ""; "/dev/sda1"; "/"];
3684        ["write_file"; "/new"; "new file contents"; "0"];
3685        ["cat"; "/new"]], "new file contents")],
3686    "make a filesystem with block size",
3687    "\
3688 This call is similar to C<guestfs_mkfs>, but it allows you to
3689 control the block size of the resulting filesystem.  Supported
3690 block sizes depend on the filesystem type, but typically they
3691 are C<1024>, C<2048> or C<4096> only.");
3692
3693   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3694    [InitEmpty, Always, TestOutput (
3695       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3696        ["mke2journal"; "4096"; "/dev/sda1"];
3697        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3698        ["mount_options"; ""; "/dev/sda2"; "/"];
3699        ["write_file"; "/new"; "new file contents"; "0"];
3700        ["cat"; "/new"]], "new file contents")],
3701    "make ext2/3/4 external journal",
3702    "\
3703 This creates an ext2 external journal on C<device>.  It is equivalent
3704 to the command:
3705
3706  mke2fs -O journal_dev -b blocksize device");
3707
3708   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3709    [InitEmpty, Always, TestOutput (
3710       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3711        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3712        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3713        ["mount_options"; ""; "/dev/sda2"; "/"];
3714        ["write_file"; "/new"; "new file contents"; "0"];
3715        ["cat"; "/new"]], "new file contents")],
3716    "make ext2/3/4 external journal with label",
3717    "\
3718 This creates an ext2 external journal on C<device> with label C<label>.");
3719
3720   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3721    (let uuid = uuidgen () in
3722     [InitEmpty, Always, TestOutput (
3723        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3724         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3725         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3726         ["mount_options"; ""; "/dev/sda2"; "/"];
3727         ["write_file"; "/new"; "new file contents"; "0"];
3728         ["cat"; "/new"]], "new file contents")]),
3729    "make ext2/3/4 external journal with UUID",
3730    "\
3731 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3732
3733   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3734    [],
3735    "make ext2/3/4 filesystem with external journal",
3736    "\
3737 This creates an ext2/3/4 filesystem on C<device> with
3738 an external journal on C<journal>.  It is equivalent
3739 to the command:
3740
3741  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3742
3743 See also C<guestfs_mke2journal>.");
3744
3745   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3746    [],
3747    "make ext2/3/4 filesystem with external journal",
3748    "\
3749 This creates an ext2/3/4 filesystem on C<device> with
3750 an external journal on the journal labeled C<label>.
3751
3752 See also C<guestfs_mke2journal_L>.");
3753
3754   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3755    [],
3756    "make ext2/3/4 filesystem with external journal",
3757    "\
3758 This creates an ext2/3/4 filesystem on C<device> with
3759 an external journal on the journal with UUID C<uuid>.
3760
3761 See also C<guestfs_mke2journal_U>.");
3762
3763   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3764    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3765    "load a kernel module",
3766    "\
3767 This loads a kernel module in the appliance.
3768
3769 The kernel module must have been whitelisted when libguestfs
3770 was built (see C<appliance/kmod.whitelist.in> in the source).");
3771
3772   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3773    [InitNone, Always, TestOutput (
3774       [["echo_daemon"; "This is a test"]], "This is a test"
3775     )],
3776    "echo arguments back to the client",
3777    "\
3778 This command concatenate the list of C<words> passed with single spaces between
3779 them and returns the resulting string.
3780
3781 You can use this command to test the connection through to the daemon.
3782
3783 See also C<guestfs_ping_daemon>.");
3784
3785   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3786    [], (* There is a regression test for this. *)
3787    "find all files and directories, returning NUL-separated list",
3788    "\
3789 This command lists out all files and directories, recursively,
3790 starting at C<directory>, placing the resulting list in the
3791 external file called C<files>.
3792
3793 This command works the same way as C<guestfs_find> with the
3794 following exceptions:
3795
3796 =over 4
3797
3798 =item *
3799
3800 The resulting list is written to an external file.
3801
3802 =item *
3803
3804 Items (filenames) in the result are separated
3805 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3806
3807 =item *
3808
3809 This command is not limited in the number of names that it
3810 can return.
3811
3812 =item *
3813
3814 The result list is not sorted.
3815
3816 =back");
3817
3818   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3819    [InitISOFS, Always, TestOutput (
3820       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3821     InitISOFS, Always, TestOutput (
3822       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3823     InitISOFS, Always, TestOutput (
3824       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3825     InitISOFS, Always, TestLastFail (
3826       [["case_sensitive_path"; "/Known-1/"]]);
3827     InitBasicFS, Always, TestOutput (
3828       [["mkdir"; "/a"];
3829        ["mkdir"; "/a/bbb"];
3830        ["touch"; "/a/bbb/c"];
3831        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3832     InitBasicFS, Always, TestOutput (
3833       [["mkdir"; "/a"];
3834        ["mkdir"; "/a/bbb"];
3835        ["touch"; "/a/bbb/c"];
3836        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3837     InitBasicFS, Always, TestLastFail (
3838       [["mkdir"; "/a"];
3839        ["mkdir"; "/a/bbb"];
3840        ["touch"; "/a/bbb/c"];
3841        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3842    "return true path on case-insensitive filesystem",
3843    "\
3844 This can be used to resolve case insensitive paths on
3845 a filesystem which is case sensitive.  The use case is
3846 to resolve paths which you have read from Windows configuration
3847 files or the Windows Registry, to the true path.
3848
3849 The command handles a peculiarity of the Linux ntfs-3g
3850 filesystem driver (and probably others), which is that although
3851 the underlying filesystem is case-insensitive, the driver
3852 exports the filesystem to Linux as case-sensitive.
3853
3854 One consequence of this is that special directories such
3855 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3856 (or other things) depending on the precise details of how
3857 they were created.  In Windows itself this would not be
3858 a problem.
3859
3860 Bug or feature?  You decide:
3861 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3862
3863 This function resolves the true case of each element in the
3864 path and returns the case-sensitive path.
3865
3866 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3867 might return C<\"/WINDOWS/system32\"> (the exact return value
3868 would depend on details of how the directories were originally
3869 created under Windows).
3870
3871 I<Note>:
3872 This function does not handle drive names, backslashes etc.
3873
3874 See also C<guestfs_realpath>.");
3875
3876   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3877    [InitBasicFS, Always, TestOutput (
3878       [["vfs_type"; "/dev/sda1"]], "ext2")],
3879    "get the Linux VFS type corresponding to a mounted device",
3880    "\
3881 This command gets the block device type corresponding to
3882 a mounted device called C<device>.
3883
3884 Usually the result is the name of the Linux VFS module that
3885 is used to mount this device (probably determined automatically
3886 if you used the C<guestfs_mount> call).");
3887
3888   ("truncate", (RErr, [Pathname "path"]), 199, [],
3889    [InitBasicFS, Always, TestOutputStruct (
3890       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3891        ["truncate"; "/test"];
3892        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3893    "truncate a file to zero size",
3894    "\
3895 This command truncates C<path> to a zero-length file.  The
3896 file must exist already.");
3897
3898   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3899    [InitBasicFS, Always, TestOutputStruct (
3900       [["touch"; "/test"];
3901        ["truncate_size"; "/test"; "1000"];
3902        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3903    "truncate a file to a particular size",
3904    "\
3905 This command truncates C<path> to size C<size> bytes.  The file
3906 must exist already.  If the file is smaller than C<size> then
3907 the file is extended to the required size with null bytes.");
3908
3909   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3910    [InitBasicFS, Always, TestOutputStruct (
3911       [["touch"; "/test"];
3912        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3913        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3914    "set timestamp of a file with nanosecond precision",
3915    "\
3916 This command sets the timestamps of a file with nanosecond
3917 precision.
3918
3919 C<atsecs, atnsecs> are the last access time (atime) in secs and
3920 nanoseconds from the epoch.
3921
3922 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3923 secs and nanoseconds from the epoch.
3924
3925 If the C<*nsecs> field contains the special value C<-1> then
3926 the corresponding timestamp is set to the current time.  (The
3927 C<*secs> field is ignored in this case).
3928
3929 If the C<*nsecs> field contains the special value C<-2> then
3930 the corresponding timestamp is left unchanged.  (The
3931 C<*secs> field is ignored in this case).");
3932
3933   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3934    [InitBasicFS, Always, TestOutputStruct (
3935       [["mkdir_mode"; "/test"; "0o111"];
3936        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3937    "create a directory with a particular mode",
3938    "\
3939 This command creates a directory, setting the initial permissions
3940 of the directory to C<mode>.
3941
3942 For common Linux filesystems, the actual mode which is set will
3943 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3944 interpret the mode in other ways.
3945
3946 See also C<guestfs_mkdir>, C<guestfs_umask>");
3947
3948   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3949    [], (* XXX *)
3950    "change file owner and group",
3951    "\
3952 Change the file owner to C<owner> and group to C<group>.
3953 This is like C<guestfs_chown> but if C<path> is a symlink then
3954 the link itself is changed, not the target.
3955
3956 Only numeric uid and gid are supported.  If you want to use
3957 names, you will need to locate and parse the password file
3958 yourself (Augeas support makes this relatively easy).");
3959
3960   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3961    [], (* XXX *)
3962    "lstat on multiple files",
3963    "\
3964 This call allows you to perform the C<guestfs_lstat> operation
3965 on multiple files, where all files are in the directory C<path>.
3966 C<names> is the list of files from this directory.
3967
3968 On return you get a list of stat structs, with a one-to-one
3969 correspondence to the C<names> list.  If any name did not exist
3970 or could not be lstat'd, then the C<ino> field of that structure
3971 is set to C<-1>.
3972
3973 This call is intended for programs that want to efficiently
3974 list a directory contents without making many round-trips.
3975 See also C<guestfs_lxattrlist> for a similarly efficient call
3976 for getting extended attributes.  Very long directory listings
3977 might cause the protocol message size to be exceeded, causing
3978 this call to fail.  The caller must split up such requests
3979 into smaller groups of names.");
3980
3981   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3982    [], (* XXX *)
3983    "lgetxattr on multiple files",
3984    "\
3985 This call allows you to get the extended attributes
3986 of multiple files, where all files are in the directory C<path>.
3987 C<names> is the list of files from this directory.
3988
3989 On return you get a flat list of xattr structs which must be
3990 interpreted sequentially.  The first xattr struct always has a zero-length
3991 C<attrname>.  C<attrval> in this struct is zero-length
3992 to indicate there was an error doing C<lgetxattr> for this
3993 file, I<or> is a C string which is a decimal number
3994 (the number of following attributes for this file, which could
3995 be C<\"0\">).  Then after the first xattr struct are the
3996 zero or more attributes for the first named file.
3997 This repeats for the second and subsequent files.
3998
3999 This call is intended for programs that want to efficiently
4000 list a directory contents without making many round-trips.
4001 See also C<guestfs_lstatlist> for a similarly efficient call
4002 for getting standard stats.  Very long directory listings
4003 might cause the protocol message size to be exceeded, causing
4004 this call to fail.  The caller must split up such requests
4005 into smaller groups of names.");
4006
4007   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4008    [], (* XXX *)
4009    "readlink on multiple files",
4010    "\
4011 This call allows you to do a C<readlink> operation
4012 on multiple files, where all files are in the directory C<path>.
4013 C<names> is the list of files from this directory.
4014
4015 On return you get a list of strings, with a one-to-one
4016 correspondence to the C<names> list.  Each string is the
4017 value of the symbol link.
4018
4019 If the C<readlink(2)> operation fails on any name, then
4020 the corresponding result string is the empty string C<\"\">.
4021 However the whole operation is completed even if there
4022 were C<readlink(2)> errors, and so you can call this
4023 function with names where you don't know if they are
4024 symbolic links already (albeit slightly less efficient).
4025
4026 This call is intended for programs that want to efficiently
4027 list a directory contents without making many round-trips.
4028 Very long directory listings might cause the protocol
4029 message size to be exceeded, causing
4030 this call to fail.  The caller must split up such requests
4031 into smaller groups of names.");
4032
4033   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4034    [InitISOFS, Always, TestOutputBuffer (
4035       [["pread"; "/known-4"; "1"; "3"]], "\n");
4036     InitISOFS, Always, TestOutputBuffer (
4037       [["pread"; "/empty"; "0"; "100"]], "")],
4038    "read part of a file",
4039    "\
4040 This command lets you read part of a file.  It reads C<count>
4041 bytes of the file, starting at C<offset>, from file C<path>.
4042
4043 This may read fewer bytes than requested.  For further details
4044 see the L<pread(2)> system call.");
4045
4046   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4047    [InitEmpty, Always, TestRun (
4048       [["part_init"; "/dev/sda"; "gpt"]])],
4049    "create an empty partition table",
4050    "\
4051 This creates an empty partition table on C<device> of one of the
4052 partition types listed below.  Usually C<parttype> should be
4053 either C<msdos> or C<gpt> (for large disks).
4054
4055 Initially there are no partitions.  Following this, you should
4056 call C<guestfs_part_add> for each partition required.
4057
4058 Possible values for C<parttype> are:
4059
4060 =over 4
4061
4062 =item B<efi> | B<gpt>
4063
4064 Intel EFI / GPT partition table.
4065
4066 This is recommended for >= 2 TB partitions that will be accessed
4067 from Linux and Intel-based Mac OS X.  It also has limited backwards
4068 compatibility with the C<mbr> format.
4069
4070 =item B<mbr> | B<msdos>
4071
4072 The standard PC \"Master Boot Record\" (MBR) format used
4073 by MS-DOS and Windows.  This partition type will B<only> work
4074 for device sizes up to 2 TB.  For large disks we recommend
4075 using C<gpt>.
4076
4077 =back
4078
4079 Other partition table types that may work but are not
4080 supported include:
4081
4082 =over 4
4083
4084 =item B<aix>
4085
4086 AIX disk labels.
4087
4088 =item B<amiga> | B<rdb>
4089
4090 Amiga \"Rigid Disk Block\" format.
4091
4092 =item B<bsd>
4093
4094 BSD disk labels.
4095
4096 =item B<dasd>
4097
4098 DASD, used on IBM mainframes.
4099
4100 =item B<dvh>
4101
4102 MIPS/SGI volumes.
4103
4104 =item B<mac>
4105
4106 Old Mac partition format.  Modern Macs use C<gpt>.
4107
4108 =item B<pc98>
4109
4110 NEC PC-98 format, common in Japan apparently.
4111
4112 =item B<sun>
4113
4114 Sun disk labels.
4115
4116 =back");
4117
4118   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4119    [InitEmpty, Always, TestRun (
4120       [["part_init"; "/dev/sda"; "mbr"];
4121        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4122     InitEmpty, Always, TestRun (
4123       [["part_init"; "/dev/sda"; "gpt"];
4124        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4125        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4126     InitEmpty, Always, TestRun (
4127       [["part_init"; "/dev/sda"; "mbr"];
4128        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4129        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4130        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4131        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4132    "add a partition to the device",
4133    "\
4134 This command adds a partition to C<device>.  If there is no partition
4135 table on the device, call C<guestfs_part_init> first.
4136
4137 The C<prlogex> parameter is the type of partition.  Normally you
4138 should pass C<p> or C<primary> here, but MBR partition tables also
4139 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4140 types.
4141
4142 C<startsect> and C<endsect> are the start and end of the partition
4143 in I<sectors>.  C<endsect> may be negative, which means it counts
4144 backwards from the end of the disk (C<-1> is the last sector).
4145
4146 Creating a partition which covers the whole disk is not so easy.
4147 Use C<guestfs_part_disk> to do that.");
4148
4149   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4150    [InitEmpty, Always, TestRun (
4151       [["part_disk"; "/dev/sda"; "mbr"]]);
4152     InitEmpty, Always, TestRun (
4153       [["part_disk"; "/dev/sda"; "gpt"]])],
4154    "partition whole disk with a single primary partition",
4155    "\
4156 This command is simply a combination of C<guestfs_part_init>
4157 followed by C<guestfs_part_add> to create a single primary partition
4158 covering the whole disk.
4159
4160 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4161 but other possible values are described in C<guestfs_part_init>.");
4162
4163   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4164    [InitEmpty, Always, TestRun (
4165       [["part_disk"; "/dev/sda"; "mbr"];
4166        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4167    "make a partition bootable",
4168    "\
4169 This sets the bootable flag on partition numbered C<partnum> on
4170 device C<device>.  Note that partitions are numbered from 1.
4171
4172 The bootable flag is used by some operating systems (notably
4173 Windows) to determine which partition to boot from.  It is by
4174 no means universally recognized.");
4175
4176   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4177    [InitEmpty, Always, TestRun (
4178       [["part_disk"; "/dev/sda"; "gpt"];
4179        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4180    "set partition name",
4181    "\
4182 This sets the partition name on partition numbered C<partnum> on
4183 device C<device>.  Note that partitions are numbered from 1.
4184
4185 The partition name can only be set on certain types of partition
4186 table.  This works on C<gpt> but not on C<mbr> partitions.");
4187
4188   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4189    [], (* XXX Add a regression test for this. *)
4190    "list partitions on a device",
4191    "\
4192 This command parses the partition table on C<device> and
4193 returns the list of partitions found.
4194
4195 The fields in the returned structure are:
4196
4197 =over 4
4198
4199 =item B<part_num>
4200
4201 Partition number, counting from 1.
4202
4203 =item B<part_start>
4204
4205 Start of the partition I<in bytes>.  To get sectors you have to
4206 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4207
4208 =item B<part_end>
4209
4210 End of the partition in bytes.
4211
4212 =item B<part_size>
4213
4214 Size of the partition in bytes.
4215
4216 =back");
4217
4218   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4219    [InitEmpty, Always, TestOutput (
4220       [["part_disk"; "/dev/sda"; "gpt"];
4221        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4222    "get the partition table type",
4223    "\
4224 This command examines the partition table on C<device> and
4225 returns the partition table type (format) being used.
4226
4227 Common return values include: C<msdos> (a DOS/Windows style MBR
4228 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4229 values are possible, although unusual.  See C<guestfs_part_init>
4230 for a full list.");
4231
4232   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4233    [InitBasicFS, Always, TestOutputBuffer (
4234       [["fill"; "0x63"; "10"; "/test"];
4235        ["read_file"; "/test"]], "cccccccccc")],
4236    "fill a file with octets",
4237    "\
4238 This command creates a new file called C<path>.  The initial
4239 content of the file is C<len> octets of C<c>, where C<c>
4240 must be a number in the range C<[0..255]>.
4241
4242 To fill a file with zero bytes (sparsely), it is
4243 much more efficient to use C<guestfs_truncate_size>.");
4244
4245   ("available", (RErr, [StringList "groups"]), 216, [],
4246    [InitNone, Always, TestRun [["available"; ""]]],
4247    "test availability of some parts of the API",
4248    "\
4249 This command is used to check the availability of some
4250 groups of functionality in the appliance, which not all builds of
4251 the libguestfs appliance will be able to provide.
4252
4253 The libguestfs groups, and the functions that those
4254 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4255
4256 The argument C<groups> is a list of group names, eg:
4257 C<[\"inotify\", \"augeas\"]> would check for the availability of
4258 the Linux inotify functions and Augeas (configuration file
4259 editing) functions.
4260
4261 The command returns no error if I<all> requested groups are available.
4262
4263 It fails with an error if one or more of the requested
4264 groups is unavailable in the appliance.
4265
4266 If an unknown group name is included in the
4267 list of groups then an error is always returned.
4268
4269 I<Notes:>
4270
4271 =over 4
4272
4273 =item *
4274
4275 You must call C<guestfs_launch> before calling this function.
4276
4277 The reason is because we don't know what groups are
4278 supported by the appliance/daemon until it is running and can
4279 be queried.
4280
4281 =item *
4282
4283 If a group of functions is available, this does not necessarily
4284 mean that they will work.  You still have to check for errors
4285 when calling individual API functions even if they are
4286 available.
4287
4288 =item *
4289
4290 It is usually the job of distro packagers to build
4291 complete functionality into the libguestfs appliance.
4292 Upstream libguestfs, if built from source with all
4293 requirements satisfied, will support everything.
4294
4295 =item *
4296
4297 This call was added in version C<1.0.80>.  In previous
4298 versions of libguestfs all you could do would be to speculatively
4299 execute a command to find out if the daemon implemented it.
4300 See also C<guestfs_version>.
4301
4302 =back");
4303
4304   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4305    [InitBasicFS, Always, TestOutputBuffer (
4306       [["write_file"; "/src"; "hello, world"; "0"];
4307        ["dd"; "/src"; "/dest"];
4308        ["read_file"; "/dest"]], "hello, world")],
4309    "copy from source to destination using dd",
4310    "\
4311 This command copies from one source device or file C<src>
4312 to another destination device or file C<dest>.  Normally you
4313 would use this to copy to or from a device or partition, for
4314 example to duplicate a filesystem.
4315
4316 If the destination is a device, it must be as large or larger
4317 than the source file or device, otherwise the copy will fail.
4318 This command cannot do partial copies (see C<guestfs_copy_size>).");
4319
4320   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4321    [InitBasicFS, Always, TestOutputInt (
4322       [["write_file"; "/file"; "hello, world"; "0"];
4323        ["filesize"; "/file"]], 12)],
4324    "return the size of the file in bytes",
4325    "\
4326 This command returns the size of C<file> in bytes.
4327
4328 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4329 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4330 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4331
4332   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4333    [InitBasicFSonLVM, Always, TestOutputList (
4334       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4335        ["lvs"]], ["/dev/VG/LV2"])],
4336    "rename an LVM logical volume",
4337    "\
4338 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4339
4340   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4341    [InitBasicFSonLVM, Always, TestOutputList (
4342       [["umount"; "/"];
4343        ["vg_activate"; "false"; "VG"];
4344        ["vgrename"; "VG"; "VG2"];
4345        ["vg_activate"; "true"; "VG2"];
4346        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4347        ["vgs"]], ["VG2"])],
4348    "rename an LVM volume group",
4349    "\
4350 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4351
4352   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4353    [InitISOFS, Always, TestOutputBuffer (
4354       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4355    "list the contents of a single file in an initrd",
4356    "\
4357 This command unpacks the file C<filename> from the initrd file
4358 called C<initrdpath>.  The filename must be given I<without> the
4359 initial C</> character.
4360
4361 For example, in guestfish you could use the following command
4362 to examine the boot script (usually called C</init>)
4363 contained in a Linux initrd or initramfs image:
4364
4365  initrd-cat /boot/initrd-<version>.img init
4366
4367 See also C<guestfs_initrd_list>.");
4368
4369   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4370    [],
4371    "get the UUID of a physical volume",
4372    "\
4373 This command returns the UUID of the LVM PV C<device>.");
4374
4375   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4376    [],
4377    "get the UUID of a volume group",
4378    "\
4379 This command returns the UUID of the LVM VG named C<vgname>.");
4380
4381   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4382    [],
4383    "get the UUID of a logical volume",
4384    "\
4385 This command returns the UUID of the LVM LV C<device>.");
4386
4387   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4388    [],
4389    "get the PV UUIDs containing the volume group",
4390    "\
4391 Given a VG called C<vgname>, this returns the UUIDs of all
4392 the physical volumes that this volume group resides on.
4393
4394 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4395 calls to associate physical volumes and volume groups.
4396
4397 See also C<guestfs_vglvuuids>.");
4398
4399   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4400    [],
4401    "get the LV UUIDs of all LVs in the volume group",
4402    "\
4403 Given a VG called C<vgname>, this returns the UUIDs of all
4404 the logical volumes created in this volume group.
4405
4406 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4407 calls to associate logical volumes and volume groups.
4408
4409 See also C<guestfs_vgpvuuids>.");
4410
4411   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4412    [InitBasicFS, Always, TestOutputBuffer (
4413       [["write_file"; "/src"; "hello, world"; "0"];
4414        ["copy_size"; "/src"; "/dest"; "5"];
4415        ["read_file"; "/dest"]], "hello")],
4416    "copy size bytes from source to destination using dd",
4417    "\
4418 This command copies exactly C<size> bytes from one source device
4419 or file C<src> to another destination device or file C<dest>.
4420
4421 Note this will fail if the source is too short or if the destination
4422 is not large enough.");
4423
4424   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4425    [InitBasicFSonLVM, Always, TestRun (
4426       [["zero_device"; "/dev/VG/LV"]])],
4427    "write zeroes to an entire device",
4428    "\
4429 This command writes zeroes over the entire C<device>.  Compare
4430 with C<guestfs_zero> which just zeroes the first few blocks of
4431 a device.");
4432
4433   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [],
4434    [InitBasicFS, Always, TestOutput (
4435       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4436        ["cat"; "/hello"]], "hello\n")],
4437    "unpack compressed tarball to directory",
4438    "\
4439 This command uploads and unpacks local file C<tarball> (an
4440 I<xz compressed> tar file) into C<directory>.");
4441
4442   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4443    [],
4444    "pack directory into compressed tarball",
4445    "\
4446 This command packs the contents of C<directory> and downloads
4447 it to local file C<tarball> (as an xz compressed tar archive).");
4448
4449   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4450    [],
4451    "resize an NTFS filesystem",
4452    "\
4453 This command resizes an NTFS filesystem, expanding or
4454 shrinking it to the size of the underlying device.
4455 See also L<ntfsresize(8)>.");
4456
4457   ("vgscan", (RErr, []), 232, [],
4458    [InitEmpty, Always, TestRun (
4459       [["vgscan"]])],
4460    "rescan for LVM physical volumes, volume groups and logical volumes",
4461    "\
4462 This rescans all block devices and rebuilds the list of LVM
4463 physical volumes, volume groups and logical volumes.");
4464
4465   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4466    [InitEmpty, Always, TestRun (
4467       [["part_init"; "/dev/sda"; "mbr"];
4468        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4469        ["part_del"; "/dev/sda"; "1"]])],
4470    "delete a partition",
4471    "\
4472 This command deletes the partition numbered C<partnum> on C<device>.
4473
4474 Note that in the case of MBR partitioning, deleting an
4475 extended partition also deletes any logical partitions
4476 it contains.");
4477
4478   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4479    [InitEmpty, Always, TestOutputTrue (
4480       [["part_init"; "/dev/sda"; "mbr"];
4481        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4482        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4483        ["part_get_bootable"; "/dev/sda"; "1"]])],
4484    "return true if a partition is bootable",
4485    "\
4486 This command returns true if the partition C<partnum> on
4487 C<device> has the bootable flag set.
4488
4489 See also C<guestfs_part_set_bootable>.");
4490
4491   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4492    [InitEmpty, Always, TestOutputInt (
4493       [["part_init"; "/dev/sda"; "mbr"];
4494        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4495        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4496        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4497    "get the MBR type byte (ID byte) from a partition",
4498    "\
4499 Returns the MBR type byte (also known as the ID byte) from
4500 the numbered partition C<partnum>.
4501
4502 Note that only MBR (old DOS-style) partitions have type bytes.
4503 You will get undefined results for other partition table
4504 types (see C<guestfs_part_get_parttype>).");
4505
4506   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4507    [], (* tested by part_get_mbr_id *)
4508    "set the MBR type byte (ID byte) of a partition",
4509    "\
4510 Sets the MBR type byte (also known as the ID byte) of
4511 the numbered partition C<partnum> to C<idbyte>.  Note
4512 that the type bytes quoted in most documentation are
4513 in fact hexadecimal numbers, but usually documented
4514 without any leading \"0x\" which might be confusing.
4515
4516 Note that only MBR (old DOS-style) partitions have type bytes.
4517 You will get undefined results for other partition table
4518 types (see C<guestfs_part_get_parttype>).");
4519
4520   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4521    [InitISOFS, Always, TestOutput (
4522       [["checksum_device"; "md5"; "/dev/sdd"]],
4523       (Digest.to_hex (Digest.file "images/test.iso")))],
4524    "compute MD5, SHAx or CRC checksum of the contents of a device",
4525    "\
4526 This call computes the MD5, SHAx or CRC checksum of the
4527 contents of the device named C<device>.  For the types of
4528 checksums supported see the C<guestfs_checksum> command.");
4529
4530   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4531    [InitNone, Always, TestRun (
4532       [["part_disk"; "/dev/sda"; "mbr"];
4533        ["pvcreate"; "/dev/sda1"];
4534        ["vgcreate"; "VG"; "/dev/sda1"];
4535        ["lvcreate"; "LV"; "VG"; "10"];
4536        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4537    "expand an LV to fill free space",
4538    "\
4539 This expands an existing logical volume C<lv> so that it fills
4540 C<pc>% of the remaining free space in the volume group.  Commonly
4541 you would call this with pc = 100 which expands the logical volume
4542 as much as possible, using all remaining free space in the volume
4543 group.");
4544
4545   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4546    [], (* XXX Augeas code needs tests. *)
4547    "clear Augeas path",
4548    "\
4549 Set the value associated with C<path> to C<NULL>.  This
4550 is the same as the L<augtool(1)> C<clear> command.");
4551
4552   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4553    [InitEmpty, Always, TestOutputInt (
4554       [["get_umask"]], 0o22)],
4555    "get the current umask",
4556    "\
4557 Return the current umask.  By default the umask is C<022>
4558 unless it has been set by calling C<guestfs_umask>.");
4559
4560   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4561    [],
4562    "upload a file to the appliance (internal use only)",
4563    "\
4564 The C<guestfs_debug_upload> command uploads a file to
4565 the libguestfs appliance.
4566
4567 There is no comprehensive help for this command.  You have
4568 to look at the file C<daemon/debug.c> in the libguestfs source
4569 to find out what it is for.");
4570
4571   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4572    [InitBasicFS, Always, TestOutput (
4573       [["base64_in"; "../images/hello.b64"; "/hello"];
4574        ["cat"; "/hello"]], "hello\n")],
4575    "upload base64-encoded data to file",
4576    "\
4577 This command uploads base64-encoded data from C<base64file>
4578 to C<filename>.");
4579
4580   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4581    [],
4582    "download file and encode as base64",
4583    "\
4584 This command downloads the contents of C<filename>, writing
4585 it out to local file C<base64file> encoded as base64.");
4586
4587   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4588    [],
4589    "compute MD5, SHAx or CRC checksum of files in a directory",
4590    "\
4591 This command computes the checksums of all regular files in
4592 C<directory> and then emits a list of those checksums to
4593 the local output file C<sumsfile>.
4594
4595 This can be used for verifying the integrity of a virtual
4596 machine.  However to be properly secure you should pay
4597 attention to the output of the checksum command (it uses
4598 the ones from GNU coreutils).  In particular when the
4599 filename is not printable, coreutils uses a special
4600 backslash syntax.  For more information, see the GNU
4601 coreutils info file.");
4602
4603 ]
4604
4605 let all_functions = non_daemon_functions @ daemon_functions
4606
4607 (* In some places we want the functions to be displayed sorted
4608  * alphabetically, so this is useful:
4609  *)
4610 let all_functions_sorted =
4611   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4612                compare n1 n2) all_functions
4613
4614 (* Field types for structures. *)
4615 type field =
4616   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4617   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4618   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4619   | FUInt32
4620   | FInt32
4621   | FUInt64
4622   | FInt64
4623   | FBytes                      (* Any int measure that counts bytes. *)
4624   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4625   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4626
4627 (* Because we generate extra parsing code for LVM command line tools,
4628  * we have to pull out the LVM columns separately here.
4629  *)
4630 let lvm_pv_cols = [
4631   "pv_name", FString;
4632   "pv_uuid", FUUID;
4633   "pv_fmt", FString;
4634   "pv_size", FBytes;
4635   "dev_size", FBytes;
4636   "pv_free", FBytes;
4637   "pv_used", FBytes;
4638   "pv_attr", FString (* XXX *);
4639   "pv_pe_count", FInt64;
4640   "pv_pe_alloc_count", FInt64;
4641   "pv_tags", FString;
4642   "pe_start", FBytes;
4643   "pv_mda_count", FInt64;
4644   "pv_mda_free", FBytes;
4645   (* Not in Fedora 10:
4646      "pv_mda_size", FBytes;
4647   *)
4648 ]
4649 let lvm_vg_cols = [
4650   "vg_name", FString;
4651   "vg_uuid", FUUID;
4652   "vg_fmt", FString;
4653   "vg_attr", FString (* XXX *);
4654   "vg_size", FBytes;
4655   "vg_free", FBytes;
4656   "vg_sysid", FString;
4657   "vg_extent_size", FBytes;
4658   "vg_extent_count", FInt64;
4659   "vg_free_count", FInt64;
4660   "max_lv", FInt64;
4661   "max_pv", FInt64;
4662   "pv_count", FInt64;
4663   "lv_count", FInt64;
4664   "snap_count", FInt64;
4665   "vg_seqno", FInt64;
4666   "vg_tags", FString;
4667   "vg_mda_count", FInt64;
4668   "vg_mda_free", FBytes;
4669   (* Not in Fedora 10:
4670      "vg_mda_size", FBytes;
4671   *)
4672 ]
4673 let lvm_lv_cols = [
4674   "lv_name", FString;
4675   "lv_uuid", FUUID;
4676   "lv_attr", FString (* XXX *);
4677   "lv_major", FInt64;
4678   "lv_minor", FInt64;
4679   "lv_kernel_major", FInt64;
4680   "lv_kernel_minor", FInt64;
4681   "lv_size", FBytes;
4682   "seg_count", FInt64;
4683   "origin", FString;
4684   "snap_percent", FOptPercent;
4685   "copy_percent", FOptPercent;
4686   "move_pv", FString;
4687   "lv_tags", FString;
4688   "mirror_log", FString;
4689   "modules", FString;
4690 ]
4691
4692 (* Names and fields in all structures (in RStruct and RStructList)
4693  * that we support.
4694  *)
4695 let structs = [
4696   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4697    * not use this struct in any new code.
4698    *)
4699   "int_bool", [
4700     "i", FInt32;                (* for historical compatibility *)
4701     "b", FInt32;                (* for historical compatibility *)
4702   ];
4703
4704   (* LVM PVs, VGs, LVs. *)
4705   "lvm_pv", lvm_pv_cols;
4706   "lvm_vg", lvm_vg_cols;
4707   "lvm_lv", lvm_lv_cols;
4708
4709   (* Column names and types from stat structures.
4710    * NB. Can't use things like 'st_atime' because glibc header files
4711    * define some of these as macros.  Ugh.
4712    *)
4713   "stat", [
4714     "dev", FInt64;
4715     "ino", FInt64;
4716     "mode", FInt64;
4717     "nlink", FInt64;
4718     "uid", FInt64;
4719     "gid", FInt64;
4720     "rdev", FInt64;
4721     "size", FInt64;
4722     "blksize", FInt64;
4723     "blocks", FInt64;
4724     "atime", FInt64;
4725     "mtime", FInt64;
4726     "ctime", FInt64;
4727   ];
4728   "statvfs", [
4729     "bsize", FInt64;
4730     "frsize", FInt64;
4731     "blocks", FInt64;
4732     "bfree", FInt64;
4733     "bavail", FInt64;
4734     "files", FInt64;
4735     "ffree", FInt64;
4736     "favail", FInt64;
4737     "fsid", FInt64;
4738     "flag", FInt64;
4739     "namemax", FInt64;
4740   ];
4741
4742   (* Column names in dirent structure. *)
4743   "dirent", [
4744     "ino", FInt64;
4745     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4746     "ftyp", FChar;
4747     "name", FString;
4748   ];
4749
4750   (* Version numbers. *)
4751   "version", [
4752     "major", FInt64;
4753     "minor", FInt64;
4754     "release", FInt64;
4755     "extra", FString;
4756   ];
4757
4758   (* Extended attribute. *)
4759   "xattr", [
4760     "attrname", FString;
4761     "attrval", FBuffer;
4762   ];
4763
4764   (* Inotify events. *)
4765   "inotify_event", [
4766     "in_wd", FInt64;
4767     "in_mask", FUInt32;
4768     "in_cookie", FUInt32;
4769     "in_name", FString;
4770   ];
4771
4772   (* Partition table entry. *)
4773   "partition", [
4774     "part_num", FInt32;
4775     "part_start", FBytes;
4776     "part_end", FBytes;
4777     "part_size", FBytes;
4778   ];
4779 ] (* end of structs *)
4780
4781 (* Ugh, Java has to be different ..
4782  * These names are also used by the Haskell bindings.
4783  *)
4784 let java_structs = [
4785   "int_bool", "IntBool";
4786   "lvm_pv", "PV";
4787   "lvm_vg", "VG";
4788   "lvm_lv", "LV";
4789   "stat", "Stat";
4790   "statvfs", "StatVFS";
4791   "dirent", "Dirent";
4792   "version", "Version";
4793   "xattr", "XAttr";
4794   "inotify_event", "INotifyEvent";
4795   "partition", "Partition";
4796 ]
4797
4798 (* What structs are actually returned. *)
4799 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4800
4801 (* Returns a list of RStruct/RStructList structs that are returned
4802  * by any function.  Each element of returned list is a pair:
4803  *
4804  * (structname, RStructOnly)
4805  *    == there exists function which returns RStruct (_, structname)
4806  * (structname, RStructListOnly)
4807  *    == there exists function which returns RStructList (_, structname)
4808  * (structname, RStructAndList)
4809  *    == there are functions returning both RStruct (_, structname)
4810  *                                      and RStructList (_, structname)
4811  *)
4812 let rstructs_used_by functions =
4813   (* ||| is a "logical OR" for rstructs_used_t *)
4814   let (|||) a b =
4815     match a, b with
4816     | RStructAndList, _
4817     | _, RStructAndList -> RStructAndList
4818     | RStructOnly, RStructListOnly
4819     | RStructListOnly, RStructOnly -> RStructAndList
4820     | RStructOnly, RStructOnly -> RStructOnly
4821     | RStructListOnly, RStructListOnly -> RStructListOnly
4822   in
4823
4824   let h = Hashtbl.create 13 in
4825
4826   (* if elem->oldv exists, update entry using ||| operator,
4827    * else just add elem->newv to the hash
4828    *)
4829   let update elem newv =
4830     try  let oldv = Hashtbl.find h elem in
4831          Hashtbl.replace h elem (newv ||| oldv)
4832     with Not_found -> Hashtbl.add h elem newv
4833   in
4834
4835   List.iter (
4836     fun (_, style, _, _, _, _, _) ->
4837       match fst style with
4838       | RStruct (_, structname) -> update structname RStructOnly
4839       | RStructList (_, structname) -> update structname RStructListOnly
4840       | _ -> ()
4841   ) functions;
4842
4843   (* return key->values as a list of (key,value) *)
4844   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4845
4846 (* Used for testing language bindings. *)
4847 type callt =
4848   | CallString of string
4849   | CallOptString of string option
4850   | CallStringList of string list
4851   | CallInt of int
4852   | CallInt64 of int64
4853   | CallBool of bool
4854
4855 (* Used to memoize the result of pod2text. *)
4856 let pod2text_memo_filename = "src/.pod2text.data"
4857 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4858   try
4859     let chan = open_in pod2text_memo_filename in
4860     let v = input_value chan in
4861     close_in chan;
4862     v
4863   with
4864     _ -> Hashtbl.create 13
4865 let pod2text_memo_updated () =
4866   let chan = open_out pod2text_memo_filename in
4867   output_value chan pod2text_memo;
4868   close_out chan
4869
4870 (* Useful functions.
4871  * Note we don't want to use any external OCaml libraries which
4872  * makes this a bit harder than it should be.
4873  *)
4874 module StringMap = Map.Make (String)
4875
4876 let failwithf fs = ksprintf failwith fs
4877
4878 let unique = let i = ref 0 in fun () -> incr i; !i
4879
4880 let replace_char s c1 c2 =
4881   let s2 = String.copy s in
4882   let r = ref false in
4883   for i = 0 to String.length s2 - 1 do
4884     if String.unsafe_get s2 i = c1 then (
4885       String.unsafe_set s2 i c2;
4886       r := true
4887     )
4888   done;
4889   if not !r then s else s2
4890
4891 let isspace c =
4892   c = ' '
4893   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4894
4895 let triml ?(test = isspace) str =
4896   let i = ref 0 in
4897   let n = ref (String.length str) in
4898   while !n > 0 && test str.[!i]; do
4899     decr n;
4900     incr i
4901   done;
4902   if !i = 0 then str
4903   else String.sub str !i !n
4904
4905 let trimr ?(test = isspace) str =
4906   let n = ref (String.length str) in
4907   while !n > 0 && test str.[!n-1]; do
4908     decr n
4909   done;
4910   if !n = String.length str then str
4911   else String.sub str 0 !n
4912
4913 let trim ?(test = isspace) str =
4914   trimr ~test (triml ~test str)
4915
4916 let rec find s sub =
4917   let len = String.length s in
4918   let sublen = String.length sub in
4919   let rec loop i =
4920     if i <= len-sublen then (
4921       let rec loop2 j =
4922         if j < sublen then (
4923           if s.[i+j] = sub.[j] then loop2 (j+1)
4924           else -1
4925         ) else
4926           i (* found *)
4927       in
4928       let r = loop2 0 in
4929       if r = -1 then loop (i+1) else r
4930     ) else
4931       -1 (* not found *)
4932   in
4933   loop 0
4934
4935 let rec replace_str s s1 s2 =
4936   let len = String.length s in
4937   let sublen = String.length s1 in
4938   let i = find s s1 in
4939   if i = -1 then s
4940   else (
4941     let s' = String.sub s 0 i in
4942     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4943     s' ^ s2 ^ replace_str s'' s1 s2
4944   )
4945
4946 let rec string_split sep str =
4947   let len = String.length str in
4948   let seplen = String.length sep in
4949   let i = find str sep in
4950   if i = -1 then [str]
4951   else (
4952     let s' = String.sub str 0 i in
4953     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4954     s' :: string_split sep s''
4955   )
4956
4957 let files_equal n1 n2 =
4958   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4959   match Sys.command cmd with
4960   | 0 -> true
4961   | 1 -> false
4962   | i -> failwithf "%s: failed with error code %d" cmd i
4963
4964 let rec filter_map f = function
4965   | [] -> []
4966   | x :: xs ->
4967       match f x with
4968       | Some y -> y :: filter_map f xs
4969       | None -> filter_map f xs
4970
4971 let rec find_map f = function
4972   | [] -> raise Not_found
4973   | x :: xs ->
4974       match f x with
4975       | Some y -> y
4976       | None -> find_map f xs
4977
4978 let iteri f xs =
4979   let rec loop i = function
4980     | [] -> ()
4981     | x :: xs -> f i x; loop (i+1) xs
4982   in
4983   loop 0 xs
4984
4985 let mapi f xs =
4986   let rec loop i = function
4987     | [] -> []
4988     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4989   in
4990   loop 0 xs
4991
4992 let count_chars c str =
4993   let count = ref 0 in
4994   for i = 0 to String.length str - 1 do
4995     if c = String.unsafe_get str i then incr count
4996   done;
4997   !count
4998
4999 let name_of_argt = function
5000   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5001   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5002   | FileIn n | FileOut n -> n
5003
5004 let java_name_of_struct typ =
5005   try List.assoc typ java_structs
5006   with Not_found ->
5007     failwithf
5008       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5009
5010 let cols_of_struct typ =
5011   try List.assoc typ structs
5012   with Not_found ->
5013     failwithf "cols_of_struct: unknown struct %s" typ
5014
5015 let seq_of_test = function
5016   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5017   | TestOutputListOfDevices (s, _)
5018   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5019   | TestOutputTrue s | TestOutputFalse s
5020   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5021   | TestOutputStruct (s, _)
5022   | TestLastFail s -> s
5023
5024 (* Handling for function flags. *)
5025 let protocol_limit_warning =
5026   "Because of the message protocol, there is a transfer limit
5027 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5028
5029 let danger_will_robinson =
5030   "B<This command is dangerous.  Without careful use you
5031 can easily destroy all your data>."
5032
5033 let deprecation_notice flags =
5034   try
5035     let alt =
5036       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5037     let txt =
5038       sprintf "This function is deprecated.
5039 In new code, use the C<%s> call instead.
5040
5041 Deprecated functions will not be removed from the API, but the
5042 fact that they are deprecated indicates that there are problems
5043 with correct use of these functions." alt in
5044     Some txt
5045   with
5046     Not_found -> None
5047
5048 (* Create list of optional groups. *)
5049 let optgroups =
5050   let h = Hashtbl.create 13 in
5051   List.iter (
5052     fun (name, _, _, flags, _, _, _) ->
5053       List.iter (
5054         function
5055         | Optional group ->
5056             let names = try Hashtbl.find h group with Not_found -> [] in
5057             Hashtbl.replace h group (name :: names)
5058         | _ -> ()
5059       ) flags
5060   ) daemon_functions;
5061   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5062   let groups =
5063     List.map (
5064       fun group -> group, List.sort compare (Hashtbl.find h group)
5065     ) groups in
5066   List.sort (fun x y -> compare (fst x) (fst y)) groups
5067
5068 (* Check function names etc. for consistency. *)
5069 let check_functions () =
5070   let contains_uppercase str =
5071     let len = String.length str in
5072     let rec loop i =
5073       if i >= len then false
5074       else (
5075         let c = str.[i] in
5076         if c >= 'A' && c <= 'Z' then true
5077         else loop (i+1)
5078       )
5079     in
5080     loop 0
5081   in
5082
5083   (* Check function names. *)
5084   List.iter (
5085     fun (name, _, _, _, _, _, _) ->
5086       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5087         failwithf "function name %s does not need 'guestfs' prefix" name;
5088       if name = "" then
5089         failwithf "function name is empty";
5090       if name.[0] < 'a' || name.[0] > 'z' then
5091         failwithf "function name %s must start with lowercase a-z" name;
5092       if String.contains name '-' then
5093         failwithf "function name %s should not contain '-', use '_' instead."
5094           name
5095   ) all_functions;
5096
5097   (* Check function parameter/return names. *)
5098   List.iter (
5099     fun (name, style, _, _, _, _, _) ->
5100       let check_arg_ret_name n =
5101         if contains_uppercase n then
5102           failwithf "%s param/ret %s should not contain uppercase chars"
5103             name n;
5104         if String.contains n '-' || String.contains n '_' then
5105           failwithf "%s param/ret %s should not contain '-' or '_'"
5106             name n;
5107         if n = "value" then
5108           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;
5109         if n = "int" || n = "char" || n = "short" || n = "long" then
5110           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5111         if n = "i" || n = "n" then
5112           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5113         if n = "argv" || n = "args" then
5114           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5115
5116         (* List Haskell, OCaml and C keywords here.
5117          * http://www.haskell.org/haskellwiki/Keywords
5118          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5119          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5120          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5121          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5122          * Omitting _-containing words, since they're handled above.
5123          * Omitting the OCaml reserved word, "val", is ok,
5124          * and saves us from renaming several parameters.
5125          *)
5126         let reserved = [
5127           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5128           "char"; "class"; "const"; "constraint"; "continue"; "data";
5129           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5130           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5131           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5132           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5133           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5134           "interface";
5135           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5136           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5137           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5138           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5139           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5140           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5141           "volatile"; "when"; "where"; "while";
5142           ] in
5143         if List.mem n reserved then
5144           failwithf "%s has param/ret using reserved word %s" name n;
5145       in
5146
5147       (match fst style with
5148        | RErr -> ()
5149        | RInt n | RInt64 n | RBool n
5150        | RConstString n | RConstOptString n | RString n
5151        | RStringList n | RStruct (n, _) | RStructList (n, _)
5152        | RHashtable n | RBufferOut n ->
5153            check_arg_ret_name n
5154       );
5155       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5156   ) all_functions;
5157
5158   (* Check short descriptions. *)
5159   List.iter (
5160     fun (name, _, _, _, _, shortdesc, _) ->
5161       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5162         failwithf "short description of %s should begin with lowercase." name;
5163       let c = shortdesc.[String.length shortdesc-1] in
5164       if c = '\n' || c = '.' then
5165         failwithf "short description of %s should not end with . or \\n." name
5166   ) all_functions;
5167
5168   (* Check long descriptions. *)
5169   List.iter (
5170     fun (name, _, _, _, _, _, longdesc) ->
5171       if longdesc.[String.length longdesc-1] = '\n' then
5172         failwithf "long description of %s should not end with \\n." name
5173   ) all_functions;
5174
5175   (* Check proc_nrs. *)
5176   List.iter (
5177     fun (name, _, proc_nr, _, _, _, _) ->
5178       if proc_nr <= 0 then
5179         failwithf "daemon function %s should have proc_nr > 0" name
5180   ) daemon_functions;
5181
5182   List.iter (
5183     fun (name, _, proc_nr, _, _, _, _) ->
5184       if proc_nr <> -1 then
5185         failwithf "non-daemon function %s should have proc_nr -1" name
5186   ) non_daemon_functions;
5187
5188   let proc_nrs =
5189     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5190       daemon_functions in
5191   let proc_nrs =
5192     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5193   let rec loop = function
5194     | [] -> ()
5195     | [_] -> ()
5196     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5197         loop rest
5198     | (name1,nr1) :: (name2,nr2) :: _ ->
5199         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5200           name1 name2 nr1 nr2
5201   in
5202   loop proc_nrs;
5203
5204   (* Check tests. *)
5205   List.iter (
5206     function
5207       (* Ignore functions that have no tests.  We generate a
5208        * warning when the user does 'make check' instead.
5209        *)
5210     | name, _, _, _, [], _, _ -> ()
5211     | name, _, _, _, tests, _, _ ->
5212         let funcs =
5213           List.map (
5214             fun (_, _, test) ->
5215               match seq_of_test test with
5216               | [] ->
5217                   failwithf "%s has a test containing an empty sequence" name
5218               | cmds -> List.map List.hd cmds
5219           ) tests in
5220         let funcs = List.flatten funcs in
5221
5222         let tested = List.mem name funcs in
5223
5224         if not tested then
5225           failwithf "function %s has tests but does not test itself" name
5226   ) all_functions
5227
5228 (* 'pr' prints to the current output file. *)
5229 let chan = ref Pervasives.stdout
5230 let lines = ref 0
5231 let pr fs =
5232   ksprintf
5233     (fun str ->
5234        let i = count_chars '\n' str in
5235        lines := !lines + i;
5236        output_string !chan str
5237     ) fs
5238
5239 let copyright_years =
5240   let this_year = 1900 + (localtime (time ())).tm_year in
5241   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5242
5243 (* Generate a header block in a number of standard styles. *)
5244 type comment_style =
5245     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5246 type license = GPLv2plus | LGPLv2plus
5247
5248 let generate_header ?(extra_inputs = []) comment license =
5249   let inputs = "src/generator.ml" :: extra_inputs in
5250   let c = match comment with
5251     | CStyle ->         pr "/* "; " *"
5252     | CPlusPlusStyle -> pr "// "; "//"
5253     | HashStyle ->      pr "# ";  "#"
5254     | OCamlStyle ->     pr "(* "; " *"
5255     | HaskellStyle ->   pr "{- "; "  " in
5256   pr "libguestfs generated file\n";
5257   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5258   List.iter (pr "%s   %s\n" c) inputs;
5259   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5260   pr "%s\n" c;
5261   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5262   pr "%s\n" c;
5263   (match license with
5264    | GPLv2plus ->
5265        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5266        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5267        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5268        pr "%s (at your option) any later version.\n" c;
5269        pr "%s\n" c;
5270        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5271        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5272        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5273        pr "%s GNU General Public License for more details.\n" c;
5274        pr "%s\n" c;
5275        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5276        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5277        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5278
5279    | LGPLv2plus ->
5280        pr "%s This library is free software; you can redistribute it and/or\n" c;
5281        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5282        pr "%s License as published by the Free Software Foundation; either\n" c;
5283        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5284        pr "%s\n" c;
5285        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5286        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5287        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5288        pr "%s Lesser General Public License for more details.\n" c;
5289        pr "%s\n" c;
5290        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5291        pr "%s License along with this library; if not, write to the Free Software\n" c;
5292        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5293   );
5294   (match comment with
5295    | CStyle -> pr " */\n"
5296    | CPlusPlusStyle
5297    | HashStyle -> ()
5298    | OCamlStyle -> pr " *)\n"
5299    | HaskellStyle -> pr "-}\n"
5300   );
5301   pr "\n"
5302
5303 (* Start of main code generation functions below this line. *)
5304
5305 (* Generate the pod documentation for the C API. *)
5306 let rec generate_actions_pod () =
5307   List.iter (
5308     fun (shortname, style, _, flags, _, _, longdesc) ->
5309       if not (List.mem NotInDocs flags) then (
5310         let name = "guestfs_" ^ shortname in
5311         pr "=head2 %s\n\n" name;
5312         pr " ";
5313         generate_prototype ~extern:false ~handle:"g" name style;
5314         pr "\n\n";
5315         pr "%s\n\n" longdesc;
5316         (match fst style with
5317          | RErr ->
5318              pr "This function returns 0 on success or -1 on error.\n\n"
5319          | RInt _ ->
5320              pr "On error this function returns -1.\n\n"
5321          | RInt64 _ ->
5322              pr "On error this function returns -1.\n\n"
5323          | RBool _ ->
5324              pr "This function returns a C truth value on success or -1 on error.\n\n"
5325          | RConstString _ ->
5326              pr "This function returns a string, or NULL on error.
5327 The string is owned by the guest handle and must I<not> be freed.\n\n"
5328          | RConstOptString _ ->
5329              pr "This function returns a string which may be NULL.
5330 There is way to return an error from this function.
5331 The string is owned by the guest handle and must I<not> be freed.\n\n"
5332          | RString _ ->
5333              pr "This function returns a string, or NULL on error.
5334 I<The caller must free the returned string after use>.\n\n"
5335          | RStringList _ ->
5336              pr "This function returns a NULL-terminated array of strings
5337 (like L<environ(3)>), or NULL if there was an error.
5338 I<The caller must free the strings and the array after use>.\n\n"
5339          | RStruct (_, typ) ->
5340              pr "This function returns a C<struct guestfs_%s *>,
5341 or NULL if there was an error.
5342 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5343          | RStructList (_, typ) ->
5344              pr "This function returns a C<struct guestfs_%s_list *>
5345 (see E<lt>guestfs-structs.hE<gt>),
5346 or NULL if there was an error.
5347 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5348          | RHashtable _ ->
5349              pr "This function returns a NULL-terminated array of
5350 strings, or NULL if there was an error.
5351 The array of strings will always have length C<2n+1>, where
5352 C<n> keys and values alternate, followed by the trailing NULL entry.
5353 I<The caller must free the strings and the array after use>.\n\n"
5354          | RBufferOut _ ->
5355              pr "This function returns a buffer, or NULL on error.
5356 The size of the returned buffer is written to C<*size_r>.
5357 I<The caller must free the returned buffer after use>.\n\n"
5358         );
5359         if List.mem ProtocolLimitWarning flags then
5360           pr "%s\n\n" protocol_limit_warning;
5361         if List.mem DangerWillRobinson flags then
5362           pr "%s\n\n" danger_will_robinson;
5363         match deprecation_notice flags with
5364         | None -> ()
5365         | Some txt -> pr "%s\n\n" txt
5366       )
5367   ) all_functions_sorted
5368
5369 and generate_structs_pod () =
5370   (* Structs documentation. *)
5371   List.iter (
5372     fun (typ, cols) ->
5373       pr "=head2 guestfs_%s\n" typ;
5374       pr "\n";
5375       pr " struct guestfs_%s {\n" typ;
5376       List.iter (
5377         function
5378         | name, FChar -> pr "   char %s;\n" name
5379         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5380         | name, FInt32 -> pr "   int32_t %s;\n" name
5381         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5382         | name, FInt64 -> pr "   int64_t %s;\n" name
5383         | name, FString -> pr "   char *%s;\n" name
5384         | name, FBuffer ->
5385             pr "   /* The next two fields describe a byte array. */\n";
5386             pr "   uint32_t %s_len;\n" name;
5387             pr "   char *%s;\n" name
5388         | name, FUUID ->
5389             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5390             pr "   char %s[32];\n" name
5391         | name, FOptPercent ->
5392             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5393             pr "   float %s;\n" name
5394       ) cols;
5395       pr " };\n";
5396       pr " \n";
5397       pr " struct guestfs_%s_list {\n" typ;
5398       pr "   uint32_t len; /* Number of elements in list. */\n";
5399       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5400       pr " };\n";
5401       pr " \n";
5402       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5403       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5404         typ typ;
5405       pr "\n"
5406   ) structs
5407
5408 and generate_availability_pod () =
5409   (* Availability documentation. *)
5410   pr "=over 4\n";
5411   pr "\n";
5412   List.iter (
5413     fun (group, functions) ->
5414       pr "=item B<%s>\n" group;
5415       pr "\n";
5416       pr "The following functions:\n";
5417       List.iter (pr "L</guestfs_%s>\n") functions;
5418       pr "\n"
5419   ) optgroups;
5420   pr "=back\n";
5421   pr "\n"
5422
5423 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5424  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5425  *
5426  * We have to use an underscore instead of a dash because otherwise
5427  * rpcgen generates incorrect code.
5428  *
5429  * This header is NOT exported to clients, but see also generate_structs_h.
5430  *)
5431 and generate_xdr () =
5432   generate_header CStyle LGPLv2plus;
5433
5434   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5435   pr "typedef string str<>;\n";
5436   pr "\n";
5437
5438   (* Internal structures. *)
5439   List.iter (
5440     function
5441     | typ, cols ->
5442         pr "struct guestfs_int_%s {\n" typ;
5443         List.iter (function
5444                    | name, FChar -> pr "  char %s;\n" name
5445                    | name, FString -> pr "  string %s<>;\n" name
5446                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5447                    | name, FUUID -> pr "  opaque %s[32];\n" name
5448                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5449                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5450                    | name, FOptPercent -> pr "  float %s;\n" name
5451                   ) cols;
5452         pr "};\n";
5453         pr "\n";
5454         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5455         pr "\n";
5456   ) structs;
5457
5458   List.iter (
5459     fun (shortname, style, _, _, _, _, _) ->
5460       let name = "guestfs_" ^ shortname in
5461
5462       (match snd style with
5463        | [] -> ()
5464        | args ->
5465            pr "struct %s_args {\n" name;
5466            List.iter (
5467              function
5468              | Pathname n | Device n | Dev_or_Path n | String n ->
5469                  pr "  string %s<>;\n" n
5470              | OptString n -> pr "  str *%s;\n" n
5471              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5472              | Bool n -> pr "  bool %s;\n" n
5473              | Int n -> pr "  int %s;\n" n
5474              | Int64 n -> pr "  hyper %s;\n" n
5475              | FileIn _ | FileOut _ -> ()
5476            ) args;
5477            pr "};\n\n"
5478       );
5479       (match fst style with
5480        | RErr -> ()
5481        | RInt n ->
5482            pr "struct %s_ret {\n" name;
5483            pr "  int %s;\n" n;
5484            pr "};\n\n"
5485        | RInt64 n ->
5486            pr "struct %s_ret {\n" name;
5487            pr "  hyper %s;\n" n;
5488            pr "};\n\n"
5489        | RBool n ->
5490            pr "struct %s_ret {\n" name;
5491            pr "  bool %s;\n" n;
5492            pr "};\n\n"
5493        | RConstString _ | RConstOptString _ ->
5494            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5495        | RString n ->
5496            pr "struct %s_ret {\n" name;
5497            pr "  string %s<>;\n" n;
5498            pr "};\n\n"
5499        | RStringList n ->
5500            pr "struct %s_ret {\n" name;
5501            pr "  str %s<>;\n" n;
5502            pr "};\n\n"
5503        | RStruct (n, typ) ->
5504            pr "struct %s_ret {\n" name;
5505            pr "  guestfs_int_%s %s;\n" typ n;
5506            pr "};\n\n"
5507        | RStructList (n, typ) ->
5508            pr "struct %s_ret {\n" name;
5509            pr "  guestfs_int_%s_list %s;\n" typ n;
5510            pr "};\n\n"
5511        | RHashtable n ->
5512            pr "struct %s_ret {\n" name;
5513            pr "  str %s<>;\n" n;
5514            pr "};\n\n"
5515        | RBufferOut n ->
5516            pr "struct %s_ret {\n" name;
5517            pr "  opaque %s<>;\n" n;
5518            pr "};\n\n"
5519       );
5520   ) daemon_functions;
5521
5522   (* Table of procedure numbers. *)
5523   pr "enum guestfs_procedure {\n";
5524   List.iter (
5525     fun (shortname, _, proc_nr, _, _, _, _) ->
5526       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5527   ) daemon_functions;
5528   pr "  GUESTFS_PROC_NR_PROCS\n";
5529   pr "};\n";
5530   pr "\n";
5531
5532   (* Having to choose a maximum message size is annoying for several
5533    * reasons (it limits what we can do in the API), but it (a) makes
5534    * the protocol a lot simpler, and (b) provides a bound on the size
5535    * of the daemon which operates in limited memory space.
5536    *)
5537   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5538   pr "\n";
5539
5540   (* Message header, etc. *)
5541   pr "\
5542 /* The communication protocol is now documented in the guestfs(3)
5543  * manpage.
5544  */
5545
5546 const GUESTFS_PROGRAM = 0x2000F5F5;
5547 const GUESTFS_PROTOCOL_VERSION = 1;
5548
5549 /* These constants must be larger than any possible message length. */
5550 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5551 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5552
5553 enum guestfs_message_direction {
5554   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5555   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5556 };
5557
5558 enum guestfs_message_status {
5559   GUESTFS_STATUS_OK = 0,
5560   GUESTFS_STATUS_ERROR = 1
5561 };
5562
5563 const GUESTFS_ERROR_LEN = 256;
5564
5565 struct guestfs_message_error {
5566   string error_message<GUESTFS_ERROR_LEN>;
5567 };
5568
5569 struct guestfs_message_header {
5570   unsigned prog;                     /* GUESTFS_PROGRAM */
5571   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5572   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5573   guestfs_message_direction direction;
5574   unsigned serial;                   /* message serial number */
5575   guestfs_message_status status;
5576 };
5577
5578 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5579
5580 struct guestfs_chunk {
5581   int cancel;                        /* if non-zero, transfer is cancelled */
5582   /* data size is 0 bytes if the transfer has finished successfully */
5583   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5584 };
5585 "
5586
5587 (* Generate the guestfs-structs.h file. *)
5588 and generate_structs_h () =
5589   generate_header CStyle LGPLv2plus;
5590
5591   (* This is a public exported header file containing various
5592    * structures.  The structures are carefully written to have
5593    * exactly the same in-memory format as the XDR structures that
5594    * we use on the wire to the daemon.  The reason for creating
5595    * copies of these structures here is just so we don't have to
5596    * export the whole of guestfs_protocol.h (which includes much
5597    * unrelated and XDR-dependent stuff that we don't want to be
5598    * public, or required by clients).
5599    *
5600    * To reiterate, we will pass these structures to and from the
5601    * client with a simple assignment or memcpy, so the format
5602    * must be identical to what rpcgen / the RFC defines.
5603    *)
5604
5605   (* Public structures. *)
5606   List.iter (
5607     fun (typ, cols) ->
5608       pr "struct guestfs_%s {\n" typ;
5609       List.iter (
5610         function
5611         | name, FChar -> pr "  char %s;\n" name
5612         | name, FString -> pr "  char *%s;\n" name
5613         | name, FBuffer ->
5614             pr "  uint32_t %s_len;\n" name;
5615             pr "  char *%s;\n" name
5616         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5617         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5618         | name, FInt32 -> pr "  int32_t %s;\n" name
5619         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5620         | name, FInt64 -> pr "  int64_t %s;\n" name
5621         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5622       ) cols;
5623       pr "};\n";
5624       pr "\n";
5625       pr "struct guestfs_%s_list {\n" typ;
5626       pr "  uint32_t len;\n";
5627       pr "  struct guestfs_%s *val;\n" typ;
5628       pr "};\n";
5629       pr "\n";
5630       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5631       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5632       pr "\n"
5633   ) structs
5634
5635 (* Generate the guestfs-actions.h file. *)
5636 and generate_actions_h () =
5637   generate_header CStyle LGPLv2plus;
5638   List.iter (
5639     fun (shortname, style, _, _, _, _, _) ->
5640       let name = "guestfs_" ^ shortname in
5641       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5642         name style
5643   ) all_functions
5644
5645 (* Generate the guestfs-internal-actions.h file. *)
5646 and generate_internal_actions_h () =
5647   generate_header CStyle LGPLv2plus;
5648   List.iter (
5649     fun (shortname, style, _, _, _, _, _) ->
5650       let name = "guestfs__" ^ shortname in
5651       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5652         name style
5653   ) non_daemon_functions
5654
5655 (* Generate the client-side dispatch stubs. *)
5656 and generate_client_actions () =
5657   generate_header CStyle LGPLv2plus;
5658
5659   pr "\
5660 #include <stdio.h>
5661 #include <stdlib.h>
5662 #include <stdint.h>
5663 #include <string.h>
5664 #include <inttypes.h>
5665
5666 #include \"guestfs.h\"
5667 #include \"guestfs-internal.h\"
5668 #include \"guestfs-internal-actions.h\"
5669 #include \"guestfs_protocol.h\"
5670
5671 #define error guestfs_error
5672 //#define perrorf guestfs_perrorf
5673 #define safe_malloc guestfs_safe_malloc
5674 #define safe_realloc guestfs_safe_realloc
5675 //#define safe_strdup guestfs_safe_strdup
5676 #define safe_memdup guestfs_safe_memdup
5677
5678 /* Check the return message from a call for validity. */
5679 static int
5680 check_reply_header (guestfs_h *g,
5681                     const struct guestfs_message_header *hdr,
5682                     unsigned int proc_nr, unsigned int serial)
5683 {
5684   if (hdr->prog != GUESTFS_PROGRAM) {
5685     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5686     return -1;
5687   }
5688   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5689     error (g, \"wrong protocol version (%%d/%%d)\",
5690            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5691     return -1;
5692   }
5693   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5694     error (g, \"unexpected message direction (%%d/%%d)\",
5695            hdr->direction, GUESTFS_DIRECTION_REPLY);
5696     return -1;
5697   }
5698   if (hdr->proc != proc_nr) {
5699     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5700     return -1;
5701   }
5702   if (hdr->serial != serial) {
5703     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5704     return -1;
5705   }
5706
5707   return 0;
5708 }
5709
5710 /* Check we are in the right state to run a high-level action. */
5711 static int
5712 check_state (guestfs_h *g, const char *caller)
5713 {
5714   if (!guestfs__is_ready (g)) {
5715     if (guestfs__is_config (g) || guestfs__is_launching (g))
5716       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5717         caller);
5718     else
5719       error (g, \"%%s called from the wrong state, %%d != READY\",
5720         caller, guestfs__get_state (g));
5721     return -1;
5722   }
5723   return 0;
5724 }
5725
5726 ";
5727
5728   (* Generate code to generate guestfish call traces. *)
5729   let trace_call shortname style =
5730     pr "  if (guestfs__get_trace (g)) {\n";
5731
5732     let needs_i =
5733       List.exists (function
5734                    | StringList _ | DeviceList _ -> true
5735                    | _ -> false) (snd style) in
5736     if needs_i then (
5737       pr "    int i;\n";
5738       pr "\n"
5739     );
5740
5741     pr "    printf (\"%s\");\n" shortname;
5742     List.iter (
5743       function
5744       | String n                        (* strings *)
5745       | Device n
5746       | Pathname n
5747       | Dev_or_Path n
5748       | FileIn n
5749       | FileOut n ->
5750           (* guestfish doesn't support string escaping, so neither do we *)
5751           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5752       | OptString n ->                  (* string option *)
5753           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5754           pr "    else printf (\" null\");\n"
5755       | StringList n
5756       | DeviceList n ->                 (* string list *)
5757           pr "    putchar (' ');\n";
5758           pr "    putchar ('\"');\n";
5759           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5760           pr "      if (i > 0) putchar (' ');\n";
5761           pr "      fputs (%s[i], stdout);\n" n;
5762           pr "    }\n";
5763           pr "    putchar ('\"');\n";
5764       | Bool n ->                       (* boolean *)
5765           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5766       | Int n ->                        (* int *)
5767           pr "    printf (\" %%d\", %s);\n" n
5768       | Int64 n ->
5769           pr "    printf (\" %%\" PRIi64, %s);\n" n
5770     ) (snd style);
5771     pr "    putchar ('\\n');\n";
5772     pr "  }\n";
5773     pr "\n";
5774   in
5775
5776   (* For non-daemon functions, generate a wrapper around each function. *)
5777   List.iter (
5778     fun (shortname, style, _, _, _, _, _) ->
5779       let name = "guestfs_" ^ shortname in
5780
5781       generate_prototype ~extern:false ~semicolon:false ~newline:true
5782         ~handle:"g" name style;
5783       pr "{\n";
5784       trace_call shortname style;
5785       pr "  return guestfs__%s " shortname;
5786       generate_c_call_args ~handle:"g" style;
5787       pr ";\n";
5788       pr "}\n";
5789       pr "\n"
5790   ) non_daemon_functions;
5791
5792   (* Client-side stubs for each function. *)
5793   List.iter (
5794     fun (shortname, style, _, _, _, _, _) ->
5795       let name = "guestfs_" ^ shortname in
5796
5797       (* Generate the action stub. *)
5798       generate_prototype ~extern:false ~semicolon:false ~newline:true
5799         ~handle:"g" name style;
5800
5801       let error_code =
5802         match fst style with
5803         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5804         | RConstString _ | RConstOptString _ ->
5805             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5806         | RString _ | RStringList _
5807         | RStruct _ | RStructList _
5808         | RHashtable _ | RBufferOut _ ->
5809             "NULL" in
5810
5811       pr "{\n";
5812
5813       (match snd style with
5814        | [] -> ()
5815        | _ -> pr "  struct %s_args args;\n" name
5816       );
5817
5818       pr "  guestfs_message_header hdr;\n";
5819       pr "  guestfs_message_error err;\n";
5820       let has_ret =
5821         match fst style with
5822         | RErr -> false
5823         | RConstString _ | RConstOptString _ ->
5824             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5825         | RInt _ | RInt64 _
5826         | RBool _ | RString _ | RStringList _
5827         | RStruct _ | RStructList _
5828         | RHashtable _ | RBufferOut _ ->
5829             pr "  struct %s_ret ret;\n" name;
5830             true in
5831
5832       pr "  int serial;\n";
5833       pr "  int r;\n";
5834       pr "\n";
5835       trace_call shortname style;
5836       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5837         shortname error_code;
5838       pr "  guestfs___set_busy (g);\n";
5839       pr "\n";
5840
5841       (* Send the main header and arguments. *)
5842       (match snd style with
5843        | [] ->
5844            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5845              (String.uppercase shortname)
5846        | args ->
5847            List.iter (
5848              function
5849              | Pathname n | Device n | Dev_or_Path n | String n ->
5850                  pr "  args.%s = (char *) %s;\n" n n
5851              | OptString n ->
5852                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5853              | StringList n | DeviceList n ->
5854                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5855                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5856              | Bool n ->
5857                  pr "  args.%s = %s;\n" n n
5858              | Int n ->
5859                  pr "  args.%s = %s;\n" n n
5860              | Int64 n ->
5861                  pr "  args.%s = %s;\n" n n
5862              | FileIn _ | FileOut _ -> ()
5863            ) args;
5864            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5865              (String.uppercase shortname);
5866            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5867              name;
5868       );
5869       pr "  if (serial == -1) {\n";
5870       pr "    guestfs___end_busy (g);\n";
5871       pr "    return %s;\n" error_code;
5872       pr "  }\n";
5873       pr "\n";
5874
5875       (* Send any additional files (FileIn) requested. *)
5876       let need_read_reply_label = ref false in
5877       List.iter (
5878         function
5879         | FileIn n ->
5880             pr "  r = guestfs___send_file (g, %s);\n" n;
5881             pr "  if (r == -1) {\n";
5882             pr "    guestfs___end_busy (g);\n";
5883             pr "    return %s;\n" error_code;
5884             pr "  }\n";
5885             pr "  if (r == -2) /* daemon cancelled */\n";
5886             pr "    goto read_reply;\n";
5887             need_read_reply_label := true;
5888             pr "\n";
5889         | _ -> ()
5890       ) (snd style);
5891
5892       (* Wait for the reply from the remote end. *)
5893       if !need_read_reply_label then pr " read_reply:\n";
5894       pr "  memset (&hdr, 0, sizeof hdr);\n";
5895       pr "  memset (&err, 0, sizeof err);\n";
5896       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5897       pr "\n";
5898       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5899       if not has_ret then
5900         pr "NULL, NULL"
5901       else
5902         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5903       pr ");\n";
5904
5905       pr "  if (r == -1) {\n";
5906       pr "    guestfs___end_busy (g);\n";
5907       pr "    return %s;\n" error_code;
5908       pr "  }\n";
5909       pr "\n";
5910
5911       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5912         (String.uppercase shortname);
5913       pr "    guestfs___end_busy (g);\n";
5914       pr "    return %s;\n" error_code;
5915       pr "  }\n";
5916       pr "\n";
5917
5918       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5919       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5920       pr "    free (err.error_message);\n";
5921       pr "    guestfs___end_busy (g);\n";
5922       pr "    return %s;\n" error_code;
5923       pr "  }\n";
5924       pr "\n";
5925
5926       (* Expecting to receive further files (FileOut)? *)
5927       List.iter (
5928         function
5929         | FileOut n ->
5930             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5931             pr "    guestfs___end_busy (g);\n";
5932             pr "    return %s;\n" error_code;
5933             pr "  }\n";
5934             pr "\n";
5935         | _ -> ()
5936       ) (snd style);
5937
5938       pr "  guestfs___end_busy (g);\n";
5939
5940       (match fst style with
5941        | RErr -> pr "  return 0;\n"
5942        | RInt n | RInt64 n | RBool n ->
5943            pr "  return ret.%s;\n" n
5944        | RConstString _ | RConstOptString _ ->
5945            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5946        | RString n ->
5947            pr "  return ret.%s; /* caller will free */\n" n
5948        | RStringList n | RHashtable n ->
5949            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5950            pr "  ret.%s.%s_val =\n" n n;
5951            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5952            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5953              n n;
5954            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5955            pr "  return ret.%s.%s_val;\n" n n
5956        | RStruct (n, _) ->
5957            pr "  /* caller will free this */\n";
5958            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5959        | RStructList (n, _) ->
5960            pr "  /* caller will free this */\n";
5961            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5962        | RBufferOut n ->
5963            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5964            pr "   * _val might be NULL here.  To make the API saner for\n";
5965            pr "   * callers, we turn this case into a unique pointer (using\n";
5966            pr "   * malloc(1)).\n";
5967            pr "   */\n";
5968            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5969            pr "    *size_r = ret.%s.%s_len;\n" n n;
5970            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5971            pr "  } else {\n";
5972            pr "    free (ret.%s.%s_val);\n" n n;
5973            pr "    char *p = safe_malloc (g, 1);\n";
5974            pr "    *size_r = ret.%s.%s_len;\n" n n;
5975            pr "    return p;\n";
5976            pr "  }\n";
5977       );
5978
5979       pr "}\n\n"
5980   ) daemon_functions;
5981
5982   (* Functions to free structures. *)
5983   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5984   pr " * structure format is identical to the XDR format.  See note in\n";
5985   pr " * generator.ml.\n";
5986   pr " */\n";
5987   pr "\n";
5988
5989   List.iter (
5990     fun (typ, _) ->
5991       pr "void\n";
5992       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5993       pr "{\n";
5994       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5995       pr "  free (x);\n";
5996       pr "}\n";
5997       pr "\n";
5998
5999       pr "void\n";
6000       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6001       pr "{\n";
6002       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6003       pr "  free (x);\n";
6004       pr "}\n";
6005       pr "\n";
6006
6007   ) structs;
6008
6009 (* Generate daemon/actions.h. *)
6010 and generate_daemon_actions_h () =
6011   generate_header CStyle GPLv2plus;
6012
6013   pr "#include \"../src/guestfs_protocol.h\"\n";
6014   pr "\n";
6015
6016   List.iter (
6017     fun (name, style, _, _, _, _, _) ->
6018       generate_prototype
6019         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6020         name style;
6021   ) daemon_functions
6022
6023 (* Generate the linker script which controls the visibility of
6024  * symbols in the public ABI and ensures no other symbols get
6025  * exported accidentally.
6026  *)
6027 and generate_linker_script () =
6028   generate_header HashStyle GPLv2plus;
6029
6030   let globals = [
6031     "guestfs_create";
6032     "guestfs_close";
6033     "guestfs_get_error_handler";
6034     "guestfs_get_out_of_memory_handler";
6035     "guestfs_last_error";
6036     "guestfs_set_error_handler";
6037     "guestfs_set_launch_done_callback";
6038     "guestfs_set_log_message_callback";
6039     "guestfs_set_out_of_memory_handler";
6040     "guestfs_set_subprocess_quit_callback";
6041
6042     (* Unofficial parts of the API: the bindings code use these
6043      * functions, so it is useful to export them.
6044      *)
6045     "guestfs_safe_calloc";
6046     "guestfs_safe_malloc";
6047   ] in
6048   let functions =
6049     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6050       all_functions in
6051   let structs =
6052     List.concat (
6053       List.map (fun (typ, _) ->
6054                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6055         structs
6056     ) in
6057   let globals = List.sort compare (globals @ functions @ structs) in
6058
6059   pr "{\n";
6060   pr "    global:\n";
6061   List.iter (pr "        %s;\n") globals;
6062   pr "\n";
6063
6064   pr "    local:\n";
6065   pr "        *;\n";
6066   pr "};\n"
6067
6068 (* Generate the server-side stubs. *)
6069 and generate_daemon_actions () =
6070   generate_header CStyle GPLv2plus;
6071
6072   pr "#include <config.h>\n";
6073   pr "\n";
6074   pr "#include <stdio.h>\n";
6075   pr "#include <stdlib.h>\n";
6076   pr "#include <string.h>\n";
6077   pr "#include <inttypes.h>\n";
6078   pr "#include <rpc/types.h>\n";
6079   pr "#include <rpc/xdr.h>\n";
6080   pr "\n";
6081   pr "#include \"daemon.h\"\n";
6082   pr "#include \"c-ctype.h\"\n";
6083   pr "#include \"../src/guestfs_protocol.h\"\n";
6084   pr "#include \"actions.h\"\n";
6085   pr "\n";
6086
6087   List.iter (
6088     fun (name, style, _, _, _, _, _) ->
6089       (* Generate server-side stubs. *)
6090       pr "static void %s_stub (XDR *xdr_in)\n" name;
6091       pr "{\n";
6092       let error_code =
6093         match fst style with
6094         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6095         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6096         | RBool _ -> pr "  int r;\n"; "-1"
6097         | RConstString _ | RConstOptString _ ->
6098             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6099         | RString _ -> pr "  char *r;\n"; "NULL"
6100         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6101         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6102         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6103         | RBufferOut _ ->
6104             pr "  size_t size = 1;\n";
6105             pr "  char *r;\n";
6106             "NULL" in
6107
6108       (match snd style with
6109        | [] -> ()
6110        | args ->
6111            pr "  struct guestfs_%s_args args;\n" name;
6112            List.iter (
6113              function
6114              | Device n | Dev_or_Path n
6115              | Pathname n
6116              | String n -> ()
6117              | OptString n -> pr "  char *%s;\n" n
6118              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6119              | Bool n -> pr "  int %s;\n" n
6120              | Int n -> pr "  int %s;\n" n
6121              | Int64 n -> pr "  int64_t %s;\n" n
6122              | FileIn _ | FileOut _ -> ()
6123            ) args
6124       );
6125       pr "\n";
6126
6127       let is_filein =
6128         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6129
6130       (match snd style with
6131        | [] -> ()
6132        | args ->
6133            pr "  memset (&args, 0, sizeof args);\n";
6134            pr "\n";
6135            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6136            if is_filein then
6137              pr "    cancel_receive ();\n";
6138            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6139            pr "    goto done;\n";
6140            pr "  }\n";
6141            let pr_args n =
6142              pr "  char *%s = args.%s;\n" n n
6143            in
6144            let pr_list_handling_code n =
6145              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6146              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6147              pr "  if (%s == NULL) {\n" n;
6148              if is_filein then
6149                pr "    cancel_receive ();\n";
6150              pr "    reply_with_perror (\"realloc\");\n";
6151              pr "    goto done;\n";
6152              pr "  }\n";
6153              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6154              pr "  args.%s.%s_val = %s;\n" n n n;
6155            in
6156            List.iter (
6157              function
6158              | Pathname n ->
6159                  pr_args n;
6160                  pr "  ABS_PATH (%s, %s, goto done);\n"
6161                    n (if is_filein then "cancel_receive ()" else "");
6162              | Device n ->
6163                  pr_args n;
6164                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6165                    n (if is_filein then "cancel_receive ()" else "");
6166              | Dev_or_Path n ->
6167                  pr_args n;
6168                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6169                    n (if is_filein then "cancel_receive ()" else "");
6170              | String n -> pr_args n
6171              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6172              | StringList n ->
6173                  pr_list_handling_code n;
6174              | DeviceList n ->
6175                  pr_list_handling_code n;
6176                  pr "  /* Ensure that each is a device,\n";
6177                  pr "   * and perform device name translation. */\n";
6178                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6179                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6180                    (if is_filein then "cancel_receive ()" else "");
6181                  pr "  }\n";
6182              | Bool n -> pr "  %s = args.%s;\n" n n
6183              | Int n -> pr "  %s = args.%s;\n" n n
6184              | Int64 n -> pr "  %s = args.%s;\n" n n
6185              | FileIn _ | FileOut _ -> ()
6186            ) args;
6187            pr "\n"
6188       );
6189
6190
6191       (* this is used at least for do_equal *)
6192       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6193         (* Emit NEED_ROOT just once, even when there are two or
6194            more Pathname args *)
6195         pr "  NEED_ROOT (%s, goto done);\n"
6196           (if is_filein then "cancel_receive ()" else "");
6197       );
6198
6199       (* Don't want to call the impl with any FileIn or FileOut
6200        * parameters, since these go "outside" the RPC protocol.
6201        *)
6202       let args' =
6203         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6204           (snd style) in
6205       pr "  r = do_%s " name;
6206       generate_c_call_args (fst style, args');
6207       pr ";\n";
6208
6209       (match fst style with
6210        | RErr | RInt _ | RInt64 _ | RBool _
6211        | RConstString _ | RConstOptString _
6212        | RString _ | RStringList _ | RHashtable _
6213        | RStruct (_, _) | RStructList (_, _) ->
6214            pr "  if (r == %s)\n" error_code;
6215            pr "    /* do_%s has already called reply_with_error */\n" name;
6216            pr "    goto done;\n";
6217            pr "\n"
6218        | RBufferOut _ ->
6219            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6220            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6221            pr "   */\n";
6222            pr "  if (size == 1 && r == %s)\n" error_code;
6223            pr "    /* do_%s has already called reply_with_error */\n" name;
6224            pr "    goto done;\n";
6225            pr "\n"
6226       );
6227
6228       (* If there are any FileOut parameters, then the impl must
6229        * send its own reply.
6230        *)
6231       let no_reply =
6232         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6233       if no_reply then
6234         pr "  /* do_%s has already sent a reply */\n" name
6235       else (
6236         match fst style with
6237         | RErr -> pr "  reply (NULL, NULL);\n"
6238         | RInt n | RInt64 n | RBool n ->
6239             pr "  struct guestfs_%s_ret ret;\n" name;
6240             pr "  ret.%s = r;\n" n;
6241             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6242               name
6243         | RConstString _ | RConstOptString _ ->
6244             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6245         | RString n ->
6246             pr "  struct guestfs_%s_ret ret;\n" name;
6247             pr "  ret.%s = r;\n" n;
6248             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6249               name;
6250             pr "  free (r);\n"
6251         | RStringList n | RHashtable n ->
6252             pr "  struct guestfs_%s_ret ret;\n" name;
6253             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6254             pr "  ret.%s.%s_val = r;\n" n n;
6255             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6256               name;
6257             pr "  free_strings (r);\n"
6258         | RStruct (n, _) ->
6259             pr "  struct guestfs_%s_ret ret;\n" name;
6260             pr "  ret.%s = *r;\n" n;
6261             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6262               name;
6263             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6264               name
6265         | RStructList (n, _) ->
6266             pr "  struct guestfs_%s_ret ret;\n" name;
6267             pr "  ret.%s = *r;\n" n;
6268             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6269               name;
6270             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6271               name
6272         | RBufferOut n ->
6273             pr "  struct guestfs_%s_ret ret;\n" name;
6274             pr "  ret.%s.%s_val = r;\n" n n;
6275             pr "  ret.%s.%s_len = size;\n" n n;
6276             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6277               name;
6278             pr "  free (r);\n"
6279       );
6280
6281       (* Free the args. *)
6282       pr "done:\n";
6283       (match snd style with
6284        | [] -> ()
6285        | _ ->
6286            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6287              name
6288       );
6289       pr "  return;\n";
6290       pr "}\n\n";
6291   ) daemon_functions;
6292
6293   (* Dispatch function. *)
6294   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6295   pr "{\n";
6296   pr "  switch (proc_nr) {\n";
6297
6298   List.iter (
6299     fun (name, style, _, _, _, _, _) ->
6300       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6301       pr "      %s_stub (xdr_in);\n" name;
6302       pr "      break;\n"
6303   ) daemon_functions;
6304
6305   pr "    default:\n";
6306   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";
6307   pr "  }\n";
6308   pr "}\n";
6309   pr "\n";
6310
6311   (* LVM columns and tokenization functions. *)
6312   (* XXX This generates crap code.  We should rethink how we
6313    * do this parsing.
6314    *)
6315   List.iter (
6316     function
6317     | typ, cols ->
6318         pr "static const char *lvm_%s_cols = \"%s\";\n"
6319           typ (String.concat "," (List.map fst cols));
6320         pr "\n";
6321
6322         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6323         pr "{\n";
6324         pr "  char *tok, *p, *next;\n";
6325         pr "  int i, j;\n";
6326         pr "\n";
6327         (*
6328           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6329           pr "\n";
6330         *)
6331         pr "  if (!str) {\n";
6332         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6333         pr "    return -1;\n";
6334         pr "  }\n";
6335         pr "  if (!*str || c_isspace (*str)) {\n";
6336         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6337         pr "    return -1;\n";
6338         pr "  }\n";
6339         pr "  tok = str;\n";
6340         List.iter (
6341           fun (name, coltype) ->
6342             pr "  if (!tok) {\n";
6343             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6344             pr "    return -1;\n";
6345             pr "  }\n";
6346             pr "  p = strchrnul (tok, ',');\n";
6347             pr "  if (*p) next = p+1; else next = NULL;\n";
6348             pr "  *p = '\\0';\n";
6349             (match coltype with
6350              | FString ->
6351                  pr "  r->%s = strdup (tok);\n" name;
6352                  pr "  if (r->%s == NULL) {\n" name;
6353                  pr "    perror (\"strdup\");\n";
6354                  pr "    return -1;\n";
6355                  pr "  }\n"
6356              | FUUID ->
6357                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6358                  pr "    if (tok[j] == '\\0') {\n";
6359                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6360                  pr "      return -1;\n";
6361                  pr "    } else if (tok[j] != '-')\n";
6362                  pr "      r->%s[i++] = tok[j];\n" name;
6363                  pr "  }\n";
6364              | FBytes ->
6365                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6366                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6367                  pr "    return -1;\n";
6368                  pr "  }\n";
6369              | FInt64 ->
6370                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6371                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6372                  pr "    return -1;\n";
6373                  pr "  }\n";
6374              | FOptPercent ->
6375                  pr "  if (tok[0] == '\\0')\n";
6376                  pr "    r->%s = -1;\n" name;
6377                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6378                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6379                  pr "    return -1;\n";
6380                  pr "  }\n";
6381              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6382                  assert false (* can never be an LVM column *)
6383             );
6384             pr "  tok = next;\n";
6385         ) cols;
6386
6387         pr "  if (tok != NULL) {\n";
6388         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6389         pr "    return -1;\n";
6390         pr "  }\n";
6391         pr "  return 0;\n";
6392         pr "}\n";
6393         pr "\n";
6394
6395         pr "guestfs_int_lvm_%s_list *\n" typ;
6396         pr "parse_command_line_%ss (void)\n" typ;
6397         pr "{\n";
6398         pr "  char *out, *err;\n";
6399         pr "  char *p, *pend;\n";
6400         pr "  int r, i;\n";
6401         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6402         pr "  void *newp;\n";
6403         pr "\n";
6404         pr "  ret = malloc (sizeof *ret);\n";
6405         pr "  if (!ret) {\n";
6406         pr "    reply_with_perror (\"malloc\");\n";
6407         pr "    return NULL;\n";
6408         pr "  }\n";
6409         pr "\n";
6410         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6411         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6412         pr "\n";
6413         pr "  r = command (&out, &err,\n";
6414         pr "           \"lvm\", \"%ss\",\n" typ;
6415         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6416         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6417         pr "  if (r == -1) {\n";
6418         pr "    reply_with_error (\"%%s\", err);\n";
6419         pr "    free (out);\n";
6420         pr "    free (err);\n";
6421         pr "    free (ret);\n";
6422         pr "    return NULL;\n";
6423         pr "  }\n";
6424         pr "\n";
6425         pr "  free (err);\n";
6426         pr "\n";
6427         pr "  /* Tokenize each line of the output. */\n";
6428         pr "  p = out;\n";
6429         pr "  i = 0;\n";
6430         pr "  while (p) {\n";
6431         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6432         pr "    if (pend) {\n";
6433         pr "      *pend = '\\0';\n";
6434         pr "      pend++;\n";
6435         pr "    }\n";
6436         pr "\n";
6437         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6438         pr "      p++;\n";
6439         pr "\n";
6440         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6441         pr "      p = pend;\n";
6442         pr "      continue;\n";
6443         pr "    }\n";
6444         pr "\n";
6445         pr "    /* Allocate some space to store this next entry. */\n";
6446         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6447         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6448         pr "    if (newp == NULL) {\n";
6449         pr "      reply_with_perror (\"realloc\");\n";
6450         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6451         pr "      free (ret);\n";
6452         pr "      free (out);\n";
6453         pr "      return NULL;\n";
6454         pr "    }\n";
6455         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6456         pr "\n";
6457         pr "    /* Tokenize the next entry. */\n";
6458         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6459         pr "    if (r == -1) {\n";
6460         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6461         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6462         pr "      free (ret);\n";
6463         pr "      free (out);\n";
6464         pr "      return NULL;\n";
6465         pr "    }\n";
6466         pr "\n";
6467         pr "    ++i;\n";
6468         pr "    p = pend;\n";
6469         pr "  }\n";
6470         pr "\n";
6471         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6472         pr "\n";
6473         pr "  free (out);\n";
6474         pr "  return ret;\n";
6475         pr "}\n"
6476
6477   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6478
6479 (* Generate a list of function names, for debugging in the daemon.. *)
6480 and generate_daemon_names () =
6481   generate_header CStyle GPLv2plus;
6482
6483   pr "#include <config.h>\n";
6484   pr "\n";
6485   pr "#include \"daemon.h\"\n";
6486   pr "\n";
6487
6488   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6489   pr "const char *function_names[] = {\n";
6490   List.iter (
6491     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6492   ) daemon_functions;
6493   pr "};\n";
6494
6495 (* Generate the optional groups for the daemon to implement
6496  * guestfs_available.
6497  *)
6498 and generate_daemon_optgroups_c () =
6499   generate_header CStyle GPLv2plus;
6500
6501   pr "#include <config.h>\n";
6502   pr "\n";
6503   pr "#include \"daemon.h\"\n";
6504   pr "#include \"optgroups.h\"\n";
6505   pr "\n";
6506
6507   pr "struct optgroup optgroups[] = {\n";
6508   List.iter (
6509     fun (group, _) ->
6510       pr "  { \"%s\", optgroup_%s_available },\n" group group
6511   ) optgroups;
6512   pr "  { NULL, NULL }\n";
6513   pr "};\n"
6514
6515 and generate_daemon_optgroups_h () =
6516   generate_header CStyle GPLv2plus;
6517
6518   List.iter (
6519     fun (group, _) ->
6520       pr "extern int optgroup_%s_available (void);\n" group
6521   ) optgroups
6522
6523 (* Generate the tests. *)
6524 and generate_tests () =
6525   generate_header CStyle GPLv2plus;
6526
6527   pr "\
6528 #include <stdio.h>
6529 #include <stdlib.h>
6530 #include <string.h>
6531 #include <unistd.h>
6532 #include <sys/types.h>
6533 #include <fcntl.h>
6534
6535 #include \"guestfs.h\"
6536 #include \"guestfs-internal.h\"
6537
6538 static guestfs_h *g;
6539 static int suppress_error = 0;
6540
6541 static void print_error (guestfs_h *g, void *data, const char *msg)
6542 {
6543   if (!suppress_error)
6544     fprintf (stderr, \"%%s\\n\", msg);
6545 }
6546
6547 /* FIXME: nearly identical code appears in fish.c */
6548 static void print_strings (char *const *argv)
6549 {
6550   int argc;
6551
6552   for (argc = 0; argv[argc] != NULL; ++argc)
6553     printf (\"\\t%%s\\n\", argv[argc]);
6554 }
6555
6556 /*
6557 static void print_table (char const *const *argv)
6558 {
6559   int i;
6560
6561   for (i = 0; argv[i] != NULL; i += 2)
6562     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6563 }
6564 */
6565
6566 ";
6567
6568   (* Generate a list of commands which are not tested anywhere. *)
6569   pr "static void no_test_warnings (void)\n";
6570   pr "{\n";
6571
6572   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6573   List.iter (
6574     fun (_, _, _, _, tests, _, _) ->
6575       let tests = filter_map (
6576         function
6577         | (_, (Always|If _|Unless _), test) -> Some test
6578         | (_, Disabled, _) -> None
6579       ) tests in
6580       let seq = List.concat (List.map seq_of_test tests) in
6581       let cmds_tested = List.map List.hd seq in
6582       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6583   ) all_functions;
6584
6585   List.iter (
6586     fun (name, _, _, _, _, _, _) ->
6587       if not (Hashtbl.mem hash name) then
6588         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6589   ) all_functions;
6590
6591   pr "}\n";
6592   pr "\n";
6593
6594   (* Generate the actual tests.  Note that we generate the tests
6595    * in reverse order, deliberately, so that (in general) the
6596    * newest tests run first.  This makes it quicker and easier to
6597    * debug them.
6598    *)
6599   let test_names =
6600     List.map (
6601       fun (name, _, _, flags, tests, _, _) ->
6602         mapi (generate_one_test name flags) tests
6603     ) (List.rev all_functions) in
6604   let test_names = List.concat test_names in
6605   let nr_tests = List.length test_names in
6606
6607   pr "\
6608 int main (int argc, char *argv[])
6609 {
6610   char c = 0;
6611   unsigned long int n_failed = 0;
6612   const char *filename;
6613   int fd;
6614   int nr_tests, test_num = 0;
6615
6616   setbuf (stdout, NULL);
6617
6618   no_test_warnings ();
6619
6620   g = guestfs_create ();
6621   if (g == NULL) {
6622     printf (\"guestfs_create FAILED\\n\");
6623     exit (EXIT_FAILURE);
6624   }
6625
6626   guestfs_set_error_handler (g, print_error, NULL);
6627
6628   guestfs_set_path (g, \"../appliance\");
6629
6630   filename = \"test1.img\";
6631   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6632   if (fd == -1) {
6633     perror (filename);
6634     exit (EXIT_FAILURE);
6635   }
6636   if (lseek (fd, %d, SEEK_SET) == -1) {
6637     perror (\"lseek\");
6638     close (fd);
6639     unlink (filename);
6640     exit (EXIT_FAILURE);
6641   }
6642   if (write (fd, &c, 1) == -1) {
6643     perror (\"write\");
6644     close (fd);
6645     unlink (filename);
6646     exit (EXIT_FAILURE);
6647   }
6648   if (close (fd) == -1) {
6649     perror (filename);
6650     unlink (filename);
6651     exit (EXIT_FAILURE);
6652   }
6653   if (guestfs_add_drive (g, filename) == -1) {
6654     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6655     exit (EXIT_FAILURE);
6656   }
6657
6658   filename = \"test2.img\";
6659   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6660   if (fd == -1) {
6661     perror (filename);
6662     exit (EXIT_FAILURE);
6663   }
6664   if (lseek (fd, %d, SEEK_SET) == -1) {
6665     perror (\"lseek\");
6666     close (fd);
6667     unlink (filename);
6668     exit (EXIT_FAILURE);
6669   }
6670   if (write (fd, &c, 1) == -1) {
6671     perror (\"write\");
6672     close (fd);
6673     unlink (filename);
6674     exit (EXIT_FAILURE);
6675   }
6676   if (close (fd) == -1) {
6677     perror (filename);
6678     unlink (filename);
6679     exit (EXIT_FAILURE);
6680   }
6681   if (guestfs_add_drive (g, filename) == -1) {
6682     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6683     exit (EXIT_FAILURE);
6684   }
6685
6686   filename = \"test3.img\";
6687   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6688   if (fd == -1) {
6689     perror (filename);
6690     exit (EXIT_FAILURE);
6691   }
6692   if (lseek (fd, %d, SEEK_SET) == -1) {
6693     perror (\"lseek\");
6694     close (fd);
6695     unlink (filename);
6696     exit (EXIT_FAILURE);
6697   }
6698   if (write (fd, &c, 1) == -1) {
6699     perror (\"write\");
6700     close (fd);
6701     unlink (filename);
6702     exit (EXIT_FAILURE);
6703   }
6704   if (close (fd) == -1) {
6705     perror (filename);
6706     unlink (filename);
6707     exit (EXIT_FAILURE);
6708   }
6709   if (guestfs_add_drive (g, filename) == -1) {
6710     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6711     exit (EXIT_FAILURE);
6712   }
6713
6714   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6715     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6716     exit (EXIT_FAILURE);
6717   }
6718
6719   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6720   alarm (600);
6721
6722   if (guestfs_launch (g) == -1) {
6723     printf (\"guestfs_launch FAILED\\n\");
6724     exit (EXIT_FAILURE);
6725   }
6726
6727   /* Cancel previous alarm. */
6728   alarm (0);
6729
6730   nr_tests = %d;
6731
6732 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6733
6734   iteri (
6735     fun i test_name ->
6736       pr "  test_num++;\n";
6737       pr "  if (guestfs_get_verbose (g))\n";
6738       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6739       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6740       pr "  if (%s () == -1) {\n" test_name;
6741       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6742       pr "    n_failed++;\n";
6743       pr "  }\n";
6744   ) test_names;
6745   pr "\n";
6746
6747   pr "  guestfs_close (g);\n";
6748   pr "  unlink (\"test1.img\");\n";
6749   pr "  unlink (\"test2.img\");\n";
6750   pr "  unlink (\"test3.img\");\n";
6751   pr "\n";
6752
6753   pr "  if (n_failed > 0) {\n";
6754   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6755   pr "    exit (EXIT_FAILURE);\n";
6756   pr "  }\n";
6757   pr "\n";
6758
6759   pr "  exit (EXIT_SUCCESS);\n";
6760   pr "}\n"
6761
6762 and generate_one_test name flags i (init, prereq, test) =
6763   let test_name = sprintf "test_%s_%d" name i in
6764
6765   pr "\
6766 static int %s_skip (void)
6767 {
6768   const char *str;
6769
6770   str = getenv (\"TEST_ONLY\");
6771   if (str)
6772     return strstr (str, \"%s\") == NULL;
6773   str = getenv (\"SKIP_%s\");
6774   if (str && STREQ (str, \"1\")) return 1;
6775   str = getenv (\"SKIP_TEST_%s\");
6776   if (str && STREQ (str, \"1\")) return 1;
6777   return 0;
6778 }
6779
6780 " test_name name (String.uppercase test_name) (String.uppercase name);
6781
6782   (match prereq with
6783    | Disabled | Always -> ()
6784    | If code | Unless code ->
6785        pr "static int %s_prereq (void)\n" test_name;
6786        pr "{\n";
6787        pr "  %s\n" code;
6788        pr "}\n";
6789        pr "\n";
6790   );
6791
6792   pr "\
6793 static int %s (void)
6794 {
6795   if (%s_skip ()) {
6796     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6797     return 0;
6798   }
6799
6800 " test_name test_name test_name;
6801
6802   (* Optional functions should only be tested if the relevant
6803    * support is available in the daemon.
6804    *)
6805   List.iter (
6806     function
6807     | Optional group ->
6808         pr "  {\n";
6809         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6810         pr "    int r;\n";
6811         pr "    suppress_error = 1;\n";
6812         pr "    r = guestfs_available (g, (char **) groups);\n";
6813         pr "    suppress_error = 0;\n";
6814         pr "    if (r == -1) {\n";
6815         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6816         pr "      return 0;\n";
6817         pr "    }\n";
6818         pr "  }\n";
6819     | _ -> ()
6820   ) flags;
6821
6822   (match prereq with
6823    | Disabled ->
6824        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6825    | If _ ->
6826        pr "  if (! %s_prereq ()) {\n" test_name;
6827        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6828        pr "    return 0;\n";
6829        pr "  }\n";
6830        pr "\n";
6831        generate_one_test_body name i test_name init test;
6832    | Unless _ ->
6833        pr "  if (%s_prereq ()) {\n" test_name;
6834        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6835        pr "    return 0;\n";
6836        pr "  }\n";
6837        pr "\n";
6838        generate_one_test_body name i test_name init test;
6839    | Always ->
6840        generate_one_test_body name i test_name init test
6841   );
6842
6843   pr "  return 0;\n";
6844   pr "}\n";
6845   pr "\n";
6846   test_name
6847
6848 and generate_one_test_body name i test_name init test =
6849   (match init with
6850    | InitNone (* XXX at some point, InitNone and InitEmpty became
6851                * folded together as the same thing.  Really we should
6852                * make InitNone do nothing at all, but the tests may
6853                * need to be checked to make sure this is OK.
6854                *)
6855    | InitEmpty ->
6856        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6857        List.iter (generate_test_command_call test_name)
6858          [["blockdev_setrw"; "/dev/sda"];
6859           ["umount_all"];
6860           ["lvm_remove_all"]]
6861    | InitPartition ->
6862        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6863        List.iter (generate_test_command_call test_name)
6864          [["blockdev_setrw"; "/dev/sda"];
6865           ["umount_all"];
6866           ["lvm_remove_all"];
6867           ["part_disk"; "/dev/sda"; "mbr"]]
6868    | InitBasicFS ->
6869        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6870        List.iter (generate_test_command_call test_name)
6871          [["blockdev_setrw"; "/dev/sda"];
6872           ["umount_all"];
6873           ["lvm_remove_all"];
6874           ["part_disk"; "/dev/sda"; "mbr"];
6875           ["mkfs"; "ext2"; "/dev/sda1"];
6876           ["mount_options"; ""; "/dev/sda1"; "/"]]
6877    | InitBasicFSonLVM ->
6878        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6879          test_name;
6880        List.iter (generate_test_command_call test_name)
6881          [["blockdev_setrw"; "/dev/sda"];
6882           ["umount_all"];
6883           ["lvm_remove_all"];
6884           ["part_disk"; "/dev/sda"; "mbr"];
6885           ["pvcreate"; "/dev/sda1"];
6886           ["vgcreate"; "VG"; "/dev/sda1"];
6887           ["lvcreate"; "LV"; "VG"; "8"];
6888           ["mkfs"; "ext2"; "/dev/VG/LV"];
6889           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6890    | InitISOFS ->
6891        pr "  /* InitISOFS for %s */\n" test_name;
6892        List.iter (generate_test_command_call test_name)
6893          [["blockdev_setrw"; "/dev/sda"];
6894           ["umount_all"];
6895           ["lvm_remove_all"];
6896           ["mount_ro"; "/dev/sdd"; "/"]]
6897   );
6898
6899   let get_seq_last = function
6900     | [] ->
6901         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6902           test_name
6903     | seq ->
6904         let seq = List.rev seq in
6905         List.rev (List.tl seq), List.hd seq
6906   in
6907
6908   match test with
6909   | TestRun seq ->
6910       pr "  /* TestRun for %s (%d) */\n" name i;
6911       List.iter (generate_test_command_call test_name) seq
6912   | TestOutput (seq, expected) ->
6913       pr "  /* TestOutput for %s (%d) */\n" name i;
6914       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6915       let seq, last = get_seq_last seq in
6916       let test () =
6917         pr "    if (STRNEQ (r, expected)) {\n";
6918         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6919         pr "      return -1;\n";
6920         pr "    }\n"
6921       in
6922       List.iter (generate_test_command_call test_name) seq;
6923       generate_test_command_call ~test test_name last
6924   | TestOutputList (seq, expected) ->
6925       pr "  /* TestOutputList for %s (%d) */\n" name i;
6926       let seq, last = get_seq_last seq in
6927       let test () =
6928         iteri (
6929           fun i str ->
6930             pr "    if (!r[%d]) {\n" i;
6931             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6932             pr "      print_strings (r);\n";
6933             pr "      return -1;\n";
6934             pr "    }\n";
6935             pr "    {\n";
6936             pr "      const char *expected = \"%s\";\n" (c_quote str);
6937             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6938             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6939             pr "        return -1;\n";
6940             pr "      }\n";
6941             pr "    }\n"
6942         ) expected;
6943         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6944         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6945           test_name;
6946         pr "      print_strings (r);\n";
6947         pr "      return -1;\n";
6948         pr "    }\n"
6949       in
6950       List.iter (generate_test_command_call test_name) seq;
6951       generate_test_command_call ~test test_name last
6952   | TestOutputListOfDevices (seq, expected) ->
6953       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6954       let seq, last = get_seq_last seq in
6955       let test () =
6956         iteri (
6957           fun i str ->
6958             pr "    if (!r[%d]) {\n" i;
6959             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6960             pr "      print_strings (r);\n";
6961             pr "      return -1;\n";
6962             pr "    }\n";
6963             pr "    {\n";
6964             pr "      const char *expected = \"%s\";\n" (c_quote str);
6965             pr "      r[%d][5] = 's';\n" i;
6966             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6967             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6968             pr "        return -1;\n";
6969             pr "      }\n";
6970             pr "    }\n"
6971         ) expected;
6972         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6973         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6974           test_name;
6975         pr "      print_strings (r);\n";
6976         pr "      return -1;\n";
6977         pr "    }\n"
6978       in
6979       List.iter (generate_test_command_call test_name) seq;
6980       generate_test_command_call ~test test_name last
6981   | TestOutputInt (seq, expected) ->
6982       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6983       let seq, last = get_seq_last seq in
6984       let test () =
6985         pr "    if (r != %d) {\n" expected;
6986         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6987           test_name expected;
6988         pr "               (int) r);\n";
6989         pr "      return -1;\n";
6990         pr "    }\n"
6991       in
6992       List.iter (generate_test_command_call test_name) seq;
6993       generate_test_command_call ~test test_name last
6994   | TestOutputIntOp (seq, op, expected) ->
6995       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6996       let seq, last = get_seq_last seq in
6997       let test () =
6998         pr "    if (! (r %s %d)) {\n" op expected;
6999         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7000           test_name op expected;
7001         pr "               (int) r);\n";
7002         pr "      return -1;\n";
7003         pr "    }\n"
7004       in
7005       List.iter (generate_test_command_call test_name) seq;
7006       generate_test_command_call ~test test_name last
7007   | TestOutputTrue seq ->
7008       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7009       let seq, last = get_seq_last seq in
7010       let test () =
7011         pr "    if (!r) {\n";
7012         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7013           test_name;
7014         pr "      return -1;\n";
7015         pr "    }\n"
7016       in
7017       List.iter (generate_test_command_call test_name) seq;
7018       generate_test_command_call ~test test_name last
7019   | TestOutputFalse seq ->
7020       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7021       let seq, last = get_seq_last seq in
7022       let test () =
7023         pr "    if (r) {\n";
7024         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7025           test_name;
7026         pr "      return -1;\n";
7027         pr "    }\n"
7028       in
7029       List.iter (generate_test_command_call test_name) seq;
7030       generate_test_command_call ~test test_name last
7031   | TestOutputLength (seq, expected) ->
7032       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7033       let seq, last = get_seq_last seq in
7034       let test () =
7035         pr "    int j;\n";
7036         pr "    for (j = 0; j < %d; ++j)\n" expected;
7037         pr "      if (r[j] == NULL) {\n";
7038         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7039           test_name;
7040         pr "        print_strings (r);\n";
7041         pr "        return -1;\n";
7042         pr "      }\n";
7043         pr "    if (r[j] != NULL) {\n";
7044         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7045           test_name;
7046         pr "      print_strings (r);\n";
7047         pr "      return -1;\n";
7048         pr "    }\n"
7049       in
7050       List.iter (generate_test_command_call test_name) seq;
7051       generate_test_command_call ~test test_name last
7052   | TestOutputBuffer (seq, expected) ->
7053       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7054       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7055       let seq, last = get_seq_last seq in
7056       let len = String.length expected in
7057       let test () =
7058         pr "    if (size != %d) {\n" len;
7059         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7060         pr "      return -1;\n";
7061         pr "    }\n";
7062         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7063         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7064         pr "      return -1;\n";
7065         pr "    }\n"
7066       in
7067       List.iter (generate_test_command_call test_name) seq;
7068       generate_test_command_call ~test test_name last
7069   | TestOutputStruct (seq, checks) ->
7070       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7071       let seq, last = get_seq_last seq in
7072       let test () =
7073         List.iter (
7074           function
7075           | CompareWithInt (field, expected) ->
7076               pr "    if (r->%s != %d) {\n" field expected;
7077               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7078                 test_name field expected;
7079               pr "               (int) r->%s);\n" field;
7080               pr "      return -1;\n";
7081               pr "    }\n"
7082           | CompareWithIntOp (field, op, expected) ->
7083               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7084               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7085                 test_name field op expected;
7086               pr "               (int) r->%s);\n" field;
7087               pr "      return -1;\n";
7088               pr "    }\n"
7089           | CompareWithString (field, expected) ->
7090               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7091               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7092                 test_name field expected;
7093               pr "               r->%s);\n" field;
7094               pr "      return -1;\n";
7095               pr "    }\n"
7096           | CompareFieldsIntEq (field1, field2) ->
7097               pr "    if (r->%s != r->%s) {\n" field1 field2;
7098               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7099                 test_name field1 field2;
7100               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7101               pr "      return -1;\n";
7102               pr "    }\n"
7103           | CompareFieldsStrEq (field1, field2) ->
7104               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7105               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7106                 test_name field1 field2;
7107               pr "               r->%s, r->%s);\n" field1 field2;
7108               pr "      return -1;\n";
7109               pr "    }\n"
7110         ) checks
7111       in
7112       List.iter (generate_test_command_call test_name) seq;
7113       generate_test_command_call ~test test_name last
7114   | TestLastFail seq ->
7115       pr "  /* TestLastFail for %s (%d) */\n" name i;
7116       let seq, last = get_seq_last seq in
7117       List.iter (generate_test_command_call test_name) seq;
7118       generate_test_command_call test_name ~expect_error:true last
7119
7120 (* Generate the code to run a command, leaving the result in 'r'.
7121  * If you expect to get an error then you should set expect_error:true.
7122  *)
7123 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7124   match cmd with
7125   | [] -> assert false
7126   | name :: args ->
7127       (* Look up the command to find out what args/ret it has. *)
7128       let style =
7129         try
7130           let _, style, _, _, _, _, _ =
7131             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7132           style
7133         with Not_found ->
7134           failwithf "%s: in test, command %s was not found" test_name name in
7135
7136       if List.length (snd style) <> List.length args then
7137         failwithf "%s: in test, wrong number of args given to %s"
7138           test_name name;
7139
7140       pr "  {\n";
7141
7142       List.iter (
7143         function
7144         | OptString n, "NULL" -> ()
7145         | Pathname n, arg
7146         | Device n, arg
7147         | Dev_or_Path n, arg
7148         | String n, arg
7149         | OptString n, arg ->
7150             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7151         | Int _, _
7152         | Int64 _, _
7153         | Bool _, _
7154         | FileIn _, _ | FileOut _, _ -> ()
7155         | StringList n, "" | DeviceList n, "" ->
7156             pr "    const char *const %s[1] = { NULL };\n" n
7157         | StringList n, arg | DeviceList n, arg ->
7158             let strs = string_split " " arg in
7159             iteri (
7160               fun i str ->
7161                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7162             ) strs;
7163             pr "    const char *const %s[] = {\n" n;
7164             iteri (
7165               fun i _ -> pr "      %s_%d,\n" n i
7166             ) strs;
7167             pr "      NULL\n";
7168             pr "    };\n";
7169       ) (List.combine (snd style) args);
7170
7171       let error_code =
7172         match fst style with
7173         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7174         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7175         | RConstString _ | RConstOptString _ ->
7176             pr "    const char *r;\n"; "NULL"
7177         | RString _ -> pr "    char *r;\n"; "NULL"
7178         | RStringList _ | RHashtable _ ->
7179             pr "    char **r;\n";
7180             pr "    int i;\n";
7181             "NULL"
7182         | RStruct (_, typ) ->
7183             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7184         | RStructList (_, typ) ->
7185             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7186         | RBufferOut _ ->
7187             pr "    char *r;\n";
7188             pr "    size_t size;\n";
7189             "NULL" in
7190
7191       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7192       pr "    r = guestfs_%s (g" name;
7193
7194       (* Generate the parameters. *)
7195       List.iter (
7196         function
7197         | OptString _, "NULL" -> pr ", NULL"
7198         | Pathname n, _
7199         | Device n, _ | Dev_or_Path n, _
7200         | String n, _
7201         | OptString n, _ ->
7202             pr ", %s" n
7203         | FileIn _, arg | FileOut _, arg ->
7204             pr ", \"%s\"" (c_quote arg)
7205         | StringList n, _ | DeviceList n, _ ->
7206             pr ", (char **) %s" n
7207         | Int _, arg ->
7208             let i =
7209               try int_of_string arg
7210               with Failure "int_of_string" ->
7211                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7212             pr ", %d" i
7213         | Int64 _, arg ->
7214             let i =
7215               try Int64.of_string arg
7216               with Failure "int_of_string" ->
7217                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7218             pr ", %Ld" i
7219         | Bool _, arg ->
7220             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7221       ) (List.combine (snd style) args);
7222
7223       (match fst style with
7224        | RBufferOut _ -> pr ", &size"
7225        | _ -> ()
7226       );
7227
7228       pr ");\n";
7229
7230       if not expect_error then
7231         pr "    if (r == %s)\n" error_code
7232       else
7233         pr "    if (r != %s)\n" error_code;
7234       pr "      return -1;\n";
7235
7236       (* Insert the test code. *)
7237       (match test with
7238        | None -> ()
7239        | Some f -> f ()
7240       );
7241
7242       (match fst style with
7243        | RErr | RInt _ | RInt64 _ | RBool _
7244        | RConstString _ | RConstOptString _ -> ()
7245        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7246        | RStringList _ | RHashtable _ ->
7247            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7248            pr "      free (r[i]);\n";
7249            pr "    free (r);\n"
7250        | RStruct (_, typ) ->
7251            pr "    guestfs_free_%s (r);\n" typ
7252        | RStructList (_, typ) ->
7253            pr "    guestfs_free_%s_list (r);\n" typ
7254       );
7255
7256       pr "  }\n"
7257
7258 and c_quote str =
7259   let str = replace_str str "\r" "\\r" in
7260   let str = replace_str str "\n" "\\n" in
7261   let str = replace_str str "\t" "\\t" in
7262   let str = replace_str str "\000" "\\0" in
7263   str
7264
7265 (* Generate a lot of different functions for guestfish. *)
7266 and generate_fish_cmds () =
7267   generate_header CStyle GPLv2plus;
7268
7269   let all_functions =
7270     List.filter (
7271       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7272     ) all_functions in
7273   let all_functions_sorted =
7274     List.filter (
7275       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7276     ) all_functions_sorted in
7277
7278   pr "#include <config.h>\n";
7279   pr "\n";
7280   pr "#include <stdio.h>\n";
7281   pr "#include <stdlib.h>\n";
7282   pr "#include <string.h>\n";
7283   pr "#include <inttypes.h>\n";
7284   pr "\n";
7285   pr "#include <guestfs.h>\n";
7286   pr "#include \"c-ctype.h\"\n";
7287   pr "#include \"full-write.h\"\n";
7288   pr "#include \"xstrtol.h\"\n";
7289   pr "#include \"fish.h\"\n";
7290   pr "\n";
7291
7292   (* list_commands function, which implements guestfish -h *)
7293   pr "void list_commands (void)\n";
7294   pr "{\n";
7295   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7296   pr "  list_builtin_commands ();\n";
7297   List.iter (
7298     fun (name, _, _, flags, _, shortdesc, _) ->
7299       let name = replace_char name '_' '-' in
7300       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7301         name shortdesc
7302   ) all_functions_sorted;
7303   pr "  printf (\"    %%s\\n\",";
7304   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7305   pr "}\n";
7306   pr "\n";
7307
7308   (* display_command function, which implements guestfish -h cmd *)
7309   pr "void display_command (const char *cmd)\n";
7310   pr "{\n";
7311   List.iter (
7312     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7313       let name2 = replace_char name '_' '-' in
7314       let alias =
7315         try find_map (function FishAlias n -> Some n | _ -> None) flags
7316         with Not_found -> name in
7317       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7318       let synopsis =
7319         match snd style with
7320         | [] -> name2
7321         | args ->
7322             sprintf "%s %s"
7323               name2 (String.concat " " (List.map name_of_argt args)) in
7324
7325       let warnings =
7326         if List.mem ProtocolLimitWarning flags then
7327           ("\n\n" ^ protocol_limit_warning)
7328         else "" in
7329
7330       (* For DangerWillRobinson commands, we should probably have
7331        * guestfish prompt before allowing you to use them (especially
7332        * in interactive mode). XXX
7333        *)
7334       let warnings =
7335         warnings ^
7336           if List.mem DangerWillRobinson flags then
7337             ("\n\n" ^ danger_will_robinson)
7338           else "" in
7339
7340       let warnings =
7341         warnings ^
7342           match deprecation_notice flags with
7343           | None -> ""
7344           | Some txt -> "\n\n" ^ txt in
7345
7346       let describe_alias =
7347         if name <> alias then
7348           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7349         else "" in
7350
7351       pr "  if (";
7352       pr "STRCASEEQ (cmd, \"%s\")" name;
7353       if name <> name2 then
7354         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7355       if name <> alias then
7356         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7357       pr ")\n";
7358       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7359         name2 shortdesc
7360         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7361          "=head1 DESCRIPTION\n\n" ^
7362          longdesc ^ warnings ^ describe_alias);
7363       pr "  else\n"
7364   ) all_functions;
7365   pr "    display_builtin_command (cmd);\n";
7366   pr "}\n";
7367   pr "\n";
7368
7369   let emit_print_list_function typ =
7370     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7371       typ typ typ;
7372     pr "{\n";
7373     pr "  unsigned int i;\n";
7374     pr "\n";
7375     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7376     pr "    printf (\"[%%d] = {\\n\", i);\n";
7377     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7378     pr "    printf (\"}\\n\");\n";
7379     pr "  }\n";
7380     pr "}\n";
7381     pr "\n";
7382   in
7383
7384   (* print_* functions *)
7385   List.iter (
7386     fun (typ, cols) ->
7387       let needs_i =
7388         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7389
7390       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7391       pr "{\n";
7392       if needs_i then (
7393         pr "  unsigned int i;\n";
7394         pr "\n"
7395       );
7396       List.iter (
7397         function
7398         | name, FString ->
7399             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7400         | name, FUUID ->
7401             pr "  printf (\"%%s%s: \", indent);\n" name;
7402             pr "  for (i = 0; i < 32; ++i)\n";
7403             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7404             pr "  printf (\"\\n\");\n"
7405         | name, FBuffer ->
7406             pr "  printf (\"%%s%s: \", indent);\n" name;
7407             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7408             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7409             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7410             pr "    else\n";
7411             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7412             pr "  printf (\"\\n\");\n"
7413         | name, (FUInt64|FBytes) ->
7414             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7415               name typ name
7416         | name, FInt64 ->
7417             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7418               name typ name
7419         | name, FUInt32 ->
7420             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7421               name typ name
7422         | name, FInt32 ->
7423             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7424               name typ name
7425         | name, FChar ->
7426             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7427               name typ name
7428         | name, FOptPercent ->
7429             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7430               typ name name typ name;
7431             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7432       ) cols;
7433       pr "}\n";
7434       pr "\n";
7435   ) structs;
7436
7437   (* Emit a print_TYPE_list function definition only if that function is used. *)
7438   List.iter (
7439     function
7440     | typ, (RStructListOnly | RStructAndList) ->
7441         (* generate the function for typ *)
7442         emit_print_list_function typ
7443     | typ, _ -> () (* empty *)
7444   ) (rstructs_used_by all_functions);
7445
7446   (* Emit a print_TYPE function definition only if that function is used. *)
7447   List.iter (
7448     function
7449     | typ, (RStructOnly | RStructAndList) ->
7450         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7451         pr "{\n";
7452         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7453         pr "}\n";
7454         pr "\n";
7455     | typ, _ -> () (* empty *)
7456   ) (rstructs_used_by all_functions);
7457
7458   (* run_<action> actions *)
7459   List.iter (
7460     fun (name, style, _, flags, _, _, _) ->
7461       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7462       pr "{\n";
7463       (match fst style with
7464        | RErr
7465        | RInt _
7466        | RBool _ -> pr "  int r;\n"
7467        | RInt64 _ -> pr "  int64_t r;\n"
7468        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7469        | RString _ -> pr "  char *r;\n"
7470        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7471        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7472        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7473        | RBufferOut _ ->
7474            pr "  char *r;\n";
7475            pr "  size_t size;\n";
7476       );
7477       List.iter (
7478         function
7479         | Device n
7480         | String n
7481         | OptString n -> pr "  const char *%s;\n" n
7482         | Pathname n
7483         | Dev_or_Path n
7484         | FileIn n
7485         | FileOut n -> pr "  char *%s;\n" n
7486         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7487         | Bool n -> pr "  int %s;\n" n
7488         | Int n -> pr "  int %s;\n" n
7489         | Int64 n -> pr "  int64_t %s;\n" n
7490       ) (snd style);
7491
7492       (* Check and convert parameters. *)
7493       let argc_expected = List.length (snd style) in
7494       pr "  if (argc != %d) {\n" argc_expected;
7495       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7496         argc_expected;
7497       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7498       pr "    return -1;\n";
7499       pr "  }\n";
7500
7501       let parse_integer fn fntyp rtyp range name i =
7502         pr "  {\n";
7503         pr "    strtol_error xerr;\n";
7504         pr "    %s r;\n" fntyp;
7505         pr "\n";
7506         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7507         pr "    if (xerr != LONGINT_OK) {\n";
7508         pr "      fprintf (stderr,\n";
7509         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7510         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7511         pr "      return -1;\n";
7512         pr "    }\n";
7513         (match range with
7514          | None -> ()
7515          | Some (min, max, comment) ->
7516              pr "    /* %s */\n" comment;
7517              pr "    if (r < %s || r > %s) {\n" min max;
7518              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7519                name;
7520              pr "      return -1;\n";
7521              pr "    }\n";
7522              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7523         );
7524         pr "    %s = r;\n" name;
7525         pr "  }\n";
7526       in
7527
7528       iteri (
7529         fun i ->
7530           function
7531           | Device name
7532           | String name ->
7533               pr "  %s = argv[%d];\n" name i
7534           | Pathname name
7535           | Dev_or_Path name ->
7536               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7537               pr "  if (%s == NULL) return -1;\n" name
7538           | OptString name ->
7539               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7540                 name i i
7541           | FileIn name ->
7542               pr "  %s = file_in (argv[%d]);\n" name i;
7543               pr "  if (%s == NULL) return -1;\n" name
7544           | FileOut name ->
7545               pr "  %s = file_out (argv[%d]);\n" name i;
7546               pr "  if (%s == NULL) return -1;\n" name
7547           | StringList name | DeviceList name ->
7548               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7549               pr "  if (%s == NULL) return -1;\n" name;
7550           | Bool name ->
7551               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7552           | Int name ->
7553               let range =
7554                 let min = "(-(2LL<<30))"
7555                 and max = "((2LL<<30)-1)"
7556                 and comment =
7557                   "The Int type in the generator is a signed 31 bit int." in
7558                 Some (min, max, comment) in
7559               parse_integer "xstrtoll" "long long" "int" range name i
7560           | Int64 name ->
7561               parse_integer "xstrtoll" "long long" "int64_t" None name i
7562       ) (snd style);
7563
7564       (* Call C API function. *)
7565       let fn =
7566         try find_map (function FishAction n -> Some n | _ -> None) flags
7567         with Not_found -> sprintf "guestfs_%s" name in
7568       pr "  r = %s " fn;
7569       generate_c_call_args ~handle:"g" style;
7570       pr ";\n";
7571
7572       List.iter (
7573         function
7574         | Device name | String name
7575         | OptString name | Bool name
7576         | Int name | Int64 name -> ()
7577         | Pathname name | Dev_or_Path name | FileOut name ->
7578             pr "  free (%s);\n" name
7579         | FileIn name ->
7580             pr "  free_file_in (%s);\n" name
7581         | StringList name | DeviceList name ->
7582             pr "  free_strings (%s);\n" name
7583       ) (snd style);
7584
7585       (* Any output flags? *)
7586       let fish_output =
7587         let flags = filter_map (
7588           function FishOutput flag -> Some flag | _ -> None
7589         ) flags in
7590         match flags with
7591         | [] -> None
7592         | [f] -> Some f
7593         | _ ->
7594             failwithf "%s: more than one FishOutput flag is not allowed" name in
7595
7596       (* Check return value for errors and display command results. *)
7597       (match fst style with
7598        | RErr -> pr "  return r;\n"
7599        | RInt _ ->
7600            pr "  if (r == -1) return -1;\n";
7601            (match fish_output with
7602             | None ->
7603                 pr "  printf (\"%%d\\n\", r);\n";
7604             | Some FishOutputOctal ->
7605                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7606             | Some FishOutputHexadecimal ->
7607                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7608            pr "  return 0;\n"
7609        | RInt64 _ ->
7610            pr "  if (r == -1) return -1;\n";
7611            (match fish_output with
7612             | None ->
7613                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7614             | Some FishOutputOctal ->
7615                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7616             | Some FishOutputHexadecimal ->
7617                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7618            pr "  return 0;\n"
7619        | RBool _ ->
7620            pr "  if (r == -1) return -1;\n";
7621            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7622            pr "  return 0;\n"
7623        | RConstString _ ->
7624            pr "  if (r == NULL) return -1;\n";
7625            pr "  printf (\"%%s\\n\", r);\n";
7626            pr "  return 0;\n"
7627        | RConstOptString _ ->
7628            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7629            pr "  return 0;\n"
7630        | RString _ ->
7631            pr "  if (r == NULL) return -1;\n";
7632            pr "  printf (\"%%s\\n\", r);\n";
7633            pr "  free (r);\n";
7634            pr "  return 0;\n"
7635        | RStringList _ ->
7636            pr "  if (r == NULL) return -1;\n";
7637            pr "  print_strings (r);\n";
7638            pr "  free_strings (r);\n";
7639            pr "  return 0;\n"
7640        | RStruct (_, typ) ->
7641            pr "  if (r == NULL) return -1;\n";
7642            pr "  print_%s (r);\n" typ;
7643            pr "  guestfs_free_%s (r);\n" typ;
7644            pr "  return 0;\n"
7645        | RStructList (_, typ) ->
7646            pr "  if (r == NULL) return -1;\n";
7647            pr "  print_%s_list (r);\n" typ;
7648            pr "  guestfs_free_%s_list (r);\n" typ;
7649            pr "  return 0;\n"
7650        | RHashtable _ ->
7651            pr "  if (r == NULL) return -1;\n";
7652            pr "  print_table (r);\n";
7653            pr "  free_strings (r);\n";
7654            pr "  return 0;\n"
7655        | RBufferOut _ ->
7656            pr "  if (r == NULL) return -1;\n";
7657            pr "  if (full_write (1, r, size) != size) {\n";
7658            pr "    perror (\"write\");\n";
7659            pr "    free (r);\n";
7660            pr "    return -1;\n";
7661            pr "  }\n";
7662            pr "  free (r);\n";
7663            pr "  return 0;\n"
7664       );
7665       pr "}\n";
7666       pr "\n"
7667   ) all_functions;
7668
7669   (* run_action function *)
7670   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7671   pr "{\n";
7672   List.iter (
7673     fun (name, _, _, flags, _, _, _) ->
7674       let name2 = replace_char name '_' '-' in
7675       let alias =
7676         try find_map (function FishAlias n -> Some n | _ -> None) flags
7677         with Not_found -> name in
7678       pr "  if (";
7679       pr "STRCASEEQ (cmd, \"%s\")" name;
7680       if name <> name2 then
7681         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7682       if name <> alias then
7683         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7684       pr ")\n";
7685       pr "    return run_%s (cmd, argc, argv);\n" name;
7686       pr "  else\n";
7687   ) all_functions;
7688   pr "    {\n";
7689   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7690   pr "      if (command_num == 1)\n";
7691   pr "        extended_help_message ();\n";
7692   pr "      return -1;\n";
7693   pr "    }\n";
7694   pr "  return 0;\n";
7695   pr "}\n";
7696   pr "\n"
7697
7698 (* Readline completion for guestfish. *)
7699 and generate_fish_completion () =
7700   generate_header CStyle GPLv2plus;
7701
7702   let all_functions =
7703     List.filter (
7704       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7705     ) all_functions in
7706
7707   pr "\
7708 #include <config.h>
7709
7710 #include <stdio.h>
7711 #include <stdlib.h>
7712 #include <string.h>
7713
7714 #ifdef HAVE_LIBREADLINE
7715 #include <readline/readline.h>
7716 #endif
7717
7718 #include \"fish.h\"
7719
7720 #ifdef HAVE_LIBREADLINE
7721
7722 static const char *const commands[] = {
7723   BUILTIN_COMMANDS_FOR_COMPLETION,
7724 ";
7725
7726   (* Get the commands, including the aliases.  They don't need to be
7727    * sorted - the generator() function just does a dumb linear search.
7728    *)
7729   let commands =
7730     List.map (
7731       fun (name, _, _, flags, _, _, _) ->
7732         let name2 = replace_char name '_' '-' in
7733         let alias =
7734           try find_map (function FishAlias n -> Some n | _ -> None) flags
7735           with Not_found -> name in
7736
7737         if name <> alias then [name2; alias] else [name2]
7738     ) all_functions in
7739   let commands = List.flatten commands in
7740
7741   List.iter (pr "  \"%s\",\n") commands;
7742
7743   pr "  NULL
7744 };
7745
7746 static char *
7747 generator (const char *text, int state)
7748 {
7749   static int index, len;
7750   const char *name;
7751
7752   if (!state) {
7753     index = 0;
7754     len = strlen (text);
7755   }
7756
7757   rl_attempted_completion_over = 1;
7758
7759   while ((name = commands[index]) != NULL) {
7760     index++;
7761     if (STRCASEEQLEN (name, text, len))
7762       return strdup (name);
7763   }
7764
7765   return NULL;
7766 }
7767
7768 #endif /* HAVE_LIBREADLINE */
7769
7770 #ifdef HAVE_RL_COMPLETION_MATCHES
7771 #define RL_COMPLETION_MATCHES rl_completion_matches
7772 #else
7773 #ifdef HAVE_COMPLETION_MATCHES
7774 #define RL_COMPLETION_MATCHES completion_matches
7775 #endif
7776 #endif /* else just fail if we don't have either symbol */
7777
7778 char **
7779 do_completion (const char *text, int start, int end)
7780 {
7781   char **matches = NULL;
7782
7783 #ifdef HAVE_LIBREADLINE
7784   rl_completion_append_character = ' ';
7785
7786   if (start == 0)
7787     matches = RL_COMPLETION_MATCHES (text, generator);
7788   else if (complete_dest_paths)
7789     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7790 #endif
7791
7792   return matches;
7793 }
7794 ";
7795
7796 (* Generate the POD documentation for guestfish. *)
7797 and generate_fish_actions_pod () =
7798   let all_functions_sorted =
7799     List.filter (
7800       fun (_, _, _, flags, _, _, _) ->
7801         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7802     ) all_functions_sorted in
7803
7804   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7805
7806   List.iter (
7807     fun (name, style, _, flags, _, _, longdesc) ->
7808       let longdesc =
7809         Str.global_substitute rex (
7810           fun s ->
7811             let sub =
7812               try Str.matched_group 1 s
7813               with Not_found ->
7814                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7815             "C<" ^ replace_char sub '_' '-' ^ ">"
7816         ) longdesc in
7817       let name = replace_char name '_' '-' in
7818       let alias =
7819         try find_map (function FishAlias n -> Some n | _ -> None) flags
7820         with Not_found -> name in
7821
7822       pr "=head2 %s" name;
7823       if name <> alias then
7824         pr " | %s" alias;
7825       pr "\n";
7826       pr "\n";
7827       pr " %s" name;
7828       List.iter (
7829         function
7830         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7831         | OptString n -> pr " %s" n
7832         | StringList n | DeviceList n -> pr " '%s ...'" n
7833         | Bool _ -> pr " true|false"
7834         | Int n -> pr " %s" n
7835         | Int64 n -> pr " %s" n
7836         | FileIn n | FileOut n -> pr " (%s|-)" n
7837       ) (snd style);
7838       pr "\n";
7839       pr "\n";
7840       pr "%s\n\n" longdesc;
7841
7842       if List.exists (function FileIn _ | FileOut _ -> true
7843                       | _ -> false) (snd style) then
7844         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7845
7846       if List.mem ProtocolLimitWarning flags then
7847         pr "%s\n\n" protocol_limit_warning;
7848
7849       if List.mem DangerWillRobinson flags then
7850         pr "%s\n\n" danger_will_robinson;
7851
7852       match deprecation_notice flags with
7853       | None -> ()
7854       | Some txt -> pr "%s\n\n" txt
7855   ) all_functions_sorted
7856
7857 (* Generate a C function prototype. *)
7858 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7859     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7860     ?(prefix = "")
7861     ?handle name style =
7862   if extern then pr "extern ";
7863   if static then pr "static ";
7864   (match fst style with
7865    | RErr -> pr "int "
7866    | RInt _ -> pr "int "
7867    | RInt64 _ -> pr "int64_t "
7868    | RBool _ -> pr "int "
7869    | RConstString _ | RConstOptString _ -> pr "const char *"
7870    | RString _ | RBufferOut _ -> pr "char *"
7871    | RStringList _ | RHashtable _ -> pr "char **"
7872    | RStruct (_, typ) ->
7873        if not in_daemon then pr "struct guestfs_%s *" typ
7874        else pr "guestfs_int_%s *" typ
7875    | RStructList (_, typ) ->
7876        if not in_daemon then pr "struct guestfs_%s_list *" typ
7877        else pr "guestfs_int_%s_list *" typ
7878   );
7879   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7880   pr "%s%s (" prefix name;
7881   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7882     pr "void"
7883   else (
7884     let comma = ref false in
7885     (match handle with
7886      | None -> ()
7887      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7888     );
7889     let next () =
7890       if !comma then (
7891         if single_line then pr ", " else pr ",\n\t\t"
7892       );
7893       comma := true
7894     in
7895     List.iter (
7896       function
7897       | Pathname n
7898       | Device n | Dev_or_Path n
7899       | String n
7900       | OptString n ->
7901           next ();
7902           pr "const char *%s" n
7903       | StringList n | DeviceList n ->
7904           next ();
7905           pr "char *const *%s" n
7906       | Bool n -> next (); pr "int %s" n
7907       | Int n -> next (); pr "int %s" n
7908       | Int64 n -> next (); pr "int64_t %s" n
7909       | FileIn n
7910       | FileOut n ->
7911           if not in_daemon then (next (); pr "const char *%s" n)
7912     ) (snd style);
7913     if is_RBufferOut then (next (); pr "size_t *size_r");
7914   );
7915   pr ")";
7916   if semicolon then pr ";";
7917   if newline then pr "\n"
7918
7919 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7920 and generate_c_call_args ?handle ?(decl = false) style =
7921   pr "(";
7922   let comma = ref false in
7923   let next () =
7924     if !comma then pr ", ";
7925     comma := true
7926   in
7927   (match handle with
7928    | None -> ()
7929    | Some handle -> pr "%s" handle; comma := true
7930   );
7931   List.iter (
7932     fun arg ->
7933       next ();
7934       pr "%s" (name_of_argt arg)
7935   ) (snd style);
7936   (* For RBufferOut calls, add implicit &size parameter. *)
7937   if not decl then (
7938     match fst style with
7939     | RBufferOut _ ->
7940         next ();
7941         pr "&size"
7942     | _ -> ()
7943   );
7944   pr ")"
7945
7946 (* Generate the OCaml bindings interface. *)
7947 and generate_ocaml_mli () =
7948   generate_header OCamlStyle LGPLv2plus;
7949
7950   pr "\
7951 (** For API documentation you should refer to the C API
7952     in the guestfs(3) manual page.  The OCaml API uses almost
7953     exactly the same calls. *)
7954
7955 type t
7956 (** A [guestfs_h] handle. *)
7957
7958 exception Error of string
7959 (** This exception is raised when there is an error. *)
7960
7961 exception Handle_closed of string
7962 (** This exception is raised if you use a {!Guestfs.t} handle
7963     after calling {!close} on it.  The string is the name of
7964     the function. *)
7965
7966 val create : unit -> t
7967 (** Create a {!Guestfs.t} handle. *)
7968
7969 val close : t -> unit
7970 (** Close the {!Guestfs.t} handle and free up all resources used
7971     by it immediately.
7972
7973     Handles are closed by the garbage collector when they become
7974     unreferenced, but callers can call this in order to provide
7975     predictable cleanup. *)
7976
7977 ";
7978   generate_ocaml_structure_decls ();
7979
7980   (* The actions. *)
7981   List.iter (
7982     fun (name, style, _, _, _, shortdesc, _) ->
7983       generate_ocaml_prototype name style;
7984       pr "(** %s *)\n" shortdesc;
7985       pr "\n"
7986   ) all_functions_sorted
7987
7988 (* Generate the OCaml bindings implementation. *)
7989 and generate_ocaml_ml () =
7990   generate_header OCamlStyle LGPLv2plus;
7991
7992   pr "\
7993 type t
7994
7995 exception Error of string
7996 exception Handle_closed of string
7997
7998 external create : unit -> t = \"ocaml_guestfs_create\"
7999 external close : t -> unit = \"ocaml_guestfs_close\"
8000
8001 (* Give the exceptions names, so they can be raised from the C code. *)
8002 let () =
8003   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8004   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8005
8006 ";
8007
8008   generate_ocaml_structure_decls ();
8009
8010   (* The actions. *)
8011   List.iter (
8012     fun (name, style, _, _, _, shortdesc, _) ->
8013       generate_ocaml_prototype ~is_external:true name style;
8014   ) all_functions_sorted
8015
8016 (* Generate the OCaml bindings C implementation. *)
8017 and generate_ocaml_c () =
8018   generate_header CStyle LGPLv2plus;
8019
8020   pr "\
8021 #include <stdio.h>
8022 #include <stdlib.h>
8023 #include <string.h>
8024
8025 #include <caml/config.h>
8026 #include <caml/alloc.h>
8027 #include <caml/callback.h>
8028 #include <caml/fail.h>
8029 #include <caml/memory.h>
8030 #include <caml/mlvalues.h>
8031 #include <caml/signals.h>
8032
8033 #include <guestfs.h>
8034
8035 #include \"guestfs_c.h\"
8036
8037 /* Copy a hashtable of string pairs into an assoc-list.  We return
8038  * the list in reverse order, but hashtables aren't supposed to be
8039  * ordered anyway.
8040  */
8041 static CAMLprim value
8042 copy_table (char * const * argv)
8043 {
8044   CAMLparam0 ();
8045   CAMLlocal5 (rv, pairv, kv, vv, cons);
8046   int i;
8047
8048   rv = Val_int (0);
8049   for (i = 0; argv[i] != NULL; i += 2) {
8050     kv = caml_copy_string (argv[i]);
8051     vv = caml_copy_string (argv[i+1]);
8052     pairv = caml_alloc (2, 0);
8053     Store_field (pairv, 0, kv);
8054     Store_field (pairv, 1, vv);
8055     cons = caml_alloc (2, 0);
8056     Store_field (cons, 1, rv);
8057     rv = cons;
8058     Store_field (cons, 0, pairv);
8059   }
8060
8061   CAMLreturn (rv);
8062 }
8063
8064 ";
8065
8066   (* Struct copy functions. *)
8067
8068   let emit_ocaml_copy_list_function typ =
8069     pr "static CAMLprim value\n";
8070     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8071     pr "{\n";
8072     pr "  CAMLparam0 ();\n";
8073     pr "  CAMLlocal2 (rv, v);\n";
8074     pr "  unsigned int i;\n";
8075     pr "\n";
8076     pr "  if (%ss->len == 0)\n" typ;
8077     pr "    CAMLreturn (Atom (0));\n";
8078     pr "  else {\n";
8079     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8080     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8081     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8082     pr "      caml_modify (&Field (rv, i), v);\n";
8083     pr "    }\n";
8084     pr "    CAMLreturn (rv);\n";
8085     pr "  }\n";
8086     pr "}\n";
8087     pr "\n";
8088   in
8089
8090   List.iter (
8091     fun (typ, cols) ->
8092       let has_optpercent_col =
8093         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8094
8095       pr "static CAMLprim value\n";
8096       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8097       pr "{\n";
8098       pr "  CAMLparam0 ();\n";
8099       if has_optpercent_col then
8100         pr "  CAMLlocal3 (rv, v, v2);\n"
8101       else
8102         pr "  CAMLlocal2 (rv, v);\n";
8103       pr "\n";
8104       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8105       iteri (
8106         fun i col ->
8107           (match col with
8108            | name, FString ->
8109                pr "  v = caml_copy_string (%s->%s);\n" typ name
8110            | name, FBuffer ->
8111                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8112                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8113                  typ name typ name
8114            | name, FUUID ->
8115                pr "  v = caml_alloc_string (32);\n";
8116                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8117            | name, (FBytes|FInt64|FUInt64) ->
8118                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8119            | name, (FInt32|FUInt32) ->
8120                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8121            | name, FOptPercent ->
8122                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8123                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8124                pr "    v = caml_alloc (1, 0);\n";
8125                pr "    Store_field (v, 0, v2);\n";
8126                pr "  } else /* None */\n";
8127                pr "    v = Val_int (0);\n";
8128            | name, FChar ->
8129                pr "  v = Val_int (%s->%s);\n" typ name
8130           );
8131           pr "  Store_field (rv, %d, v);\n" i
8132       ) cols;
8133       pr "  CAMLreturn (rv);\n";
8134       pr "}\n";
8135       pr "\n";
8136   ) structs;
8137
8138   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8139   List.iter (
8140     function
8141     | typ, (RStructListOnly | RStructAndList) ->
8142         (* generate the function for typ *)
8143         emit_ocaml_copy_list_function typ
8144     | typ, _ -> () (* empty *)
8145   ) (rstructs_used_by all_functions);
8146
8147   (* The wrappers. *)
8148   List.iter (
8149     fun (name, style, _, _, _, _, _) ->
8150       pr "/* Automatically generated wrapper for function\n";
8151       pr " * ";
8152       generate_ocaml_prototype name style;
8153       pr " */\n";
8154       pr "\n";
8155
8156       let params =
8157         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8158
8159       let needs_extra_vs =
8160         match fst style with RConstOptString _ -> true | _ -> false in
8161
8162       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8163       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8164       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8165       pr "\n";
8166
8167       pr "CAMLprim value\n";
8168       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8169       List.iter (pr ", value %s") (List.tl params);
8170       pr ")\n";
8171       pr "{\n";
8172
8173       (match params with
8174        | [p1; p2; p3; p4; p5] ->
8175            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8176        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8177            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8178            pr "  CAMLxparam%d (%s);\n"
8179              (List.length rest) (String.concat ", " rest)
8180        | ps ->
8181            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8182       );
8183       if not needs_extra_vs then
8184         pr "  CAMLlocal1 (rv);\n"
8185       else
8186         pr "  CAMLlocal3 (rv, v, v2);\n";
8187       pr "\n";
8188
8189       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8190       pr "  if (g == NULL)\n";
8191       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8192       pr "\n";
8193
8194       List.iter (
8195         function
8196         | Pathname n
8197         | Device n | Dev_or_Path n
8198         | String n
8199         | FileIn n
8200         | FileOut n ->
8201             pr "  const char *%s = String_val (%sv);\n" n n
8202         | OptString n ->
8203             pr "  const char *%s =\n" n;
8204             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8205               n n
8206         | StringList n | DeviceList n ->
8207             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8208         | Bool n ->
8209             pr "  int %s = Bool_val (%sv);\n" n n
8210         | Int n ->
8211             pr "  int %s = Int_val (%sv);\n" n n
8212         | Int64 n ->
8213             pr "  int64_t %s = Int64_val (%sv);\n" n n
8214       ) (snd style);
8215       let error_code =
8216         match fst style with
8217         | RErr -> pr "  int r;\n"; "-1"
8218         | RInt _ -> pr "  int r;\n"; "-1"
8219         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8220         | RBool _ -> pr "  int r;\n"; "-1"
8221         | RConstString _ | RConstOptString _ ->
8222             pr "  const char *r;\n"; "NULL"
8223         | RString _ -> pr "  char *r;\n"; "NULL"
8224         | RStringList _ ->
8225             pr "  int i;\n";
8226             pr "  char **r;\n";
8227             "NULL"
8228         | RStruct (_, typ) ->
8229             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8230         | RStructList (_, typ) ->
8231             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8232         | RHashtable _ ->
8233             pr "  int i;\n";
8234             pr "  char **r;\n";
8235             "NULL"
8236         | RBufferOut _ ->
8237             pr "  char *r;\n";
8238             pr "  size_t size;\n";
8239             "NULL" in
8240       pr "\n";
8241
8242       pr "  caml_enter_blocking_section ();\n";
8243       pr "  r = guestfs_%s " name;
8244       generate_c_call_args ~handle:"g" style;
8245       pr ";\n";
8246       pr "  caml_leave_blocking_section ();\n";
8247
8248       List.iter (
8249         function
8250         | StringList n | DeviceList n ->
8251             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8252         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8253         | Bool _ | Int _ | Int64 _
8254         | FileIn _ | FileOut _ -> ()
8255       ) (snd style);
8256
8257       pr "  if (r == %s)\n" error_code;
8258       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8259       pr "\n";
8260
8261       (match fst style with
8262        | RErr -> pr "  rv = Val_unit;\n"
8263        | RInt _ -> pr "  rv = Val_int (r);\n"
8264        | RInt64 _ ->
8265            pr "  rv = caml_copy_int64 (r);\n"
8266        | RBool _ -> pr "  rv = Val_bool (r);\n"
8267        | RConstString _ ->
8268            pr "  rv = caml_copy_string (r);\n"
8269        | RConstOptString _ ->
8270            pr "  if (r) { /* Some string */\n";
8271            pr "    v = caml_alloc (1, 0);\n";
8272            pr "    v2 = caml_copy_string (r);\n";
8273            pr "    Store_field (v, 0, v2);\n";
8274            pr "  } else /* None */\n";
8275            pr "    v = Val_int (0);\n";
8276        | RString _ ->
8277            pr "  rv = caml_copy_string (r);\n";
8278            pr "  free (r);\n"
8279        | RStringList _ ->
8280            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8281            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8282            pr "  free (r);\n"
8283        | RStruct (_, typ) ->
8284            pr "  rv = copy_%s (r);\n" typ;
8285            pr "  guestfs_free_%s (r);\n" typ;
8286        | RStructList (_, typ) ->
8287            pr "  rv = copy_%s_list (r);\n" typ;
8288            pr "  guestfs_free_%s_list (r);\n" typ;
8289        | RHashtable _ ->
8290            pr "  rv = copy_table (r);\n";
8291            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8292            pr "  free (r);\n";
8293        | RBufferOut _ ->
8294            pr "  rv = caml_alloc_string (size);\n";
8295            pr "  memcpy (String_val (rv), r, size);\n";
8296       );
8297
8298       pr "  CAMLreturn (rv);\n";
8299       pr "}\n";
8300       pr "\n";
8301
8302       if List.length params > 5 then (
8303         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8304         pr "CAMLprim value ";
8305         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8306         pr "CAMLprim value\n";
8307         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8308         pr "{\n";
8309         pr "  return ocaml_guestfs_%s (argv[0]" name;
8310         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8311         pr ");\n";
8312         pr "}\n";
8313         pr "\n"
8314       )
8315   ) all_functions_sorted
8316
8317 and generate_ocaml_structure_decls () =
8318   List.iter (
8319     fun (typ, cols) ->
8320       pr "type %s = {\n" typ;
8321       List.iter (
8322         function
8323         | name, FString -> pr "  %s : string;\n" name
8324         | name, FBuffer -> pr "  %s : string;\n" name
8325         | name, FUUID -> pr "  %s : string;\n" name
8326         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8327         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8328         | name, FChar -> pr "  %s : char;\n" name
8329         | name, FOptPercent -> pr "  %s : float option;\n" name
8330       ) cols;
8331       pr "}\n";
8332       pr "\n"
8333   ) structs
8334
8335 and generate_ocaml_prototype ?(is_external = false) name style =
8336   if is_external then pr "external " else pr "val ";
8337   pr "%s : t -> " name;
8338   List.iter (
8339     function
8340     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8341     | OptString _ -> pr "string option -> "
8342     | StringList _ | DeviceList _ -> pr "string array -> "
8343     | Bool _ -> pr "bool -> "
8344     | Int _ -> pr "int -> "
8345     | Int64 _ -> pr "int64 -> "
8346   ) (snd style);
8347   (match fst style with
8348    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8349    | RInt _ -> pr "int"
8350    | RInt64 _ -> pr "int64"
8351    | RBool _ -> pr "bool"
8352    | RConstString _ -> pr "string"
8353    | RConstOptString _ -> pr "string option"
8354    | RString _ | RBufferOut _ -> pr "string"
8355    | RStringList _ -> pr "string array"
8356    | RStruct (_, typ) -> pr "%s" typ
8357    | RStructList (_, typ) -> pr "%s array" typ
8358    | RHashtable _ -> pr "(string * string) list"
8359   );
8360   if is_external then (
8361     pr " = ";
8362     if List.length (snd style) + 1 > 5 then
8363       pr "\"ocaml_guestfs_%s_byte\" " name;
8364     pr "\"ocaml_guestfs_%s\"" name
8365   );
8366   pr "\n"
8367
8368 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8369 and generate_perl_xs () =
8370   generate_header CStyle LGPLv2plus;
8371
8372   pr "\
8373 #include \"EXTERN.h\"
8374 #include \"perl.h\"
8375 #include \"XSUB.h\"
8376
8377 #include <guestfs.h>
8378
8379 #ifndef PRId64
8380 #define PRId64 \"lld\"
8381 #endif
8382
8383 static SV *
8384 my_newSVll(long long val) {
8385 #ifdef USE_64_BIT_ALL
8386   return newSViv(val);
8387 #else
8388   char buf[100];
8389   int len;
8390   len = snprintf(buf, 100, \"%%\" PRId64, val);
8391   return newSVpv(buf, len);
8392 #endif
8393 }
8394
8395 #ifndef PRIu64
8396 #define PRIu64 \"llu\"
8397 #endif
8398
8399 static SV *
8400 my_newSVull(unsigned long long val) {
8401 #ifdef USE_64_BIT_ALL
8402   return newSVuv(val);
8403 #else
8404   char buf[100];
8405   int len;
8406   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8407   return newSVpv(buf, len);
8408 #endif
8409 }
8410
8411 /* http://www.perlmonks.org/?node_id=680842 */
8412 static char **
8413 XS_unpack_charPtrPtr (SV *arg) {
8414   char **ret;
8415   AV *av;
8416   I32 i;
8417
8418   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8419     croak (\"array reference expected\");
8420
8421   av = (AV *)SvRV (arg);
8422   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8423   if (!ret)
8424     croak (\"malloc failed\");
8425
8426   for (i = 0; i <= av_len (av); i++) {
8427     SV **elem = av_fetch (av, i, 0);
8428
8429     if (!elem || !*elem)
8430       croak (\"missing element in list\");
8431
8432     ret[i] = SvPV_nolen (*elem);
8433   }
8434
8435   ret[i] = NULL;
8436
8437   return ret;
8438 }
8439
8440 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8441
8442 PROTOTYPES: ENABLE
8443
8444 guestfs_h *
8445 _create ()
8446    CODE:
8447       RETVAL = guestfs_create ();
8448       if (!RETVAL)
8449         croak (\"could not create guestfs handle\");
8450       guestfs_set_error_handler (RETVAL, NULL, NULL);
8451  OUTPUT:
8452       RETVAL
8453
8454 void
8455 DESTROY (g)
8456       guestfs_h *g;
8457  PPCODE:
8458       guestfs_close (g);
8459
8460 ";
8461
8462   List.iter (
8463     fun (name, style, _, _, _, _, _) ->
8464       (match fst style with
8465        | RErr -> pr "void\n"
8466        | RInt _ -> pr "SV *\n"
8467        | RInt64 _ -> pr "SV *\n"
8468        | RBool _ -> pr "SV *\n"
8469        | RConstString _ -> pr "SV *\n"
8470        | RConstOptString _ -> pr "SV *\n"
8471        | RString _ -> pr "SV *\n"
8472        | RBufferOut _ -> pr "SV *\n"
8473        | RStringList _
8474        | RStruct _ | RStructList _
8475        | RHashtable _ ->
8476            pr "void\n" (* all lists returned implictly on the stack *)
8477       );
8478       (* Call and arguments. *)
8479       pr "%s " name;
8480       generate_c_call_args ~handle:"g" ~decl:true style;
8481       pr "\n";
8482       pr "      guestfs_h *g;\n";
8483       iteri (
8484         fun i ->
8485           function
8486           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8487               pr "      char *%s;\n" n
8488           | OptString n ->
8489               (* http://www.perlmonks.org/?node_id=554277
8490                * Note that the implicit handle argument means we have
8491                * to add 1 to the ST(x) operator.
8492                *)
8493               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8494           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8495           | Bool n -> pr "      int %s;\n" n
8496           | Int n -> pr "      int %s;\n" n
8497           | Int64 n -> pr "      int64_t %s;\n" n
8498       ) (snd style);
8499
8500       let do_cleanups () =
8501         List.iter (
8502           function
8503           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8504           | Bool _ | Int _ | Int64 _
8505           | FileIn _ | FileOut _ -> ()
8506           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8507         ) (snd style)
8508       in
8509
8510       (* Code. *)
8511       (match fst style with
8512        | RErr ->
8513            pr "PREINIT:\n";
8514            pr "      int r;\n";
8515            pr " PPCODE:\n";
8516            pr "      r = guestfs_%s " name;
8517            generate_c_call_args ~handle:"g" style;
8518            pr ";\n";
8519            do_cleanups ();
8520            pr "      if (r == -1)\n";
8521            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8522        | RInt n
8523        | RBool n ->
8524            pr "PREINIT:\n";
8525            pr "      int %s;\n" n;
8526            pr "   CODE:\n";
8527            pr "      %s = guestfs_%s " n name;
8528            generate_c_call_args ~handle:"g" style;
8529            pr ";\n";
8530            do_cleanups ();
8531            pr "      if (%s == -1)\n" n;
8532            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8533            pr "      RETVAL = newSViv (%s);\n" n;
8534            pr " OUTPUT:\n";
8535            pr "      RETVAL\n"
8536        | RInt64 n ->
8537            pr "PREINIT:\n";
8538            pr "      int64_t %s;\n" n;
8539            pr "   CODE:\n";
8540            pr "      %s = guestfs_%s " n name;
8541            generate_c_call_args ~handle:"g" style;
8542            pr ";\n";
8543            do_cleanups ();
8544            pr "      if (%s == -1)\n" n;
8545            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8546            pr "      RETVAL = my_newSVll (%s);\n" n;
8547            pr " OUTPUT:\n";
8548            pr "      RETVAL\n"
8549        | RConstString n ->
8550            pr "PREINIT:\n";
8551            pr "      const char *%s;\n" n;
8552            pr "   CODE:\n";
8553            pr "      %s = guestfs_%s " n name;
8554            generate_c_call_args ~handle:"g" style;
8555            pr ";\n";
8556            do_cleanups ();
8557            pr "      if (%s == NULL)\n" n;
8558            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8559            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8560            pr " OUTPUT:\n";
8561            pr "      RETVAL\n"
8562        | RConstOptString n ->
8563            pr "PREINIT:\n";
8564            pr "      const char *%s;\n" n;
8565            pr "   CODE:\n";
8566            pr "      %s = guestfs_%s " n name;
8567            generate_c_call_args ~handle:"g" style;
8568            pr ";\n";
8569            do_cleanups ();
8570            pr "      if (%s == NULL)\n" n;
8571            pr "        RETVAL = &PL_sv_undef;\n";
8572            pr "      else\n";
8573            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8574            pr " OUTPUT:\n";
8575            pr "      RETVAL\n"
8576        | RString n ->
8577            pr "PREINIT:\n";
8578            pr "      char *%s;\n" n;
8579            pr "   CODE:\n";
8580            pr "      %s = guestfs_%s " n name;
8581            generate_c_call_args ~handle:"g" style;
8582            pr ";\n";
8583            do_cleanups ();
8584            pr "      if (%s == NULL)\n" n;
8585            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8586            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8587            pr "      free (%s);\n" n;
8588            pr " OUTPUT:\n";
8589            pr "      RETVAL\n"
8590        | RStringList n | RHashtable n ->
8591            pr "PREINIT:\n";
8592            pr "      char **%s;\n" n;
8593            pr "      int i, n;\n";
8594            pr " PPCODE:\n";
8595            pr "      %s = guestfs_%s " n name;
8596            generate_c_call_args ~handle:"g" style;
8597            pr ";\n";
8598            do_cleanups ();
8599            pr "      if (%s == NULL)\n" n;
8600            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8601            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8602            pr "      EXTEND (SP, n);\n";
8603            pr "      for (i = 0; i < n; ++i) {\n";
8604            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8605            pr "        free (%s[i]);\n" n;
8606            pr "      }\n";
8607            pr "      free (%s);\n" n;
8608        | RStruct (n, typ) ->
8609            let cols = cols_of_struct typ in
8610            generate_perl_struct_code typ cols name style n do_cleanups
8611        | RStructList (n, typ) ->
8612            let cols = cols_of_struct typ in
8613            generate_perl_struct_list_code typ cols name style n do_cleanups
8614        | RBufferOut n ->
8615            pr "PREINIT:\n";
8616            pr "      char *%s;\n" n;
8617            pr "      size_t size;\n";
8618            pr "   CODE:\n";
8619            pr "      %s = guestfs_%s " n name;
8620            generate_c_call_args ~handle:"g" style;
8621            pr ";\n";
8622            do_cleanups ();
8623            pr "      if (%s == NULL)\n" n;
8624            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8625            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8626            pr "      free (%s);\n" n;
8627            pr " OUTPUT:\n";
8628            pr "      RETVAL\n"
8629       );
8630
8631       pr "\n"
8632   ) all_functions
8633
8634 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8635   pr "PREINIT:\n";
8636   pr "      struct guestfs_%s_list *%s;\n" typ n;
8637   pr "      int i;\n";
8638   pr "      HV *hv;\n";
8639   pr " PPCODE:\n";
8640   pr "      %s = guestfs_%s " n name;
8641   generate_c_call_args ~handle:"g" style;
8642   pr ";\n";
8643   do_cleanups ();
8644   pr "      if (%s == NULL)\n" n;
8645   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8646   pr "      EXTEND (SP, %s->len);\n" n;
8647   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8648   pr "        hv = newHV ();\n";
8649   List.iter (
8650     function
8651     | name, FString ->
8652         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8653           name (String.length name) n name
8654     | name, FUUID ->
8655         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8656           name (String.length name) n name
8657     | name, FBuffer ->
8658         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8659           name (String.length name) n name n name
8660     | name, (FBytes|FUInt64) ->
8661         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8662           name (String.length name) n name
8663     | name, FInt64 ->
8664         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8665           name (String.length name) n name
8666     | name, (FInt32|FUInt32) ->
8667         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8668           name (String.length name) n name
8669     | name, FChar ->
8670         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8671           name (String.length name) n name
8672     | name, FOptPercent ->
8673         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8674           name (String.length name) n name
8675   ) cols;
8676   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8677   pr "      }\n";
8678   pr "      guestfs_free_%s_list (%s);\n" typ n
8679
8680 and generate_perl_struct_code typ cols name style n do_cleanups =
8681   pr "PREINIT:\n";
8682   pr "      struct guestfs_%s *%s;\n" typ n;
8683   pr " PPCODE:\n";
8684   pr "      %s = guestfs_%s " n name;
8685   generate_c_call_args ~handle:"g" style;
8686   pr ";\n";
8687   do_cleanups ();
8688   pr "      if (%s == NULL)\n" n;
8689   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8690   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8691   List.iter (
8692     fun ((name, _) as col) ->
8693       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8694
8695       match col with
8696       | name, FString ->
8697           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8698             n name
8699       | name, FBuffer ->
8700           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8701             n name n name
8702       | name, FUUID ->
8703           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8704             n name
8705       | name, (FBytes|FUInt64) ->
8706           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8707             n name
8708       | name, FInt64 ->
8709           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8710             n name
8711       | name, (FInt32|FUInt32) ->
8712           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8713             n name
8714       | name, FChar ->
8715           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8716             n name
8717       | name, FOptPercent ->
8718           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8719             n name
8720   ) cols;
8721   pr "      free (%s);\n" n
8722
8723 (* Generate Sys/Guestfs.pm. *)
8724 and generate_perl_pm () =
8725   generate_header HashStyle LGPLv2plus;
8726
8727   pr "\
8728 =pod
8729
8730 =head1 NAME
8731
8732 Sys::Guestfs - Perl bindings for libguestfs
8733
8734 =head1 SYNOPSIS
8735
8736  use Sys::Guestfs;
8737
8738  my $h = Sys::Guestfs->new ();
8739  $h->add_drive ('guest.img');
8740  $h->launch ();
8741  $h->mount ('/dev/sda1', '/');
8742  $h->touch ('/hello');
8743  $h->sync ();
8744
8745 =head1 DESCRIPTION
8746
8747 The C<Sys::Guestfs> module provides a Perl XS binding to the
8748 libguestfs API for examining and modifying virtual machine
8749 disk images.
8750
8751 Amongst the things this is good for: making batch configuration
8752 changes to guests, getting disk used/free statistics (see also:
8753 virt-df), migrating between virtualization systems (see also:
8754 virt-p2v), performing partial backups, performing partial guest
8755 clones, cloning guests and changing registry/UUID/hostname info, and
8756 much else besides.
8757
8758 Libguestfs uses Linux kernel and qemu code, and can access any type of
8759 guest filesystem that Linux and qemu can, including but not limited
8760 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8761 schemes, qcow, qcow2, vmdk.
8762
8763 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8764 LVs, what filesystem is in each LV, etc.).  It can also run commands
8765 in the context of the guest.  Also you can access filesystems over
8766 FUSE.
8767
8768 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8769 functions for using libguestfs from Perl, including integration
8770 with libvirt.
8771
8772 =head1 ERRORS
8773
8774 All errors turn into calls to C<croak> (see L<Carp(3)>).
8775
8776 =head1 METHODS
8777
8778 =over 4
8779
8780 =cut
8781
8782 package Sys::Guestfs;
8783
8784 use strict;
8785 use warnings;
8786
8787 require XSLoader;
8788 XSLoader::load ('Sys::Guestfs');
8789
8790 =item $h = Sys::Guestfs->new ();
8791
8792 Create a new guestfs handle.
8793
8794 =cut
8795
8796 sub new {
8797   my $proto = shift;
8798   my $class = ref ($proto) || $proto;
8799
8800   my $self = Sys::Guestfs::_create ();
8801   bless $self, $class;
8802   return $self;
8803 }
8804
8805 ";
8806
8807   (* Actions.  We only need to print documentation for these as
8808    * they are pulled in from the XS code automatically.
8809    *)
8810   List.iter (
8811     fun (name, style, _, flags, _, _, longdesc) ->
8812       if not (List.mem NotInDocs flags) then (
8813         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8814         pr "=item ";
8815         generate_perl_prototype name style;
8816         pr "\n\n";
8817         pr "%s\n\n" longdesc;
8818         if List.mem ProtocolLimitWarning flags then
8819           pr "%s\n\n" protocol_limit_warning;
8820         if List.mem DangerWillRobinson flags then
8821           pr "%s\n\n" danger_will_robinson;
8822         match deprecation_notice flags with
8823         | None -> ()
8824         | Some txt -> pr "%s\n\n" txt
8825       )
8826   ) all_functions_sorted;
8827
8828   (* End of file. *)
8829   pr "\
8830 =cut
8831
8832 1;
8833
8834 =back
8835
8836 =head1 COPYRIGHT
8837
8838 Copyright (C) %s Red Hat Inc.
8839
8840 =head1 LICENSE
8841
8842 Please see the file COPYING.LIB for the full license.
8843
8844 =head1 SEE ALSO
8845
8846 L<guestfs(3)>,
8847 L<guestfish(1)>,
8848 L<http://libguestfs.org>,
8849 L<Sys::Guestfs::Lib(3)>.
8850
8851 =cut
8852 " copyright_years
8853
8854 and generate_perl_prototype name style =
8855   (match fst style with
8856    | RErr -> ()
8857    | RBool n
8858    | RInt n
8859    | RInt64 n
8860    | RConstString n
8861    | RConstOptString n
8862    | RString n
8863    | RBufferOut n -> pr "$%s = " n
8864    | RStruct (n,_)
8865    | RHashtable n -> pr "%%%s = " n
8866    | RStringList n
8867    | RStructList (n,_) -> pr "@%s = " n
8868   );
8869   pr "$h->%s (" name;
8870   let comma = ref false in
8871   List.iter (
8872     fun arg ->
8873       if !comma then pr ", ";
8874       comma := true;
8875       match arg with
8876       | Pathname n | Device n | Dev_or_Path n | String n
8877       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8878           pr "$%s" n
8879       | StringList n | DeviceList n ->
8880           pr "\\@%s" n
8881   ) (snd style);
8882   pr ");"
8883
8884 (* Generate Python C module. *)
8885 and generate_python_c () =
8886   generate_header CStyle LGPLv2plus;
8887
8888   pr "\
8889 #include <Python.h>
8890
8891 #include <stdio.h>
8892 #include <stdlib.h>
8893 #include <assert.h>
8894
8895 #include \"guestfs.h\"
8896
8897 typedef struct {
8898   PyObject_HEAD
8899   guestfs_h *g;
8900 } Pyguestfs_Object;
8901
8902 static guestfs_h *
8903 get_handle (PyObject *obj)
8904 {
8905   assert (obj);
8906   assert (obj != Py_None);
8907   return ((Pyguestfs_Object *) obj)->g;
8908 }
8909
8910 static PyObject *
8911 put_handle (guestfs_h *g)
8912 {
8913   assert (g);
8914   return
8915     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8916 }
8917
8918 /* This list should be freed (but not the strings) after use. */
8919 static char **
8920 get_string_list (PyObject *obj)
8921 {
8922   int i, len;
8923   char **r;
8924
8925   assert (obj);
8926
8927   if (!PyList_Check (obj)) {
8928     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8929     return NULL;
8930   }
8931
8932   len = PyList_Size (obj);
8933   r = malloc (sizeof (char *) * (len+1));
8934   if (r == NULL) {
8935     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8936     return NULL;
8937   }
8938
8939   for (i = 0; i < len; ++i)
8940     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8941   r[len] = NULL;
8942
8943   return r;
8944 }
8945
8946 static PyObject *
8947 put_string_list (char * const * const argv)
8948 {
8949   PyObject *list;
8950   int argc, i;
8951
8952   for (argc = 0; argv[argc] != NULL; ++argc)
8953     ;
8954
8955   list = PyList_New (argc);
8956   for (i = 0; i < argc; ++i)
8957     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8958
8959   return list;
8960 }
8961
8962 static PyObject *
8963 put_table (char * const * const argv)
8964 {
8965   PyObject *list, *item;
8966   int argc, i;
8967
8968   for (argc = 0; argv[argc] != NULL; ++argc)
8969     ;
8970
8971   list = PyList_New (argc >> 1);
8972   for (i = 0; i < argc; i += 2) {
8973     item = PyTuple_New (2);
8974     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8975     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8976     PyList_SetItem (list, i >> 1, item);
8977   }
8978
8979   return list;
8980 }
8981
8982 static void
8983 free_strings (char **argv)
8984 {
8985   int argc;
8986
8987   for (argc = 0; argv[argc] != NULL; ++argc)
8988     free (argv[argc]);
8989   free (argv);
8990 }
8991
8992 static PyObject *
8993 py_guestfs_create (PyObject *self, PyObject *args)
8994 {
8995   guestfs_h *g;
8996
8997   g = guestfs_create ();
8998   if (g == NULL) {
8999     PyErr_SetString (PyExc_RuntimeError,
9000                      \"guestfs.create: failed to allocate handle\");
9001     return NULL;
9002   }
9003   guestfs_set_error_handler (g, NULL, NULL);
9004   return put_handle (g);
9005 }
9006
9007 static PyObject *
9008 py_guestfs_close (PyObject *self, PyObject *args)
9009 {
9010   PyObject *py_g;
9011   guestfs_h *g;
9012
9013   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9014     return NULL;
9015   g = get_handle (py_g);
9016
9017   guestfs_close (g);
9018
9019   Py_INCREF (Py_None);
9020   return Py_None;
9021 }
9022
9023 ";
9024
9025   let emit_put_list_function typ =
9026     pr "static PyObject *\n";
9027     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9028     pr "{\n";
9029     pr "  PyObject *list;\n";
9030     pr "  int i;\n";
9031     pr "\n";
9032     pr "  list = PyList_New (%ss->len);\n" typ;
9033     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9034     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9035     pr "  return list;\n";
9036     pr "};\n";
9037     pr "\n"
9038   in
9039
9040   (* Structures, turned into Python dictionaries. *)
9041   List.iter (
9042     fun (typ, cols) ->
9043       pr "static PyObject *\n";
9044       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9045       pr "{\n";
9046       pr "  PyObject *dict;\n";
9047       pr "\n";
9048       pr "  dict = PyDict_New ();\n";
9049       List.iter (
9050         function
9051         | name, FString ->
9052             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9053             pr "                        PyString_FromString (%s->%s));\n"
9054               typ name
9055         | name, FBuffer ->
9056             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9057             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9058               typ name typ name
9059         | name, FUUID ->
9060             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9061             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9062               typ name
9063         | name, (FBytes|FUInt64) ->
9064             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9065             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9066               typ name
9067         | name, FInt64 ->
9068             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9069             pr "                        PyLong_FromLongLong (%s->%s));\n"
9070               typ name
9071         | name, FUInt32 ->
9072             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9073             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9074               typ name
9075         | name, FInt32 ->
9076             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9077             pr "                        PyLong_FromLong (%s->%s));\n"
9078               typ name
9079         | name, FOptPercent ->
9080             pr "  if (%s->%s >= 0)\n" typ name;
9081             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9082             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9083               typ name;
9084             pr "  else {\n";
9085             pr "    Py_INCREF (Py_None);\n";
9086             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9087             pr "  }\n"
9088         | name, FChar ->
9089             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9090             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9091       ) cols;
9092       pr "  return dict;\n";
9093       pr "};\n";
9094       pr "\n";
9095
9096   ) structs;
9097
9098   (* Emit a put_TYPE_list function definition only if that function is used. *)
9099   List.iter (
9100     function
9101     | typ, (RStructListOnly | RStructAndList) ->
9102         (* generate the function for typ *)
9103         emit_put_list_function typ
9104     | typ, _ -> () (* empty *)
9105   ) (rstructs_used_by all_functions);
9106
9107   (* Python wrapper functions. *)
9108   List.iter (
9109     fun (name, style, _, _, _, _, _) ->
9110       pr "static PyObject *\n";
9111       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9112       pr "{\n";
9113
9114       pr "  PyObject *py_g;\n";
9115       pr "  guestfs_h *g;\n";
9116       pr "  PyObject *py_r;\n";
9117
9118       let error_code =
9119         match fst style with
9120         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9121         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9122         | RConstString _ | RConstOptString _ ->
9123             pr "  const char *r;\n"; "NULL"
9124         | RString _ -> pr "  char *r;\n"; "NULL"
9125         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9126         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9127         | RStructList (_, typ) ->
9128             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9129         | RBufferOut _ ->
9130             pr "  char *r;\n";
9131             pr "  size_t size;\n";
9132             "NULL" in
9133
9134       List.iter (
9135         function
9136         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9137             pr "  const char *%s;\n" n
9138         | OptString n -> pr "  const char *%s;\n" n
9139         | StringList n | DeviceList n ->
9140             pr "  PyObject *py_%s;\n" n;
9141             pr "  char **%s;\n" n
9142         | Bool n -> pr "  int %s;\n" n
9143         | Int n -> pr "  int %s;\n" n
9144         | Int64 n -> pr "  long long %s;\n" n
9145       ) (snd style);
9146
9147       pr "\n";
9148
9149       (* Convert the parameters. *)
9150       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9151       List.iter (
9152         function
9153         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9154         | OptString _ -> pr "z"
9155         | StringList _ | DeviceList _ -> pr "O"
9156         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9157         | Int _ -> pr "i"
9158         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9159                              * emulate C's int/long/long long in Python?
9160                              *)
9161       ) (snd style);
9162       pr ":guestfs_%s\",\n" name;
9163       pr "                         &py_g";
9164       List.iter (
9165         function
9166         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9167         | OptString n -> pr ", &%s" n
9168         | StringList n | DeviceList n -> pr ", &py_%s" n
9169         | Bool n -> pr ", &%s" n
9170         | Int n -> pr ", &%s" n
9171         | Int64 n -> pr ", &%s" n
9172       ) (snd style);
9173
9174       pr "))\n";
9175       pr "    return NULL;\n";
9176
9177       pr "  g = get_handle (py_g);\n";
9178       List.iter (
9179         function
9180         | Pathname _ | Device _ | Dev_or_Path _ | String _
9181         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9182         | StringList n | DeviceList n ->
9183             pr "  %s = get_string_list (py_%s);\n" n n;
9184             pr "  if (!%s) return NULL;\n" n
9185       ) (snd style);
9186
9187       pr "\n";
9188
9189       pr "  r = guestfs_%s " name;
9190       generate_c_call_args ~handle:"g" style;
9191       pr ";\n";
9192
9193       List.iter (
9194         function
9195         | Pathname _ | Device _ | Dev_or_Path _ | String _
9196         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9197         | StringList n | DeviceList n ->
9198             pr "  free (%s);\n" n
9199       ) (snd style);
9200
9201       pr "  if (r == %s) {\n" error_code;
9202       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9203       pr "    return NULL;\n";
9204       pr "  }\n";
9205       pr "\n";
9206
9207       (match fst style with
9208        | RErr ->
9209            pr "  Py_INCREF (Py_None);\n";
9210            pr "  py_r = Py_None;\n"
9211        | RInt _
9212        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9213        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9214        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9215        | RConstOptString _ ->
9216            pr "  if (r)\n";
9217            pr "    py_r = PyString_FromString (r);\n";
9218            pr "  else {\n";
9219            pr "    Py_INCREF (Py_None);\n";
9220            pr "    py_r = Py_None;\n";
9221            pr "  }\n"
9222        | RString _ ->
9223            pr "  py_r = PyString_FromString (r);\n";
9224            pr "  free (r);\n"
9225        | RStringList _ ->
9226            pr "  py_r = put_string_list (r);\n";
9227            pr "  free_strings (r);\n"
9228        | RStruct (_, typ) ->
9229            pr "  py_r = put_%s (r);\n" typ;
9230            pr "  guestfs_free_%s (r);\n" typ
9231        | RStructList (_, typ) ->
9232            pr "  py_r = put_%s_list (r);\n" typ;
9233            pr "  guestfs_free_%s_list (r);\n" typ
9234        | RHashtable n ->
9235            pr "  py_r = put_table (r);\n";
9236            pr "  free_strings (r);\n"
9237        | RBufferOut _ ->
9238            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9239            pr "  free (r);\n"
9240       );
9241
9242       pr "  return py_r;\n";
9243       pr "}\n";
9244       pr "\n"
9245   ) all_functions;
9246
9247   (* Table of functions. *)
9248   pr "static PyMethodDef methods[] = {\n";
9249   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9250   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9251   List.iter (
9252     fun (name, _, _, _, _, _, _) ->
9253       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9254         name name
9255   ) all_functions;
9256   pr "  { NULL, NULL, 0, NULL }\n";
9257   pr "};\n";
9258   pr "\n";
9259
9260   (* Init function. *)
9261   pr "\
9262 void
9263 initlibguestfsmod (void)
9264 {
9265   static int initialized = 0;
9266
9267   if (initialized) return;
9268   Py_InitModule ((char *) \"libguestfsmod\", methods);
9269   initialized = 1;
9270 }
9271 "
9272
9273 (* Generate Python module. *)
9274 and generate_python_py () =
9275   generate_header HashStyle LGPLv2plus;
9276
9277   pr "\
9278 u\"\"\"Python bindings for libguestfs
9279
9280 import guestfs
9281 g = guestfs.GuestFS ()
9282 g.add_drive (\"guest.img\")
9283 g.launch ()
9284 parts = g.list_partitions ()
9285
9286 The guestfs module provides a Python binding to the libguestfs API
9287 for examining and modifying virtual machine disk images.
9288
9289 Amongst the things this is good for: making batch configuration
9290 changes to guests, getting disk used/free statistics (see also:
9291 virt-df), migrating between virtualization systems (see also:
9292 virt-p2v), performing partial backups, performing partial guest
9293 clones, cloning guests and changing registry/UUID/hostname info, and
9294 much else besides.
9295
9296 Libguestfs uses Linux kernel and qemu code, and can access any type of
9297 guest filesystem that Linux and qemu can, including but not limited
9298 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9299 schemes, qcow, qcow2, vmdk.
9300
9301 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9302 LVs, what filesystem is in each LV, etc.).  It can also run commands
9303 in the context of the guest.  Also you can access filesystems over
9304 FUSE.
9305
9306 Errors which happen while using the API are turned into Python
9307 RuntimeError exceptions.
9308
9309 To create a guestfs handle you usually have to perform the following
9310 sequence of calls:
9311
9312 # Create the handle, call add_drive at least once, and possibly
9313 # several times if the guest has multiple block devices:
9314 g = guestfs.GuestFS ()
9315 g.add_drive (\"guest.img\")
9316
9317 # Launch the qemu subprocess and wait for it to become ready:
9318 g.launch ()
9319
9320 # Now you can issue commands, for example:
9321 logvols = g.lvs ()
9322
9323 \"\"\"
9324
9325 import libguestfsmod
9326
9327 class GuestFS:
9328     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9329
9330     def __init__ (self):
9331         \"\"\"Create a new libguestfs handle.\"\"\"
9332         self._o = libguestfsmod.create ()
9333
9334     def __del__ (self):
9335         libguestfsmod.close (self._o)
9336
9337 ";
9338
9339   List.iter (
9340     fun (name, style, _, flags, _, _, longdesc) ->
9341       pr "    def %s " name;
9342       generate_py_call_args ~handle:"self" (snd style);
9343       pr ":\n";
9344
9345       if not (List.mem NotInDocs flags) then (
9346         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9347         let doc =
9348           match fst style with
9349           | RErr | RInt _ | RInt64 _ | RBool _
9350           | RConstOptString _ | RConstString _
9351           | RString _ | RBufferOut _ -> doc
9352           | RStringList _ ->
9353               doc ^ "\n\nThis function returns a list of strings."
9354           | RStruct (_, typ) ->
9355               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9356           | RStructList (_, typ) ->
9357               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9358           | RHashtable _ ->
9359               doc ^ "\n\nThis function returns a dictionary." in
9360         let doc =
9361           if List.mem ProtocolLimitWarning flags then
9362             doc ^ "\n\n" ^ protocol_limit_warning
9363           else doc in
9364         let doc =
9365           if List.mem DangerWillRobinson flags then
9366             doc ^ "\n\n" ^ danger_will_robinson
9367           else doc in
9368         let doc =
9369           match deprecation_notice flags with
9370           | None -> doc
9371           | Some txt -> doc ^ "\n\n" ^ txt in
9372         let doc = pod2text ~width:60 name doc in
9373         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9374         let doc = String.concat "\n        " doc in
9375         pr "        u\"\"\"%s\"\"\"\n" doc;
9376       );
9377       pr "        return libguestfsmod.%s " name;
9378       generate_py_call_args ~handle:"self._o" (snd style);
9379       pr "\n";
9380       pr "\n";
9381   ) all_functions
9382
9383 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9384 and generate_py_call_args ~handle args =
9385   pr "(%s" handle;
9386   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9387   pr ")"
9388
9389 (* Useful if you need the longdesc POD text as plain text.  Returns a
9390  * list of lines.
9391  *
9392  * Because this is very slow (the slowest part of autogeneration),
9393  * we memoize the results.
9394  *)
9395 and pod2text ~width name longdesc =
9396   let key = width, name, longdesc in
9397   try Hashtbl.find pod2text_memo key
9398   with Not_found ->
9399     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9400     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9401     close_out chan;
9402     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9403     let chan = open_process_in cmd in
9404     let lines = ref [] in
9405     let rec loop i =
9406       let line = input_line chan in
9407       if i = 1 then             (* discard the first line of output *)
9408         loop (i+1)
9409       else (
9410         let line = triml line in
9411         lines := line :: !lines;
9412         loop (i+1)
9413       ) in
9414     let lines = try loop 1 with End_of_file -> List.rev !lines in
9415     unlink filename;
9416     (match close_process_in chan with
9417      | WEXITED 0 -> ()
9418      | WEXITED i ->
9419          failwithf "pod2text: process exited with non-zero status (%d)" i
9420      | WSIGNALED i | WSTOPPED i ->
9421          failwithf "pod2text: process signalled or stopped by signal %d" i
9422     );
9423     Hashtbl.add pod2text_memo key lines;
9424     pod2text_memo_updated ();
9425     lines
9426
9427 (* Generate ruby bindings. *)
9428 and generate_ruby_c () =
9429   generate_header CStyle LGPLv2plus;
9430
9431   pr "\
9432 #include <stdio.h>
9433 #include <stdlib.h>
9434
9435 #include <ruby.h>
9436
9437 #include \"guestfs.h\"
9438
9439 #include \"extconf.h\"
9440
9441 /* For Ruby < 1.9 */
9442 #ifndef RARRAY_LEN
9443 #define RARRAY_LEN(r) (RARRAY((r))->len)
9444 #endif
9445
9446 static VALUE m_guestfs;                 /* guestfs module */
9447 static VALUE c_guestfs;                 /* guestfs_h handle */
9448 static VALUE e_Error;                   /* used for all errors */
9449
9450 static void ruby_guestfs_free (void *p)
9451 {
9452   if (!p) return;
9453   guestfs_close ((guestfs_h *) p);
9454 }
9455
9456 static VALUE ruby_guestfs_create (VALUE m)
9457 {
9458   guestfs_h *g;
9459
9460   g = guestfs_create ();
9461   if (!g)
9462     rb_raise (e_Error, \"failed to create guestfs handle\");
9463
9464   /* Don't print error messages to stderr by default. */
9465   guestfs_set_error_handler (g, NULL, NULL);
9466
9467   /* Wrap it, and make sure the close function is called when the
9468    * handle goes away.
9469    */
9470   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9471 }
9472
9473 static VALUE ruby_guestfs_close (VALUE gv)
9474 {
9475   guestfs_h *g;
9476   Data_Get_Struct (gv, guestfs_h, g);
9477
9478   ruby_guestfs_free (g);
9479   DATA_PTR (gv) = NULL;
9480
9481   return Qnil;
9482 }
9483
9484 ";
9485
9486   List.iter (
9487     fun (name, style, _, _, _, _, _) ->
9488       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9489       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9490       pr ")\n";
9491       pr "{\n";
9492       pr "  guestfs_h *g;\n";
9493       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9494       pr "  if (!g)\n";
9495       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9496         name;
9497       pr "\n";
9498
9499       List.iter (
9500         function
9501         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9502             pr "  Check_Type (%sv, T_STRING);\n" n;
9503             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9504             pr "  if (!%s)\n" n;
9505             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9506             pr "              \"%s\", \"%s\");\n" n name
9507         | OptString n ->
9508             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9509         | StringList n | DeviceList n ->
9510             pr "  char **%s;\n" n;
9511             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9512             pr "  {\n";
9513             pr "    int i, len;\n";
9514             pr "    len = RARRAY_LEN (%sv);\n" n;
9515             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9516               n;
9517             pr "    for (i = 0; i < len; ++i) {\n";
9518             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9519             pr "      %s[i] = StringValueCStr (v);\n" n;
9520             pr "    }\n";
9521             pr "    %s[len] = NULL;\n" n;
9522             pr "  }\n";
9523         | Bool n ->
9524             pr "  int %s = RTEST (%sv);\n" n n
9525         | Int n ->
9526             pr "  int %s = NUM2INT (%sv);\n" n n
9527         | Int64 n ->
9528             pr "  long long %s = NUM2LL (%sv);\n" n n
9529       ) (snd style);
9530       pr "\n";
9531
9532       let error_code =
9533         match fst style with
9534         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9535         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9536         | RConstString _ | RConstOptString _ ->
9537             pr "  const char *r;\n"; "NULL"
9538         | RString _ -> pr "  char *r;\n"; "NULL"
9539         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9540         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9541         | RStructList (_, typ) ->
9542             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9543         | RBufferOut _ ->
9544             pr "  char *r;\n";
9545             pr "  size_t size;\n";
9546             "NULL" in
9547       pr "\n";
9548
9549       pr "  r = guestfs_%s " name;
9550       generate_c_call_args ~handle:"g" style;
9551       pr ";\n";
9552
9553       List.iter (
9554         function
9555         | Pathname _ | Device _ | Dev_or_Path _ | String _
9556         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9557         | StringList n | DeviceList n ->
9558             pr "  free (%s);\n" n
9559       ) (snd style);
9560
9561       pr "  if (r == %s)\n" error_code;
9562       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9563       pr "\n";
9564
9565       (match fst style with
9566        | RErr ->
9567            pr "  return Qnil;\n"
9568        | RInt _ | RBool _ ->
9569            pr "  return INT2NUM (r);\n"
9570        | RInt64 _ ->
9571            pr "  return ULL2NUM (r);\n"
9572        | RConstString _ ->
9573            pr "  return rb_str_new2 (r);\n";
9574        | RConstOptString _ ->
9575            pr "  if (r)\n";
9576            pr "    return rb_str_new2 (r);\n";
9577            pr "  else\n";
9578            pr "    return Qnil;\n";
9579        | RString _ ->
9580            pr "  VALUE rv = rb_str_new2 (r);\n";
9581            pr "  free (r);\n";
9582            pr "  return rv;\n";
9583        | RStringList _ ->
9584            pr "  int i, len = 0;\n";
9585            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9586            pr "  VALUE rv = rb_ary_new2 (len);\n";
9587            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9588            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9589            pr "    free (r[i]);\n";
9590            pr "  }\n";
9591            pr "  free (r);\n";
9592            pr "  return rv;\n"
9593        | RStruct (_, typ) ->
9594            let cols = cols_of_struct typ in
9595            generate_ruby_struct_code typ cols
9596        | RStructList (_, typ) ->
9597            let cols = cols_of_struct typ in
9598            generate_ruby_struct_list_code typ cols
9599        | RHashtable _ ->
9600            pr "  VALUE rv = rb_hash_new ();\n";
9601            pr "  int i;\n";
9602            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9603            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9604            pr "    free (r[i]);\n";
9605            pr "    free (r[i+1]);\n";
9606            pr "  }\n";
9607            pr "  free (r);\n";
9608            pr "  return rv;\n"
9609        | RBufferOut _ ->
9610            pr "  VALUE rv = rb_str_new (r, size);\n";
9611            pr "  free (r);\n";
9612            pr "  return rv;\n";
9613       );
9614
9615       pr "}\n";
9616       pr "\n"
9617   ) all_functions;
9618
9619   pr "\
9620 /* Initialize the module. */
9621 void Init__guestfs ()
9622 {
9623   m_guestfs = rb_define_module (\"Guestfs\");
9624   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9625   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9626
9627   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9628   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9629
9630 ";
9631   (* Define the rest of the methods. *)
9632   List.iter (
9633     fun (name, style, _, _, _, _, _) ->
9634       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9635       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9636   ) all_functions;
9637
9638   pr "}\n"
9639
9640 (* Ruby code to return a struct. *)
9641 and generate_ruby_struct_code typ cols =
9642   pr "  VALUE rv = rb_hash_new ();\n";
9643   List.iter (
9644     function
9645     | name, FString ->
9646         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9647     | name, FBuffer ->
9648         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9649     | name, FUUID ->
9650         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9651     | name, (FBytes|FUInt64) ->
9652         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9653     | name, FInt64 ->
9654         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9655     | name, FUInt32 ->
9656         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9657     | name, FInt32 ->
9658         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9659     | name, FOptPercent ->
9660         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9661     | name, FChar -> (* XXX wrong? *)
9662         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9663   ) cols;
9664   pr "  guestfs_free_%s (r);\n" typ;
9665   pr "  return rv;\n"
9666
9667 (* Ruby code to return a struct list. *)
9668 and generate_ruby_struct_list_code typ cols =
9669   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9670   pr "  int i;\n";
9671   pr "  for (i = 0; i < r->len; ++i) {\n";
9672   pr "    VALUE hv = rb_hash_new ();\n";
9673   List.iter (
9674     function
9675     | name, FString ->
9676         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9677     | name, FBuffer ->
9678         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
9679     | name, FUUID ->
9680         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9681     | name, (FBytes|FUInt64) ->
9682         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9683     | name, FInt64 ->
9684         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9685     | name, FUInt32 ->
9686         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9687     | name, FInt32 ->
9688         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9689     | name, FOptPercent ->
9690         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9691     | name, FChar -> (* XXX wrong? *)
9692         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9693   ) cols;
9694   pr "    rb_ary_push (rv, hv);\n";
9695   pr "  }\n";
9696   pr "  guestfs_free_%s_list (r);\n" typ;
9697   pr "  return rv;\n"
9698
9699 (* Generate Java bindings GuestFS.java file. *)
9700 and generate_java_java () =
9701   generate_header CStyle LGPLv2plus;
9702
9703   pr "\
9704 package com.redhat.et.libguestfs;
9705
9706 import java.util.HashMap;
9707 import com.redhat.et.libguestfs.LibGuestFSException;
9708 import com.redhat.et.libguestfs.PV;
9709 import com.redhat.et.libguestfs.VG;
9710 import com.redhat.et.libguestfs.LV;
9711 import com.redhat.et.libguestfs.Stat;
9712 import com.redhat.et.libguestfs.StatVFS;
9713 import com.redhat.et.libguestfs.IntBool;
9714 import com.redhat.et.libguestfs.Dirent;
9715
9716 /**
9717  * The GuestFS object is a libguestfs handle.
9718  *
9719  * @author rjones
9720  */
9721 public class GuestFS {
9722   // Load the native code.
9723   static {
9724     System.loadLibrary (\"guestfs_jni\");
9725   }
9726
9727   /**
9728    * The native guestfs_h pointer.
9729    */
9730   long g;
9731
9732   /**
9733    * Create a libguestfs handle.
9734    *
9735    * @throws LibGuestFSException
9736    */
9737   public GuestFS () throws LibGuestFSException
9738   {
9739     g = _create ();
9740   }
9741   private native long _create () throws LibGuestFSException;
9742
9743   /**
9744    * Close a libguestfs handle.
9745    *
9746    * You can also leave handles to be collected by the garbage
9747    * collector, but this method ensures that the resources used
9748    * by the handle are freed up immediately.  If you call any
9749    * other methods after closing the handle, you will get an
9750    * exception.
9751    *
9752    * @throws LibGuestFSException
9753    */
9754   public void close () throws LibGuestFSException
9755   {
9756     if (g != 0)
9757       _close (g);
9758     g = 0;
9759   }
9760   private native void _close (long g) throws LibGuestFSException;
9761
9762   public void finalize () throws LibGuestFSException
9763   {
9764     close ();
9765   }
9766
9767 ";
9768
9769   List.iter (
9770     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9771       if not (List.mem NotInDocs flags); then (
9772         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9773         let doc =
9774           if List.mem ProtocolLimitWarning flags then
9775             doc ^ "\n\n" ^ protocol_limit_warning
9776           else doc in
9777         let doc =
9778           if List.mem DangerWillRobinson flags then
9779             doc ^ "\n\n" ^ danger_will_robinson
9780           else doc in
9781         let doc =
9782           match deprecation_notice flags with
9783           | None -> doc
9784           | Some txt -> doc ^ "\n\n" ^ txt in
9785         let doc = pod2text ~width:60 name doc in
9786         let doc = List.map (            (* RHBZ#501883 *)
9787           function
9788           | "" -> "<p>"
9789           | nonempty -> nonempty
9790         ) doc in
9791         let doc = String.concat "\n   * " doc in
9792
9793         pr "  /**\n";
9794         pr "   * %s\n" shortdesc;
9795         pr "   * <p>\n";
9796         pr "   * %s\n" doc;
9797         pr "   * @throws LibGuestFSException\n";
9798         pr "   */\n";
9799         pr "  ";
9800       );
9801       generate_java_prototype ~public:true ~semicolon:false name style;
9802       pr "\n";
9803       pr "  {\n";
9804       pr "    if (g == 0)\n";
9805       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9806         name;
9807       pr "    ";
9808       if fst style <> RErr then pr "return ";
9809       pr "_%s " name;
9810       generate_java_call_args ~handle:"g" (snd style);
9811       pr ";\n";
9812       pr "  }\n";
9813       pr "  ";
9814       generate_java_prototype ~privat:true ~native:true name style;
9815       pr "\n";
9816       pr "\n";
9817   ) all_functions;
9818
9819   pr "}\n"
9820
9821 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9822 and generate_java_call_args ~handle args =
9823   pr "(%s" handle;
9824   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9825   pr ")"
9826
9827 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9828     ?(semicolon=true) name style =
9829   if privat then pr "private ";
9830   if public then pr "public ";
9831   if native then pr "native ";
9832
9833   (* return type *)
9834   (match fst style with
9835    | RErr -> pr "void ";
9836    | RInt _ -> pr "int ";
9837    | RInt64 _ -> pr "long ";
9838    | RBool _ -> pr "boolean ";
9839    | RConstString _ | RConstOptString _ | RString _
9840    | RBufferOut _ -> pr "String ";
9841    | RStringList _ -> pr "String[] ";
9842    | RStruct (_, typ) ->
9843        let name = java_name_of_struct typ in
9844        pr "%s " name;
9845    | RStructList (_, typ) ->
9846        let name = java_name_of_struct typ in
9847        pr "%s[] " name;
9848    | RHashtable _ -> pr "HashMap<String,String> ";
9849   );
9850
9851   if native then pr "_%s " name else pr "%s " name;
9852   pr "(";
9853   let needs_comma = ref false in
9854   if native then (
9855     pr "long g";
9856     needs_comma := true
9857   );
9858
9859   (* args *)
9860   List.iter (
9861     fun arg ->
9862       if !needs_comma then pr ", ";
9863       needs_comma := true;
9864
9865       match arg with
9866       | Pathname n
9867       | Device n | Dev_or_Path n
9868       | String n
9869       | OptString n
9870       | FileIn n
9871       | FileOut n ->
9872           pr "String %s" n
9873       | StringList n | DeviceList n ->
9874           pr "String[] %s" n
9875       | Bool n ->
9876           pr "boolean %s" n
9877       | Int n ->
9878           pr "int %s" n
9879       | Int64 n ->
9880           pr "long %s" n
9881   ) (snd style);
9882
9883   pr ")\n";
9884   pr "    throws LibGuestFSException";
9885   if semicolon then pr ";"
9886
9887 and generate_java_struct jtyp cols () =
9888   generate_header CStyle LGPLv2plus;
9889
9890   pr "\
9891 package com.redhat.et.libguestfs;
9892
9893 /**
9894  * Libguestfs %s structure.
9895  *
9896  * @author rjones
9897  * @see GuestFS
9898  */
9899 public class %s {
9900 " jtyp jtyp;
9901
9902   List.iter (
9903     function
9904     | name, FString
9905     | name, FUUID
9906     | name, FBuffer -> pr "  public String %s;\n" name
9907     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9908     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9909     | name, FChar -> pr "  public char %s;\n" name
9910     | name, FOptPercent ->
9911         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9912         pr "  public float %s;\n" name
9913   ) cols;
9914
9915   pr "}\n"
9916
9917 and generate_java_c () =
9918   generate_header CStyle LGPLv2plus;
9919
9920   pr "\
9921 #include <stdio.h>
9922 #include <stdlib.h>
9923 #include <string.h>
9924
9925 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9926 #include \"guestfs.h\"
9927
9928 /* Note that this function returns.  The exception is not thrown
9929  * until after the wrapper function returns.
9930  */
9931 static void
9932 throw_exception (JNIEnv *env, const char *msg)
9933 {
9934   jclass cl;
9935   cl = (*env)->FindClass (env,
9936                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9937   (*env)->ThrowNew (env, cl, msg);
9938 }
9939
9940 JNIEXPORT jlong JNICALL
9941 Java_com_redhat_et_libguestfs_GuestFS__1create
9942   (JNIEnv *env, jobject obj)
9943 {
9944   guestfs_h *g;
9945
9946   g = guestfs_create ();
9947   if (g == NULL) {
9948     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9949     return 0;
9950   }
9951   guestfs_set_error_handler (g, NULL, NULL);
9952   return (jlong) (long) g;
9953 }
9954
9955 JNIEXPORT void JNICALL
9956 Java_com_redhat_et_libguestfs_GuestFS__1close
9957   (JNIEnv *env, jobject obj, jlong jg)
9958 {
9959   guestfs_h *g = (guestfs_h *) (long) jg;
9960   guestfs_close (g);
9961 }
9962
9963 ";
9964
9965   List.iter (
9966     fun (name, style, _, _, _, _, _) ->
9967       pr "JNIEXPORT ";
9968       (match fst style with
9969        | RErr -> pr "void ";
9970        | RInt _ -> pr "jint ";
9971        | RInt64 _ -> pr "jlong ";
9972        | RBool _ -> pr "jboolean ";
9973        | RConstString _ | RConstOptString _ | RString _
9974        | RBufferOut _ -> pr "jstring ";
9975        | RStruct _ | RHashtable _ ->
9976            pr "jobject ";
9977        | RStringList _ | RStructList _ ->
9978            pr "jobjectArray ";
9979       );
9980       pr "JNICALL\n";
9981       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9982       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9983       pr "\n";
9984       pr "  (JNIEnv *env, jobject obj, jlong jg";
9985       List.iter (
9986         function
9987         | Pathname n
9988         | Device n | Dev_or_Path n
9989         | String n
9990         | OptString n
9991         | FileIn n
9992         | FileOut n ->
9993             pr ", jstring j%s" n
9994         | StringList n | DeviceList n ->
9995             pr ", jobjectArray j%s" n
9996         | Bool n ->
9997             pr ", jboolean j%s" n
9998         | Int n ->
9999             pr ", jint j%s" n
10000         | Int64 n ->
10001             pr ", jlong j%s" n
10002       ) (snd style);
10003       pr ")\n";
10004       pr "{\n";
10005       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10006       let error_code, no_ret =
10007         match fst style with
10008         | RErr -> pr "  int r;\n"; "-1", ""
10009         | RBool _
10010         | RInt _ -> pr "  int r;\n"; "-1", "0"
10011         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10012         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10013         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10014         | RString _ ->
10015             pr "  jstring jr;\n";
10016             pr "  char *r;\n"; "NULL", "NULL"
10017         | RStringList _ ->
10018             pr "  jobjectArray jr;\n";
10019             pr "  int r_len;\n";
10020             pr "  jclass cl;\n";
10021             pr "  jstring jstr;\n";
10022             pr "  char **r;\n"; "NULL", "NULL"
10023         | RStruct (_, typ) ->
10024             pr "  jobject jr;\n";
10025             pr "  jclass cl;\n";
10026             pr "  jfieldID fl;\n";
10027             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10028         | RStructList (_, typ) ->
10029             pr "  jobjectArray jr;\n";
10030             pr "  jclass cl;\n";
10031             pr "  jfieldID fl;\n";
10032             pr "  jobject jfl;\n";
10033             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10034         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10035         | RBufferOut _ ->
10036             pr "  jstring jr;\n";
10037             pr "  char *r;\n";
10038             pr "  size_t size;\n";
10039             "NULL", "NULL" in
10040       List.iter (
10041         function
10042         | Pathname n
10043         | Device n | Dev_or_Path n
10044         | String n
10045         | OptString n
10046         | FileIn n
10047         | FileOut n ->
10048             pr "  const char *%s;\n" n
10049         | StringList n | DeviceList n ->
10050             pr "  int %s_len;\n" n;
10051             pr "  const char **%s;\n" n
10052         | Bool n
10053         | Int n ->
10054             pr "  int %s;\n" n
10055         | Int64 n ->
10056             pr "  int64_t %s;\n" n
10057       ) (snd style);
10058
10059       let needs_i =
10060         (match fst style with
10061          | RStringList _ | RStructList _ -> true
10062          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10063          | RConstOptString _
10064          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10065           List.exists (function
10066                        | StringList _ -> true
10067                        | DeviceList _ -> true
10068                        | _ -> false) (snd style) in
10069       if needs_i then
10070         pr "  int i;\n";
10071
10072       pr "\n";
10073
10074       (* Get the parameters. *)
10075       List.iter (
10076         function
10077         | Pathname n
10078         | Device n | Dev_or_Path n
10079         | String n
10080         | FileIn n
10081         | FileOut n ->
10082             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10083         | OptString n ->
10084             (* This is completely undocumented, but Java null becomes
10085              * a NULL parameter.
10086              *)
10087             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10088         | StringList n | DeviceList n ->
10089             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10090             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10091             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10092             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10093               n;
10094             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10095             pr "  }\n";
10096             pr "  %s[%s_len] = NULL;\n" n n;
10097         | Bool n
10098         | Int n
10099         | Int64 n ->
10100             pr "  %s = j%s;\n" n n
10101       ) (snd style);
10102
10103       (* Make the call. *)
10104       pr "  r = guestfs_%s " name;
10105       generate_c_call_args ~handle:"g" style;
10106       pr ";\n";
10107
10108       (* Release the parameters. *)
10109       List.iter (
10110         function
10111         | Pathname n
10112         | Device n | Dev_or_Path n
10113         | String n
10114         | FileIn n
10115         | FileOut n ->
10116             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10117         | OptString n ->
10118             pr "  if (j%s)\n" n;
10119             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10120         | StringList n | DeviceList n ->
10121             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10122             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10123               n;
10124             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10125             pr "  }\n";
10126             pr "  free (%s);\n" n
10127         | Bool n
10128         | Int n
10129         | Int64 n -> ()
10130       ) (snd style);
10131
10132       (* Check for errors. *)
10133       pr "  if (r == %s) {\n" error_code;
10134       pr "    throw_exception (env, guestfs_last_error (g));\n";
10135       pr "    return %s;\n" no_ret;
10136       pr "  }\n";
10137
10138       (* Return value. *)
10139       (match fst style with
10140        | RErr -> ()
10141        | RInt _ -> pr "  return (jint) r;\n"
10142        | RBool _ -> pr "  return (jboolean) r;\n"
10143        | RInt64 _ -> pr "  return (jlong) r;\n"
10144        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10145        | RConstOptString _ ->
10146            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10147        | RString _ ->
10148            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10149            pr "  free (r);\n";
10150            pr "  return jr;\n"
10151        | RStringList _ ->
10152            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10153            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10154            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10155            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10156            pr "  for (i = 0; i < r_len; ++i) {\n";
10157            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10158            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10159            pr "    free (r[i]);\n";
10160            pr "  }\n";
10161            pr "  free (r);\n";
10162            pr "  return jr;\n"
10163        | RStruct (_, typ) ->
10164            let jtyp = java_name_of_struct typ in
10165            let cols = cols_of_struct typ in
10166            generate_java_struct_return typ jtyp cols
10167        | RStructList (_, typ) ->
10168            let jtyp = java_name_of_struct typ in
10169            let cols = cols_of_struct typ in
10170            generate_java_struct_list_return typ jtyp cols
10171        | RHashtable _ ->
10172            (* XXX *)
10173            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10174            pr "  return NULL;\n"
10175        | RBufferOut _ ->
10176            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10177            pr "  free (r);\n";
10178            pr "  return jr;\n"
10179       );
10180
10181       pr "}\n";
10182       pr "\n"
10183   ) all_functions
10184
10185 and generate_java_struct_return typ jtyp cols =
10186   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10187   pr "  jr = (*env)->AllocObject (env, cl);\n";
10188   List.iter (
10189     function
10190     | name, FString ->
10191         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10192         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10193     | name, FUUID ->
10194         pr "  {\n";
10195         pr "    char s[33];\n";
10196         pr "    memcpy (s, r->%s, 32);\n" name;
10197         pr "    s[32] = 0;\n";
10198         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10199         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10200         pr "  }\n";
10201     | name, FBuffer ->
10202         pr "  {\n";
10203         pr "    int len = r->%s_len;\n" name;
10204         pr "    char s[len+1];\n";
10205         pr "    memcpy (s, r->%s, len);\n" name;
10206         pr "    s[len] = 0;\n";
10207         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10208         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10209         pr "  }\n";
10210     | name, (FBytes|FUInt64|FInt64) ->
10211         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10212         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10213     | name, (FUInt32|FInt32) ->
10214         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10215         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10216     | name, FOptPercent ->
10217         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10218         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10219     | name, FChar ->
10220         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10221         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10222   ) cols;
10223   pr "  free (r);\n";
10224   pr "  return jr;\n"
10225
10226 and generate_java_struct_list_return typ jtyp cols =
10227   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10228   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10229   pr "  for (i = 0; i < r->len; ++i) {\n";
10230   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10231   List.iter (
10232     function
10233     | name, FString ->
10234         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10235         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10236     | name, FUUID ->
10237         pr "    {\n";
10238         pr "      char s[33];\n";
10239         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10240         pr "      s[32] = 0;\n";
10241         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10242         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10243         pr "    }\n";
10244     | name, FBuffer ->
10245         pr "    {\n";
10246         pr "      int len = r->val[i].%s_len;\n" name;
10247         pr "      char s[len+1];\n";
10248         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10249         pr "      s[len] = 0;\n";
10250         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10251         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10252         pr "    }\n";
10253     | name, (FBytes|FUInt64|FInt64) ->
10254         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10255         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10256     | name, (FUInt32|FInt32) ->
10257         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10258         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10259     | name, FOptPercent ->
10260         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10261         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10262     | name, FChar ->
10263         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10264         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10265   ) cols;
10266   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10267   pr "  }\n";
10268   pr "  guestfs_free_%s_list (r);\n" typ;
10269   pr "  return jr;\n"
10270
10271 and generate_java_makefile_inc () =
10272   generate_header HashStyle GPLv2plus;
10273
10274   pr "java_built_sources = \\\n";
10275   List.iter (
10276     fun (typ, jtyp) ->
10277         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10278   ) java_structs;
10279   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10280
10281 and generate_haskell_hs () =
10282   generate_header HaskellStyle LGPLv2plus;
10283
10284   (* XXX We only know how to generate partial FFI for Haskell
10285    * at the moment.  Please help out!
10286    *)
10287   let can_generate style =
10288     match style with
10289     | RErr, _
10290     | RInt _, _
10291     | RInt64 _, _ -> true
10292     | RBool _, _
10293     | RConstString _, _
10294     | RConstOptString _, _
10295     | RString _, _
10296     | RStringList _, _
10297     | RStruct _, _
10298     | RStructList _, _
10299     | RHashtable _, _
10300     | RBufferOut _, _ -> false in
10301
10302   pr "\
10303 {-# INCLUDE <guestfs.h> #-}
10304 {-# LANGUAGE ForeignFunctionInterface #-}
10305
10306 module Guestfs (
10307   create";
10308
10309   (* List out the names of the actions we want to export. *)
10310   List.iter (
10311     fun (name, style, _, _, _, _, _) ->
10312       if can_generate style then pr ",\n  %s" name
10313   ) all_functions;
10314
10315   pr "
10316   ) where
10317
10318 -- Unfortunately some symbols duplicate ones already present
10319 -- in Prelude.  We don't know which, so we hard-code a list
10320 -- here.
10321 import Prelude hiding (truncate)
10322
10323 import Foreign
10324 import Foreign.C
10325 import Foreign.C.Types
10326 import IO
10327 import Control.Exception
10328 import Data.Typeable
10329
10330 data GuestfsS = GuestfsS            -- represents the opaque C struct
10331 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10332 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10333
10334 -- XXX define properly later XXX
10335 data PV = PV
10336 data VG = VG
10337 data LV = LV
10338 data IntBool = IntBool
10339 data Stat = Stat
10340 data StatVFS = StatVFS
10341 data Hashtable = Hashtable
10342
10343 foreign import ccall unsafe \"guestfs_create\" c_create
10344   :: IO GuestfsP
10345 foreign import ccall unsafe \"&guestfs_close\" c_close
10346   :: FunPtr (GuestfsP -> IO ())
10347 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10348   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10349
10350 create :: IO GuestfsH
10351 create = do
10352   p <- c_create
10353   c_set_error_handler p nullPtr nullPtr
10354   h <- newForeignPtr c_close p
10355   return h
10356
10357 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10358   :: GuestfsP -> IO CString
10359
10360 -- last_error :: GuestfsH -> IO (Maybe String)
10361 -- last_error h = do
10362 --   str <- withForeignPtr h (\\p -> c_last_error p)
10363 --   maybePeek peekCString str
10364
10365 last_error :: GuestfsH -> IO (String)
10366 last_error h = do
10367   str <- withForeignPtr h (\\p -> c_last_error p)
10368   if (str == nullPtr)
10369     then return \"no error\"
10370     else peekCString str
10371
10372 ";
10373
10374   (* Generate wrappers for each foreign function. *)
10375   List.iter (
10376     fun (name, style, _, _, _, _, _) ->
10377       if can_generate style then (
10378         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10379         pr "  :: ";
10380         generate_haskell_prototype ~handle:"GuestfsP" style;
10381         pr "\n";
10382         pr "\n";
10383         pr "%s :: " name;
10384         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10385         pr "\n";
10386         pr "%s %s = do\n" name
10387           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10388         pr "  r <- ";
10389         (* Convert pointer arguments using with* functions. *)
10390         List.iter (
10391           function
10392           | FileIn n
10393           | FileOut n
10394           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10395           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10396           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10397           | Bool _ | Int _ | Int64 _ -> ()
10398         ) (snd style);
10399         (* Convert integer arguments. *)
10400         let args =
10401           List.map (
10402             function
10403             | Bool n -> sprintf "(fromBool %s)" n
10404             | Int n -> sprintf "(fromIntegral %s)" n
10405             | Int64 n -> sprintf "(fromIntegral %s)" n
10406             | FileIn n | FileOut n
10407             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10408           ) (snd style) in
10409         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10410           (String.concat " " ("p" :: args));
10411         (match fst style with
10412          | RErr | RInt _ | RInt64 _ | RBool _ ->
10413              pr "  if (r == -1)\n";
10414              pr "    then do\n";
10415              pr "      err <- last_error h\n";
10416              pr "      fail err\n";
10417          | RConstString _ | RConstOptString _ | RString _
10418          | RStringList _ | RStruct _
10419          | RStructList _ | RHashtable _ | RBufferOut _ ->
10420              pr "  if (r == nullPtr)\n";
10421              pr "    then do\n";
10422              pr "      err <- last_error h\n";
10423              pr "      fail err\n";
10424         );
10425         (match fst style with
10426          | RErr ->
10427              pr "    else return ()\n"
10428          | RInt _ ->
10429              pr "    else return (fromIntegral r)\n"
10430          | RInt64 _ ->
10431              pr "    else return (fromIntegral r)\n"
10432          | RBool _ ->
10433              pr "    else return (toBool r)\n"
10434          | RConstString _
10435          | RConstOptString _
10436          | RString _
10437          | RStringList _
10438          | RStruct _
10439          | RStructList _
10440          | RHashtable _
10441          | RBufferOut _ ->
10442              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10443         );
10444         pr "\n";
10445       )
10446   ) all_functions
10447
10448 and generate_haskell_prototype ~handle ?(hs = false) style =
10449   pr "%s -> " handle;
10450   let string = if hs then "String" else "CString" in
10451   let int = if hs then "Int" else "CInt" in
10452   let bool = if hs then "Bool" else "CInt" in
10453   let int64 = if hs then "Integer" else "Int64" in
10454   List.iter (
10455     fun arg ->
10456       (match arg with
10457        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10458        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10459        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10460        | Bool _ -> pr "%s" bool
10461        | Int _ -> pr "%s" int
10462        | Int64 _ -> pr "%s" int
10463        | FileIn _ -> pr "%s" string
10464        | FileOut _ -> pr "%s" string
10465       );
10466       pr " -> ";
10467   ) (snd style);
10468   pr "IO (";
10469   (match fst style with
10470    | RErr -> if not hs then pr "CInt"
10471    | RInt _ -> pr "%s" int
10472    | RInt64 _ -> pr "%s" int64
10473    | RBool _ -> pr "%s" bool
10474    | RConstString _ -> pr "%s" string
10475    | RConstOptString _ -> pr "Maybe %s" string
10476    | RString _ -> pr "%s" string
10477    | RStringList _ -> pr "[%s]" string
10478    | RStruct (_, typ) ->
10479        let name = java_name_of_struct typ in
10480        pr "%s" name
10481    | RStructList (_, typ) ->
10482        let name = java_name_of_struct typ in
10483        pr "[%s]" name
10484    | RHashtable _ -> pr "Hashtable"
10485    | RBufferOut _ -> pr "%s" string
10486   );
10487   pr ")"
10488
10489 and generate_csharp () =
10490   generate_header CPlusPlusStyle LGPLv2plus;
10491
10492   (* XXX Make this configurable by the C# assembly users. *)
10493   let library = "libguestfs.so.0" in
10494
10495   pr "\
10496 // These C# bindings are highly experimental at present.
10497 //
10498 // Firstly they only work on Linux (ie. Mono).  In order to get them
10499 // to work on Windows (ie. .Net) you would need to port the library
10500 // itself to Windows first.
10501 //
10502 // The second issue is that some calls are known to be incorrect and
10503 // can cause Mono to segfault.  Particularly: calls which pass or
10504 // return string[], or return any structure value.  This is because
10505 // we haven't worked out the correct way to do this from C#.
10506 //
10507 // The third issue is that when compiling you get a lot of warnings.
10508 // We are not sure whether the warnings are important or not.
10509 //
10510 // Fourthly we do not routinely build or test these bindings as part
10511 // of the make && make check cycle, which means that regressions might
10512 // go unnoticed.
10513 //
10514 // Suggestions and patches are welcome.
10515
10516 // To compile:
10517 //
10518 // gmcs Libguestfs.cs
10519 // mono Libguestfs.exe
10520 //
10521 // (You'll probably want to add a Test class / static main function
10522 // otherwise this won't do anything useful).
10523
10524 using System;
10525 using System.IO;
10526 using System.Runtime.InteropServices;
10527 using System.Runtime.Serialization;
10528 using System.Collections;
10529
10530 namespace Guestfs
10531 {
10532   class Error : System.ApplicationException
10533   {
10534     public Error (string message) : base (message) {}
10535     protected Error (SerializationInfo info, StreamingContext context) {}
10536   }
10537
10538   class Guestfs
10539   {
10540     IntPtr _handle;
10541
10542     [DllImport (\"%s\")]
10543     static extern IntPtr guestfs_create ();
10544
10545     public Guestfs ()
10546     {
10547       _handle = guestfs_create ();
10548       if (_handle == IntPtr.Zero)
10549         throw new Error (\"could not create guestfs handle\");
10550     }
10551
10552     [DllImport (\"%s\")]
10553     static extern void guestfs_close (IntPtr h);
10554
10555     ~Guestfs ()
10556     {
10557       guestfs_close (_handle);
10558     }
10559
10560     [DllImport (\"%s\")]
10561     static extern string guestfs_last_error (IntPtr h);
10562
10563 " library library library;
10564
10565   (* Generate C# structure bindings.  We prefix struct names with
10566    * underscore because C# cannot have conflicting struct names and
10567    * method names (eg. "class stat" and "stat").
10568    *)
10569   List.iter (
10570     fun (typ, cols) ->
10571       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10572       pr "    public class _%s {\n" typ;
10573       List.iter (
10574         function
10575         | name, FChar -> pr "      char %s;\n" name
10576         | name, FString -> pr "      string %s;\n" name
10577         | name, FBuffer ->
10578             pr "      uint %s_len;\n" name;
10579             pr "      string %s;\n" name
10580         | name, FUUID ->
10581             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10582             pr "      string %s;\n" name
10583         | name, FUInt32 -> pr "      uint %s;\n" name
10584         | name, FInt32 -> pr "      int %s;\n" name
10585         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10586         | name, FInt64 -> pr "      long %s;\n" name
10587         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10588       ) cols;
10589       pr "    }\n";
10590       pr "\n"
10591   ) structs;
10592
10593   (* Generate C# function bindings. *)
10594   List.iter (
10595     fun (name, style, _, _, _, shortdesc, _) ->
10596       let rec csharp_return_type () =
10597         match fst style with
10598         | RErr -> "void"
10599         | RBool n -> "bool"
10600         | RInt n -> "int"
10601         | RInt64 n -> "long"
10602         | RConstString n
10603         | RConstOptString n
10604         | RString n
10605         | RBufferOut n -> "string"
10606         | RStruct (_,n) -> "_" ^ n
10607         | RHashtable n -> "Hashtable"
10608         | RStringList n -> "string[]"
10609         | RStructList (_,n) -> sprintf "_%s[]" n
10610
10611       and c_return_type () =
10612         match fst style with
10613         | RErr
10614         | RBool _
10615         | RInt _ -> "int"
10616         | RInt64 _ -> "long"
10617         | RConstString _
10618         | RConstOptString _
10619         | RString _
10620         | RBufferOut _ -> "string"
10621         | RStruct (_,n) -> "_" ^ n
10622         | RHashtable _
10623         | RStringList _ -> "string[]"
10624         | RStructList (_,n) -> sprintf "_%s[]" n
10625
10626       and c_error_comparison () =
10627         match fst style with
10628         | RErr
10629         | RBool _
10630         | RInt _
10631         | RInt64 _ -> "== -1"
10632         | RConstString _
10633         | RConstOptString _
10634         | RString _
10635         | RBufferOut _
10636         | RStruct (_,_)
10637         | RHashtable _
10638         | RStringList _
10639         | RStructList (_,_) -> "== null"
10640
10641       and generate_extern_prototype () =
10642         pr "    static extern %s guestfs_%s (IntPtr h"
10643           (c_return_type ()) name;
10644         List.iter (
10645           function
10646           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10647           | FileIn n | FileOut n ->
10648               pr ", [In] string %s" n
10649           | StringList n | DeviceList n ->
10650               pr ", [In] string[] %s" n
10651           | Bool n ->
10652               pr ", bool %s" n
10653           | Int n ->
10654               pr ", int %s" n
10655           | Int64 n ->
10656               pr ", long %s" n
10657         ) (snd style);
10658         pr ");\n"
10659
10660       and generate_public_prototype () =
10661         pr "    public %s %s (" (csharp_return_type ()) name;
10662         let comma = ref false in
10663         let next () =
10664           if !comma then pr ", ";
10665           comma := true
10666         in
10667         List.iter (
10668           function
10669           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10670           | FileIn n | FileOut n ->
10671               next (); pr "string %s" n
10672           | StringList n | DeviceList n ->
10673               next (); pr "string[] %s" n
10674           | Bool n ->
10675               next (); pr "bool %s" n
10676           | Int n ->
10677               next (); pr "int %s" n
10678           | Int64 n ->
10679               next (); pr "long %s" n
10680         ) (snd style);
10681         pr ")\n"
10682
10683       and generate_call () =
10684         pr "guestfs_%s (_handle" name;
10685         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10686         pr ");\n";
10687       in
10688
10689       pr "    [DllImport (\"%s\")]\n" library;
10690       generate_extern_prototype ();
10691       pr "\n";
10692       pr "    /// <summary>\n";
10693       pr "    /// %s\n" shortdesc;
10694       pr "    /// </summary>\n";
10695       generate_public_prototype ();
10696       pr "    {\n";
10697       pr "      %s r;\n" (c_return_type ());
10698       pr "      r = ";
10699       generate_call ();
10700       pr "      if (r %s)\n" (c_error_comparison ());
10701       pr "        throw new Error (guestfs_last_error (_handle));\n";
10702       (match fst style with
10703        | RErr -> ()
10704        | RBool _ ->
10705            pr "      return r != 0 ? true : false;\n"
10706        | RHashtable _ ->
10707            pr "      Hashtable rr = new Hashtable ();\n";
10708            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10709            pr "        rr.Add (r[i], r[i+1]);\n";
10710            pr "      return rr;\n"
10711        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10712        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10713        | RStructList _ ->
10714            pr "      return r;\n"
10715       );
10716       pr "    }\n";
10717       pr "\n";
10718   ) all_functions_sorted;
10719
10720   pr "  }
10721 }
10722 "
10723
10724 and generate_bindtests () =
10725   generate_header CStyle LGPLv2plus;
10726
10727   pr "\
10728 #include <stdio.h>
10729 #include <stdlib.h>
10730 #include <inttypes.h>
10731 #include <string.h>
10732
10733 #include \"guestfs.h\"
10734 #include \"guestfs-internal.h\"
10735 #include \"guestfs-internal-actions.h\"
10736 #include \"guestfs_protocol.h\"
10737
10738 #define error guestfs_error
10739 #define safe_calloc guestfs_safe_calloc
10740 #define safe_malloc guestfs_safe_malloc
10741
10742 static void
10743 print_strings (char *const *argv)
10744 {
10745   int argc;
10746
10747   printf (\"[\");
10748   for (argc = 0; argv[argc] != NULL; ++argc) {
10749     if (argc > 0) printf (\", \");
10750     printf (\"\\\"%%s\\\"\", argv[argc]);
10751   }
10752   printf (\"]\\n\");
10753 }
10754
10755 /* The test0 function prints its parameters to stdout. */
10756 ";
10757
10758   let test0, tests =
10759     match test_functions with
10760     | [] -> assert false
10761     | test0 :: tests -> test0, tests in
10762
10763   let () =
10764     let (name, style, _, _, _, _, _) = test0 in
10765     generate_prototype ~extern:false ~semicolon:false ~newline:true
10766       ~handle:"g" ~prefix:"guestfs__" name style;
10767     pr "{\n";
10768     List.iter (
10769       function
10770       | Pathname n
10771       | Device n | Dev_or_Path n
10772       | String n
10773       | FileIn n
10774       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10775       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10776       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10777       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10778       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10779       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10780     ) (snd style);
10781     pr "  /* Java changes stdout line buffering so we need this: */\n";
10782     pr "  fflush (stdout);\n";
10783     pr "  return 0;\n";
10784     pr "}\n";
10785     pr "\n" in
10786
10787   List.iter (
10788     fun (name, style, _, _, _, _, _) ->
10789       if String.sub name (String.length name - 3) 3 <> "err" then (
10790         pr "/* Test normal return. */\n";
10791         generate_prototype ~extern:false ~semicolon:false ~newline:true
10792           ~handle:"g" ~prefix:"guestfs__" name style;
10793         pr "{\n";
10794         (match fst style with
10795          | RErr ->
10796              pr "  return 0;\n"
10797          | RInt _ ->
10798              pr "  int r;\n";
10799              pr "  sscanf (val, \"%%d\", &r);\n";
10800              pr "  return r;\n"
10801          | RInt64 _ ->
10802              pr "  int64_t r;\n";
10803              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10804              pr "  return r;\n"
10805          | RBool _ ->
10806              pr "  return STREQ (val, \"true\");\n"
10807          | RConstString _
10808          | RConstOptString _ ->
10809              (* Can't return the input string here.  Return a static
10810               * string so we ensure we get a segfault if the caller
10811               * tries to free it.
10812               *)
10813              pr "  return \"static string\";\n"
10814          | RString _ ->
10815              pr "  return strdup (val);\n"
10816          | RStringList _ ->
10817              pr "  char **strs;\n";
10818              pr "  int n, i;\n";
10819              pr "  sscanf (val, \"%%d\", &n);\n";
10820              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10821              pr "  for (i = 0; i < n; ++i) {\n";
10822              pr "    strs[i] = safe_malloc (g, 16);\n";
10823              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10824              pr "  }\n";
10825              pr "  strs[n] = NULL;\n";
10826              pr "  return strs;\n"
10827          | RStruct (_, typ) ->
10828              pr "  struct guestfs_%s *r;\n" typ;
10829              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10830              pr "  return r;\n"
10831          | RStructList (_, typ) ->
10832              pr "  struct guestfs_%s_list *r;\n" typ;
10833              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10834              pr "  sscanf (val, \"%%d\", &r->len);\n";
10835              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10836              pr "  return r;\n"
10837          | RHashtable _ ->
10838              pr "  char **strs;\n";
10839              pr "  int n, i;\n";
10840              pr "  sscanf (val, \"%%d\", &n);\n";
10841              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10842              pr "  for (i = 0; i < n; ++i) {\n";
10843              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10844              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10845              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10846              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10847              pr "  }\n";
10848              pr "  strs[n*2] = NULL;\n";
10849              pr "  return strs;\n"
10850          | RBufferOut _ ->
10851              pr "  return strdup (val);\n"
10852         );
10853         pr "}\n";
10854         pr "\n"
10855       ) else (
10856         pr "/* Test error return. */\n";
10857         generate_prototype ~extern:false ~semicolon:false ~newline:true
10858           ~handle:"g" ~prefix:"guestfs__" name style;
10859         pr "{\n";
10860         pr "  error (g, \"error\");\n";
10861         (match fst style with
10862          | RErr | RInt _ | RInt64 _ | RBool _ ->
10863              pr "  return -1;\n"
10864          | RConstString _ | RConstOptString _
10865          | RString _ | RStringList _ | RStruct _
10866          | RStructList _
10867          | RHashtable _
10868          | RBufferOut _ ->
10869              pr "  return NULL;\n"
10870         );
10871         pr "}\n";
10872         pr "\n"
10873       )
10874   ) tests
10875
10876 and generate_ocaml_bindtests () =
10877   generate_header OCamlStyle GPLv2plus;
10878
10879   pr "\
10880 let () =
10881   let g = Guestfs.create () in
10882 ";
10883
10884   let mkargs args =
10885     String.concat " " (
10886       List.map (
10887         function
10888         | CallString s -> "\"" ^ s ^ "\""
10889         | CallOptString None -> "None"
10890         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10891         | CallStringList xs ->
10892             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10893         | CallInt i when i >= 0 -> string_of_int i
10894         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10895         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10896         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10897         | CallBool b -> string_of_bool b
10898       ) args
10899     )
10900   in
10901
10902   generate_lang_bindtests (
10903     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10904   );
10905
10906   pr "print_endline \"EOF\"\n"
10907
10908 and generate_perl_bindtests () =
10909   pr "#!/usr/bin/perl -w\n";
10910   generate_header HashStyle GPLv2plus;
10911
10912   pr "\
10913 use strict;
10914
10915 use Sys::Guestfs;
10916
10917 my $g = Sys::Guestfs->new ();
10918 ";
10919
10920   let mkargs args =
10921     String.concat ", " (
10922       List.map (
10923         function
10924         | CallString s -> "\"" ^ s ^ "\""
10925         | CallOptString None -> "undef"
10926         | CallOptString (Some s) -> sprintf "\"%s\"" s
10927         | CallStringList xs ->
10928             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10929         | CallInt i -> string_of_int i
10930         | CallInt64 i -> Int64.to_string i
10931         | CallBool b -> if b then "1" else "0"
10932       ) args
10933     )
10934   in
10935
10936   generate_lang_bindtests (
10937     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10938   );
10939
10940   pr "print \"EOF\\n\"\n"
10941
10942 and generate_python_bindtests () =
10943   generate_header HashStyle GPLv2plus;
10944
10945   pr "\
10946 import guestfs
10947
10948 g = guestfs.GuestFS ()
10949 ";
10950
10951   let mkargs args =
10952     String.concat ", " (
10953       List.map (
10954         function
10955         | CallString s -> "\"" ^ s ^ "\""
10956         | CallOptString None -> "None"
10957         | CallOptString (Some s) -> sprintf "\"%s\"" s
10958         | CallStringList xs ->
10959             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10960         | CallInt i -> string_of_int i
10961         | CallInt64 i -> Int64.to_string i
10962         | CallBool b -> if b then "1" else "0"
10963       ) args
10964     )
10965   in
10966
10967   generate_lang_bindtests (
10968     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10969   );
10970
10971   pr "print \"EOF\"\n"
10972
10973 and generate_ruby_bindtests () =
10974   generate_header HashStyle GPLv2plus;
10975
10976   pr "\
10977 require 'guestfs'
10978
10979 g = Guestfs::create()
10980 ";
10981
10982   let mkargs args =
10983     String.concat ", " (
10984       List.map (
10985         function
10986         | CallString s -> "\"" ^ s ^ "\""
10987         | CallOptString None -> "nil"
10988         | CallOptString (Some s) -> sprintf "\"%s\"" s
10989         | CallStringList xs ->
10990             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10991         | CallInt i -> string_of_int i
10992         | CallInt64 i -> Int64.to_string i
10993         | CallBool b -> string_of_bool b
10994       ) args
10995     )
10996   in
10997
10998   generate_lang_bindtests (
10999     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11000   );
11001
11002   pr "print \"EOF\\n\"\n"
11003
11004 and generate_java_bindtests () =
11005   generate_header CStyle GPLv2plus;
11006
11007   pr "\
11008 import com.redhat.et.libguestfs.*;
11009
11010 public class Bindtests {
11011     public static void main (String[] argv)
11012     {
11013         try {
11014             GuestFS g = new GuestFS ();
11015 ";
11016
11017   let mkargs args =
11018     String.concat ", " (
11019       List.map (
11020         function
11021         | CallString s -> "\"" ^ s ^ "\""
11022         | CallOptString None -> "null"
11023         | CallOptString (Some s) -> sprintf "\"%s\"" s
11024         | CallStringList xs ->
11025             "new String[]{" ^
11026               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11027         | CallInt i -> string_of_int i
11028         | CallInt64 i -> Int64.to_string i
11029         | CallBool b -> string_of_bool b
11030       ) args
11031     )
11032   in
11033
11034   generate_lang_bindtests (
11035     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11036   );
11037
11038   pr "
11039             System.out.println (\"EOF\");
11040         }
11041         catch (Exception exn) {
11042             System.err.println (exn);
11043             System.exit (1);
11044         }
11045     }
11046 }
11047 "
11048
11049 and generate_haskell_bindtests () =
11050   generate_header HaskellStyle GPLv2plus;
11051
11052   pr "\
11053 module Bindtests where
11054 import qualified Guestfs
11055
11056 main = do
11057   g <- Guestfs.create
11058 ";
11059
11060   let mkargs args =
11061     String.concat " " (
11062       List.map (
11063         function
11064         | CallString s -> "\"" ^ s ^ "\""
11065         | CallOptString None -> "Nothing"
11066         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11067         | CallStringList xs ->
11068             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11069         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11070         | CallInt i -> string_of_int i
11071         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11072         | CallInt64 i -> Int64.to_string i
11073         | CallBool true -> "True"
11074         | CallBool false -> "False"
11075       ) args
11076     )
11077   in
11078
11079   generate_lang_bindtests (
11080     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11081   );
11082
11083   pr "  putStrLn \"EOF\"\n"
11084
11085 (* Language-independent bindings tests - we do it this way to
11086  * ensure there is parity in testing bindings across all languages.
11087  *)
11088 and generate_lang_bindtests call =
11089   call "test0" [CallString "abc"; CallOptString (Some "def");
11090                 CallStringList []; CallBool false;
11091                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11092   call "test0" [CallString "abc"; CallOptString None;
11093                 CallStringList []; CallBool false;
11094                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11095   call "test0" [CallString ""; CallOptString (Some "def");
11096                 CallStringList []; CallBool false;
11097                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11098   call "test0" [CallString ""; CallOptString (Some "");
11099                 CallStringList []; CallBool false;
11100                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11101   call "test0" [CallString "abc"; CallOptString (Some "def");
11102                 CallStringList ["1"]; CallBool false;
11103                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11104   call "test0" [CallString "abc"; CallOptString (Some "def");
11105                 CallStringList ["1"; "2"]; CallBool false;
11106                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11107   call "test0" [CallString "abc"; CallOptString (Some "def");
11108                 CallStringList ["1"]; CallBool true;
11109                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
11110   call "test0" [CallString "abc"; CallOptString (Some "def");
11111                 CallStringList ["1"]; CallBool false;
11112                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
11113   call "test0" [CallString "abc"; CallOptString (Some "def");
11114                 CallStringList ["1"]; CallBool false;
11115                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
11116   call "test0" [CallString "abc"; CallOptString (Some "def");
11117                 CallStringList ["1"]; CallBool false;
11118                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
11119   call "test0" [CallString "abc"; CallOptString (Some "def");
11120                 CallStringList ["1"]; CallBool false;
11121                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
11122   call "test0" [CallString "abc"; CallOptString (Some "def");
11123                 CallStringList ["1"]; CallBool false;
11124                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11125   call "test0" [CallString "abc"; CallOptString (Some "def");
11126                 CallStringList ["1"]; CallBool false;
11127                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11128
11129 (* XXX Add here tests of the return and error functions. *)
11130
11131 (* Code to generator bindings for virt-inspector.  Currently only
11132  * implemented for OCaml code (for virt-p2v 2.0).
11133  *)
11134 let rng_input = "inspector/virt-inspector.rng"
11135
11136 (* Read the input file and parse it into internal structures.  This is
11137  * by no means a complete RELAX NG parser, but is just enough to be
11138  * able to parse the specific input file.
11139  *)
11140 type rng =
11141   | Element of string * rng list        (* <element name=name/> *)
11142   | Attribute of string * rng list        (* <attribute name=name/> *)
11143   | Interleave of rng list                (* <interleave/> *)
11144   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11145   | OneOrMore of rng                        (* <oneOrMore/> *)
11146   | Optional of rng                        (* <optional/> *)
11147   | Choice of string list                (* <choice><value/>*</choice> *)
11148   | Value of string                        (* <value>str</value> *)
11149   | Text                                (* <text/> *)
11150
11151 let rec string_of_rng = function
11152   | Element (name, xs) ->
11153       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11154   | Attribute (name, xs) ->
11155       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11156   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11157   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11158   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11159   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11160   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11161   | Value value -> "Value \"" ^ value ^ "\""
11162   | Text -> "Text"
11163
11164 and string_of_rng_list xs =
11165   String.concat ", " (List.map string_of_rng xs)
11166
11167 let rec parse_rng ?defines context = function
11168   | [] -> []
11169   | Xml.Element ("element", ["name", name], children) :: rest ->
11170       Element (name, parse_rng ?defines context children)
11171       :: parse_rng ?defines context rest
11172   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11173       Attribute (name, parse_rng ?defines context children)
11174       :: parse_rng ?defines context rest
11175   | Xml.Element ("interleave", [], children) :: rest ->
11176       Interleave (parse_rng ?defines context children)
11177       :: parse_rng ?defines context rest
11178   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11179       let rng = parse_rng ?defines context [child] in
11180       (match rng with
11181        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11182        | _ ->
11183            failwithf "%s: <zeroOrMore> contains more than one child element"
11184              context
11185       )
11186   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11187       let rng = parse_rng ?defines context [child] in
11188       (match rng with
11189        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11190        | _ ->
11191            failwithf "%s: <oneOrMore> contains more than one child element"
11192              context
11193       )
11194   | Xml.Element ("optional", [], [child]) :: rest ->
11195       let rng = parse_rng ?defines context [child] in
11196       (match rng with
11197        | [child] -> Optional child :: parse_rng ?defines context rest
11198        | _ ->
11199            failwithf "%s: <optional> contains more than one child element"
11200              context
11201       )
11202   | Xml.Element ("choice", [], children) :: rest ->
11203       let values = List.map (
11204         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11205         | _ ->
11206             failwithf "%s: can't handle anything except <value> in <choice>"
11207               context
11208       ) children in
11209       Choice values
11210       :: parse_rng ?defines context rest
11211   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11212       Value value :: parse_rng ?defines context rest
11213   | Xml.Element ("text", [], []) :: rest ->
11214       Text :: parse_rng ?defines context rest
11215   | Xml.Element ("ref", ["name", name], []) :: rest ->
11216       (* Look up the reference.  Because of limitations in this parser,
11217        * we can't handle arbitrarily nested <ref> yet.  You can only
11218        * use <ref> from inside <start>.
11219        *)
11220       (match defines with
11221        | None ->
11222            failwithf "%s: contains <ref>, but no refs are defined yet" context
11223        | Some map ->
11224            let rng = StringMap.find name map in
11225            rng @ parse_rng ?defines context rest
11226       )
11227   | x :: _ ->
11228       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11229
11230 let grammar =
11231   let xml = Xml.parse_file rng_input in
11232   match xml with
11233   | Xml.Element ("grammar", _,
11234                  Xml.Element ("start", _, gram) :: defines) ->
11235       (* The <define/> elements are referenced in the <start> section,
11236        * so build a map of those first.
11237        *)
11238       let defines = List.fold_left (
11239         fun map ->
11240           function Xml.Element ("define", ["name", name], defn) ->
11241             StringMap.add name defn map
11242           | _ ->
11243               failwithf "%s: expected <define name=name/>" rng_input
11244       ) StringMap.empty defines in
11245       let defines = StringMap.mapi parse_rng defines in
11246
11247       (* Parse the <start> clause, passing the defines. *)
11248       parse_rng ~defines "<start>" gram
11249   | _ ->
11250       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11251         rng_input
11252
11253 let name_of_field = function
11254   | Element (name, _) | Attribute (name, _)
11255   | ZeroOrMore (Element (name, _))
11256   | OneOrMore (Element (name, _))
11257   | Optional (Element (name, _)) -> name
11258   | Optional (Attribute (name, _)) -> name
11259   | Text -> (* an unnamed field in an element *)
11260       "data"
11261   | rng ->
11262       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11263
11264 (* At the moment this function only generates OCaml types.  However we
11265  * should parameterize it later so it can generate types/structs in a
11266  * variety of languages.
11267  *)
11268 let generate_types xs =
11269   (* A simple type is one that can be printed out directly, eg.
11270    * "string option".  A complex type is one which has a name and has
11271    * to be defined via another toplevel definition, eg. a struct.
11272    *
11273    * generate_type generates code for either simple or complex types.
11274    * In the simple case, it returns the string ("string option").  In
11275    * the complex case, it returns the name ("mountpoint").  In the
11276    * complex case it has to print out the definition before returning,
11277    * so it should only be called when we are at the beginning of a
11278    * new line (BOL context).
11279    *)
11280   let rec generate_type = function
11281     | Text ->                                (* string *)
11282         "string", true
11283     | Choice values ->                        (* [`val1|`val2|...] *)
11284         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11285     | ZeroOrMore rng ->                        (* <rng> list *)
11286         let t, is_simple = generate_type rng in
11287         t ^ " list (* 0 or more *)", is_simple
11288     | OneOrMore rng ->                        (* <rng> list *)
11289         let t, is_simple = generate_type rng in
11290         t ^ " list (* 1 or more *)", is_simple
11291                                         (* virt-inspector hack: bool *)
11292     | Optional (Attribute (name, [Value "1"])) ->
11293         "bool", true
11294     | Optional rng ->                        (* <rng> list *)
11295         let t, is_simple = generate_type rng in
11296         t ^ " option", is_simple
11297                                         (* type name = { fields ... } *)
11298     | Element (name, fields) when is_attrs_interleave fields ->
11299         generate_type_struct name (get_attrs_interleave fields)
11300     | Element (name, [field])                (* type name = field *)
11301     | Attribute (name, [field]) ->
11302         let t, is_simple = generate_type field in
11303         if is_simple then (t, true)
11304         else (
11305           pr "type %s = %s\n" name t;
11306           name, false
11307         )
11308     | Element (name, fields) ->              (* type name = { fields ... } *)
11309         generate_type_struct name fields
11310     | rng ->
11311         failwithf "generate_type failed at: %s" (string_of_rng rng)
11312
11313   and is_attrs_interleave = function
11314     | [Interleave _] -> true
11315     | Attribute _ :: fields -> is_attrs_interleave fields
11316     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11317     | _ -> false
11318
11319   and get_attrs_interleave = function
11320     | [Interleave fields] -> fields
11321     | ((Attribute _) as field) :: fields
11322     | ((Optional (Attribute _)) as field) :: fields ->
11323         field :: get_attrs_interleave fields
11324     | _ -> assert false
11325
11326   and generate_types xs =
11327     List.iter (fun x -> ignore (generate_type x)) xs
11328
11329   and generate_type_struct name fields =
11330     (* Calculate the types of the fields first.  We have to do this
11331      * before printing anything so we are still in BOL context.
11332      *)
11333     let types = List.map fst (List.map generate_type fields) in
11334
11335     (* Special case of a struct containing just a string and another
11336      * field.  Turn it into an assoc list.
11337      *)
11338     match types with
11339     | ["string"; other] ->
11340         let fname1, fname2 =
11341           match fields with
11342           | [f1; f2] -> name_of_field f1, name_of_field f2
11343           | _ -> assert false in
11344         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11345         name, false
11346
11347     | types ->
11348         pr "type %s = {\n" name;
11349         List.iter (
11350           fun (field, ftype) ->
11351             let fname = name_of_field field in
11352             pr "  %s_%s : %s;\n" name fname ftype
11353         ) (List.combine fields types);
11354         pr "}\n";
11355         (* Return the name of this type, and
11356          * false because it's not a simple type.
11357          *)
11358         name, false
11359   in
11360
11361   generate_types xs
11362
11363 let generate_parsers xs =
11364   (* As for generate_type above, generate_parser makes a parser for
11365    * some type, and returns the name of the parser it has generated.
11366    * Because it (may) need to print something, it should always be
11367    * called in BOL context.
11368    *)
11369   let rec generate_parser = function
11370     | Text ->                                (* string *)
11371         "string_child_or_empty"
11372     | Choice values ->                        (* [`val1|`val2|...] *)
11373         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11374           (String.concat "|"
11375              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11376     | ZeroOrMore rng ->                        (* <rng> list *)
11377         let pa = generate_parser rng in
11378         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11379     | OneOrMore rng ->                        (* <rng> list *)
11380         let pa = generate_parser rng in
11381         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11382                                         (* virt-inspector hack: bool *)
11383     | Optional (Attribute (name, [Value "1"])) ->
11384         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11385     | Optional rng ->                        (* <rng> list *)
11386         let pa = generate_parser rng in
11387         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11388                                         (* type name = { fields ... } *)
11389     | Element (name, fields) when is_attrs_interleave fields ->
11390         generate_parser_struct name (get_attrs_interleave fields)
11391     | Element (name, [field]) ->        (* type name = field *)
11392         let pa = generate_parser field in
11393         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11394         pr "let %s =\n" parser_name;
11395         pr "  %s\n" pa;
11396         pr "let parse_%s = %s\n" name parser_name;
11397         parser_name
11398     | Attribute (name, [field]) ->
11399         let pa = generate_parser field in
11400         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11401         pr "let %s =\n" parser_name;
11402         pr "  %s\n" pa;
11403         pr "let parse_%s = %s\n" name parser_name;
11404         parser_name
11405     | Element (name, fields) ->              (* type name = { fields ... } *)
11406         generate_parser_struct name ([], fields)
11407     | rng ->
11408         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11409
11410   and is_attrs_interleave = function
11411     | [Interleave _] -> true
11412     | Attribute _ :: fields -> is_attrs_interleave fields
11413     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11414     | _ -> false
11415
11416   and get_attrs_interleave = function
11417     | [Interleave fields] -> [], fields
11418     | ((Attribute _) as field) :: fields
11419     | ((Optional (Attribute _)) as field) :: fields ->
11420         let attrs, interleaves = get_attrs_interleave fields in
11421         (field :: attrs), interleaves
11422     | _ -> assert false
11423
11424   and generate_parsers xs =
11425     List.iter (fun x -> ignore (generate_parser x)) xs
11426
11427   and generate_parser_struct name (attrs, interleaves) =
11428     (* Generate parsers for the fields first.  We have to do this
11429      * before printing anything so we are still in BOL context.
11430      *)
11431     let fields = attrs @ interleaves in
11432     let pas = List.map generate_parser fields in
11433
11434     (* Generate an intermediate tuple from all the fields first.
11435      * If the type is just a string + another field, then we will
11436      * return this directly, otherwise it is turned into a record.
11437      *
11438      * RELAX NG note: This code treats <interleave> and plain lists of
11439      * fields the same.  In other words, it doesn't bother enforcing
11440      * any ordering of fields in the XML.
11441      *)
11442     pr "let parse_%s x =\n" name;
11443     pr "  let t = (\n    ";
11444     let comma = ref false in
11445     List.iter (
11446       fun x ->
11447         if !comma then pr ",\n    ";
11448         comma := true;
11449         match x with
11450         | Optional (Attribute (fname, [field])), pa ->
11451             pr "%s x" pa
11452         | Optional (Element (fname, [field])), pa ->
11453             pr "%s (optional_child %S x)" pa fname
11454         | Attribute (fname, [Text]), _ ->
11455             pr "attribute %S x" fname
11456         | (ZeroOrMore _ | OneOrMore _), pa ->
11457             pr "%s x" pa
11458         | Text, pa ->
11459             pr "%s x" pa
11460         | (field, pa) ->
11461             let fname = name_of_field field in
11462             pr "%s (child %S x)" pa fname
11463     ) (List.combine fields pas);
11464     pr "\n  ) in\n";
11465
11466     (match fields with
11467      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11468          pr "  t\n"
11469
11470      | _ ->
11471          pr "  (Obj.magic t : %s)\n" name
11472 (*
11473          List.iter (
11474            function
11475            | (Optional (Attribute (fname, [field])), pa) ->
11476                pr "  %s_%s =\n" name fname;
11477                pr "    %s x;\n" pa
11478            | (Optional (Element (fname, [field])), pa) ->
11479                pr "  %s_%s =\n" name fname;
11480                pr "    (let x = optional_child %S x in\n" fname;
11481                pr "     %s x);\n" pa
11482            | (field, pa) ->
11483                let fname = name_of_field field in
11484                pr "  %s_%s =\n" name fname;
11485                pr "    (let x = child %S x in\n" fname;
11486                pr "     %s x);\n" pa
11487          ) (List.combine fields pas);
11488          pr "}\n"
11489 *)
11490     );
11491     sprintf "parse_%s" name
11492   in
11493
11494   generate_parsers xs
11495
11496 (* Generate ocaml/guestfs_inspector.mli. *)
11497 let generate_ocaml_inspector_mli () =
11498   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11499
11500   pr "\
11501 (** This is an OCaml language binding to the external [virt-inspector]
11502     program.
11503
11504     For more information, please read the man page [virt-inspector(1)].
11505 *)
11506
11507 ";
11508
11509   generate_types grammar;
11510   pr "(** The nested information returned from the {!inspect} function. *)\n";
11511   pr "\n";
11512
11513   pr "\
11514 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11515 (** To inspect a libvirt domain called [name], pass a singleton
11516     list: [inspect [name]].  When using libvirt only, you may
11517     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11518
11519     To inspect a disk image or images, pass a list of the filenames
11520     of the disk images: [inspect filenames]
11521
11522     This function inspects the given guest or disk images and
11523     returns a list of operating system(s) found and a large amount
11524     of information about them.  In the vast majority of cases,
11525     a virtual machine only contains a single operating system.
11526
11527     If the optional [~xml] parameter is given, then this function
11528     skips running the external virt-inspector program and just
11529     parses the given XML directly (which is expected to be XML
11530     produced from a previous run of virt-inspector).  The list of
11531     names and connect URI are ignored in this case.
11532
11533     This function can throw a wide variety of exceptions, for example
11534     if the external virt-inspector program cannot be found, or if
11535     it doesn't generate valid XML.
11536 *)
11537 "
11538
11539 (* Generate ocaml/guestfs_inspector.ml. *)
11540 let generate_ocaml_inspector_ml () =
11541   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11542
11543   pr "open Unix\n";
11544   pr "\n";
11545
11546   generate_types grammar;
11547   pr "\n";
11548
11549   pr "\
11550 (* Misc functions which are used by the parser code below. *)
11551 let first_child = function
11552   | Xml.Element (_, _, c::_) -> c
11553   | Xml.Element (name, _, []) ->
11554       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11555   | Xml.PCData str ->
11556       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11557
11558 let string_child_or_empty = function
11559   | Xml.Element (_, _, [Xml.PCData s]) -> s
11560   | Xml.Element (_, _, []) -> \"\"
11561   | Xml.Element (x, _, _) ->
11562       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11563                 x ^ \" instead\")
11564   | Xml.PCData str ->
11565       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11566
11567 let optional_child name xml =
11568   let children = Xml.children xml in
11569   try
11570     Some (List.find (function
11571                      | Xml.Element (n, _, _) when n = name -> true
11572                      | _ -> false) children)
11573   with
11574     Not_found -> None
11575
11576 let child name xml =
11577   match optional_child name xml with
11578   | Some c -> c
11579   | None ->
11580       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11581
11582 let attribute name xml =
11583   try Xml.attrib xml name
11584   with Xml.No_attribute _ ->
11585     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11586
11587 ";
11588
11589   generate_parsers grammar;
11590   pr "\n";
11591
11592   pr "\
11593 (* Run external virt-inspector, then use parser to parse the XML. *)
11594 let inspect ?connect ?xml names =
11595   let xml =
11596     match xml with
11597     | None ->
11598         if names = [] then invalid_arg \"inspect: no names given\";
11599         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11600           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11601           names in
11602         let cmd = List.map Filename.quote cmd in
11603         let cmd = String.concat \" \" cmd in
11604         let chan = open_process_in cmd in
11605         let xml = Xml.parse_in chan in
11606         (match close_process_in chan with
11607          | WEXITED 0 -> ()
11608          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11609          | WSIGNALED i | WSTOPPED i ->
11610              failwith (\"external virt-inspector command died or stopped on sig \" ^
11611                        string_of_int i)
11612         );
11613         xml
11614     | Some doc ->
11615         Xml.parse_string doc in
11616   parse_operatingsystems xml
11617 "
11618
11619 (* This is used to generate the src/MAX_PROC_NR file which
11620  * contains the maximum procedure number, a surrogate for the
11621  * ABI version number.  See src/Makefile.am for the details.
11622  *)
11623 and generate_max_proc_nr () =
11624   let proc_nrs = List.map (
11625     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11626   ) daemon_functions in
11627
11628   let max_proc_nr = List.fold_left max 0 proc_nrs in
11629
11630   pr "%d\n" max_proc_nr
11631
11632 let output_to filename k =
11633   let filename_new = filename ^ ".new" in
11634   chan := open_out filename_new;
11635   k ();
11636   close_out !chan;
11637   chan := Pervasives.stdout;
11638
11639   (* Is the new file different from the current file? *)
11640   if Sys.file_exists filename && files_equal filename filename_new then
11641     unlink filename_new                 (* same, so skip it *)
11642   else (
11643     (* different, overwrite old one *)
11644     (try chmod filename 0o644 with Unix_error _ -> ());
11645     rename filename_new filename;
11646     chmod filename 0o444;
11647     printf "written %s\n%!" filename;
11648   )
11649
11650 let perror msg = function
11651   | Unix_error (err, _, _) ->
11652       eprintf "%s: %s\n" msg (error_message err)
11653   | exn ->
11654       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11655
11656 (* Main program. *)
11657 let () =
11658   let lock_fd =
11659     try openfile "HACKING" [O_RDWR] 0
11660     with
11661     | Unix_error (ENOENT, _, _) ->
11662         eprintf "\
11663 You are probably running this from the wrong directory.
11664 Run it from the top source directory using the command
11665   src/generator.ml
11666 ";
11667         exit 1
11668     | exn ->
11669         perror "open: HACKING" exn;
11670         exit 1 in
11671
11672   (* Acquire a lock so parallel builds won't try to run the generator
11673    * twice at the same time.  Subsequent builds will wait for the first
11674    * one to finish.  Note the lock is released implicitly when the
11675    * program exits.
11676    *)
11677   (try lockf lock_fd F_LOCK 1
11678    with exn ->
11679      perror "lock: HACKING" exn;
11680      exit 1);
11681
11682   check_functions ();
11683
11684   output_to "src/guestfs_protocol.x" generate_xdr;
11685   output_to "src/guestfs-structs.h" generate_structs_h;
11686   output_to "src/guestfs-actions.h" generate_actions_h;
11687   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11688   output_to "src/guestfs-actions.c" generate_client_actions;
11689   output_to "src/guestfs-bindtests.c" generate_bindtests;
11690   output_to "src/guestfs-structs.pod" generate_structs_pod;
11691   output_to "src/guestfs-actions.pod" generate_actions_pod;
11692   output_to "src/guestfs-availability.pod" generate_availability_pod;
11693   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11694   output_to "src/libguestfs.syms" generate_linker_script;
11695   output_to "daemon/actions.h" generate_daemon_actions_h;
11696   output_to "daemon/stubs.c" generate_daemon_actions;
11697   output_to "daemon/names.c" generate_daemon_names;
11698   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11699   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11700   output_to "capitests/tests.c" generate_tests;
11701   output_to "fish/cmds.c" generate_fish_cmds;
11702   output_to "fish/completion.c" generate_fish_completion;
11703   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11704   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11705   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11706   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11707   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11708   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11709   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11710   output_to "perl/Guestfs.xs" generate_perl_xs;
11711   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11712   output_to "perl/bindtests.pl" generate_perl_bindtests;
11713   output_to "python/guestfs-py.c" generate_python_c;
11714   output_to "python/guestfs.py" generate_python_py;
11715   output_to "python/bindtests.py" generate_python_bindtests;
11716   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11717   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11718   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11719
11720   List.iter (
11721     fun (typ, jtyp) ->
11722       let cols = cols_of_struct typ in
11723       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11724       output_to filename (generate_java_struct jtyp cols);
11725   ) java_structs;
11726
11727   output_to "java/Makefile.inc" generate_java_makefile_inc;
11728   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11729   output_to "java/Bindtests.java" generate_java_bindtests;
11730   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11731   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11732   output_to "csharp/Libguestfs.cs" generate_csharp;
11733
11734   (* Always generate this file last, and unconditionally.  It's used
11735    * by the Makefile to know when we must re-run the generator.
11736    *)
11737   let chan = open_out "src/stamp-generator" in
11738   fprintf chan "1\n";
11739   close_out chan;
11740
11741   printf "generated %d lines of code\n" !lines