New API: get-umask, returns the current umask (RHBZ#582891).
[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 The filesystem options C<sync> and C<noatime> are set with this
962 call, in order to improve reliability.");
963
964   ("sync", (RErr, []), 2, [],
965    [ InitEmpty, Always, TestRun [["sync"]]],
966    "sync disks, writes are flushed through to the disk image",
967    "\
968 This syncs the disk, so that any writes are flushed through to the
969 underlying disk image.
970
971 You should always call this if you have modified a disk image, before
972 closing the handle.");
973
974   ("touch", (RErr, [Pathname "path"]), 3, [],
975    [InitBasicFS, Always, TestOutputTrue (
976       [["touch"; "/new"];
977        ["exists"; "/new"]])],
978    "update file timestamps or create a new file",
979    "\
980 Touch acts like the L<touch(1)> command.  It can be used to
981 update the timestamps on a file, or, if the file does not exist,
982 to create a new zero-length file.");
983
984   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
985    [InitISOFS, Always, TestOutput (
986       [["cat"; "/known-2"]], "abcdef\n")],
987    "list the contents of a file",
988    "\
989 Return the contents of the file named C<path>.
990
991 Note that this function cannot correctly handle binary files
992 (specifically, files containing C<\\0> character which is treated
993 as end of string).  For those you need to use the C<guestfs_read_file>
994 or C<guestfs_download> functions which have a more complex interface.");
995
996   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
997    [], (* XXX Tricky to test because it depends on the exact format
998         * of the 'ls -l' command, which changes between F10 and F11.
999         *)
1000    "list the files in a directory (long format)",
1001    "\
1002 List the files in C<directory> (relative to the root directory,
1003 there is no cwd) in the format of 'ls -la'.
1004
1005 This command is mostly useful for interactive sessions.  It
1006 is I<not> intended that you try to parse the output string.");
1007
1008   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1009    [InitBasicFS, Always, TestOutputList (
1010       [["touch"; "/new"];
1011        ["touch"; "/newer"];
1012        ["touch"; "/newest"];
1013        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1014    "list the files in a directory",
1015    "\
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd).  The '.' and '..' entries are not returned, but
1018 hidden files are shown.
1019
1020 This command is mostly useful for interactive sessions.  Programs
1021 should probably use C<guestfs_readdir> instead.");
1022
1023   ("list_devices", (RStringList "devices", []), 7, [],
1024    [InitEmpty, Always, TestOutputListOfDevices (
1025       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1026    "list the block devices",
1027    "\
1028 List all the block devices.
1029
1030 The full block device names are returned, eg. C</dev/sda>");
1031
1032   ("list_partitions", (RStringList "partitions", []), 8, [],
1033    [InitBasicFS, Always, TestOutputListOfDevices (
1034       [["list_partitions"]], ["/dev/sda1"]);
1035     InitEmpty, Always, TestOutputListOfDevices (
1036       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1037        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1038    "list the partitions",
1039    "\
1040 List all the partitions detected on all block devices.
1041
1042 The full partition device names are returned, eg. C</dev/sda1>
1043
1044 This does not return logical volumes.  For that you will need to
1045 call C<guestfs_lvs>.");
1046
1047   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1048    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1049       [["pvs"]], ["/dev/sda1"]);
1050     InitEmpty, Always, TestOutputListOfDevices (
1051       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1052        ["pvcreate"; "/dev/sda1"];
1053        ["pvcreate"; "/dev/sda2"];
1054        ["pvcreate"; "/dev/sda3"];
1055        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1056    "list the LVM physical volumes (PVs)",
1057    "\
1058 List all the physical volumes detected.  This is the equivalent
1059 of the L<pvs(8)> command.
1060
1061 This returns a list of just the device names that contain
1062 PVs (eg. C</dev/sda2>).
1063
1064 See also C<guestfs_pvs_full>.");
1065
1066   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1067    [InitBasicFSonLVM, Always, TestOutputList (
1068       [["vgs"]], ["VG"]);
1069     InitEmpty, Always, TestOutputList (
1070       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1071        ["pvcreate"; "/dev/sda1"];
1072        ["pvcreate"; "/dev/sda2"];
1073        ["pvcreate"; "/dev/sda3"];
1074        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1075        ["vgcreate"; "VG2"; "/dev/sda3"];
1076        ["vgs"]], ["VG1"; "VG2"])],
1077    "list the LVM volume groups (VGs)",
1078    "\
1079 List all the volumes groups detected.  This is the equivalent
1080 of the L<vgs(8)> command.
1081
1082 This returns a list of just the volume group names that were
1083 detected (eg. C<VolGroup00>).
1084
1085 See also C<guestfs_vgs_full>.");
1086
1087   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1088    [InitBasicFSonLVM, Always, TestOutputList (
1089       [["lvs"]], ["/dev/VG/LV"]);
1090     InitEmpty, Always, TestOutputList (
1091       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1092        ["pvcreate"; "/dev/sda1"];
1093        ["pvcreate"; "/dev/sda2"];
1094        ["pvcreate"; "/dev/sda3"];
1095        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1096        ["vgcreate"; "VG2"; "/dev/sda3"];
1097        ["lvcreate"; "LV1"; "VG1"; "50"];
1098        ["lvcreate"; "LV2"; "VG1"; "50"];
1099        ["lvcreate"; "LV3"; "VG2"; "50"];
1100        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1101    "list the LVM logical volumes (LVs)",
1102    "\
1103 List all the logical volumes detected.  This is the equivalent
1104 of the L<lvs(8)> command.
1105
1106 This returns a list of the logical volume device names
1107 (eg. C</dev/VolGroup00/LogVol00>).
1108
1109 See also C<guestfs_lvs_full>.");
1110
1111   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1112    [], (* XXX how to test? *)
1113    "list the LVM physical volumes (PVs)",
1114    "\
1115 List all the physical volumes detected.  This is the equivalent
1116 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1117
1118   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1119    [], (* XXX how to test? *)
1120    "list the LVM volume groups (VGs)",
1121    "\
1122 List all the volumes groups detected.  This is the equivalent
1123 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1124
1125   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM logical volumes (LVs)",
1128    "\
1129 List all the logical volumes detected.  This is the equivalent
1130 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1133    [InitISOFS, Always, TestOutputList (
1134       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1135     InitISOFS, Always, TestOutputList (
1136       [["read_lines"; "/empty"]], [])],
1137    "read file as lines",
1138    "\
1139 Return the contents of the file named C<path>.
1140
1141 The file contents are returned as a list of lines.  Trailing
1142 C<LF> and C<CRLF> character sequences are I<not> returned.
1143
1144 Note that this function cannot correctly handle binary files
1145 (specifically, files containing C<\\0> character which is treated
1146 as end of line).  For those you need to use the C<guestfs_read_file>
1147 function which has a more complex interface.");
1148
1149   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1150    [], (* XXX Augeas code needs tests. *)
1151    "create a new Augeas handle",
1152    "\
1153 Create a new Augeas handle for editing configuration files.
1154 If there was any previous Augeas handle associated with this
1155 guestfs session, then it is closed.
1156
1157 You must call this before using any other C<guestfs_aug_*>
1158 commands.
1159
1160 C<root> is the filesystem root.  C<root> must not be NULL,
1161 use C</> instead.
1162
1163 The flags are the same as the flags defined in
1164 E<lt>augeas.hE<gt>, the logical I<or> of the following
1165 integers:
1166
1167 =over 4
1168
1169 =item C<AUG_SAVE_BACKUP> = 1
1170
1171 Keep the original file with a C<.augsave> extension.
1172
1173 =item C<AUG_SAVE_NEWFILE> = 2
1174
1175 Save changes into a file with extension C<.augnew>, and
1176 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1177
1178 =item C<AUG_TYPE_CHECK> = 4
1179
1180 Typecheck lenses (can be expensive).
1181
1182 =item C<AUG_NO_STDINC> = 8
1183
1184 Do not use standard load path for modules.
1185
1186 =item C<AUG_SAVE_NOOP> = 16
1187
1188 Make save a no-op, just record what would have been changed.
1189
1190 =item C<AUG_NO_LOAD> = 32
1191
1192 Do not load the tree in C<guestfs_aug_init>.
1193
1194 =back
1195
1196 To close the handle, you can call C<guestfs_aug_close>.
1197
1198 To find out more about Augeas, see L<http://augeas.net/>.");
1199
1200   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1201    [], (* XXX Augeas code needs tests. *)
1202    "close the current Augeas handle",
1203    "\
1204 Close the current Augeas handle and free up any resources
1205 used by it.  After calling this, you have to call
1206 C<guestfs_aug_init> again before you can use any other
1207 Augeas functions.");
1208
1209   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1210    [], (* XXX Augeas code needs tests. *)
1211    "define an Augeas variable",
1212    "\
1213 Defines an Augeas variable C<name> whose value is the result
1214 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1215 undefined.
1216
1217 On success this returns the number of nodes in C<expr>, or
1218 C<0> if C<expr> evaluates to something which is not a nodeset.");
1219
1220   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1221    [], (* XXX Augeas code needs tests. *)
1222    "define an Augeas node",
1223    "\
1224 Defines a variable C<name> whose value is the result of
1225 evaluating C<expr>.
1226
1227 If C<expr> evaluates to an empty nodeset, a node is created,
1228 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1229 C<name> will be the nodeset containing that single node.
1230
1231 On success this returns a pair containing the
1232 number of nodes in the nodeset, and a boolean flag
1233 if a node was created.");
1234
1235   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1236    [], (* XXX Augeas code needs tests. *)
1237    "look up the value of an Augeas path",
1238    "\
1239 Look up the value associated with C<path>.  If C<path>
1240 matches exactly one node, the C<value> is returned.");
1241
1242   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1243    [], (* XXX Augeas code needs tests. *)
1244    "set Augeas path to value",
1245    "\
1246 Set the value associated with C<path> to C<val>.
1247
1248 In the Augeas API, it is possible to clear a node by setting
1249 the value to NULL.  Due to an oversight in the libguestfs API
1250 you cannot do that with this call.  Instead you must use the
1251 C<guestfs_aug_clear> call.");
1252
1253   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1254    [], (* XXX Augeas code needs tests. *)
1255    "insert a sibling Augeas node",
1256    "\
1257 Create a new sibling C<label> for C<path>, inserting it into
1258 the tree before or after C<path> (depending on the boolean
1259 flag C<before>).
1260
1261 C<path> must match exactly one existing node in the tree, and
1262 C<label> must be a label, ie. not contain C</>, C<*> or end
1263 with a bracketed index C<[N]>.");
1264
1265   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1266    [], (* XXX Augeas code needs tests. *)
1267    "remove an Augeas path",
1268    "\
1269 Remove C<path> and all of its children.
1270
1271 On success this returns the number of entries which were removed.");
1272
1273   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1274    [], (* XXX Augeas code needs tests. *)
1275    "move Augeas node",
1276    "\
1277 Move the node C<src> to C<dest>.  C<src> must match exactly
1278 one node.  C<dest> is overwritten if it exists.");
1279
1280   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1281    [], (* XXX Augeas code needs tests. *)
1282    "return Augeas nodes which match augpath",
1283    "\
1284 Returns a list of paths which match the path expression C<path>.
1285 The returned paths are sufficiently qualified so that they match
1286 exactly one node in the current tree.");
1287
1288   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1289    [], (* XXX Augeas code needs tests. *)
1290    "write all pending Augeas changes to disk",
1291    "\
1292 This writes all pending changes to disk.
1293
1294 The flags which were passed to C<guestfs_aug_init> affect exactly
1295 how files are saved.");
1296
1297   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1298    [], (* XXX Augeas code needs tests. *)
1299    "load files into the tree",
1300    "\
1301 Load files into the tree.
1302
1303 See C<aug_load> in the Augeas documentation for the full gory
1304 details.");
1305
1306   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1307    [], (* XXX Augeas code needs tests. *)
1308    "list Augeas nodes under augpath",
1309    "\
1310 This is just a shortcut for listing C<guestfs_aug_match>
1311 C<path/*> and sorting the resulting nodes into alphabetical order.");
1312
1313   ("rm", (RErr, [Pathname "path"]), 29, [],
1314    [InitBasicFS, Always, TestRun
1315       [["touch"; "/new"];
1316        ["rm"; "/new"]];
1317     InitBasicFS, Always, TestLastFail
1318       [["rm"; "/new"]];
1319     InitBasicFS, Always, TestLastFail
1320       [["mkdir"; "/new"];
1321        ["rm"; "/new"]]],
1322    "remove a file",
1323    "\
1324 Remove the single file C<path>.");
1325
1326   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1327    [InitBasicFS, Always, TestRun
1328       [["mkdir"; "/new"];
1329        ["rmdir"; "/new"]];
1330     InitBasicFS, Always, TestLastFail
1331       [["rmdir"; "/new"]];
1332     InitBasicFS, Always, TestLastFail
1333       [["touch"; "/new"];
1334        ["rmdir"; "/new"]]],
1335    "remove a directory",
1336    "\
1337 Remove the single directory C<path>.");
1338
1339   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1340    [InitBasicFS, Always, TestOutputFalse
1341       [["mkdir"; "/new"];
1342        ["mkdir"; "/new/foo"];
1343        ["touch"; "/new/foo/bar"];
1344        ["rm_rf"; "/new"];
1345        ["exists"; "/new"]]],
1346    "remove a file or directory recursively",
1347    "\
1348 Remove the file or directory C<path>, recursively removing the
1349 contents if its a directory.  This is like the C<rm -rf> shell
1350 command.");
1351
1352   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1353    [InitBasicFS, Always, TestOutputTrue
1354       [["mkdir"; "/new"];
1355        ["is_dir"; "/new"]];
1356     InitBasicFS, Always, TestLastFail
1357       [["mkdir"; "/new/foo/bar"]]],
1358    "create a directory",
1359    "\
1360 Create a directory named C<path>.");
1361
1362   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir_p"; "/new/foo/bar"];
1365        ["is_dir"; "/new/foo/bar"]];
1366     InitBasicFS, Always, TestOutputTrue
1367       [["mkdir_p"; "/new/foo/bar"];
1368        ["is_dir"; "/new/foo"]];
1369     InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new"]];
1372     (* Regression tests for RHBZ#503133: *)
1373     InitBasicFS, Always, TestRun
1374       [["mkdir"; "/new"];
1375        ["mkdir_p"; "/new"]];
1376     InitBasicFS, Always, TestLastFail
1377       [["touch"; "/new"];
1378        ["mkdir_p"; "/new"]]],
1379    "create a directory and parents",
1380    "\
1381 Create a directory named C<path>, creating any parent directories
1382 as necessary.  This is like the C<mkdir -p> shell command.");
1383
1384   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1385    [], (* XXX Need stat command to test *)
1386    "change file mode",
1387    "\
1388 Change the mode (permissions) of C<path> to C<mode>.  Only
1389 numeric modes are supported.
1390
1391 I<Note>: When using this command from guestfish, C<mode>
1392 by default would be decimal, unless you prefix it with
1393 C<0> to get octal, ie. use C<0700> not C<700>.");
1394
1395   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1396    [], (* XXX Need stat command to test *)
1397    "change file owner and group",
1398    "\
1399 Change the file owner to C<owner> and group to C<group>.
1400
1401 Only numeric uid and gid are supported.  If you want to use
1402 names, you will need to locate and parse the password file
1403 yourself (Augeas support makes this relatively easy).");
1404
1405   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1406    [InitISOFS, Always, TestOutputTrue (
1407       [["exists"; "/empty"]]);
1408     InitISOFS, Always, TestOutputTrue (
1409       [["exists"; "/directory"]])],
1410    "test if file or directory exists",
1411    "\
1412 This returns C<true> if and only if there is a file, directory
1413 (or anything) with the given C<path> name.
1414
1415 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1416
1417   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1418    [InitISOFS, Always, TestOutputTrue (
1419       [["is_file"; "/known-1"]]);
1420     InitISOFS, Always, TestOutputFalse (
1421       [["is_file"; "/directory"]])],
1422    "test if file exists",
1423    "\
1424 This returns C<true> if and only if there is a file
1425 with the given C<path> name.  Note that it returns false for
1426 other objects like directories.
1427
1428 See also C<guestfs_stat>.");
1429
1430   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1431    [InitISOFS, Always, TestOutputFalse (
1432       [["is_dir"; "/known-3"]]);
1433     InitISOFS, Always, TestOutputTrue (
1434       [["is_dir"; "/directory"]])],
1435    "test if file exists",
1436    "\
1437 This returns C<true> if and only if there is a directory
1438 with the given C<path> name.  Note that it returns false for
1439 other objects like files.
1440
1441 See also C<guestfs_stat>.");
1442
1443   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1444    [InitEmpty, Always, TestOutputListOfDevices (
1445       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1446        ["pvcreate"; "/dev/sda1"];
1447        ["pvcreate"; "/dev/sda2"];
1448        ["pvcreate"; "/dev/sda3"];
1449        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1450    "create an LVM physical volume",
1451    "\
1452 This creates an LVM physical volume on the named C<device>,
1453 where C<device> should usually be a partition name such
1454 as C</dev/sda1>.");
1455
1456   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1457    [InitEmpty, Always, TestOutputList (
1458       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1459        ["pvcreate"; "/dev/sda1"];
1460        ["pvcreate"; "/dev/sda2"];
1461        ["pvcreate"; "/dev/sda3"];
1462        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1463        ["vgcreate"; "VG2"; "/dev/sda3"];
1464        ["vgs"]], ["VG1"; "VG2"])],
1465    "create an LVM volume group",
1466    "\
1467 This creates an LVM volume group called C<volgroup>
1468 from the non-empty list of physical volumes C<physvols>.");
1469
1470   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1471    [InitEmpty, Always, TestOutputList (
1472       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1473        ["pvcreate"; "/dev/sda1"];
1474        ["pvcreate"; "/dev/sda2"];
1475        ["pvcreate"; "/dev/sda3"];
1476        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1477        ["vgcreate"; "VG2"; "/dev/sda3"];
1478        ["lvcreate"; "LV1"; "VG1"; "50"];
1479        ["lvcreate"; "LV2"; "VG1"; "50"];
1480        ["lvcreate"; "LV3"; "VG2"; "50"];
1481        ["lvcreate"; "LV4"; "VG2"; "50"];
1482        ["lvcreate"; "LV5"; "VG2"; "50"];
1483        ["lvs"]],
1484       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1485        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1486    "create an LVM logical volume",
1487    "\
1488 This creates an LVM logical volume called C<logvol>
1489 on the volume group C<volgroup>, with C<size> megabytes.");
1490
1491   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1492    [InitEmpty, Always, TestOutput (
1493       [["part_disk"; "/dev/sda"; "mbr"];
1494        ["mkfs"; "ext2"; "/dev/sda1"];
1495        ["mount_options"; ""; "/dev/sda1"; "/"];
1496        ["write_file"; "/new"; "new file contents"; "0"];
1497        ["cat"; "/new"]], "new file contents")],
1498    "make a filesystem",
1499    "\
1500 This creates a filesystem on C<device> (usually a partition
1501 or LVM logical volume).  The filesystem type is C<fstype>, for
1502 example C<ext3>.");
1503
1504   ("sfdisk", (RErr, [Device "device";
1505                      Int "cyls"; Int "heads"; Int "sectors";
1506                      StringList "lines"]), 43, [DangerWillRobinson],
1507    [],
1508    "create partitions on a block device",
1509    "\
1510 This is a direct interface to the L<sfdisk(8)> program for creating
1511 partitions on block devices.
1512
1513 C<device> should be a block device, for example C</dev/sda>.
1514
1515 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1516 and sectors on the device, which are passed directly to sfdisk as
1517 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1518 of these, then the corresponding parameter is omitted.  Usually for
1519 'large' disks, you can just pass C<0> for these, but for small
1520 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1521 out the right geometry and you will need to tell it.
1522
1523 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1524 information refer to the L<sfdisk(8)> manpage.
1525
1526 To create a single partition occupying the whole disk, you would
1527 pass C<lines> as a single element list, when the single element being
1528 the string C<,> (comma).
1529
1530 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1531 C<guestfs_part_init>");
1532
1533   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1534    [InitBasicFS, Always, TestOutput (
1535       [["write_file"; "/new"; "new file contents"; "0"];
1536        ["cat"; "/new"]], "new file contents");
1537     InitBasicFS, Always, TestOutput (
1538       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1539        ["cat"; "/new"]], "\nnew file contents\n");
1540     InitBasicFS, Always, TestOutput (
1541       [["write_file"; "/new"; "\n\n"; "0"];
1542        ["cat"; "/new"]], "\n\n");
1543     InitBasicFS, Always, TestOutput (
1544       [["write_file"; "/new"; ""; "0"];
1545        ["cat"; "/new"]], "");
1546     InitBasicFS, Always, TestOutput (
1547       [["write_file"; "/new"; "\n\n\n"; "0"];
1548        ["cat"; "/new"]], "\n\n\n");
1549     InitBasicFS, Always, TestOutput (
1550       [["write_file"; "/new"; "\n"; "0"];
1551        ["cat"; "/new"]], "\n")],
1552    "create a file",
1553    "\
1554 This call creates a file called C<path>.  The contents of the
1555 file is the string C<content> (which can contain any 8 bit data),
1556 with length C<size>.
1557
1558 As a special case, if C<size> is C<0>
1559 then the length is calculated using C<strlen> (so in this case
1560 the content cannot contain embedded ASCII NULs).
1561
1562 I<NB.> Owing to a bug, writing content containing ASCII NUL
1563 characters does I<not> work, even if the length is specified.
1564 We hope to resolve this bug in a future version.  In the meantime
1565 use C<guestfs_upload>.");
1566
1567   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1568    [InitEmpty, Always, TestOutputListOfDevices (
1569       [["part_disk"; "/dev/sda"; "mbr"];
1570        ["mkfs"; "ext2"; "/dev/sda1"];
1571        ["mount_options"; ""; "/dev/sda1"; "/"];
1572        ["mounts"]], ["/dev/sda1"]);
1573     InitEmpty, Always, TestOutputList (
1574       [["part_disk"; "/dev/sda"; "mbr"];
1575        ["mkfs"; "ext2"; "/dev/sda1"];
1576        ["mount_options"; ""; "/dev/sda1"; "/"];
1577        ["umount"; "/"];
1578        ["mounts"]], [])],
1579    "unmount a filesystem",
1580    "\
1581 This unmounts the given filesystem.  The filesystem may be
1582 specified either by its mountpoint (path) or the device which
1583 contains the filesystem.");
1584
1585   ("mounts", (RStringList "devices", []), 46, [],
1586    [InitBasicFS, Always, TestOutputListOfDevices (
1587       [["mounts"]], ["/dev/sda1"])],
1588    "show mounted filesystems",
1589    "\
1590 This returns the list of currently mounted filesystems.  It returns
1591 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1592
1593 Some internal mounts are not shown.
1594
1595 See also: C<guestfs_mountpoints>");
1596
1597   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1598    [InitBasicFS, Always, TestOutputList (
1599       [["umount_all"];
1600        ["mounts"]], []);
1601     (* check that umount_all can unmount nested mounts correctly: *)
1602     InitEmpty, Always, TestOutputList (
1603       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1604        ["mkfs"; "ext2"; "/dev/sda1"];
1605        ["mkfs"; "ext2"; "/dev/sda2"];
1606        ["mkfs"; "ext2"; "/dev/sda3"];
1607        ["mount_options"; ""; "/dev/sda1"; "/"];
1608        ["mkdir"; "/mp1"];
1609        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1610        ["mkdir"; "/mp1/mp2"];
1611        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1612        ["mkdir"; "/mp1/mp2/mp3"];
1613        ["umount_all"];
1614        ["mounts"]], [])],
1615    "unmount all filesystems",
1616    "\
1617 This unmounts all mounted filesystems.
1618
1619 Some internal mounts are not unmounted by this call.");
1620
1621   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1622    [],
1623    "remove all LVM LVs, VGs and PVs",
1624    "\
1625 This command removes all LVM logical volumes, volume groups
1626 and physical volumes.");
1627
1628   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1629    [InitISOFS, Always, TestOutput (
1630       [["file"; "/empty"]], "empty");
1631     InitISOFS, Always, TestOutput (
1632       [["file"; "/known-1"]], "ASCII text");
1633     InitISOFS, Always, TestLastFail (
1634       [["file"; "/notexists"]])],
1635    "determine file type",
1636    "\
1637 This call uses the standard L<file(1)> command to determine
1638 the type or contents of the file.  This also works on devices,
1639 for example to find out whether a partition contains a filesystem.
1640
1641 This call will also transparently look inside various types
1642 of compressed file.
1643
1644 The exact command which runs is C<file -zbsL path>.  Note in
1645 particular that the filename is not prepended to the output
1646 (the C<-b> option).");
1647
1648   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1649    [InitBasicFS, Always, TestOutput (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command"; "/test-command 1"]], "Result1");
1653     InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 2"]], "Result2\n");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 3"]], "\nResult3");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 4"]], "\nResult4\n");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 5"]], "\nResult5\n\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 7"]], "");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 8"]], "\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 9"]], "\n\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1693     InitBasicFS, Always, TestLastFail (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command"]])],
1697    "run a command from the guest filesystem",
1698    "\
1699 This call runs a command from the guest filesystem.  The
1700 filesystem must be mounted, and must contain a compatible
1701 operating system (ie. something Linux, with the same
1702 or compatible processor architecture).
1703
1704 The single parameter is an argv-style list of arguments.
1705 The first element is the name of the program to run.
1706 Subsequent elements are parameters.  The list must be
1707 non-empty (ie. must contain a program name).  Note that
1708 the command runs directly, and is I<not> invoked via
1709 the shell (see C<guestfs_sh>).
1710
1711 The return value is anything printed to I<stdout> by
1712 the command.
1713
1714 If the command returns a non-zero exit status, then
1715 this function returns an error message.  The error message
1716 string is the content of I<stderr> from the command.
1717
1718 The C<$PATH> environment variable will contain at least
1719 C</usr/bin> and C</bin>.  If you require a program from
1720 another location, you should provide the full path in the
1721 first parameter.
1722
1723 Shared libraries and data files required by the program
1724 must be available on filesystems which are mounted in the
1725 correct places.  It is the caller's responsibility to ensure
1726 all filesystems that are needed are mounted at the right
1727 locations.");
1728
1729   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1730    [InitBasicFS, Always, TestOutputList (
1731       [["upload"; "test-command"; "/test-command"];
1732        ["chmod"; "0o755"; "/test-command"];
1733        ["command_lines"; "/test-command 1"]], ["Result1"]);
1734     InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 2"]], ["Result2"]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 7"]], []);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 8"]], [""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 9"]], ["";""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1774    "run a command, returning lines",
1775    "\
1776 This is the same as C<guestfs_command>, but splits the
1777 result into a list of lines.
1778
1779 See also: C<guestfs_sh_lines>");
1780
1781   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1782    [InitISOFS, Always, TestOutputStruct (
1783       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1784    "get file information",
1785    "\
1786 Returns file information for the given C<path>.
1787
1788 This is the same as the C<stat(2)> system call.");
1789
1790   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1791    [InitISOFS, Always, TestOutputStruct (
1792       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1793    "get file information for a symbolic link",
1794    "\
1795 Returns file information for the given C<path>.
1796
1797 This is the same as C<guestfs_stat> except that if C<path>
1798 is a symbolic link, then the link is stat-ed, not the file it
1799 refers to.
1800
1801 This is the same as the C<lstat(2)> system call.");
1802
1803   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1804    [InitISOFS, Always, TestOutputStruct (
1805       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1806    "get file system statistics",
1807    "\
1808 Returns file system statistics for any mounted file system.
1809 C<path> should be a file or directory in the mounted file system
1810 (typically it is the mount point itself, but it doesn't need to be).
1811
1812 This is the same as the C<statvfs(2)> system call.");
1813
1814   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1815    [], (* XXX test *)
1816    "get ext2/ext3/ext4 superblock details",
1817    "\
1818 This returns the contents of the ext2, ext3 or ext4 filesystem
1819 superblock on C<device>.
1820
1821 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1822 manpage for more details.  The list of fields returned isn't
1823 clearly defined, and depends on both the version of C<tune2fs>
1824 that libguestfs was built against, and the filesystem itself.");
1825
1826   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1827    [InitEmpty, Always, TestOutputTrue (
1828       [["blockdev_setro"; "/dev/sda"];
1829        ["blockdev_getro"; "/dev/sda"]])],
1830    "set block device to read-only",
1831    "\
1832 Sets the block device named C<device> to read-only.
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1837    [InitEmpty, Always, TestOutputFalse (
1838       [["blockdev_setrw"; "/dev/sda"];
1839        ["blockdev_getro"; "/dev/sda"]])],
1840    "set block device to read-write",
1841    "\
1842 Sets the block device named C<device> to read-write.
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1847    [InitEmpty, Always, TestOutputTrue (
1848       [["blockdev_setro"; "/dev/sda"];
1849        ["blockdev_getro"; "/dev/sda"]])],
1850    "is block device set to read-only",
1851    "\
1852 Returns a boolean indicating if the block device is read-only
1853 (true if read-only, false if not).
1854
1855 This uses the L<blockdev(8)> command.");
1856
1857   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1858    [InitEmpty, Always, TestOutputInt (
1859       [["blockdev_getss"; "/dev/sda"]], 512)],
1860    "get sectorsize of block device",
1861    "\
1862 This returns the size of sectors on a block device.
1863 Usually 512, but can be larger for modern devices.
1864
1865 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1866 for that).
1867
1868 This uses the L<blockdev(8)> command.");
1869
1870   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1871    [InitEmpty, Always, TestOutputInt (
1872       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1873    "get blocksize of block device",
1874    "\
1875 This returns the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1883    [], (* XXX test *)
1884    "set blocksize of block device",
1885    "\
1886 This sets the block size of a device.
1887
1888 (Note this is different from both I<size in blocks> and
1889 I<filesystem block size>).
1890
1891 This uses the L<blockdev(8)> command.");
1892
1893   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1894    [InitEmpty, Always, TestOutputInt (
1895       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1896    "get total size of device in 512-byte sectors",
1897    "\
1898 This returns the size of the device in units of 512-byte sectors
1899 (even if the sectorsize isn't 512 bytes ... weird).
1900
1901 See also C<guestfs_blockdev_getss> for the real sector size of
1902 the device, and C<guestfs_blockdev_getsize64> for the more
1903 useful I<size in bytes>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1908    [InitEmpty, Always, TestOutputInt (
1909       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1910    "get total size of device in bytes",
1911    "\
1912 This returns the size of the device in bytes.
1913
1914 See also C<guestfs_blockdev_getsz>.
1915
1916 This uses the L<blockdev(8)> command.");
1917
1918   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1919    [InitEmpty, Always, TestRun
1920       [["blockdev_flushbufs"; "/dev/sda"]]],
1921    "flush device buffers",
1922    "\
1923 This tells the kernel to flush internal buffers associated
1924 with C<device>.
1925
1926 This uses the L<blockdev(8)> command.");
1927
1928   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1929    [InitEmpty, Always, TestRun
1930       [["blockdev_rereadpt"; "/dev/sda"]]],
1931    "reread partition table",
1932    "\
1933 Reread the partition table on C<device>.
1934
1935 This uses the L<blockdev(8)> command.");
1936
1937   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1938    [InitBasicFS, Always, TestOutput (
1939       (* Pick a file from cwd which isn't likely to change. *)
1940       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1941        ["checksum"; "md5"; "/COPYING.LIB"]],
1942       Digest.to_hex (Digest.file "COPYING.LIB"))],
1943    "upload a file from the local machine",
1944    "\
1945 Upload local file C<filename> to C<remotefilename> on the
1946 filesystem.
1947
1948 C<filename> can also be a named pipe.
1949
1950 See also C<guestfs_download>.");
1951
1952   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1953    [InitBasicFS, Always, TestOutput (
1954       (* Pick a file from cwd which isn't likely to change. *)
1955       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1956        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1957        ["upload"; "testdownload.tmp"; "/upload"];
1958        ["checksum"; "md5"; "/upload"]],
1959       Digest.to_hex (Digest.file "COPYING.LIB"))],
1960    "download a file to the local machine",
1961    "\
1962 Download file C<remotefilename> and save it as C<filename>
1963 on the local machine.
1964
1965 C<filename> can also be a named pipe.
1966
1967 See also C<guestfs_upload>, C<guestfs_cat>.");
1968
1969   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1970    [InitISOFS, Always, TestOutput (
1971       [["checksum"; "crc"; "/known-3"]], "2891671662");
1972     InitISOFS, Always, TestLastFail (
1973       [["checksum"; "crc"; "/notexists"]]);
1974     InitISOFS, Always, TestOutput (
1975       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1978     InitISOFS, Always, TestOutput (
1979       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1982     InitISOFS, Always, TestOutput (
1983       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1984     InitISOFS, Always, TestOutput (
1985       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1986    "compute MD5, SHAx or CRC checksum of file",
1987    "\
1988 This call computes the MD5, SHAx or CRC checksum of the
1989 file named C<path>.
1990
1991 The type of checksum to compute is given by the C<csumtype>
1992 parameter which must have one of the following values:
1993
1994 =over 4
1995
1996 =item C<crc>
1997
1998 Compute the cyclic redundancy check (CRC) specified by POSIX
1999 for the C<cksum> command.
2000
2001 =item C<md5>
2002
2003 Compute the MD5 hash (using the C<md5sum> program).
2004
2005 =item C<sha1>
2006
2007 Compute the SHA1 hash (using the C<sha1sum> program).
2008
2009 =item C<sha224>
2010
2011 Compute the SHA224 hash (using the C<sha224sum> program).
2012
2013 =item C<sha256>
2014
2015 Compute the SHA256 hash (using the C<sha256sum> program).
2016
2017 =item C<sha384>
2018
2019 Compute the SHA384 hash (using the C<sha384sum> program).
2020
2021 =item C<sha512>
2022
2023 Compute the SHA512 hash (using the C<sha512sum> program).
2024
2025 =back
2026
2027 The checksum is returned as a printable string.");
2028
2029   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2030    [InitBasicFS, Always, TestOutput (
2031       [["tar_in"; "../images/helloworld.tar"; "/"];
2032        ["cat"; "/hello"]], "hello\n")],
2033    "unpack tarfile to directory",
2034    "\
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2037
2038 To upload a compressed tarball, use C<guestfs_tgz_in>
2039 or C<guestfs_txz_in>.");
2040
2041   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2042    [],
2043    "pack directory into tarfile",
2044    "\
2045 This command packs the contents of C<directory> and downloads
2046 it to local file C<tarfile>.
2047
2048 To download a compressed tarball, use C<guestfs_tgz_out>
2049 or C<guestfs_txz_out>.");
2050
2051   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2052    [InitBasicFS, Always, TestOutput (
2053       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2054        ["cat"; "/hello"]], "hello\n")],
2055    "unpack compressed tarball to directory",
2056    "\
2057 This command uploads and unpacks local file C<tarball> (a
2058 I<gzip compressed> tar file) into C<directory>.
2059
2060 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2061
2062   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2063    [],
2064    "pack directory into compressed tarball",
2065    "\
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarball>.
2068
2069 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2070
2071   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2072    [InitBasicFS, Always, TestLastFail (
2073       [["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["touch"; "/new"]]);
2076     InitBasicFS, Always, TestOutput (
2077       [["write_file"; "/new"; "data"; "0"];
2078        ["umount"; "/"];
2079        ["mount_ro"; "/dev/sda1"; "/"];
2080        ["cat"; "/new"]], "data")],
2081    "mount a guest disk, read-only",
2082    "\
2083 This is the same as the C<guestfs_mount> command, but it
2084 mounts the filesystem with the read-only (I<-o ro>) flag.");
2085
2086   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2087    [],
2088    "mount a guest disk with mount options",
2089    "\
2090 This is the same as the C<guestfs_mount> command, but it
2091 allows you to set the mount options as for the
2092 L<mount(8)> I<-o> flag.");
2093
2094   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2095    [],
2096    "mount a guest disk with mount options and vfstype",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set both the mount options and the vfstype
2100 as for the L<mount(8)> I<-o> and I<-t> flags.");
2101
2102   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2103    [],
2104    "debugging and internals",
2105    "\
2106 The C<guestfs_debug> command exposes some internals of
2107 C<guestfsd> (the guestfs daemon) that runs inside the
2108 qemu subprocess.
2109
2110 There is no comprehensive help for this command.  You have
2111 to look at the file C<daemon/debug.c> in the libguestfs source
2112 to find out what you can do.");
2113
2114   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2115    [InitEmpty, Always, TestOutputList (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["lvremove"; "/dev/VG/LV1"];
2122        ["lvs"]], ["/dev/VG/LV2"]);
2123     InitEmpty, Always, TestOutputList (
2124       [["part_disk"; "/dev/sda"; "mbr"];
2125        ["pvcreate"; "/dev/sda1"];
2126        ["vgcreate"; "VG"; "/dev/sda1"];
2127        ["lvcreate"; "LV1"; "VG"; "50"];
2128        ["lvcreate"; "LV2"; "VG"; "50"];
2129        ["lvremove"; "/dev/VG"];
2130        ["lvs"]], []);
2131     InitEmpty, Always, TestOutputList (
2132       [["part_disk"; "/dev/sda"; "mbr"];
2133        ["pvcreate"; "/dev/sda1"];
2134        ["vgcreate"; "VG"; "/dev/sda1"];
2135        ["lvcreate"; "LV1"; "VG"; "50"];
2136        ["lvcreate"; "LV2"; "VG"; "50"];
2137        ["lvremove"; "/dev/VG"];
2138        ["vgs"]], ["VG"])],
2139    "remove an LVM logical volume",
2140    "\
2141 Remove an LVM logical volume C<device>, where C<device> is
2142 the path to the LV, such as C</dev/VG/LV>.
2143
2144 You can also remove all LVs in a volume group by specifying
2145 the VG name, C</dev/VG>.");
2146
2147   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2148    [InitEmpty, Always, TestOutputList (
2149       [["part_disk"; "/dev/sda"; "mbr"];
2150        ["pvcreate"; "/dev/sda1"];
2151        ["vgcreate"; "VG"; "/dev/sda1"];
2152        ["lvcreate"; "LV1"; "VG"; "50"];
2153        ["lvcreate"; "LV2"; "VG"; "50"];
2154        ["vgremove"; "VG"];
2155        ["lvs"]], []);
2156     InitEmpty, Always, TestOutputList (
2157       [["part_disk"; "/dev/sda"; "mbr"];
2158        ["pvcreate"; "/dev/sda1"];
2159        ["vgcreate"; "VG"; "/dev/sda1"];
2160        ["lvcreate"; "LV1"; "VG"; "50"];
2161        ["lvcreate"; "LV2"; "VG"; "50"];
2162        ["vgremove"; "VG"];
2163        ["vgs"]], [])],
2164    "remove an LVM volume group",
2165    "\
2166 Remove an LVM volume group C<vgname>, (for example C<VG>).
2167
2168 This also forcibly removes all logical volumes in the volume
2169 group (if any).");
2170
2171   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2172    [InitEmpty, Always, TestOutputListOfDevices (
2173       [["part_disk"; "/dev/sda"; "mbr"];
2174        ["pvcreate"; "/dev/sda1"];
2175        ["vgcreate"; "VG"; "/dev/sda1"];
2176        ["lvcreate"; "LV1"; "VG"; "50"];
2177        ["lvcreate"; "LV2"; "VG"; "50"];
2178        ["vgremove"; "VG"];
2179        ["pvremove"; "/dev/sda1"];
2180        ["lvs"]], []);
2181     InitEmpty, Always, TestOutputListOfDevices (
2182       [["part_disk"; "/dev/sda"; "mbr"];
2183        ["pvcreate"; "/dev/sda1"];
2184        ["vgcreate"; "VG"; "/dev/sda1"];
2185        ["lvcreate"; "LV1"; "VG"; "50"];
2186        ["lvcreate"; "LV2"; "VG"; "50"];
2187        ["vgremove"; "VG"];
2188        ["pvremove"; "/dev/sda1"];
2189        ["vgs"]], []);
2190     InitEmpty, Always, TestOutputListOfDevices (
2191       [["part_disk"; "/dev/sda"; "mbr"];
2192        ["pvcreate"; "/dev/sda1"];
2193        ["vgcreate"; "VG"; "/dev/sda1"];
2194        ["lvcreate"; "LV1"; "VG"; "50"];
2195        ["lvcreate"; "LV2"; "VG"; "50"];
2196        ["vgremove"; "VG"];
2197        ["pvremove"; "/dev/sda1"];
2198        ["pvs"]], [])],
2199    "remove an LVM physical volume",
2200    "\
2201 This wipes a physical volume C<device> so that LVM will no longer
2202 recognise it.
2203
2204 The implementation uses the C<pvremove> command which refuses to
2205 wipe physical volumes that contain any volume groups, so you have
2206 to remove those first.");
2207
2208   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2209    [InitBasicFS, Always, TestOutput (
2210       [["set_e2label"; "/dev/sda1"; "testlabel"];
2211        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2212    "set the ext2/3/4 filesystem label",
2213    "\
2214 This sets the ext2/3/4 filesystem label of the filesystem on
2215 C<device> to C<label>.  Filesystem labels are limited to
2216 16 characters.
2217
2218 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2219 to return the existing label on a filesystem.");
2220
2221   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2222    [],
2223    "get the ext2/3/4 filesystem label",
2224    "\
2225 This returns the ext2/3/4 filesystem label of the filesystem on
2226 C<device>.");
2227
2228   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2229    (let uuid = uuidgen () in
2230     [InitBasicFS, Always, TestOutput (
2231        [["set_e2uuid"; "/dev/sda1"; uuid];
2232         ["get_e2uuid"; "/dev/sda1"]], uuid);
2233      InitBasicFS, Always, TestOutput (
2234        [["set_e2uuid"; "/dev/sda1"; "clear"];
2235         ["get_e2uuid"; "/dev/sda1"]], "");
2236      (* We can't predict what UUIDs will be, so just check the commands run. *)
2237      InitBasicFS, Always, TestRun (
2238        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2241    "set the ext2/3/4 filesystem UUID",
2242    "\
2243 This sets the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device> to C<uuid>.  The format of the UUID and alternatives
2245 such as C<clear>, C<random> and C<time> are described in the
2246 L<tune2fs(8)> manpage.
2247
2248 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2249 to return the existing UUID of a filesystem.");
2250
2251   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2252    [],
2253    "get the ext2/3/4 filesystem UUID",
2254    "\
2255 This returns the ext2/3/4 filesystem UUID of the filesystem on
2256 C<device>.");
2257
2258   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2259    [InitBasicFS, Always, TestOutputInt (
2260       [["umount"; "/dev/sda1"];
2261        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2262     InitBasicFS, Always, TestOutputInt (
2263       [["umount"; "/dev/sda1"];
2264        ["zero"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2266    "run the filesystem checker",
2267    "\
2268 This runs the filesystem checker (fsck) on C<device> which
2269 should have filesystem type C<fstype>.
2270
2271 The returned integer is the status.  See L<fsck(8)> for the
2272 list of status codes from C<fsck>.
2273
2274 Notes:
2275
2276 =over 4
2277
2278 =item *
2279
2280 Multiple status codes can be summed together.
2281
2282 =item *
2283
2284 A non-zero return code can mean \"success\", for example if
2285 errors have been corrected on the filesystem.
2286
2287 =item *
2288
2289 Checking or repairing NTFS volumes is not supported
2290 (by linux-ntfs).
2291
2292 =back
2293
2294 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2295
2296   ("zero", (RErr, [Device "device"]), 85, [],
2297    [InitBasicFS, Always, TestOutput (
2298       [["umount"; "/dev/sda1"];
2299        ["zero"; "/dev/sda1"];
2300        ["file"; "/dev/sda1"]], "data")],
2301    "write zeroes to the device",
2302    "\
2303 This command writes zeroes over the first few blocks of C<device>.
2304
2305 How many blocks are zeroed isn't specified (but it's I<not> enough
2306 to securely wipe the device).  It should be sufficient to remove
2307 any partition tables, filesystem superblocks and so on.
2308
2309 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2310
2311   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2312    (* Test disabled because grub-install incompatible with virtio-blk driver.
2313     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2314     *)
2315    [InitBasicFS, Disabled, TestOutputTrue (
2316       [["grub_install"; "/"; "/dev/sda1"];
2317        ["is_dir"; "/boot"]])],
2318    "install GRUB",
2319    "\
2320 This command installs GRUB (the Grand Unified Bootloader) on
2321 C<device>, with the root directory being C<root>.");
2322
2323   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2324    [InitBasicFS, Always, TestOutput (
2325       [["write_file"; "/old"; "file content"; "0"];
2326        ["cp"; "/old"; "/new"];
2327        ["cat"; "/new"]], "file content");
2328     InitBasicFS, Always, TestOutputTrue (
2329       [["write_file"; "/old"; "file content"; "0"];
2330        ["cp"; "/old"; "/new"];
2331        ["is_file"; "/old"]]);
2332     InitBasicFS, Always, TestOutput (
2333       [["write_file"; "/old"; "file content"; "0"];
2334        ["mkdir"; "/dir"];
2335        ["cp"; "/old"; "/dir/new"];
2336        ["cat"; "/dir/new"]], "file content")],
2337    "copy a file",
2338    "\
2339 This copies a file from C<src> to C<dest> where C<dest> is
2340 either a destination filename or destination directory.");
2341
2342   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["mkdir"; "/olddir"];
2345        ["mkdir"; "/newdir"];
2346        ["write_file"; "/olddir/file"; "file content"; "0"];
2347        ["cp_a"; "/olddir"; "/newdir"];
2348        ["cat"; "/newdir/olddir/file"]], "file content")],
2349    "copy a file or directory recursively",
2350    "\
2351 This copies a file or directory from C<src> to C<dest>
2352 recursively using the C<cp -a> command.");
2353
2354   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2355    [InitBasicFS, Always, TestOutput (
2356       [["write_file"; "/old"; "file content"; "0"];
2357        ["mv"; "/old"; "/new"];
2358        ["cat"; "/new"]], "file content");
2359     InitBasicFS, Always, TestOutputFalse (
2360       [["write_file"; "/old"; "file content"; "0"];
2361        ["mv"; "/old"; "/new"];
2362        ["is_file"; "/old"]])],
2363    "move a file",
2364    "\
2365 This moves a file from C<src> to C<dest> where C<dest> is
2366 either a destination filename or destination directory.");
2367
2368   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2369    [InitEmpty, Always, TestRun (
2370       [["drop_caches"; "3"]])],
2371    "drop kernel page cache, dentries and inodes",
2372    "\
2373 This instructs the guest kernel to drop its page cache,
2374 and/or dentries and inode caches.  The parameter C<whattodrop>
2375 tells the kernel what precisely to drop, see
2376 L<http://linux-mm.org/Drop_Caches>
2377
2378 Setting C<whattodrop> to 3 should drop everything.
2379
2380 This automatically calls L<sync(2)> before the operation,
2381 so that the maximum guest memory is freed.");
2382
2383   ("dmesg", (RString "kmsgs", []), 91, [],
2384    [InitEmpty, Always, TestRun (
2385       [["dmesg"]])],
2386    "return kernel messages",
2387    "\
2388 This returns the kernel messages (C<dmesg> output) from
2389 the guest kernel.  This is sometimes useful for extended
2390 debugging of problems.
2391
2392 Another way to get the same information is to enable
2393 verbose messages with C<guestfs_set_verbose> or by setting
2394 the environment variable C<LIBGUESTFS_DEBUG=1> before
2395 running the program.");
2396
2397   ("ping_daemon", (RErr, []), 92, [],
2398    [InitEmpty, Always, TestRun (
2399       [["ping_daemon"]])],
2400    "ping the guest daemon",
2401    "\
2402 This is a test probe into the guestfs daemon running inside
2403 the qemu subprocess.  Calling this function checks that the
2404 daemon responds to the ping message, without affecting the daemon
2405 or attached block device(s) in any other way.");
2406
2407   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2408    [InitBasicFS, Always, TestOutputTrue (
2409       [["write_file"; "/file1"; "contents of a file"; "0"];
2410        ["cp"; "/file1"; "/file2"];
2411        ["equal"; "/file1"; "/file2"]]);
2412     InitBasicFS, Always, TestOutputFalse (
2413       [["write_file"; "/file1"; "contents of a file"; "0"];
2414        ["write_file"; "/file2"; "contents of another file"; "0"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestLastFail (
2417       [["equal"; "/file1"; "/file2"]])],
2418    "test if two files have equal contents",
2419    "\
2420 This compares the two files C<file1> and C<file2> and returns
2421 true if their content is exactly equal, or false otherwise.
2422
2423 The external L<cmp(1)> program is used for the comparison.");
2424
2425   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2428     InitISOFS, Always, TestOutputList (
2429       [["strings"; "/empty"]], [])],
2430    "print the printable strings in a file",
2431    "\
2432 This runs the L<strings(1)> command on a file and returns
2433 the list of printable strings found.");
2434
2435   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2436    [InitISOFS, Always, TestOutputList (
2437       [["strings_e"; "b"; "/known-5"]], []);
2438     InitBasicFS, Disabled, TestOutputList (
2439       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2440        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2441    "print the printable strings in a file",
2442    "\
2443 This is like the C<guestfs_strings> command, but allows you to
2444 specify the encoding.
2445
2446 See the L<strings(1)> manpage for the full list of encodings.
2447
2448 Commonly useful encodings are C<l> (lower case L) which will
2449 show strings inside Windows/x86 files.
2450
2451 The returned strings are transcoded to UTF-8.");
2452
2453   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2454    [InitISOFS, Always, TestOutput (
2455       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2456     (* Test for RHBZ#501888c2 regression which caused large hexdump
2457      * commands to segfault.
2458      *)
2459     InitISOFS, Always, TestRun (
2460       [["hexdump"; "/100krandom"]])],
2461    "dump a file in hexadecimal",
2462    "\
2463 This runs C<hexdump -C> on the given C<path>.  The result is
2464 the human-readable, canonical hex dump of the file.");
2465
2466   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2467    [InitNone, Always, TestOutput (
2468       [["part_disk"; "/dev/sda"; "mbr"];
2469        ["mkfs"; "ext3"; "/dev/sda1"];
2470        ["mount_options"; ""; "/dev/sda1"; "/"];
2471        ["write_file"; "/new"; "test file"; "0"];
2472        ["umount"; "/dev/sda1"];
2473        ["zerofree"; "/dev/sda1"];
2474        ["mount_options"; ""; "/dev/sda1"; "/"];
2475        ["cat"; "/new"]], "test file")],
2476    "zero unused inodes and disk blocks on ext2/3 filesystem",
2477    "\
2478 This runs the I<zerofree> program on C<device>.  This program
2479 claims to zero unused inodes and disk blocks on an ext2/3
2480 filesystem, thus making it possible to compress the filesystem
2481 more effectively.
2482
2483 You should B<not> run this program if the filesystem is
2484 mounted.
2485
2486 It is possible that using this program can damage the filesystem
2487 or data on the filesystem.");
2488
2489   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2490    [],
2491    "resize an LVM physical volume",
2492    "\
2493 This resizes (expands or shrinks) an existing LVM physical
2494 volume to match the new size of the underlying device.");
2495
2496   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2497                        Int "cyls"; Int "heads"; Int "sectors";
2498                        String "line"]), 99, [DangerWillRobinson],
2499    [],
2500    "modify a single partition on a block device",
2501    "\
2502 This runs L<sfdisk(8)> option to modify just the single
2503 partition C<n> (note: C<n> counts from 1).
2504
2505 For other parameters, see C<guestfs_sfdisk>.  You should usually
2506 pass C<0> for the cyls/heads/sectors parameters.
2507
2508 See also: C<guestfs_part_add>");
2509
2510   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2511    [],
2512    "display the partition table",
2513    "\
2514 This displays the partition table on C<device>, in the
2515 human-readable output of the L<sfdisk(8)> command.  It is
2516 not intended to be parsed.
2517
2518 See also: C<guestfs_part_list>");
2519
2520   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2521    [],
2522    "display the kernel geometry",
2523    "\
2524 This displays the kernel's idea of the geometry of C<device>.
2525
2526 The result is in human-readable format, and not designed to
2527 be parsed.");
2528
2529   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2530    [],
2531    "display the disk geometry from the partition table",
2532    "\
2533 This displays the disk geometry of C<device> read from the
2534 partition table.  Especially in the case where the underlying
2535 block device has been resized, this can be different from the
2536 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2537
2538 The result is in human-readable format, and not designed to
2539 be parsed.");
2540
2541   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2542    [],
2543    "activate or deactivate all volume groups",
2544    "\
2545 This command activates or (if C<activate> is false) deactivates
2546 all logical volumes in all volume groups.
2547 If activated, then they are made known to the
2548 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2549 then those devices disappear.
2550
2551 This command is the same as running C<vgchange -a y|n>");
2552
2553   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2554    [],
2555    "activate or deactivate some volume groups",
2556    "\
2557 This command activates or (if C<activate> is false) deactivates
2558 all logical volumes in the listed volume groups C<volgroups>.
2559 If activated, then they are made known to the
2560 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2561 then those devices disappear.
2562
2563 This command is the same as running C<vgchange -a y|n volgroups...>
2564
2565 Note that if C<volgroups> is an empty list then B<all> volume groups
2566 are activated or deactivated.");
2567
2568   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2569    [InitNone, Always, TestOutput (
2570       [["part_disk"; "/dev/sda"; "mbr"];
2571        ["pvcreate"; "/dev/sda1"];
2572        ["vgcreate"; "VG"; "/dev/sda1"];
2573        ["lvcreate"; "LV"; "VG"; "10"];
2574        ["mkfs"; "ext2"; "/dev/VG/LV"];
2575        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2576        ["write_file"; "/new"; "test content"; "0"];
2577        ["umount"; "/"];
2578        ["lvresize"; "/dev/VG/LV"; "20"];
2579        ["e2fsck_f"; "/dev/VG/LV"];
2580        ["resize2fs"; "/dev/VG/LV"];
2581        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2582        ["cat"; "/new"]], "test content")],
2583    "resize an LVM logical volume",
2584    "\
2585 This resizes (expands or shrinks) an existing LVM logical
2586 volume to C<mbytes>.  When reducing, data in the reduced part
2587 is lost.");
2588
2589   ("resize2fs", (RErr, [Device "device"]), 106, [],
2590    [], (* lvresize tests this *)
2591    "resize an ext2/ext3 filesystem",
2592    "\
2593 This resizes an ext2 or ext3 filesystem to match the size of
2594 the underlying device.
2595
2596 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2597 on the C<device> before calling this command.  For unknown reasons
2598 C<resize2fs> sometimes gives an error about this and sometimes not.
2599 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2600 calling this function.");
2601
2602   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2603    [InitBasicFS, Always, TestOutputList (
2604       [["find"; "/"]], ["lost+found"]);
2605     InitBasicFS, Always, TestOutputList (
2606       [["touch"; "/a"];
2607        ["mkdir"; "/b"];
2608        ["touch"; "/b/c"];
2609        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2610     InitBasicFS, Always, TestOutputList (
2611       [["mkdir_p"; "/a/b/c"];
2612        ["touch"; "/a/b/c/d"];
2613        ["find"; "/a/b/"]], ["c"; "c/d"])],
2614    "find all files and directories",
2615    "\
2616 This command lists out all files and directories, recursively,
2617 starting at C<directory>.  It is essentially equivalent to
2618 running the shell command C<find directory -print> but some
2619 post-processing happens on the output, described below.
2620
2621 This returns a list of strings I<without any prefix>.  Thus
2622 if the directory structure was:
2623
2624  /tmp/a
2625  /tmp/b
2626  /tmp/c/d
2627
2628 then the returned list from C<guestfs_find> C</tmp> would be
2629 4 elements:
2630
2631  a
2632  b
2633  c
2634  c/d
2635
2636 If C<directory> is not a directory, then this command returns
2637 an error.
2638
2639 The returned list is sorted.
2640
2641 See also C<guestfs_find0>.");
2642
2643   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2644    [], (* lvresize tests this *)
2645    "check an ext2/ext3 filesystem",
2646    "\
2647 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2648 filesystem checker on C<device>, noninteractively (C<-p>),
2649 even if the filesystem appears to be clean (C<-f>).
2650
2651 This command is only needed because of C<guestfs_resize2fs>
2652 (q.v.).  Normally you should use C<guestfs_fsck>.");
2653
2654   ("sleep", (RErr, [Int "secs"]), 109, [],
2655    [InitNone, Always, TestRun (
2656       [["sleep"; "1"]])],
2657    "sleep for some seconds",
2658    "\
2659 Sleep for C<secs> seconds.");
2660
2661   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2662    [InitNone, Always, TestOutputInt (
2663       [["part_disk"; "/dev/sda"; "mbr"];
2664        ["mkfs"; "ntfs"; "/dev/sda1"];
2665        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2666     InitNone, Always, TestOutputInt (
2667       [["part_disk"; "/dev/sda"; "mbr"];
2668        ["mkfs"; "ext2"; "/dev/sda1"];
2669        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2670    "probe NTFS volume",
2671    "\
2672 This command runs the L<ntfs-3g.probe(8)> command which probes
2673 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2674 be mounted read-write, and some cannot be mounted at all).
2675
2676 C<rw> is a boolean flag.  Set it to true if you want to test
2677 if the volume can be mounted read-write.  Set it to false if
2678 you want to test if the volume can be mounted read-only.
2679
2680 The return value is an integer which C<0> if the operation
2681 would succeed, or some non-zero value documented in the
2682 L<ntfs-3g.probe(8)> manual page.");
2683
2684   ("sh", (RString "output", [String "command"]), 111, [],
2685    [], (* XXX needs tests *)
2686    "run a command via the shell",
2687    "\
2688 This call runs a command from the guest filesystem via the
2689 guest's C</bin/sh>.
2690
2691 This is like C<guestfs_command>, but passes the command to:
2692
2693  /bin/sh -c \"command\"
2694
2695 Depending on the guest's shell, this usually results in
2696 wildcards being expanded, shell expressions being interpolated
2697 and so on.
2698
2699 All the provisos about C<guestfs_command> apply to this call.");
2700
2701   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2702    [], (* XXX needs tests *)
2703    "run a command via the shell returning lines",
2704    "\
2705 This is the same as C<guestfs_sh>, but splits the result
2706 into a list of lines.
2707
2708 See also: C<guestfs_command_lines>");
2709
2710   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2711    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2712     * code in stubs.c, since all valid glob patterns must start with "/".
2713     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2714     *)
2715    [InitBasicFS, Always, TestOutputList (
2716       [["mkdir_p"; "/a/b/c"];
2717        ["touch"; "/a/b/c/d"];
2718        ["touch"; "/a/b/c/e"];
2719        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2720     InitBasicFS, Always, TestOutputList (
2721       [["mkdir_p"; "/a/b/c"];
2722        ["touch"; "/a/b/c/d"];
2723        ["touch"; "/a/b/c/e"];
2724        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2725     InitBasicFS, Always, TestOutputList (
2726       [["mkdir_p"; "/a/b/c"];
2727        ["touch"; "/a/b/c/d"];
2728        ["touch"; "/a/b/c/e"];
2729        ["glob_expand"; "/a/*/x/*"]], [])],
2730    "expand a wildcard path",
2731    "\
2732 This command searches for all the pathnames matching
2733 C<pattern> according to the wildcard expansion rules
2734 used by the shell.
2735
2736 If no paths match, then this returns an empty list
2737 (note: not an error).
2738
2739 It is just a wrapper around the C L<glob(3)> function
2740 with flags C<GLOB_MARK|GLOB_BRACE>.
2741 See that manual page for more details.");
2742
2743   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2744    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2745       [["scrub_device"; "/dev/sdc"]])],
2746    "scrub (securely wipe) a device",
2747    "\
2748 This command writes patterns over C<device> to make data retrieval
2749 more difficult.
2750
2751 It is an interface to the L<scrub(1)> program.  See that
2752 manual page for more details.");
2753
2754   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2755    [InitBasicFS, Always, TestRun (
2756       [["write_file"; "/file"; "content"; "0"];
2757        ["scrub_file"; "/file"]])],
2758    "scrub (securely wipe) a file",
2759    "\
2760 This command writes patterns over a file to make data retrieval
2761 more difficult.
2762
2763 The file is I<removed> after scrubbing.
2764
2765 It is an interface to the L<scrub(1)> program.  See that
2766 manual page for more details.");
2767
2768   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2769    [], (* XXX needs testing *)
2770    "scrub (securely wipe) free space",
2771    "\
2772 This command creates the directory C<dir> and then fills it
2773 with files until the filesystem is full, and scrubs the files
2774 as for C<guestfs_scrub_file>, and deletes them.
2775 The intention is to scrub any free space on the partition
2776 containing C<dir>.
2777
2778 It is an interface to the L<scrub(1)> program.  See that
2779 manual page for more details.");
2780
2781   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2782    [InitBasicFS, Always, TestRun (
2783       [["mkdir"; "/tmp"];
2784        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2785    "create a temporary directory",
2786    "\
2787 This command creates a temporary directory.  The
2788 C<template> parameter should be a full pathname for the
2789 temporary directory name with the final six characters being
2790 \"XXXXXX\".
2791
2792 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2793 the second one being suitable for Windows filesystems.
2794
2795 The name of the temporary directory that was created
2796 is returned.
2797
2798 The temporary directory is created with mode 0700
2799 and is owned by root.
2800
2801 The caller is responsible for deleting the temporary
2802 directory and its contents after use.
2803
2804 See also: L<mkdtemp(3)>");
2805
2806   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2807    [InitISOFS, Always, TestOutputInt (
2808       [["wc_l"; "/10klines"]], 10000)],
2809    "count lines in a file",
2810    "\
2811 This command counts the lines in a file, using the
2812 C<wc -l> external command.");
2813
2814   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2815    [InitISOFS, Always, TestOutputInt (
2816       [["wc_w"; "/10klines"]], 10000)],
2817    "count words in a file",
2818    "\
2819 This command counts the words in a file, using the
2820 C<wc -w> external command.");
2821
2822   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2823    [InitISOFS, Always, TestOutputInt (
2824       [["wc_c"; "/100kallspaces"]], 102400)],
2825    "count characters in a file",
2826    "\
2827 This command counts the characters in a file, using the
2828 C<wc -c> external command.");
2829
2830   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2831    [InitISOFS, Always, TestOutputList (
2832       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2833    "return first 10 lines of a file",
2834    "\
2835 This command returns up to the first 10 lines of a file as
2836 a list of strings.");
2837
2838   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2839    [InitISOFS, Always, TestOutputList (
2840       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2841     InitISOFS, Always, TestOutputList (
2842       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2843     InitISOFS, Always, TestOutputList (
2844       [["head_n"; "0"; "/10klines"]], [])],
2845    "return first N lines of a file",
2846    "\
2847 If the parameter C<nrlines> is a positive number, this returns the first
2848 C<nrlines> lines of the file C<path>.
2849
2850 If the parameter C<nrlines> is a negative number, this returns lines
2851 from the file C<path>, excluding the last C<nrlines> lines.
2852
2853 If the parameter C<nrlines> is zero, this returns an empty list.");
2854
2855   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2856    [InitISOFS, Always, TestOutputList (
2857       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2858    "return last 10 lines of a file",
2859    "\
2860 This command returns up to the last 10 lines of a file as
2861 a list of strings.");
2862
2863   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2864    [InitISOFS, Always, TestOutputList (
2865       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2866     InitISOFS, Always, TestOutputList (
2867       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2868     InitISOFS, Always, TestOutputList (
2869       [["tail_n"; "0"; "/10klines"]], [])],
2870    "return last N lines of a file",
2871    "\
2872 If the parameter C<nrlines> is a positive number, this returns the last
2873 C<nrlines> lines of the file C<path>.
2874
2875 If the parameter C<nrlines> is a negative number, this returns lines
2876 from the file C<path>, starting with the C<-nrlines>th line.
2877
2878 If the parameter C<nrlines> is zero, this returns an empty list.");
2879
2880   ("df", (RString "output", []), 125, [],
2881    [], (* XXX Tricky to test because it depends on the exact format
2882         * of the 'df' command and other imponderables.
2883         *)
2884    "report file system disk space usage",
2885    "\
2886 This command runs the C<df> command to report disk space used.
2887
2888 This command is mostly useful for interactive sessions.  It
2889 is I<not> intended that you try to parse the output string.
2890 Use C<statvfs> from programs.");
2891
2892   ("df_h", (RString "output", []), 126, [],
2893    [], (* XXX Tricky to test because it depends on the exact format
2894         * of the 'df' command and other imponderables.
2895         *)
2896    "report file system disk space usage (human readable)",
2897    "\
2898 This command runs the C<df -h> command to report disk space used
2899 in human-readable format.
2900
2901 This command is mostly useful for interactive sessions.  It
2902 is I<not> intended that you try to parse the output string.
2903 Use C<statvfs> from programs.");
2904
2905   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2906    [InitISOFS, Always, TestOutputInt (
2907       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2908    "estimate file space usage",
2909    "\
2910 This command runs the C<du -s> command to estimate file space
2911 usage for C<path>.
2912
2913 C<path> can be a file or a directory.  If C<path> is a directory
2914 then the estimate includes the contents of the directory and all
2915 subdirectories (recursively).
2916
2917 The result is the estimated size in I<kilobytes>
2918 (ie. units of 1024 bytes).");
2919
2920   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2921    [InitISOFS, Always, TestOutputList (
2922       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2923    "list files in an initrd",
2924    "\
2925 This command lists out files contained in an initrd.
2926
2927 The files are listed without any initial C</> character.  The
2928 files are listed in the order they appear (not necessarily
2929 alphabetical).  Directory names are listed as separate items.
2930
2931 Old Linux kernels (2.4 and earlier) used a compressed ext2
2932 filesystem as initrd.  We I<only> support the newer initramfs
2933 format (compressed cpio files).");
2934
2935   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2936    [],
2937    "mount a file using the loop device",
2938    "\
2939 This command lets you mount C<file> (a filesystem image
2940 in a file) on a mount point.  It is entirely equivalent to
2941 the command C<mount -o loop file mountpoint>.");
2942
2943   ("mkswap", (RErr, [Device "device"]), 130, [],
2944    [InitEmpty, Always, TestRun (
2945       [["part_disk"; "/dev/sda"; "mbr"];
2946        ["mkswap"; "/dev/sda1"]])],
2947    "create a swap partition",
2948    "\
2949 Create a swap partition on C<device>.");
2950
2951   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2952    [InitEmpty, Always, TestRun (
2953       [["part_disk"; "/dev/sda"; "mbr"];
2954        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2955    "create a swap partition with a label",
2956    "\
2957 Create a swap partition on C<device> with label C<label>.
2958
2959 Note that you cannot attach a swap label to a block device
2960 (eg. C</dev/sda>), just to a partition.  This appears to be
2961 a limitation of the kernel or swap tools.");
2962
2963   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2964    (let uuid = uuidgen () in
2965     [InitEmpty, Always, TestRun (
2966        [["part_disk"; "/dev/sda"; "mbr"];
2967         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2968    "create a swap partition with an explicit UUID",
2969    "\
2970 Create a swap partition on C<device> with UUID C<uuid>.");
2971
2972   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2973    [InitBasicFS, Always, TestOutputStruct (
2974       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2975        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2976        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2977     InitBasicFS, Always, TestOutputStruct (
2978       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2979        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2980    "make block, character or FIFO devices",
2981    "\
2982 This call creates block or character special devices, or
2983 named pipes (FIFOs).
2984
2985 The C<mode> parameter should be the mode, using the standard
2986 constants.  C<devmajor> and C<devminor> are the
2987 device major and minor numbers, only used when creating block
2988 and character special devices.");
2989
2990   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2991    [InitBasicFS, Always, TestOutputStruct (
2992       [["mkfifo"; "0o777"; "/node"];
2993        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2994    "make FIFO (named pipe)",
2995    "\
2996 This call creates a FIFO (named pipe) called C<path> with
2997 mode C<mode>.  It is just a convenient wrapper around
2998 C<guestfs_mknod>.");
2999
3000   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3001    [InitBasicFS, Always, TestOutputStruct (
3002       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3003        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3004    "make block device node",
3005    "\
3006 This call creates a block device node called C<path> with
3007 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3008 It is just a convenient wrapper around C<guestfs_mknod>.");
3009
3010   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3011    [InitBasicFS, Always, TestOutputStruct (
3012       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3013        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3014    "make char device node",
3015    "\
3016 This call creates a char device node called C<path> with
3017 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3018 It is just a convenient wrapper around C<guestfs_mknod>.");
3019
3020   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3021    [InitEmpty, Always, TestOutputInt (
3022       [["umask"; "0o22"]], 0o22)],
3023    "set file mode creation mask (umask)",
3024    "\
3025 This function sets the mask used for creating new files and
3026 device nodes to C<mask & 0777>.
3027
3028 Typical umask values would be C<022> which creates new files
3029 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3030 C<002> which creates new files with permissions like
3031 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3032
3033 The default umask is C<022>.  This is important because it
3034 means that directories and device nodes will be created with
3035 C<0644> or C<0755> mode even if you specify C<0777>.
3036
3037 See also C<guestfs_get_umask>,
3038 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3039
3040 This call returns the previous umask.");
3041
3042   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3043    [],
3044    "read directories entries",
3045    "\
3046 This returns the list of directory entries in directory C<dir>.
3047
3048 All entries in the directory are returned, including C<.> and
3049 C<..>.  The entries are I<not> sorted, but returned in the same
3050 order as the underlying filesystem.
3051
3052 Also this call returns basic file type information about each
3053 file.  The C<ftyp> field will contain one of the following characters:
3054
3055 =over 4
3056
3057 =item 'b'
3058
3059 Block special
3060
3061 =item 'c'
3062
3063 Char special
3064
3065 =item 'd'
3066
3067 Directory
3068
3069 =item 'f'
3070
3071 FIFO (named pipe)
3072
3073 =item 'l'
3074
3075 Symbolic link
3076
3077 =item 'r'
3078
3079 Regular file
3080
3081 =item 's'
3082
3083 Socket
3084
3085 =item 'u'
3086
3087 Unknown file type
3088
3089 =item '?'
3090
3091 The L<readdir(3)> returned a C<d_type> field with an
3092 unexpected value
3093
3094 =back
3095
3096 This function is primarily intended for use by programs.  To
3097 get a simple list of names, use C<guestfs_ls>.  To get a printable
3098 directory for human consumption, use C<guestfs_ll>.");
3099
3100   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3101    [],
3102    "create partitions on a block device",
3103    "\
3104 This is a simplified interface to the C<guestfs_sfdisk>
3105 command, where partition sizes are specified in megabytes
3106 only (rounded to the nearest cylinder) and you don't need
3107 to specify the cyls, heads and sectors parameters which
3108 were rarely if ever used anyway.
3109
3110 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3111 and C<guestfs_part_disk>");
3112
3113   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3114    [],
3115    "determine file type inside a compressed file",
3116    "\
3117 This command runs C<file> after first decompressing C<path>
3118 using C<method>.
3119
3120 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3121
3122 Since 1.0.63, use C<guestfs_file> instead which can now
3123 process compressed files.");
3124
3125   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3126    [],
3127    "list extended attributes of a file or directory",
3128    "\
3129 This call lists the extended attributes of the file or directory
3130 C<path>.
3131
3132 At the system call level, this is a combination of the
3133 L<listxattr(2)> and L<getxattr(2)> calls.
3134
3135 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3136
3137   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3138    [],
3139    "list extended attributes of a file or directory",
3140    "\
3141 This is the same as C<guestfs_getxattrs>, but if C<path>
3142 is a symbolic link, then it returns the extended attributes
3143 of the link itself.");
3144
3145   ("setxattr", (RErr, [String "xattr";
3146                        String "val"; Int "vallen"; (* will be BufferIn *)
3147                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3148    [],
3149    "set extended attribute of a file or directory",
3150    "\
3151 This call sets the extended attribute named C<xattr>
3152 of the file C<path> to the value C<val> (of length C<vallen>).
3153 The value is arbitrary 8 bit data.
3154
3155 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3156
3157   ("lsetxattr", (RErr, [String "xattr";
3158                         String "val"; Int "vallen"; (* will be BufferIn *)
3159                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3160    [],
3161    "set extended attribute of a file or directory",
3162    "\
3163 This is the same as C<guestfs_setxattr>, but if C<path>
3164 is a symbolic link, then it sets an extended attribute
3165 of the link itself.");
3166
3167   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3168    [],
3169    "remove extended attribute of a file or directory",
3170    "\
3171 This call removes the extended attribute named C<xattr>
3172 of the file C<path>.
3173
3174 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3175
3176   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3177    [],
3178    "remove extended attribute of a file or directory",
3179    "\
3180 This is the same as C<guestfs_removexattr>, but if C<path>
3181 is a symbolic link, then it removes an extended attribute
3182 of the link itself.");
3183
3184   ("mountpoints", (RHashtable "mps", []), 147, [],
3185    [],
3186    "show mountpoints",
3187    "\
3188 This call is similar to C<guestfs_mounts>.  That call returns
3189 a list of devices.  This one returns a hash table (map) of
3190 device name to directory where the device is mounted.");
3191
3192   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3193    (* This is a special case: while you would expect a parameter
3194     * of type "Pathname", that doesn't work, because it implies
3195     * NEED_ROOT in the generated calling code in stubs.c, and
3196     * this function cannot use NEED_ROOT.
3197     *)
3198    [],
3199    "create a mountpoint",
3200    "\
3201 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3202 specialized calls that can be used to create extra mountpoints
3203 before mounting the first filesystem.
3204
3205 These calls are I<only> necessary in some very limited circumstances,
3206 mainly the case where you want to mount a mix of unrelated and/or
3207 read-only filesystems together.
3208
3209 For example, live CDs often contain a \"Russian doll\" nest of
3210 filesystems, an ISO outer layer, with a squashfs image inside, with
3211 an ext2/3 image inside that.  You can unpack this as follows
3212 in guestfish:
3213
3214  add-ro Fedora-11-i686-Live.iso
3215  run
3216  mkmountpoint /cd
3217  mkmountpoint /squash
3218  mkmountpoint /ext3
3219  mount /dev/sda /cd
3220  mount-loop /cd/LiveOS/squashfs.img /squash
3221  mount-loop /squash/LiveOS/ext3fs.img /ext3
3222
3223 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3224
3225   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3226    [],
3227    "remove a mountpoint",
3228    "\
3229 This calls removes a mountpoint that was previously created
3230 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3231 for full details.");
3232
3233   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3234    [InitISOFS, Always, TestOutputBuffer (
3235       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3236    "read a file",
3237    "\
3238 This calls returns the contents of the file C<path> as a
3239 buffer.
3240
3241 Unlike C<guestfs_cat>, this function can correctly
3242 handle files that contain embedded ASCII NUL characters.
3243 However unlike C<guestfs_download>, this function is limited
3244 in the total size of file that can be handled.");
3245
3246   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3247    [InitISOFS, Always, TestOutputList (
3248       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3249     InitISOFS, Always, TestOutputList (
3250       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3251    "return lines matching a pattern",
3252    "\
3253 This calls the external C<grep> program and returns the
3254 matching lines.");
3255
3256   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3257    [InitISOFS, Always, TestOutputList (
3258       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3259    "return lines matching a pattern",
3260    "\
3261 This calls the external C<egrep> program and returns the
3262 matching lines.");
3263
3264   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3265    [InitISOFS, Always, TestOutputList (
3266       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3267    "return lines matching a pattern",
3268    "\
3269 This calls the external C<fgrep> program and returns the
3270 matching lines.");
3271
3272   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3273    [InitISOFS, Always, TestOutputList (
3274       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3275    "return lines matching a pattern",
3276    "\
3277 This calls the external C<grep -i> program and returns the
3278 matching lines.");
3279
3280   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3281    [InitISOFS, Always, TestOutputList (
3282       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3283    "return lines matching a pattern",
3284    "\
3285 This calls the external C<egrep -i> program and returns the
3286 matching lines.");
3287
3288   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3289    [InitISOFS, Always, TestOutputList (
3290       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3291    "return lines matching a pattern",
3292    "\
3293 This calls the external C<fgrep -i> program and returns the
3294 matching lines.");
3295
3296   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3297    [InitISOFS, Always, TestOutputList (
3298       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3299    "return lines matching a pattern",
3300    "\
3301 This calls the external C<zgrep> program and returns the
3302 matching lines.");
3303
3304   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3305    [InitISOFS, Always, TestOutputList (
3306       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3307    "return lines matching a pattern",
3308    "\
3309 This calls the external C<zegrep> program and returns the
3310 matching lines.");
3311
3312   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3313    [InitISOFS, Always, TestOutputList (
3314       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3315    "return lines matching a pattern",
3316    "\
3317 This calls the external C<zfgrep> program and returns the
3318 matching lines.");
3319
3320   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3321    [InitISOFS, Always, TestOutputList (
3322       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3323    "return lines matching a pattern",
3324    "\
3325 This calls the external C<zgrep -i> program and returns the
3326 matching lines.");
3327
3328   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3329    [InitISOFS, Always, TestOutputList (
3330       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3331    "return lines matching a pattern",
3332    "\
3333 This calls the external C<zegrep -i> program and returns the
3334 matching lines.");
3335
3336   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3337    [InitISOFS, Always, TestOutputList (
3338       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3339    "return lines matching a pattern",
3340    "\
3341 This calls the external C<zfgrep -i> program and returns the
3342 matching lines.");
3343
3344   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3345    [InitISOFS, Always, TestOutput (
3346       [["realpath"; "/../directory"]], "/directory")],
3347    "canonicalized absolute pathname",
3348    "\
3349 Return the canonicalized absolute pathname of C<path>.  The
3350 returned path has no C<.>, C<..> or symbolic link path elements.");
3351
3352   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3353    [InitBasicFS, Always, TestOutputStruct (
3354       [["touch"; "/a"];
3355        ["ln"; "/a"; "/b"];
3356        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3357    "create a hard link",
3358    "\
3359 This command creates a hard link using the C<ln> command.");
3360
3361   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3362    [InitBasicFS, Always, TestOutputStruct (
3363       [["touch"; "/a"];
3364        ["touch"; "/b"];
3365        ["ln_f"; "/a"; "/b"];
3366        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3367    "create a hard link",
3368    "\
3369 This command creates a hard link using the C<ln -f> command.
3370 The C<-f> option removes the link (C<linkname>) if it exists already.");
3371
3372   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3373    [InitBasicFS, Always, TestOutputStruct (
3374       [["touch"; "/a"];
3375        ["ln_s"; "a"; "/b"];
3376        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3377    "create a symbolic link",
3378    "\
3379 This command creates a symbolic link using the C<ln -s> command.");
3380
3381   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3382    [InitBasicFS, Always, TestOutput (
3383       [["mkdir_p"; "/a/b"];
3384        ["touch"; "/a/b/c"];
3385        ["ln_sf"; "../d"; "/a/b/c"];
3386        ["readlink"; "/a/b/c"]], "../d")],
3387    "create a symbolic link",
3388    "\
3389 This command creates a symbolic link using the C<ln -sf> command,
3390 The C<-f> option removes the link (C<linkname>) if it exists already.");
3391
3392   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3393    [] (* XXX tested above *),
3394    "read the target of a symbolic link",
3395    "\
3396 This command reads the target of a symbolic link.");
3397
3398   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3399    [InitBasicFS, Always, TestOutputStruct (
3400       [["fallocate"; "/a"; "1000000"];
3401        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3402    "preallocate a file in the guest filesystem",
3403    "\
3404 This command preallocates a file (containing zero bytes) named
3405 C<path> of size C<len> bytes.  If the file exists already, it
3406 is overwritten.
3407
3408 Do not confuse this with the guestfish-specific
3409 C<alloc> command which allocates a file in the host and
3410 attaches it as a device.");
3411
3412   ("swapon_device", (RErr, [Device "device"]), 170, [],
3413    [InitPartition, Always, TestRun (
3414       [["mkswap"; "/dev/sda1"];
3415        ["swapon_device"; "/dev/sda1"];
3416        ["swapoff_device"; "/dev/sda1"]])],
3417    "enable swap on device",
3418    "\
3419 This command enables the libguestfs appliance to use the
3420 swap device or partition named C<device>.  The increased
3421 memory is made available for all commands, for example
3422 those run using C<guestfs_command> or C<guestfs_sh>.
3423
3424 Note that you should not swap to existing guest swap
3425 partitions unless you know what you are doing.  They may
3426 contain hibernation information, or other information that
3427 the guest doesn't want you to trash.  You also risk leaking
3428 information about the host to the guest this way.  Instead,
3429 attach a new host device to the guest and swap on that.");
3430
3431   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3432    [], (* XXX tested by swapon_device *)
3433    "disable swap on device",
3434    "\
3435 This command disables the libguestfs appliance swap
3436 device or partition named C<device>.
3437 See C<guestfs_swapon_device>.");
3438
3439   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3440    [InitBasicFS, Always, TestRun (
3441       [["fallocate"; "/swap"; "8388608"];
3442        ["mkswap_file"; "/swap"];
3443        ["swapon_file"; "/swap"];
3444        ["swapoff_file"; "/swap"]])],
3445    "enable swap on file",
3446    "\
3447 This command enables swap to a file.
3448 See C<guestfs_swapon_device> for other notes.");
3449
3450   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3451    [], (* XXX tested by swapon_file *)
3452    "disable swap on file",
3453    "\
3454 This command disables the libguestfs appliance swap on file.");
3455
3456   ("swapon_label", (RErr, [String "label"]), 174, [],
3457    [InitEmpty, Always, TestRun (
3458       [["part_disk"; "/dev/sdb"; "mbr"];
3459        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3460        ["swapon_label"; "swapit"];
3461        ["swapoff_label"; "swapit"];
3462        ["zero"; "/dev/sdb"];
3463        ["blockdev_rereadpt"; "/dev/sdb"]])],
3464    "enable swap on labeled swap partition",
3465    "\
3466 This command enables swap to a labeled swap partition.
3467 See C<guestfs_swapon_device> for other notes.");
3468
3469   ("swapoff_label", (RErr, [String "label"]), 175, [],
3470    [], (* XXX tested by swapon_label *)
3471    "disable swap on labeled swap partition",
3472    "\
3473 This command disables the libguestfs appliance swap on
3474 labeled swap partition.");
3475
3476   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3477    (let uuid = uuidgen () in
3478     [InitEmpty, Always, TestRun (
3479        [["mkswap_U"; uuid; "/dev/sdb"];
3480         ["swapon_uuid"; uuid];
3481         ["swapoff_uuid"; uuid]])]),
3482    "enable swap on swap partition by UUID",
3483    "\
3484 This command enables swap to a swap partition with the given UUID.
3485 See C<guestfs_swapon_device> for other notes.");
3486
3487   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3488    [], (* XXX tested by swapon_uuid *)
3489    "disable swap on swap partition by UUID",
3490    "\
3491 This command disables the libguestfs appliance swap partition
3492 with the given UUID.");
3493
3494   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3495    [InitBasicFS, Always, TestRun (
3496       [["fallocate"; "/swap"; "8388608"];
3497        ["mkswap_file"; "/swap"]])],
3498    "create a swap file",
3499    "\
3500 Create a swap file.
3501
3502 This command just writes a swap file signature to an existing
3503 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3504
3505   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3506    [InitISOFS, Always, TestRun (
3507       [["inotify_init"; "0"]])],
3508    "create an inotify handle",
3509    "\
3510 This command creates a new inotify handle.
3511 The inotify subsystem can be used to notify events which happen to
3512 objects in the guest filesystem.
3513
3514 C<maxevents> is the maximum number of events which will be
3515 queued up between calls to C<guestfs_inotify_read> or
3516 C<guestfs_inotify_files>.
3517 If this is passed as C<0>, then the kernel (or previously set)
3518 default is used.  For Linux 2.6.29 the default was 16384 events.
3519 Beyond this limit, the kernel throws away events, but records
3520 the fact that it threw them away by setting a flag
3521 C<IN_Q_OVERFLOW> in the returned structure list (see
3522 C<guestfs_inotify_read>).
3523
3524 Before any events are generated, you have to add some
3525 watches to the internal watch list.  See:
3526 C<guestfs_inotify_add_watch>,
3527 C<guestfs_inotify_rm_watch> and
3528 C<guestfs_inotify_watch_all>.
3529
3530 Queued up events should be read periodically by calling
3531 C<guestfs_inotify_read>
3532 (or C<guestfs_inotify_files> which is just a helpful
3533 wrapper around C<guestfs_inotify_read>).  If you don't
3534 read the events out often enough then you risk the internal
3535 queue overflowing.
3536
3537 The handle should be closed after use by calling
3538 C<guestfs_inotify_close>.  This also removes any
3539 watches automatically.
3540
3541 See also L<inotify(7)> for an overview of the inotify interface
3542 as exposed by the Linux kernel, which is roughly what we expose
3543 via libguestfs.  Note that there is one global inotify handle
3544 per libguestfs instance.");
3545
3546   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3547    [InitBasicFS, Always, TestOutputList (
3548       [["inotify_init"; "0"];
3549        ["inotify_add_watch"; "/"; "1073741823"];
3550        ["touch"; "/a"];
3551        ["touch"; "/b"];
3552        ["inotify_files"]], ["a"; "b"])],
3553    "add an inotify watch",
3554    "\
3555 Watch C<path> for the events listed in C<mask>.
3556
3557 Note that if C<path> is a directory then events within that
3558 directory are watched, but this does I<not> happen recursively
3559 (in subdirectories).
3560
3561 Note for non-C or non-Linux callers: the inotify events are
3562 defined by the Linux kernel ABI and are listed in
3563 C</usr/include/sys/inotify.h>.");
3564
3565   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3566    [],
3567    "remove an inotify watch",
3568    "\
3569 Remove a previously defined inotify watch.
3570 See C<guestfs_inotify_add_watch>.");
3571
3572   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3573    [],
3574    "return list of inotify events",
3575    "\
3576 Return the complete queue of events that have happened
3577 since the previous read call.
3578
3579 If no events have happened, this returns an empty list.
3580
3581 I<Note>: In order to make sure that all events have been
3582 read, you must call this function repeatedly until it
3583 returns an empty list.  The reason is that the call will
3584 read events up to the maximum appliance-to-host message
3585 size and leave remaining events in the queue.");
3586
3587   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3588    [],
3589    "return list of watched files that had events",
3590    "\
3591 This function is a helpful wrapper around C<guestfs_inotify_read>
3592 which just returns a list of pathnames of objects that were
3593 touched.  The returned pathnames are sorted and deduplicated.");
3594
3595   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3596    [],
3597    "close the inotify handle",
3598    "\
3599 This closes the inotify handle which was previously
3600 opened by inotify_init.  It removes all watches, throws
3601 away any pending events, and deallocates all resources.");
3602
3603   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3604    [],
3605    "set SELinux security context",
3606    "\
3607 This sets the SELinux security context of the daemon
3608 to the string C<context>.
3609
3610 See the documentation about SELINUX in L<guestfs(3)>.");
3611
3612   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3613    [],
3614    "get SELinux security context",
3615    "\
3616 This gets the SELinux security context of the daemon.
3617
3618 See the documentation about SELINUX in L<guestfs(3)>,
3619 and C<guestfs_setcon>");
3620
3621   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3622    [InitEmpty, Always, TestOutput (
3623       [["part_disk"; "/dev/sda"; "mbr"];
3624        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3625        ["mount_options"; ""; "/dev/sda1"; "/"];
3626        ["write_file"; "/new"; "new file contents"; "0"];
3627        ["cat"; "/new"]], "new file contents")],
3628    "make a filesystem with block size",
3629    "\
3630 This call is similar to C<guestfs_mkfs>, but it allows you to
3631 control the block size of the resulting filesystem.  Supported
3632 block sizes depend on the filesystem type, but typically they
3633 are C<1024>, C<2048> or C<4096> only.");
3634
3635   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3636    [InitEmpty, Always, TestOutput (
3637       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3638        ["mke2journal"; "4096"; "/dev/sda1"];
3639        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3640        ["mount_options"; ""; "/dev/sda2"; "/"];
3641        ["write_file"; "/new"; "new file contents"; "0"];
3642        ["cat"; "/new"]], "new file contents")],
3643    "make ext2/3/4 external journal",
3644    "\
3645 This creates an ext2 external journal on C<device>.  It is equivalent
3646 to the command:
3647
3648  mke2fs -O journal_dev -b blocksize device");
3649
3650   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3651    [InitEmpty, Always, TestOutput (
3652       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3653        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3654        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3655        ["mount_options"; ""; "/dev/sda2"; "/"];
3656        ["write_file"; "/new"; "new file contents"; "0"];
3657        ["cat"; "/new"]], "new file contents")],
3658    "make ext2/3/4 external journal with label",
3659    "\
3660 This creates an ext2 external journal on C<device> with label C<label>.");
3661
3662   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3663    (let uuid = uuidgen () in
3664     [InitEmpty, Always, TestOutput (
3665        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3666         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3667         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3668         ["mount_options"; ""; "/dev/sda2"; "/"];
3669         ["write_file"; "/new"; "new file contents"; "0"];
3670         ["cat"; "/new"]], "new file contents")]),
3671    "make ext2/3/4 external journal with UUID",
3672    "\
3673 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3674
3675   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3676    [],
3677    "make ext2/3/4 filesystem with external journal",
3678    "\
3679 This creates an ext2/3/4 filesystem on C<device> with
3680 an external journal on C<journal>.  It is equivalent
3681 to the command:
3682
3683  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3684
3685 See also C<guestfs_mke2journal>.");
3686
3687   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3688    [],
3689    "make ext2/3/4 filesystem with external journal",
3690    "\
3691 This creates an ext2/3/4 filesystem on C<device> with
3692 an external journal on the journal labeled C<label>.
3693
3694 See also C<guestfs_mke2journal_L>.");
3695
3696   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3697    [],
3698    "make ext2/3/4 filesystem with external journal",
3699    "\
3700 This creates an ext2/3/4 filesystem on C<device> with
3701 an external journal on the journal with UUID C<uuid>.
3702
3703 See also C<guestfs_mke2journal_U>.");
3704
3705   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3706    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3707    "load a kernel module",
3708    "\
3709 This loads a kernel module in the appliance.
3710
3711 The kernel module must have been whitelisted when libguestfs
3712 was built (see C<appliance/kmod.whitelist.in> in the source).");
3713
3714   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3715    [InitNone, Always, TestOutput (
3716       [["echo_daemon"; "This is a test"]], "This is a test"
3717     )],
3718    "echo arguments back to the client",
3719    "\
3720 This command concatenate the list of C<words> passed with single spaces between
3721 them and returns the resulting string.
3722
3723 You can use this command to test the connection through to the daemon.
3724
3725 See also C<guestfs_ping_daemon>.");
3726
3727   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3728    [], (* There is a regression test for this. *)
3729    "find all files and directories, returning NUL-separated list",
3730    "\
3731 This command lists out all files and directories, recursively,
3732 starting at C<directory>, placing the resulting list in the
3733 external file called C<files>.
3734
3735 This command works the same way as C<guestfs_find> with the
3736 following exceptions:
3737
3738 =over 4
3739
3740 =item *
3741
3742 The resulting list is written to an external file.
3743
3744 =item *
3745
3746 Items (filenames) in the result are separated
3747 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3748
3749 =item *
3750
3751 This command is not limited in the number of names that it
3752 can return.
3753
3754 =item *
3755
3756 The result list is not sorted.
3757
3758 =back");
3759
3760   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3761    [InitISOFS, Always, TestOutput (
3762       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3763     InitISOFS, Always, TestOutput (
3764       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3765     InitISOFS, Always, TestOutput (
3766       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3767     InitISOFS, Always, TestLastFail (
3768       [["case_sensitive_path"; "/Known-1/"]]);
3769     InitBasicFS, Always, TestOutput (
3770       [["mkdir"; "/a"];
3771        ["mkdir"; "/a/bbb"];
3772        ["touch"; "/a/bbb/c"];
3773        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3774     InitBasicFS, Always, TestOutput (
3775       [["mkdir"; "/a"];
3776        ["mkdir"; "/a/bbb"];
3777        ["touch"; "/a/bbb/c"];
3778        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3779     InitBasicFS, Always, TestLastFail (
3780       [["mkdir"; "/a"];
3781        ["mkdir"; "/a/bbb"];
3782        ["touch"; "/a/bbb/c"];
3783        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3784    "return true path on case-insensitive filesystem",
3785    "\
3786 This can be used to resolve case insensitive paths on
3787 a filesystem which is case sensitive.  The use case is
3788 to resolve paths which you have read from Windows configuration
3789 files or the Windows Registry, to the true path.
3790
3791 The command handles a peculiarity of the Linux ntfs-3g
3792 filesystem driver (and probably others), which is that although
3793 the underlying filesystem is case-insensitive, the driver
3794 exports the filesystem to Linux as case-sensitive.
3795
3796 One consequence of this is that special directories such
3797 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3798 (or other things) depending on the precise details of how
3799 they were created.  In Windows itself this would not be
3800 a problem.
3801
3802 Bug or feature?  You decide:
3803 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3804
3805 This function resolves the true case of each element in the
3806 path and returns the case-sensitive path.
3807
3808 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3809 might return C<\"/WINDOWS/system32\"> (the exact return value
3810 would depend on details of how the directories were originally
3811 created under Windows).
3812
3813 I<Note>:
3814 This function does not handle drive names, backslashes etc.
3815
3816 See also C<guestfs_realpath>.");
3817
3818   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3819    [InitBasicFS, Always, TestOutput (
3820       [["vfs_type"; "/dev/sda1"]], "ext2")],
3821    "get the Linux VFS type corresponding to a mounted device",
3822    "\
3823 This command gets the block device type corresponding to
3824 a mounted device called C<device>.
3825
3826 Usually the result is the name of the Linux VFS module that
3827 is used to mount this device (probably determined automatically
3828 if you used the C<guestfs_mount> call).");
3829
3830   ("truncate", (RErr, [Pathname "path"]), 199, [],
3831    [InitBasicFS, Always, TestOutputStruct (
3832       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3833        ["truncate"; "/test"];
3834        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3835    "truncate a file to zero size",
3836    "\
3837 This command truncates C<path> to a zero-length file.  The
3838 file must exist already.");
3839
3840   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3841    [InitBasicFS, Always, TestOutputStruct (
3842       [["touch"; "/test"];
3843        ["truncate_size"; "/test"; "1000"];
3844        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3845    "truncate a file to a particular size",
3846    "\
3847 This command truncates C<path> to size C<size> bytes.  The file
3848 must exist already.  If the file is smaller than C<size> then
3849 the file is extended to the required size with null bytes.");
3850
3851   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3852    [InitBasicFS, Always, TestOutputStruct (
3853       [["touch"; "/test"];
3854        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3855        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3856    "set timestamp of a file with nanosecond precision",
3857    "\
3858 This command sets the timestamps of a file with nanosecond
3859 precision.
3860
3861 C<atsecs, atnsecs> are the last access time (atime) in secs and
3862 nanoseconds from the epoch.
3863
3864 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3865 secs and nanoseconds from the epoch.
3866
3867 If the C<*nsecs> field contains the special value C<-1> then
3868 the corresponding timestamp is set to the current time.  (The
3869 C<*secs> field is ignored in this case).
3870
3871 If the C<*nsecs> field contains the special value C<-2> then
3872 the corresponding timestamp is left unchanged.  (The
3873 C<*secs> field is ignored in this case).");
3874
3875   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3876    [InitBasicFS, Always, TestOutputStruct (
3877       [["mkdir_mode"; "/test"; "0o111"];
3878        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3879    "create a directory with a particular mode",
3880    "\
3881 This command creates a directory, setting the initial permissions
3882 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3883
3884   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3885    [], (* XXX *)
3886    "change file owner and group",
3887    "\
3888 Change the file owner to C<owner> and group to C<group>.
3889 This is like C<guestfs_chown> but if C<path> is a symlink then
3890 the link itself is changed, not the target.
3891
3892 Only numeric uid and gid are supported.  If you want to use
3893 names, you will need to locate and parse the password file
3894 yourself (Augeas support makes this relatively easy).");
3895
3896   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3897    [], (* XXX *)
3898    "lstat on multiple files",
3899    "\
3900 This call allows you to perform the C<guestfs_lstat> operation
3901 on multiple files, where all files are in the directory C<path>.
3902 C<names> is the list of files from this directory.
3903
3904 On return you get a list of stat structs, with a one-to-one
3905 correspondence to the C<names> list.  If any name did not exist
3906 or could not be lstat'd, then the C<ino> field of that structure
3907 is set to C<-1>.
3908
3909 This call is intended for programs that want to efficiently
3910 list a directory contents without making many round-trips.
3911 See also C<guestfs_lxattrlist> for a similarly efficient call
3912 for getting extended attributes.  Very long directory listings
3913 might cause the protocol message size to be exceeded, causing
3914 this call to fail.  The caller must split up such requests
3915 into smaller groups of names.");
3916
3917   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3918    [], (* XXX *)
3919    "lgetxattr on multiple files",
3920    "\
3921 This call allows you to get the extended attributes
3922 of multiple files, where all files are in the directory C<path>.
3923 C<names> is the list of files from this directory.
3924
3925 On return you get a flat list of xattr structs which must be
3926 interpreted sequentially.  The first xattr struct always has a zero-length
3927 C<attrname>.  C<attrval> in this struct is zero-length
3928 to indicate there was an error doing C<lgetxattr> for this
3929 file, I<or> is a C string which is a decimal number
3930 (the number of following attributes for this file, which could
3931 be C<\"0\">).  Then after the first xattr struct are the
3932 zero or more attributes for the first named file.
3933 This repeats for the second and subsequent files.
3934
3935 This call is intended for programs that want to efficiently
3936 list a directory contents without making many round-trips.
3937 See also C<guestfs_lstatlist> for a similarly efficient call
3938 for getting standard stats.  Very long directory listings
3939 might cause the protocol message size to be exceeded, causing
3940 this call to fail.  The caller must split up such requests
3941 into smaller groups of names.");
3942
3943   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3944    [], (* XXX *)
3945    "readlink on multiple files",
3946    "\
3947 This call allows you to do a C<readlink> operation
3948 on multiple files, where all files are in the directory C<path>.
3949 C<names> is the list of files from this directory.
3950
3951 On return you get a list of strings, with a one-to-one
3952 correspondence to the C<names> list.  Each string is the
3953 value of the symbol link.
3954
3955 If the C<readlink(2)> operation fails on any name, then
3956 the corresponding result string is the empty string C<\"\">.
3957 However the whole operation is completed even if there
3958 were C<readlink(2)> errors, and so you can call this
3959 function with names where you don't know if they are
3960 symbolic links already (albeit slightly less efficient).
3961
3962 This call is intended for programs that want to efficiently
3963 list a directory contents without making many round-trips.
3964 Very long directory listings might cause the protocol
3965 message size to be exceeded, causing
3966 this call to fail.  The caller must split up such requests
3967 into smaller groups of names.");
3968
3969   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3970    [InitISOFS, Always, TestOutputBuffer (
3971       [["pread"; "/known-4"; "1"; "3"]], "\n");
3972     InitISOFS, Always, TestOutputBuffer (
3973       [["pread"; "/empty"; "0"; "100"]], "")],
3974    "read part of a file",
3975    "\
3976 This command lets you read part of a file.  It reads C<count>
3977 bytes of the file, starting at C<offset>, from file C<path>.
3978
3979 This may read fewer bytes than requested.  For further details
3980 see the L<pread(2)> system call.");
3981
3982   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3983    [InitEmpty, Always, TestRun (
3984       [["part_init"; "/dev/sda"; "gpt"]])],
3985    "create an empty partition table",
3986    "\
3987 This creates an empty partition table on C<device> of one of the
3988 partition types listed below.  Usually C<parttype> should be
3989 either C<msdos> or C<gpt> (for large disks).
3990
3991 Initially there are no partitions.  Following this, you should
3992 call C<guestfs_part_add> for each partition required.
3993
3994 Possible values for C<parttype> are:
3995
3996 =over 4
3997
3998 =item B<efi> | B<gpt>
3999
4000 Intel EFI / GPT partition table.
4001
4002 This is recommended for >= 2 TB partitions that will be accessed
4003 from Linux and Intel-based Mac OS X.  It also has limited backwards
4004 compatibility with the C<mbr> format.
4005
4006 =item B<mbr> | B<msdos>
4007
4008 The standard PC \"Master Boot Record\" (MBR) format used
4009 by MS-DOS and Windows.  This partition type will B<only> work
4010 for device sizes up to 2 TB.  For large disks we recommend
4011 using C<gpt>.
4012
4013 =back
4014
4015 Other partition table types that may work but are not
4016 supported include:
4017
4018 =over 4
4019
4020 =item B<aix>
4021
4022 AIX disk labels.
4023
4024 =item B<amiga> | B<rdb>
4025
4026 Amiga \"Rigid Disk Block\" format.
4027
4028 =item B<bsd>
4029
4030 BSD disk labels.
4031
4032 =item B<dasd>
4033
4034 DASD, used on IBM mainframes.
4035
4036 =item B<dvh>
4037
4038 MIPS/SGI volumes.
4039
4040 =item B<mac>
4041
4042 Old Mac partition format.  Modern Macs use C<gpt>.
4043
4044 =item B<pc98>
4045
4046 NEC PC-98 format, common in Japan apparently.
4047
4048 =item B<sun>
4049
4050 Sun disk labels.
4051
4052 =back");
4053
4054   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4055    [InitEmpty, Always, TestRun (
4056       [["part_init"; "/dev/sda"; "mbr"];
4057        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4058     InitEmpty, Always, TestRun (
4059       [["part_init"; "/dev/sda"; "gpt"];
4060        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4061        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4062     InitEmpty, Always, TestRun (
4063       [["part_init"; "/dev/sda"; "mbr"];
4064        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4065        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4066        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4067        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4068    "add a partition to the device",
4069    "\
4070 This command adds a partition to C<device>.  If there is no partition
4071 table on the device, call C<guestfs_part_init> first.
4072
4073 The C<prlogex> parameter is the type of partition.  Normally you
4074 should pass C<p> or C<primary> here, but MBR partition tables also
4075 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4076 types.
4077
4078 C<startsect> and C<endsect> are the start and end of the partition
4079 in I<sectors>.  C<endsect> may be negative, which means it counts
4080 backwards from the end of the disk (C<-1> is the last sector).
4081
4082 Creating a partition which covers the whole disk is not so easy.
4083 Use C<guestfs_part_disk> to do that.");
4084
4085   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4086    [InitEmpty, Always, TestRun (
4087       [["part_disk"; "/dev/sda"; "mbr"]]);
4088     InitEmpty, Always, TestRun (
4089       [["part_disk"; "/dev/sda"; "gpt"]])],
4090    "partition whole disk with a single primary partition",
4091    "\
4092 This command is simply a combination of C<guestfs_part_init>
4093 followed by C<guestfs_part_add> to create a single primary partition
4094 covering the whole disk.
4095
4096 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4097 but other possible values are described in C<guestfs_part_init>.");
4098
4099   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4100    [InitEmpty, Always, TestRun (
4101       [["part_disk"; "/dev/sda"; "mbr"];
4102        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4103    "make a partition bootable",
4104    "\
4105 This sets the bootable flag on partition numbered C<partnum> on
4106 device C<device>.  Note that partitions are numbered from 1.
4107
4108 The bootable flag is used by some operating systems (notably
4109 Windows) to determine which partition to boot from.  It is by
4110 no means universally recognized.");
4111
4112   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4113    [InitEmpty, Always, TestRun (
4114       [["part_disk"; "/dev/sda"; "gpt"];
4115        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4116    "set partition name",
4117    "\
4118 This sets the partition name on partition numbered C<partnum> on
4119 device C<device>.  Note that partitions are numbered from 1.
4120
4121 The partition name can only be set on certain types of partition
4122 table.  This works on C<gpt> but not on C<mbr> partitions.");
4123
4124   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4125    [], (* XXX Add a regression test for this. *)
4126    "list partitions on a device",
4127    "\
4128 This command parses the partition table on C<device> and
4129 returns the list of partitions found.
4130
4131 The fields in the returned structure are:
4132
4133 =over 4
4134
4135 =item B<part_num>
4136
4137 Partition number, counting from 1.
4138
4139 =item B<part_start>
4140
4141 Start of the partition I<in bytes>.  To get sectors you have to
4142 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4143
4144 =item B<part_end>
4145
4146 End of the partition in bytes.
4147
4148 =item B<part_size>
4149
4150 Size of the partition in bytes.
4151
4152 =back");
4153
4154   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4155    [InitEmpty, Always, TestOutput (
4156       [["part_disk"; "/dev/sda"; "gpt"];
4157        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4158    "get the partition table type",
4159    "\
4160 This command examines the partition table on C<device> and
4161 returns the partition table type (format) being used.
4162
4163 Common return values include: C<msdos> (a DOS/Windows style MBR
4164 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4165 values are possible, although unusual.  See C<guestfs_part_init>
4166 for a full list.");
4167
4168   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4169    [InitBasicFS, Always, TestOutputBuffer (
4170       [["fill"; "0x63"; "10"; "/test"];
4171        ["read_file"; "/test"]], "cccccccccc")],
4172    "fill a file with octets",
4173    "\
4174 This command creates a new file called C<path>.  The initial
4175 content of the file is C<len> octets of C<c>, where C<c>
4176 must be a number in the range C<[0..255]>.
4177
4178 To fill a file with zero bytes (sparsely), it is
4179 much more efficient to use C<guestfs_truncate_size>.");
4180
4181   ("available", (RErr, [StringList "groups"]), 216, [],
4182    [InitNone, Always, TestRun [["available"; ""]]],
4183    "test availability of some parts of the API",
4184    "\
4185 This command is used to check the availability of some
4186 groups of functionality in the appliance, which not all builds of
4187 the libguestfs appliance will be able to provide.
4188
4189 The libguestfs groups, and the functions that those
4190 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4191
4192 The argument C<groups> is a list of group names, eg:
4193 C<[\"inotify\", \"augeas\"]> would check for the availability of
4194 the Linux inotify functions and Augeas (configuration file
4195 editing) functions.
4196
4197 The command returns no error if I<all> requested groups are available.
4198
4199 It fails with an error if one or more of the requested
4200 groups is unavailable in the appliance.
4201
4202 If an unknown group name is included in the
4203 list of groups then an error is always returned.
4204
4205 I<Notes:>
4206
4207 =over 4
4208
4209 =item *
4210
4211 You must call C<guestfs_launch> before calling this function.
4212
4213 The reason is because we don't know what groups are
4214 supported by the appliance/daemon until it is running and can
4215 be queried.
4216
4217 =item *
4218
4219 If a group of functions is available, this does not necessarily
4220 mean that they will work.  You still have to check for errors
4221 when calling individual API functions even if they are
4222 available.
4223
4224 =item *
4225
4226 It is usually the job of distro packagers to build
4227 complete functionality into the libguestfs appliance.
4228 Upstream libguestfs, if built from source with all
4229 requirements satisfied, will support everything.
4230
4231 =item *
4232
4233 This call was added in version C<1.0.80>.  In previous
4234 versions of libguestfs all you could do would be to speculatively
4235 execute a command to find out if the daemon implemented it.
4236 See also C<guestfs_version>.
4237
4238 =back");
4239
4240   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4241    [InitBasicFS, Always, TestOutputBuffer (
4242       [["write_file"; "/src"; "hello, world"; "0"];
4243        ["dd"; "/src"; "/dest"];
4244        ["read_file"; "/dest"]], "hello, world")],
4245    "copy from source to destination using dd",
4246    "\
4247 This command copies from one source device or file C<src>
4248 to another destination device or file C<dest>.  Normally you
4249 would use this to copy to or from a device or partition, for
4250 example to duplicate a filesystem.
4251
4252 If the destination is a device, it must be as large or larger
4253 than the source file or device, otherwise the copy will fail.
4254 This command cannot do partial copies (see C<guestfs_copy_size>).");
4255
4256   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4257    [InitBasicFS, Always, TestOutputInt (
4258       [["write_file"; "/file"; "hello, world"; "0"];
4259        ["filesize"; "/file"]], 12)],
4260    "return the size of the file in bytes",
4261    "\
4262 This command returns the size of C<file> in bytes.
4263
4264 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4265 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4266 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4267
4268   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4269    [InitBasicFSonLVM, Always, TestOutputList (
4270       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4271        ["lvs"]], ["/dev/VG/LV2"])],
4272    "rename an LVM logical volume",
4273    "\
4274 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4275
4276   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4277    [InitBasicFSonLVM, Always, TestOutputList (
4278       [["umount"; "/"];
4279        ["vg_activate"; "false"; "VG"];
4280        ["vgrename"; "VG"; "VG2"];
4281        ["vg_activate"; "true"; "VG2"];
4282        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4283        ["vgs"]], ["VG2"])],
4284    "rename an LVM volume group",
4285    "\
4286 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4287
4288   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4289    [InitISOFS, Always, TestOutputBuffer (
4290       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4291    "list the contents of a single file in an initrd",
4292    "\
4293 This command unpacks the file C<filename> from the initrd file
4294 called C<initrdpath>.  The filename must be given I<without> the
4295 initial C</> character.
4296
4297 For example, in guestfish you could use the following command
4298 to examine the boot script (usually called C</init>)
4299 contained in a Linux initrd or initramfs image:
4300
4301  initrd-cat /boot/initrd-<version>.img init
4302
4303 See also C<guestfs_initrd_list>.");
4304
4305   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4306    [],
4307    "get the UUID of a physical volume",
4308    "\
4309 This command returns the UUID of the LVM PV C<device>.");
4310
4311   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4312    [],
4313    "get the UUID of a volume group",
4314    "\
4315 This command returns the UUID of the LVM VG named C<vgname>.");
4316
4317   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4318    [],
4319    "get the UUID of a logical volume",
4320    "\
4321 This command returns the UUID of the LVM LV C<device>.");
4322
4323   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4324    [],
4325    "get the PV UUIDs containing the volume group",
4326    "\
4327 Given a VG called C<vgname>, this returns the UUIDs of all
4328 the physical volumes that this volume group resides on.
4329
4330 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4331 calls to associate physical volumes and volume groups.
4332
4333 See also C<guestfs_vglvuuids>.");
4334
4335   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4336    [],
4337    "get the LV UUIDs of all LVs in the volume group",
4338    "\
4339 Given a VG called C<vgname>, this returns the UUIDs of all
4340 the logical volumes created in this volume group.
4341
4342 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4343 calls to associate logical volumes and volume groups.
4344
4345 See also C<guestfs_vgpvuuids>.");
4346
4347   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4348    [InitBasicFS, Always, TestOutputBuffer (
4349       [["write_file"; "/src"; "hello, world"; "0"];
4350        ["copy_size"; "/src"; "/dest"; "5"];
4351        ["read_file"; "/dest"]], "hello")],
4352    "copy size bytes from source to destination using dd",
4353    "\
4354 This command copies exactly C<size> bytes from one source device
4355 or file C<src> to another destination device or file C<dest>.
4356
4357 Note this will fail if the source is too short or if the destination
4358 is not large enough.");
4359
4360   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4361    [InitBasicFSonLVM, Always, TestRun (
4362       [["zero_device"; "/dev/VG/LV"]])],
4363    "write zeroes to an entire device",
4364    "\
4365 This command writes zeroes over the entire C<device>.  Compare
4366 with C<guestfs_zero> which just zeroes the first few blocks of
4367 a device.");
4368
4369   ("txz_in", (RErr, [FileIn "tarball"; String "directory"]), 229, [],
4370    [InitBasicFS, Always, TestOutput (
4371       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4372        ["cat"; "/hello"]], "hello\n")],
4373    "unpack compressed tarball to directory",
4374    "\
4375 This command uploads and unpacks local file C<tarball> (an
4376 I<xz compressed> tar file) into C<directory>.");
4377
4378   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [],
4379    [],
4380    "pack directory into compressed tarball",
4381    "\
4382 This command packs the contents of C<directory> and downloads
4383 it to local file C<tarball> (as an xz compressed tar archive).");
4384
4385   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4386    [],
4387    "resize an NTFS filesystem",
4388    "\
4389 This command resizes an NTFS filesystem, expanding or
4390 shrinking it to the size of the underlying device.
4391 See also L<ntfsresize(8)>.");
4392
4393   ("vgscan", (RErr, []), 232, [],
4394    [InitEmpty, Always, TestRun (
4395       [["vgscan"]])],
4396    "rescan for LVM physical volumes, volume groups and logical volumes",
4397    "\
4398 This rescans all block devices and rebuilds the list of LVM
4399 physical volumes, volume groups and logical volumes.");
4400
4401   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4402    [InitEmpty, Always, TestRun (
4403       [["part_init"; "/dev/sda"; "mbr"];
4404        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4405        ["part_del"; "/dev/sda"; "1"]])],
4406    "delete a partition",
4407    "\
4408 This command deletes the partition numbered C<partnum> on C<device>.
4409
4410 Note that in the case of MBR partitioning, deleting an
4411 extended partition also deletes any logical partitions
4412 it contains.");
4413
4414   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4415    [InitEmpty, Always, TestOutputTrue (
4416       [["part_init"; "/dev/sda"; "mbr"];
4417        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4418        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4419        ["part_get_bootable"; "/dev/sda"; "1"]])],
4420    "return true if a partition is bootable",
4421    "\
4422 This command returns true if the partition C<partnum> on
4423 C<device> has the bootable flag set.
4424
4425 See also C<guestfs_part_set_bootable>.");
4426
4427   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4428    [InitEmpty, Always, TestOutputInt (
4429       [["part_init"; "/dev/sda"; "mbr"];
4430        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4431        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4432        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4433    "get the MBR type byte (ID byte) from a partition",
4434    "\
4435 Returns the MBR type byte (also known as the ID byte) from
4436 the numbered partition C<partnum>.
4437
4438 Note that only MBR (old DOS-style) partitions have type bytes.
4439 You will get undefined results for other partition table
4440 types (see C<guestfs_part_get_parttype>).");
4441
4442   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4443    [], (* tested by part_get_mbr_id *)
4444    "set the MBR type byte (ID byte) of a partition",
4445    "\
4446 Sets the MBR type byte (also known as the ID byte) of
4447 the numbered partition C<partnum> to C<idbyte>.  Note
4448 that the type bytes quoted in most documentation are
4449 in fact hexadecimal numbers, but usually documented
4450 without any leading \"0x\" which might be confusing.
4451
4452 Note that only MBR (old DOS-style) partitions have type bytes.
4453 You will get undefined results for other partition table
4454 types (see C<guestfs_part_get_parttype>).");
4455
4456   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4457    [InitISOFS, Always, TestOutput (
4458       [["checksum_device"; "md5"; "/dev/sdd"]],
4459       (Digest.to_hex (Digest.file "images/test.iso")))],
4460    "compute MD5, SHAx or CRC checksum of the contents of a device",
4461    "\
4462 This call computes the MD5, SHAx or CRC checksum of the
4463 contents of the device named C<device>.  For the types of
4464 checksums supported see the C<guestfs_checksum> command.");
4465
4466   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4467    [InitNone, Always, TestRun (
4468       [["part_disk"; "/dev/sda"; "mbr"];
4469        ["pvcreate"; "/dev/sda1"];
4470        ["vgcreate"; "VG"; "/dev/sda1"];
4471        ["lvcreate"; "LV"; "VG"; "10"];
4472        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4473    "expand an LV to fill free space",
4474    "\
4475 This expands an existing logical volume C<lv> so that it fills
4476 C<pc>% of the remaining free space in the volume group.  Commonly
4477 you would call this with pc = 100 which expands the logical volume
4478 as much as possible, using all remaining free space in the volume
4479 group.");
4480
4481   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4482    [], (* XXX Augeas code needs tests. *)
4483    "clear Augeas path",
4484    "\
4485 Set the value associated with C<path> to C<NULL>.  This
4486 is the same as the L<augtool(1)> C<clear> command.");
4487
4488   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4489    [InitEmpty, Always, TestOutputInt (
4490       [["get_umask"]], 0o22)],
4491    "get the current umask",
4492    "\
4493 Return the current umask.  By default the umask is C<022>
4494 unless it has been set by calling C<guestfs_umask>.");
4495
4496 ]
4497
4498 let all_functions = non_daemon_functions @ daemon_functions
4499
4500 (* In some places we want the functions to be displayed sorted
4501  * alphabetically, so this is useful:
4502  *)
4503 let all_functions_sorted =
4504   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4505                compare n1 n2) all_functions
4506
4507 (* Field types for structures. *)
4508 type field =
4509   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4510   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4511   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4512   | FUInt32
4513   | FInt32
4514   | FUInt64
4515   | FInt64
4516   | FBytes                      (* Any int measure that counts bytes. *)
4517   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4518   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4519
4520 (* Because we generate extra parsing code for LVM command line tools,
4521  * we have to pull out the LVM columns separately here.
4522  *)
4523 let lvm_pv_cols = [
4524   "pv_name", FString;
4525   "pv_uuid", FUUID;
4526   "pv_fmt", FString;
4527   "pv_size", FBytes;
4528   "dev_size", FBytes;
4529   "pv_free", FBytes;
4530   "pv_used", FBytes;
4531   "pv_attr", FString (* XXX *);
4532   "pv_pe_count", FInt64;
4533   "pv_pe_alloc_count", FInt64;
4534   "pv_tags", FString;
4535   "pe_start", FBytes;
4536   "pv_mda_count", FInt64;
4537   "pv_mda_free", FBytes;
4538   (* Not in Fedora 10:
4539      "pv_mda_size", FBytes;
4540   *)
4541 ]
4542 let lvm_vg_cols = [
4543   "vg_name", FString;
4544   "vg_uuid", FUUID;
4545   "vg_fmt", FString;
4546   "vg_attr", FString (* XXX *);
4547   "vg_size", FBytes;
4548   "vg_free", FBytes;
4549   "vg_sysid", FString;
4550   "vg_extent_size", FBytes;
4551   "vg_extent_count", FInt64;
4552   "vg_free_count", FInt64;
4553   "max_lv", FInt64;
4554   "max_pv", FInt64;
4555   "pv_count", FInt64;
4556   "lv_count", FInt64;
4557   "snap_count", FInt64;
4558   "vg_seqno", FInt64;
4559   "vg_tags", FString;
4560   "vg_mda_count", FInt64;
4561   "vg_mda_free", FBytes;
4562   (* Not in Fedora 10:
4563      "vg_mda_size", FBytes;
4564   *)
4565 ]
4566 let lvm_lv_cols = [
4567   "lv_name", FString;
4568   "lv_uuid", FUUID;
4569   "lv_attr", FString (* XXX *);
4570   "lv_major", FInt64;
4571   "lv_minor", FInt64;
4572   "lv_kernel_major", FInt64;
4573   "lv_kernel_minor", FInt64;
4574   "lv_size", FBytes;
4575   "seg_count", FInt64;
4576   "origin", FString;
4577   "snap_percent", FOptPercent;
4578   "copy_percent", FOptPercent;
4579   "move_pv", FString;
4580   "lv_tags", FString;
4581   "mirror_log", FString;
4582   "modules", FString;
4583 ]
4584
4585 (* Names and fields in all structures (in RStruct and RStructList)
4586  * that we support.
4587  *)
4588 let structs = [
4589   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4590    * not use this struct in any new code.
4591    *)
4592   "int_bool", [
4593     "i", FInt32;                (* for historical compatibility *)
4594     "b", FInt32;                (* for historical compatibility *)
4595   ];
4596
4597   (* LVM PVs, VGs, LVs. *)
4598   "lvm_pv", lvm_pv_cols;
4599   "lvm_vg", lvm_vg_cols;
4600   "lvm_lv", lvm_lv_cols;
4601
4602   (* Column names and types from stat structures.
4603    * NB. Can't use things like 'st_atime' because glibc header files
4604    * define some of these as macros.  Ugh.
4605    *)
4606   "stat", [
4607     "dev", FInt64;
4608     "ino", FInt64;
4609     "mode", FInt64;
4610     "nlink", FInt64;
4611     "uid", FInt64;
4612     "gid", FInt64;
4613     "rdev", FInt64;
4614     "size", FInt64;
4615     "blksize", FInt64;
4616     "blocks", FInt64;
4617     "atime", FInt64;
4618     "mtime", FInt64;
4619     "ctime", FInt64;
4620   ];
4621   "statvfs", [
4622     "bsize", FInt64;
4623     "frsize", FInt64;
4624     "blocks", FInt64;
4625     "bfree", FInt64;
4626     "bavail", FInt64;
4627     "files", FInt64;
4628     "ffree", FInt64;
4629     "favail", FInt64;
4630     "fsid", FInt64;
4631     "flag", FInt64;
4632     "namemax", FInt64;
4633   ];
4634
4635   (* Column names in dirent structure. *)
4636   "dirent", [
4637     "ino", FInt64;
4638     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4639     "ftyp", FChar;
4640     "name", FString;
4641   ];
4642
4643   (* Version numbers. *)
4644   "version", [
4645     "major", FInt64;
4646     "minor", FInt64;
4647     "release", FInt64;
4648     "extra", FString;
4649   ];
4650
4651   (* Extended attribute. *)
4652   "xattr", [
4653     "attrname", FString;
4654     "attrval", FBuffer;
4655   ];
4656
4657   (* Inotify events. *)
4658   "inotify_event", [
4659     "in_wd", FInt64;
4660     "in_mask", FUInt32;
4661     "in_cookie", FUInt32;
4662     "in_name", FString;
4663   ];
4664
4665   (* Partition table entry. *)
4666   "partition", [
4667     "part_num", FInt32;
4668     "part_start", FBytes;
4669     "part_end", FBytes;
4670     "part_size", FBytes;
4671   ];
4672 ] (* end of structs *)
4673
4674 (* Ugh, Java has to be different ..
4675  * These names are also used by the Haskell bindings.
4676  *)
4677 let java_structs = [
4678   "int_bool", "IntBool";
4679   "lvm_pv", "PV";
4680   "lvm_vg", "VG";
4681   "lvm_lv", "LV";
4682   "stat", "Stat";
4683   "statvfs", "StatVFS";
4684   "dirent", "Dirent";
4685   "version", "Version";
4686   "xattr", "XAttr";
4687   "inotify_event", "INotifyEvent";
4688   "partition", "Partition";
4689 ]
4690
4691 (* What structs are actually returned. *)
4692 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4693
4694 (* Returns a list of RStruct/RStructList structs that are returned
4695  * by any function.  Each element of returned list is a pair:
4696  *
4697  * (structname, RStructOnly)
4698  *    == there exists function which returns RStruct (_, structname)
4699  * (structname, RStructListOnly)
4700  *    == there exists function which returns RStructList (_, structname)
4701  * (structname, RStructAndList)
4702  *    == there are functions returning both RStruct (_, structname)
4703  *                                      and RStructList (_, structname)
4704  *)
4705 let rstructs_used_by functions =
4706   (* ||| is a "logical OR" for rstructs_used_t *)
4707   let (|||) a b =
4708     match a, b with
4709     | RStructAndList, _
4710     | _, RStructAndList -> RStructAndList
4711     | RStructOnly, RStructListOnly
4712     | RStructListOnly, RStructOnly -> RStructAndList
4713     | RStructOnly, RStructOnly -> RStructOnly
4714     | RStructListOnly, RStructListOnly -> RStructListOnly
4715   in
4716
4717   let h = Hashtbl.create 13 in
4718
4719   (* if elem->oldv exists, update entry using ||| operator,
4720    * else just add elem->newv to the hash
4721    *)
4722   let update elem newv =
4723     try  let oldv = Hashtbl.find h elem in
4724          Hashtbl.replace h elem (newv ||| oldv)
4725     with Not_found -> Hashtbl.add h elem newv
4726   in
4727
4728   List.iter (
4729     fun (_, style, _, _, _, _, _) ->
4730       match fst style with
4731       | RStruct (_, structname) -> update structname RStructOnly
4732       | RStructList (_, structname) -> update structname RStructListOnly
4733       | _ -> ()
4734   ) functions;
4735
4736   (* return key->values as a list of (key,value) *)
4737   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4738
4739 (* Used for testing language bindings. *)
4740 type callt =
4741   | CallString of string
4742   | CallOptString of string option
4743   | CallStringList of string list
4744   | CallInt of int
4745   | CallInt64 of int64
4746   | CallBool of bool
4747
4748 (* Used to memoize the result of pod2text. *)
4749 let pod2text_memo_filename = "src/.pod2text.data"
4750 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4751   try
4752     let chan = open_in pod2text_memo_filename in
4753     let v = input_value chan in
4754     close_in chan;
4755     v
4756   with
4757     _ -> Hashtbl.create 13
4758 let pod2text_memo_updated () =
4759   let chan = open_out pod2text_memo_filename in
4760   output_value chan pod2text_memo;
4761   close_out chan
4762
4763 (* Useful functions.
4764  * Note we don't want to use any external OCaml libraries which
4765  * makes this a bit harder than it should be.
4766  *)
4767 module StringMap = Map.Make (String)
4768
4769 let failwithf fs = ksprintf failwith fs
4770
4771 let unique = let i = ref 0 in fun () -> incr i; !i
4772
4773 let replace_char s c1 c2 =
4774   let s2 = String.copy s in
4775   let r = ref false in
4776   for i = 0 to String.length s2 - 1 do
4777     if String.unsafe_get s2 i = c1 then (
4778       String.unsafe_set s2 i c2;
4779       r := true
4780     )
4781   done;
4782   if not !r then s else s2
4783
4784 let isspace c =
4785   c = ' '
4786   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4787
4788 let triml ?(test = isspace) str =
4789   let i = ref 0 in
4790   let n = ref (String.length str) in
4791   while !n > 0 && test str.[!i]; do
4792     decr n;
4793     incr i
4794   done;
4795   if !i = 0 then str
4796   else String.sub str !i !n
4797
4798 let trimr ?(test = isspace) str =
4799   let n = ref (String.length str) in
4800   while !n > 0 && test str.[!n-1]; do
4801     decr n
4802   done;
4803   if !n = String.length str then str
4804   else String.sub str 0 !n
4805
4806 let trim ?(test = isspace) str =
4807   trimr ~test (triml ~test str)
4808
4809 let rec find s sub =
4810   let len = String.length s in
4811   let sublen = String.length sub in
4812   let rec loop i =
4813     if i <= len-sublen then (
4814       let rec loop2 j =
4815         if j < sublen then (
4816           if s.[i+j] = sub.[j] then loop2 (j+1)
4817           else -1
4818         ) else
4819           i (* found *)
4820       in
4821       let r = loop2 0 in
4822       if r = -1 then loop (i+1) else r
4823     ) else
4824       -1 (* not found *)
4825   in
4826   loop 0
4827
4828 let rec replace_str s s1 s2 =
4829   let len = String.length s in
4830   let sublen = String.length s1 in
4831   let i = find s s1 in
4832   if i = -1 then s
4833   else (
4834     let s' = String.sub s 0 i in
4835     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4836     s' ^ s2 ^ replace_str s'' s1 s2
4837   )
4838
4839 let rec string_split sep str =
4840   let len = String.length str in
4841   let seplen = String.length sep in
4842   let i = find str sep in
4843   if i = -1 then [str]
4844   else (
4845     let s' = String.sub str 0 i in
4846     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4847     s' :: string_split sep s''
4848   )
4849
4850 let files_equal n1 n2 =
4851   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4852   match Sys.command cmd with
4853   | 0 -> true
4854   | 1 -> false
4855   | i -> failwithf "%s: failed with error code %d" cmd i
4856
4857 let rec filter_map f = function
4858   | [] -> []
4859   | x :: xs ->
4860       match f x with
4861       | Some y -> y :: filter_map f xs
4862       | None -> filter_map f xs
4863
4864 let rec find_map f = function
4865   | [] -> raise Not_found
4866   | x :: xs ->
4867       match f x with
4868       | Some y -> y
4869       | None -> find_map f xs
4870
4871 let iteri f xs =
4872   let rec loop i = function
4873     | [] -> ()
4874     | x :: xs -> f i x; loop (i+1) xs
4875   in
4876   loop 0 xs
4877
4878 let mapi f xs =
4879   let rec loop i = function
4880     | [] -> []
4881     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4882   in
4883   loop 0 xs
4884
4885 let count_chars c str =
4886   let count = ref 0 in
4887   for i = 0 to String.length str - 1 do
4888     if c = String.unsafe_get str i then incr count
4889   done;
4890   !count
4891
4892 let name_of_argt = function
4893   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4894   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4895   | FileIn n | FileOut n -> n
4896
4897 let java_name_of_struct typ =
4898   try List.assoc typ java_structs
4899   with Not_found ->
4900     failwithf
4901       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4902
4903 let cols_of_struct typ =
4904   try List.assoc typ structs
4905   with Not_found ->
4906     failwithf "cols_of_struct: unknown struct %s" typ
4907
4908 let seq_of_test = function
4909   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4910   | TestOutputListOfDevices (s, _)
4911   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4912   | TestOutputTrue s | TestOutputFalse s
4913   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4914   | TestOutputStruct (s, _)
4915   | TestLastFail s -> s
4916
4917 (* Handling for function flags. *)
4918 let protocol_limit_warning =
4919   "Because of the message protocol, there is a transfer limit
4920 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4921
4922 let danger_will_robinson =
4923   "B<This command is dangerous.  Without careful use you
4924 can easily destroy all your data>."
4925
4926 let deprecation_notice flags =
4927   try
4928     let alt =
4929       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4930     let txt =
4931       sprintf "This function is deprecated.
4932 In new code, use the C<%s> call instead.
4933
4934 Deprecated functions will not be removed from the API, but the
4935 fact that they are deprecated indicates that there are problems
4936 with correct use of these functions." alt in
4937     Some txt
4938   with
4939     Not_found -> None
4940
4941 (* Create list of optional groups. *)
4942 let optgroups =
4943   let h = Hashtbl.create 13 in
4944   List.iter (
4945     fun (name, _, _, flags, _, _, _) ->
4946       List.iter (
4947         function
4948         | Optional group ->
4949             let names = try Hashtbl.find h group with Not_found -> [] in
4950             Hashtbl.replace h group (name :: names)
4951         | _ -> ()
4952       ) flags
4953   ) daemon_functions;
4954   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4955   let groups =
4956     List.map (
4957       fun group -> group, List.sort compare (Hashtbl.find h group)
4958     ) groups in
4959   List.sort (fun x y -> compare (fst x) (fst y)) groups
4960
4961 (* Check function names etc. for consistency. *)
4962 let check_functions () =
4963   let contains_uppercase str =
4964     let len = String.length str in
4965     let rec loop i =
4966       if i >= len then false
4967       else (
4968         let c = str.[i] in
4969         if c >= 'A' && c <= 'Z' then true
4970         else loop (i+1)
4971       )
4972     in
4973     loop 0
4974   in
4975
4976   (* Check function names. *)
4977   List.iter (
4978     fun (name, _, _, _, _, _, _) ->
4979       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4980         failwithf "function name %s does not need 'guestfs' prefix" name;
4981       if name = "" then
4982         failwithf "function name is empty";
4983       if name.[0] < 'a' || name.[0] > 'z' then
4984         failwithf "function name %s must start with lowercase a-z" name;
4985       if String.contains name '-' then
4986         failwithf "function name %s should not contain '-', use '_' instead."
4987           name
4988   ) all_functions;
4989
4990   (* Check function parameter/return names. *)
4991   List.iter (
4992     fun (name, style, _, _, _, _, _) ->
4993       let check_arg_ret_name n =
4994         if contains_uppercase n then
4995           failwithf "%s param/ret %s should not contain uppercase chars"
4996             name n;
4997         if String.contains n '-' || String.contains n '_' then
4998           failwithf "%s param/ret %s should not contain '-' or '_'"
4999             name n;
5000         if n = "value" then
5001           failwithf "%s has a param/ret called 'value', which causes conflicts in the OCaml bindings, use something like 'val' or a more descriptive name" name;
5002         if n = "int" || n = "char" || n = "short" || n = "long" then
5003           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5004         if n = "i" || n = "n" then
5005           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5006         if n = "argv" || n = "args" then
5007           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5008
5009         (* List Haskell, OCaml and C keywords here.
5010          * http://www.haskell.org/haskellwiki/Keywords
5011          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5012          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5013          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5014          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5015          * Omitting _-containing words, since they're handled above.
5016          * Omitting the OCaml reserved word, "val", is ok,
5017          * and saves us from renaming several parameters.
5018          *)
5019         let reserved = [
5020           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5021           "char"; "class"; "const"; "constraint"; "continue"; "data";
5022           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5023           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5024           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5025           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5026           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5027           "interface";
5028           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5029           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5030           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5031           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5032           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5033           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5034           "volatile"; "when"; "where"; "while";
5035           ] in
5036         if List.mem n reserved then
5037           failwithf "%s has param/ret using reserved word %s" name n;
5038       in
5039
5040       (match fst style with
5041        | RErr -> ()
5042        | RInt n | RInt64 n | RBool n
5043        | RConstString n | RConstOptString n | RString n
5044        | RStringList n | RStruct (n, _) | RStructList (n, _)
5045        | RHashtable n | RBufferOut n ->
5046            check_arg_ret_name n
5047       );
5048       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5049   ) all_functions;
5050
5051   (* Check short descriptions. *)
5052   List.iter (
5053     fun (name, _, _, _, _, shortdesc, _) ->
5054       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5055         failwithf "short description of %s should begin with lowercase." name;
5056       let c = shortdesc.[String.length shortdesc-1] in
5057       if c = '\n' || c = '.' then
5058         failwithf "short description of %s should not end with . or \\n." name
5059   ) all_functions;
5060
5061   (* Check long dscriptions. *)
5062   List.iter (
5063     fun (name, _, _, _, _, _, longdesc) ->
5064       if longdesc.[String.length longdesc-1] = '\n' then
5065         failwithf "long description of %s should not end with \\n." name
5066   ) all_functions;
5067
5068   (* Check proc_nrs. *)
5069   List.iter (
5070     fun (name, _, proc_nr, _, _, _, _) ->
5071       if proc_nr <= 0 then
5072         failwithf "daemon function %s should have proc_nr > 0" name
5073   ) daemon_functions;
5074
5075   List.iter (
5076     fun (name, _, proc_nr, _, _, _, _) ->
5077       if proc_nr <> -1 then
5078         failwithf "non-daemon function %s should have proc_nr -1" name
5079   ) non_daemon_functions;
5080
5081   let proc_nrs =
5082     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5083       daemon_functions in
5084   let proc_nrs =
5085     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5086   let rec loop = function
5087     | [] -> ()
5088     | [_] -> ()
5089     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5090         loop rest
5091     | (name1,nr1) :: (name2,nr2) :: _ ->
5092         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5093           name1 name2 nr1 nr2
5094   in
5095   loop proc_nrs;
5096
5097   (* Check tests. *)
5098   List.iter (
5099     function
5100       (* Ignore functions that have no tests.  We generate a
5101        * warning when the user does 'make check' instead.
5102        *)
5103     | name, _, _, _, [], _, _ -> ()
5104     | name, _, _, _, tests, _, _ ->
5105         let funcs =
5106           List.map (
5107             fun (_, _, test) ->
5108               match seq_of_test test with
5109               | [] ->
5110                   failwithf "%s has a test containing an empty sequence" name
5111               | cmds -> List.map List.hd cmds
5112           ) tests in
5113         let funcs = List.flatten funcs in
5114
5115         let tested = List.mem name funcs in
5116
5117         if not tested then
5118           failwithf "function %s has tests but does not test itself" name
5119   ) all_functions
5120
5121 (* 'pr' prints to the current output file. *)
5122 let chan = ref Pervasives.stdout
5123 let lines = ref 0
5124 let pr fs =
5125   ksprintf
5126     (fun str ->
5127        let i = count_chars '\n' str in
5128        lines := !lines + i;
5129        output_string !chan str
5130     ) fs
5131
5132 let copyright_years =
5133   let this_year = 1900 + (localtime (time ())).tm_year in
5134   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5135
5136 (* Generate a header block in a number of standard styles. *)
5137 type comment_style =
5138     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5139 type license = GPLv2plus | LGPLv2plus
5140
5141 let generate_header ?(extra_inputs = []) comment license =
5142   let inputs = "src/generator.ml" :: extra_inputs in
5143   let c = match comment with
5144     | CStyle ->         pr "/* "; " *"
5145     | CPlusPlusStyle -> pr "// "; "//"
5146     | HashStyle ->      pr "# ";  "#"
5147     | OCamlStyle ->     pr "(* "; " *"
5148     | HaskellStyle ->   pr "{- "; "  " in
5149   pr "libguestfs generated file\n";
5150   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5151   List.iter (pr "%s   %s\n" c) inputs;
5152   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5153   pr "%s\n" c;
5154   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5155   pr "%s\n" c;
5156   (match license with
5157    | GPLv2plus ->
5158        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5159        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5160        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5161        pr "%s (at your option) any later version.\n" c;
5162        pr "%s\n" c;
5163        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5164        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5165        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5166        pr "%s GNU General Public License for more details.\n" c;
5167        pr "%s\n" c;
5168        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5169        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5170        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5171
5172    | LGPLv2plus ->
5173        pr "%s This library is free software; you can redistribute it and/or\n" c;
5174        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5175        pr "%s License as published by the Free Software Foundation; either\n" c;
5176        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5177        pr "%s\n" c;
5178        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5179        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5180        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5181        pr "%s Lesser General Public License for more details.\n" c;
5182        pr "%s\n" c;
5183        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5184        pr "%s License along with this library; if not, write to the Free Software\n" c;
5185        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5186   );
5187   (match comment with
5188    | CStyle -> pr " */\n"
5189    | CPlusPlusStyle
5190    | HashStyle -> ()
5191    | OCamlStyle -> pr " *)\n"
5192    | HaskellStyle -> pr "-}\n"
5193   );
5194   pr "\n"
5195
5196 (* Start of main code generation functions below this line. *)
5197
5198 (* Generate the pod documentation for the C API. *)
5199 let rec generate_actions_pod () =
5200   List.iter (
5201     fun (shortname, style, _, flags, _, _, longdesc) ->
5202       if not (List.mem NotInDocs flags) then (
5203         let name = "guestfs_" ^ shortname in
5204         pr "=head2 %s\n\n" name;
5205         pr " ";
5206         generate_prototype ~extern:false ~handle:"handle" name style;
5207         pr "\n\n";
5208         pr "%s\n\n" longdesc;
5209         (match fst style with
5210          | RErr ->
5211              pr "This function returns 0 on success or -1 on error.\n\n"
5212          | RInt _ ->
5213              pr "On error this function returns -1.\n\n"
5214          | RInt64 _ ->
5215              pr "On error this function returns -1.\n\n"
5216          | RBool _ ->
5217              pr "This function returns a C truth value on success or -1 on error.\n\n"
5218          | RConstString _ ->
5219              pr "This function returns a string, or NULL on error.
5220 The string is owned by the guest handle and must I<not> be freed.\n\n"
5221          | RConstOptString _ ->
5222              pr "This function returns a string which may be NULL.
5223 There is way to return an error from this function.
5224 The string is owned by the guest handle and must I<not> be freed.\n\n"
5225          | RString _ ->
5226              pr "This function returns a string, or NULL on error.
5227 I<The caller must free the returned string after use>.\n\n"
5228          | RStringList _ ->
5229              pr "This function returns a NULL-terminated array of strings
5230 (like L<environ(3)>), or NULL if there was an error.
5231 I<The caller must free the strings and the array after use>.\n\n"
5232          | RStruct (_, typ) ->
5233              pr "This function returns a C<struct guestfs_%s *>,
5234 or NULL if there was an error.
5235 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5236          | RStructList (_, typ) ->
5237              pr "This function returns a C<struct guestfs_%s_list *>
5238 (see E<lt>guestfs-structs.hE<gt>),
5239 or NULL if there was an error.
5240 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5241          | RHashtable _ ->
5242              pr "This function returns a NULL-terminated array of
5243 strings, or NULL if there was an error.
5244 The array of strings will always have length C<2n+1>, where
5245 C<n> keys and values alternate, followed by the trailing NULL entry.
5246 I<The caller must free the strings and the array after use>.\n\n"
5247          | RBufferOut _ ->
5248              pr "This function returns a buffer, or NULL on error.
5249 The size of the returned buffer is written to C<*size_r>.
5250 I<The caller must free the returned buffer after use>.\n\n"
5251         );
5252         if List.mem ProtocolLimitWarning flags then
5253           pr "%s\n\n" protocol_limit_warning;
5254         if List.mem DangerWillRobinson flags then
5255           pr "%s\n\n" danger_will_robinson;
5256         match deprecation_notice flags with
5257         | None -> ()
5258         | Some txt -> pr "%s\n\n" txt
5259       )
5260   ) all_functions_sorted
5261
5262 and generate_structs_pod () =
5263   (* Structs documentation. *)
5264   List.iter (
5265     fun (typ, cols) ->
5266       pr "=head2 guestfs_%s\n" typ;
5267       pr "\n";
5268       pr " struct guestfs_%s {\n" typ;
5269       List.iter (
5270         function
5271         | name, FChar -> pr "   char %s;\n" name
5272         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5273         | name, FInt32 -> pr "   int32_t %s;\n" name
5274         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5275         | name, FInt64 -> pr "   int64_t %s;\n" name
5276         | name, FString -> pr "   char *%s;\n" name
5277         | name, FBuffer ->
5278             pr "   /* The next two fields describe a byte array. */\n";
5279             pr "   uint32_t %s_len;\n" name;
5280             pr "   char *%s;\n" name
5281         | name, FUUID ->
5282             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5283             pr "   char %s[32];\n" name
5284         | name, FOptPercent ->
5285             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5286             pr "   float %s;\n" name
5287       ) cols;
5288       pr " };\n";
5289       pr " \n";
5290       pr " struct guestfs_%s_list {\n" typ;
5291       pr "   uint32_t len; /* Number of elements in list. */\n";
5292       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5293       pr " };\n";
5294       pr " \n";
5295       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5296       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5297         typ typ;
5298       pr "\n"
5299   ) structs
5300
5301 and generate_availability_pod () =
5302   (* Availability documentation. *)
5303   pr "=over 4\n";
5304   pr "\n";
5305   List.iter (
5306     fun (group, functions) ->
5307       pr "=item B<%s>\n" group;
5308       pr "\n";
5309       pr "The following functions:\n";
5310       List.iter (pr "L</guestfs_%s>\n") functions;
5311       pr "\n"
5312   ) optgroups;
5313   pr "=back\n";
5314   pr "\n"
5315
5316 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5317  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5318  *
5319  * We have to use an underscore instead of a dash because otherwise
5320  * rpcgen generates incorrect code.
5321  *
5322  * This header is NOT exported to clients, but see also generate_structs_h.
5323  *)
5324 and generate_xdr () =
5325   generate_header CStyle LGPLv2plus;
5326
5327   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5328   pr "typedef string str<>;\n";
5329   pr "\n";
5330
5331   (* Internal structures. *)
5332   List.iter (
5333     function
5334     | typ, cols ->
5335         pr "struct guestfs_int_%s {\n" typ;
5336         List.iter (function
5337                    | name, FChar -> pr "  char %s;\n" name
5338                    | name, FString -> pr "  string %s<>;\n" name
5339                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5340                    | name, FUUID -> pr "  opaque %s[32];\n" name
5341                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5342                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5343                    | name, FOptPercent -> pr "  float %s;\n" name
5344                   ) cols;
5345         pr "};\n";
5346         pr "\n";
5347         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5348         pr "\n";
5349   ) structs;
5350
5351   List.iter (
5352     fun (shortname, style, _, _, _, _, _) ->
5353       let name = "guestfs_" ^ shortname in
5354
5355       (match snd style with
5356        | [] -> ()
5357        | args ->
5358            pr "struct %s_args {\n" name;
5359            List.iter (
5360              function
5361              | Pathname n | Device n | Dev_or_Path n | String n ->
5362                  pr "  string %s<>;\n" n
5363              | OptString n -> pr "  str *%s;\n" n
5364              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5365              | Bool n -> pr "  bool %s;\n" n
5366              | Int n -> pr "  int %s;\n" n
5367              | Int64 n -> pr "  hyper %s;\n" n
5368              | FileIn _ | FileOut _ -> ()
5369            ) args;
5370            pr "};\n\n"
5371       );
5372       (match fst style with
5373        | RErr -> ()
5374        | RInt n ->
5375            pr "struct %s_ret {\n" name;
5376            pr "  int %s;\n" n;
5377            pr "};\n\n"
5378        | RInt64 n ->
5379            pr "struct %s_ret {\n" name;
5380            pr "  hyper %s;\n" n;
5381            pr "};\n\n"
5382        | RBool n ->
5383            pr "struct %s_ret {\n" name;
5384            pr "  bool %s;\n" n;
5385            pr "};\n\n"
5386        | RConstString _ | RConstOptString _ ->
5387            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5388        | RString n ->
5389            pr "struct %s_ret {\n" name;
5390            pr "  string %s<>;\n" n;
5391            pr "};\n\n"
5392        | RStringList n ->
5393            pr "struct %s_ret {\n" name;
5394            pr "  str %s<>;\n" n;
5395            pr "};\n\n"
5396        | RStruct (n, typ) ->
5397            pr "struct %s_ret {\n" name;
5398            pr "  guestfs_int_%s %s;\n" typ n;
5399            pr "};\n\n"
5400        | RStructList (n, typ) ->
5401            pr "struct %s_ret {\n" name;
5402            pr "  guestfs_int_%s_list %s;\n" typ n;
5403            pr "};\n\n"
5404        | RHashtable n ->
5405            pr "struct %s_ret {\n" name;
5406            pr "  str %s<>;\n" n;
5407            pr "};\n\n"
5408        | RBufferOut n ->
5409            pr "struct %s_ret {\n" name;
5410            pr "  opaque %s<>;\n" n;
5411            pr "};\n\n"
5412       );
5413   ) daemon_functions;
5414
5415   (* Table of procedure numbers. *)
5416   pr "enum guestfs_procedure {\n";
5417   List.iter (
5418     fun (shortname, _, proc_nr, _, _, _, _) ->
5419       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5420   ) daemon_functions;
5421   pr "  GUESTFS_PROC_NR_PROCS\n";
5422   pr "};\n";
5423   pr "\n";
5424
5425   (* Having to choose a maximum message size is annoying for several
5426    * reasons (it limits what we can do in the API), but it (a) makes
5427    * the protocol a lot simpler, and (b) provides a bound on the size
5428    * of the daemon which operates in limited memory space.
5429    *)
5430   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5431   pr "\n";
5432
5433   (* Message header, etc. *)
5434   pr "\
5435 /* The communication protocol is now documented in the guestfs(3)
5436  * manpage.
5437  */
5438
5439 const GUESTFS_PROGRAM = 0x2000F5F5;
5440 const GUESTFS_PROTOCOL_VERSION = 1;
5441
5442 /* These constants must be larger than any possible message length. */
5443 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5444 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5445
5446 enum guestfs_message_direction {
5447   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5448   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5449 };
5450
5451 enum guestfs_message_status {
5452   GUESTFS_STATUS_OK = 0,
5453   GUESTFS_STATUS_ERROR = 1
5454 };
5455
5456 const GUESTFS_ERROR_LEN = 256;
5457
5458 struct guestfs_message_error {
5459   string error_message<GUESTFS_ERROR_LEN>;
5460 };
5461
5462 struct guestfs_message_header {
5463   unsigned prog;                     /* GUESTFS_PROGRAM */
5464   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5465   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5466   guestfs_message_direction direction;
5467   unsigned serial;                   /* message serial number */
5468   guestfs_message_status status;
5469 };
5470
5471 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5472
5473 struct guestfs_chunk {
5474   int cancel;                        /* if non-zero, transfer is cancelled */
5475   /* data size is 0 bytes if the transfer has finished successfully */
5476   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5477 };
5478 "
5479
5480 (* Generate the guestfs-structs.h file. *)
5481 and generate_structs_h () =
5482   generate_header CStyle LGPLv2plus;
5483
5484   (* This is a public exported header file containing various
5485    * structures.  The structures are carefully written to have
5486    * exactly the same in-memory format as the XDR structures that
5487    * we use on the wire to the daemon.  The reason for creating
5488    * copies of these structures here is just so we don't have to
5489    * export the whole of guestfs_protocol.h (which includes much
5490    * unrelated and XDR-dependent stuff that we don't want to be
5491    * public, or required by clients).
5492    *
5493    * To reiterate, we will pass these structures to and from the
5494    * client with a simple assignment or memcpy, so the format
5495    * must be identical to what rpcgen / the RFC defines.
5496    *)
5497
5498   (* Public structures. *)
5499   List.iter (
5500     fun (typ, cols) ->
5501       pr "struct guestfs_%s {\n" typ;
5502       List.iter (
5503         function
5504         | name, FChar -> pr "  char %s;\n" name
5505         | name, FString -> pr "  char *%s;\n" name
5506         | name, FBuffer ->
5507             pr "  uint32_t %s_len;\n" name;
5508             pr "  char *%s;\n" name
5509         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5510         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5511         | name, FInt32 -> pr "  int32_t %s;\n" name
5512         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5513         | name, FInt64 -> pr "  int64_t %s;\n" name
5514         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5515       ) cols;
5516       pr "};\n";
5517       pr "\n";
5518       pr "struct guestfs_%s_list {\n" typ;
5519       pr "  uint32_t len;\n";
5520       pr "  struct guestfs_%s *val;\n" typ;
5521       pr "};\n";
5522       pr "\n";
5523       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5524       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5525       pr "\n"
5526   ) structs
5527
5528 (* Generate the guestfs-actions.h file. *)
5529 and generate_actions_h () =
5530   generate_header CStyle LGPLv2plus;
5531   List.iter (
5532     fun (shortname, style, _, _, _, _, _) ->
5533       let name = "guestfs_" ^ shortname in
5534       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5535         name style
5536   ) all_functions
5537
5538 (* Generate the guestfs-internal-actions.h file. *)
5539 and generate_internal_actions_h () =
5540   generate_header CStyle LGPLv2plus;
5541   List.iter (
5542     fun (shortname, style, _, _, _, _, _) ->
5543       let name = "guestfs__" ^ shortname in
5544       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5545         name style
5546   ) non_daemon_functions
5547
5548 (* Generate the client-side dispatch stubs. *)
5549 and generate_client_actions () =
5550   generate_header CStyle LGPLv2plus;
5551
5552   pr "\
5553 #include <stdio.h>
5554 #include <stdlib.h>
5555 #include <stdint.h>
5556 #include <string.h>
5557 #include <inttypes.h>
5558
5559 #include \"guestfs.h\"
5560 #include \"guestfs-internal.h\"
5561 #include \"guestfs-internal-actions.h\"
5562 #include \"guestfs_protocol.h\"
5563
5564 #define error guestfs_error
5565 //#define perrorf guestfs_perrorf
5566 #define safe_malloc guestfs_safe_malloc
5567 #define safe_realloc guestfs_safe_realloc
5568 //#define safe_strdup guestfs_safe_strdup
5569 #define safe_memdup guestfs_safe_memdup
5570
5571 /* Check the return message from a call for validity. */
5572 static int
5573 check_reply_header (guestfs_h *g,
5574                     const struct guestfs_message_header *hdr,
5575                     unsigned int proc_nr, unsigned int serial)
5576 {
5577   if (hdr->prog != GUESTFS_PROGRAM) {
5578     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5579     return -1;
5580   }
5581   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5582     error (g, \"wrong protocol version (%%d/%%d)\",
5583            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5584     return -1;
5585   }
5586   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5587     error (g, \"unexpected message direction (%%d/%%d)\",
5588            hdr->direction, GUESTFS_DIRECTION_REPLY);
5589     return -1;
5590   }
5591   if (hdr->proc != proc_nr) {
5592     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5593     return -1;
5594   }
5595   if (hdr->serial != serial) {
5596     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5597     return -1;
5598   }
5599
5600   return 0;
5601 }
5602
5603 /* Check we are in the right state to run a high-level action. */
5604 static int
5605 check_state (guestfs_h *g, const char *caller)
5606 {
5607   if (!guestfs__is_ready (g)) {
5608     if (guestfs__is_config (g) || guestfs__is_launching (g))
5609       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5610         caller);
5611     else
5612       error (g, \"%%s called from the wrong state, %%d != READY\",
5613         caller, guestfs__get_state (g));
5614     return -1;
5615   }
5616   return 0;
5617 }
5618
5619 ";
5620
5621   (* Generate code to generate guestfish call traces. *)
5622   let trace_call shortname style =
5623     pr "  if (guestfs__get_trace (g)) {\n";
5624
5625     let needs_i =
5626       List.exists (function
5627                    | StringList _ | DeviceList _ -> true
5628                    | _ -> false) (snd style) in
5629     if needs_i then (
5630       pr "    int i;\n";
5631       pr "\n"
5632     );
5633
5634     pr "    printf (\"%s\");\n" shortname;
5635     List.iter (
5636       function
5637       | String n                        (* strings *)
5638       | Device n
5639       | Pathname n
5640       | Dev_or_Path n
5641       | FileIn n
5642       | FileOut n ->
5643           (* guestfish doesn't support string escaping, so neither do we *)
5644           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5645       | OptString n ->                  (* string option *)
5646           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5647           pr "    else printf (\" null\");\n"
5648       | StringList n
5649       | DeviceList n ->                 (* string list *)
5650           pr "    putchar (' ');\n";
5651           pr "    putchar ('\"');\n";
5652           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5653           pr "      if (i > 0) putchar (' ');\n";
5654           pr "      fputs (%s[i], stdout);\n" n;
5655           pr "    }\n";
5656           pr "    putchar ('\"');\n";
5657       | Bool n ->                       (* boolean *)
5658           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5659       | Int n ->                        (* int *)
5660           pr "    printf (\" %%d\", %s);\n" n
5661       | Int64 n ->
5662           pr "    printf (\" %%\" PRIi64, %s);\n" n
5663     ) (snd style);
5664     pr "    putchar ('\\n');\n";
5665     pr "  }\n";
5666     pr "\n";
5667   in
5668
5669   (* For non-daemon functions, generate a wrapper around each function. *)
5670   List.iter (
5671     fun (shortname, style, _, _, _, _, _) ->
5672       let name = "guestfs_" ^ shortname in
5673
5674       generate_prototype ~extern:false ~semicolon:false ~newline:true
5675         ~handle:"g" name style;
5676       pr "{\n";
5677       trace_call shortname style;
5678       pr "  return guestfs__%s " shortname;
5679       generate_c_call_args ~handle:"g" style;
5680       pr ";\n";
5681       pr "}\n";
5682       pr "\n"
5683   ) non_daemon_functions;
5684
5685   (* Client-side stubs for each function. *)
5686   List.iter (
5687     fun (shortname, style, _, _, _, _, _) ->
5688       let name = "guestfs_" ^ shortname in
5689
5690       (* Generate the action stub. *)
5691       generate_prototype ~extern:false ~semicolon:false ~newline:true
5692         ~handle:"g" name style;
5693
5694       let error_code =
5695         match fst style with
5696         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5697         | RConstString _ | RConstOptString _ ->
5698             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5699         | RString _ | RStringList _
5700         | RStruct _ | RStructList _
5701         | RHashtable _ | RBufferOut _ ->
5702             "NULL" in
5703
5704       pr "{\n";
5705
5706       (match snd style with
5707        | [] -> ()
5708        | _ -> pr "  struct %s_args args;\n" name
5709       );
5710
5711       pr "  guestfs_message_header hdr;\n";
5712       pr "  guestfs_message_error err;\n";
5713       let has_ret =
5714         match fst style with
5715         | RErr -> false
5716         | RConstString _ | RConstOptString _ ->
5717             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5718         | RInt _ | RInt64 _
5719         | RBool _ | RString _ | RStringList _
5720         | RStruct _ | RStructList _
5721         | RHashtable _ | RBufferOut _ ->
5722             pr "  struct %s_ret ret;\n" name;
5723             true in
5724
5725       pr "  int serial;\n";
5726       pr "  int r;\n";
5727       pr "\n";
5728       trace_call shortname style;
5729       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5730       pr "  guestfs___set_busy (g);\n";
5731       pr "\n";
5732
5733       (* Send the main header and arguments. *)
5734       (match snd style with
5735        | [] ->
5736            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5737              (String.uppercase shortname)
5738        | args ->
5739            List.iter (
5740              function
5741              | Pathname n | Device n | Dev_or_Path n | String n ->
5742                  pr "  args.%s = (char *) %s;\n" n n
5743              | OptString n ->
5744                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5745              | StringList n | DeviceList n ->
5746                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5747                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5748              | Bool n ->
5749                  pr "  args.%s = %s;\n" n n
5750              | Int n ->
5751                  pr "  args.%s = %s;\n" n n
5752              | Int64 n ->
5753                  pr "  args.%s = %s;\n" n n
5754              | FileIn _ | FileOut _ -> ()
5755            ) args;
5756            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5757              (String.uppercase shortname);
5758            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5759              name;
5760       );
5761       pr "  if (serial == -1) {\n";
5762       pr "    guestfs___end_busy (g);\n";
5763       pr "    return %s;\n" error_code;
5764       pr "  }\n";
5765       pr "\n";
5766
5767       (* Send any additional files (FileIn) requested. *)
5768       let need_read_reply_label = ref false in
5769       List.iter (
5770         function
5771         | FileIn n ->
5772             pr "  r = guestfs___send_file (g, %s);\n" n;
5773             pr "  if (r == -1) {\n";
5774             pr "    guestfs___end_busy (g);\n";
5775             pr "    return %s;\n" error_code;
5776             pr "  }\n";
5777             pr "  if (r == -2) /* daemon cancelled */\n";
5778             pr "    goto read_reply;\n";
5779             need_read_reply_label := true;
5780             pr "\n";
5781         | _ -> ()
5782       ) (snd style);
5783
5784       (* Wait for the reply from the remote end. *)
5785       if !need_read_reply_label then pr " read_reply:\n";
5786       pr "  memset (&hdr, 0, sizeof hdr);\n";
5787       pr "  memset (&err, 0, sizeof err);\n";
5788       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5789       pr "\n";
5790       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5791       if not has_ret then
5792         pr "NULL, NULL"
5793       else
5794         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5795       pr ");\n";
5796
5797       pr "  if (r == -1) {\n";
5798       pr "    guestfs___end_busy (g);\n";
5799       pr "    return %s;\n" error_code;
5800       pr "  }\n";
5801       pr "\n";
5802
5803       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5804         (String.uppercase shortname);
5805       pr "    guestfs___end_busy (g);\n";
5806       pr "    return %s;\n" error_code;
5807       pr "  }\n";
5808       pr "\n";
5809
5810       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5811       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5812       pr "    free (err.error_message);\n";
5813       pr "    guestfs___end_busy (g);\n";
5814       pr "    return %s;\n" error_code;
5815       pr "  }\n";
5816       pr "\n";
5817
5818       (* Expecting to receive further files (FileOut)? *)
5819       List.iter (
5820         function
5821         | FileOut n ->
5822             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5823             pr "    guestfs___end_busy (g);\n";
5824             pr "    return %s;\n" error_code;
5825             pr "  }\n";
5826             pr "\n";
5827         | _ -> ()
5828       ) (snd style);
5829
5830       pr "  guestfs___end_busy (g);\n";
5831
5832       (match fst style with
5833        | RErr -> pr "  return 0;\n"
5834        | RInt n | RInt64 n | RBool n ->
5835            pr "  return ret.%s;\n" n
5836        | RConstString _ | RConstOptString _ ->
5837            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5838        | RString n ->
5839            pr "  return ret.%s; /* caller will free */\n" n
5840        | RStringList n | RHashtable n ->
5841            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5842            pr "  ret.%s.%s_val =\n" n n;
5843            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5844            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5845              n n;
5846            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5847            pr "  return ret.%s.%s_val;\n" n n
5848        | RStruct (n, _) ->
5849            pr "  /* caller will free this */\n";
5850            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5851        | RStructList (n, _) ->
5852            pr "  /* caller will free this */\n";
5853            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5854        | RBufferOut n ->
5855            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5856            pr "   * _val might be NULL here.  To make the API saner for\n";
5857            pr "   * callers, we turn this case into a unique pointer (using\n";
5858            pr "   * malloc(1)).\n";
5859            pr "   */\n";
5860            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5861            pr "    *size_r = ret.%s.%s_len;\n" n n;
5862            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5863            pr "  } else {\n";
5864            pr "    free (ret.%s.%s_val);\n" n n;
5865            pr "    char *p = safe_malloc (g, 1);\n";
5866            pr "    *size_r = ret.%s.%s_len;\n" n n;
5867            pr "    return p;\n";
5868            pr "  }\n";
5869       );
5870
5871       pr "}\n\n"
5872   ) daemon_functions;
5873
5874   (* Functions to free structures. *)
5875   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5876   pr " * structure format is identical to the XDR format.  See note in\n";
5877   pr " * generator.ml.\n";
5878   pr " */\n";
5879   pr "\n";
5880
5881   List.iter (
5882     fun (typ, _) ->
5883       pr "void\n";
5884       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5885       pr "{\n";
5886       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5887       pr "  free (x);\n";
5888       pr "}\n";
5889       pr "\n";
5890
5891       pr "void\n";
5892       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5893       pr "{\n";
5894       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5895       pr "  free (x);\n";
5896       pr "}\n";
5897       pr "\n";
5898
5899   ) structs;
5900
5901 (* Generate daemon/actions.h. *)
5902 and generate_daemon_actions_h () =
5903   generate_header CStyle GPLv2plus;
5904
5905   pr "#include \"../src/guestfs_protocol.h\"\n";
5906   pr "\n";
5907
5908   List.iter (
5909     fun (name, style, _, _, _, _, _) ->
5910       generate_prototype
5911         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5912         name style;
5913   ) daemon_functions
5914
5915 (* Generate the linker script which controls the visibility of
5916  * symbols in the public ABI and ensures no other symbols get
5917  * exported accidentally.
5918  *)
5919 and generate_linker_script () =
5920   generate_header HashStyle GPLv2plus;
5921
5922   let globals = [
5923     "guestfs_create";
5924     "guestfs_close";
5925     "guestfs_get_error_handler";
5926     "guestfs_get_out_of_memory_handler";
5927     "guestfs_last_error";
5928     "guestfs_set_error_handler";
5929     "guestfs_set_launch_done_callback";
5930     "guestfs_set_log_message_callback";
5931     "guestfs_set_out_of_memory_handler";
5932     "guestfs_set_subprocess_quit_callback";
5933
5934     (* Unofficial parts of the API: the bindings code use these
5935      * functions, so it is useful to export them.
5936      *)
5937     "guestfs_safe_calloc";
5938     "guestfs_safe_malloc";
5939   ] in
5940   let functions =
5941     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5942       all_functions in
5943   let structs =
5944     List.concat (
5945       List.map (fun (typ, _) ->
5946                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5947         structs
5948     ) in
5949   let globals = List.sort compare (globals @ functions @ structs) in
5950
5951   pr "{\n";
5952   pr "    global:\n";
5953   List.iter (pr "        %s;\n") globals;
5954   pr "\n";
5955
5956   pr "    local:\n";
5957   pr "        *;\n";
5958   pr "};\n"
5959
5960 (* Generate the server-side stubs. *)
5961 and generate_daemon_actions () =
5962   generate_header CStyle GPLv2plus;
5963
5964   pr "#include <config.h>\n";
5965   pr "\n";
5966   pr "#include <stdio.h>\n";
5967   pr "#include <stdlib.h>\n";
5968   pr "#include <string.h>\n";
5969   pr "#include <inttypes.h>\n";
5970   pr "#include <rpc/types.h>\n";
5971   pr "#include <rpc/xdr.h>\n";
5972   pr "\n";
5973   pr "#include \"daemon.h\"\n";
5974   pr "#include \"c-ctype.h\"\n";
5975   pr "#include \"../src/guestfs_protocol.h\"\n";
5976   pr "#include \"actions.h\"\n";
5977   pr "\n";
5978
5979   List.iter (
5980     fun (name, style, _, _, _, _, _) ->
5981       (* Generate server-side stubs. *)
5982       pr "static void %s_stub (XDR *xdr_in)\n" name;
5983       pr "{\n";
5984       let error_code =
5985         match fst style with
5986         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5987         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5988         | RBool _ -> pr "  int r;\n"; "-1"
5989         | RConstString _ | RConstOptString _ ->
5990             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5991         | RString _ -> pr "  char *r;\n"; "NULL"
5992         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5993         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5994         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5995         | RBufferOut _ ->
5996             pr "  size_t size = 1;\n";
5997             pr "  char *r;\n";
5998             "NULL" in
5999
6000       (match snd style with
6001        | [] -> ()
6002        | args ->
6003            pr "  struct guestfs_%s_args args;\n" name;
6004            List.iter (
6005              function
6006              | Device n | Dev_or_Path n
6007              | Pathname n
6008              | String n -> ()
6009              | OptString n -> pr "  char *%s;\n" n
6010              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6011              | Bool n -> pr "  int %s;\n" n
6012              | Int n -> pr "  int %s;\n" n
6013              | Int64 n -> pr "  int64_t %s;\n" n
6014              | FileIn _ | FileOut _ -> ()
6015            ) args
6016       );
6017       pr "\n";
6018
6019       (match snd style with
6020        | [] -> ()
6021        | args ->
6022            pr "  memset (&args, 0, sizeof args);\n";
6023            pr "\n";
6024            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6025            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6026            pr "    return;\n";
6027            pr "  }\n";
6028            let pr_args n =
6029              pr "  char *%s = args.%s;\n" n n
6030            in
6031            let pr_list_handling_code n =
6032              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6033              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6034              pr "  if (%s == NULL) {\n" n;
6035              pr "    reply_with_perror (\"realloc\");\n";
6036              pr "    goto done;\n";
6037              pr "  }\n";
6038              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6039              pr "  args.%s.%s_val = %s;\n" n n n;
6040            in
6041            List.iter (
6042              function
6043              | Pathname n ->
6044                  pr_args n;
6045                  pr "  ABS_PATH (%s, goto done);\n" n;
6046              | Device n ->
6047                  pr_args n;
6048                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
6049              | Dev_or_Path n ->
6050                  pr_args n;
6051                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
6052              | String n -> pr_args n
6053              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6054              | StringList n ->
6055                  pr_list_handling_code n;
6056              | DeviceList n ->
6057                  pr_list_handling_code n;
6058                  pr "  /* Ensure that each is a device,\n";
6059                  pr "   * and perform device name translation. */\n";
6060                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6061                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
6062                  pr "  }\n";
6063              | Bool n -> pr "  %s = args.%s;\n" n n
6064              | Int n -> pr "  %s = args.%s;\n" n n
6065              | Int64 n -> pr "  %s = args.%s;\n" n n
6066              | FileIn _ | FileOut _ -> ()
6067            ) args;
6068            pr "\n"
6069       );
6070
6071
6072       (* this is used at least for do_equal *)
6073       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6074         (* Emit NEED_ROOT just once, even when there are two or
6075            more Pathname args *)
6076         pr "  NEED_ROOT (goto done);\n";
6077       );
6078
6079       (* Don't want to call the impl with any FileIn or FileOut
6080        * parameters, since these go "outside" the RPC protocol.
6081        *)
6082       let args' =
6083         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6084           (snd style) in
6085       pr "  r = do_%s " name;
6086       generate_c_call_args (fst style, args');
6087       pr ";\n";
6088
6089       (match fst style with
6090        | RErr | RInt _ | RInt64 _ | RBool _
6091        | RConstString _ | RConstOptString _
6092        | RString _ | RStringList _ | RHashtable _
6093        | RStruct (_, _) | RStructList (_, _) ->
6094            pr "  if (r == %s)\n" error_code;
6095            pr "    /* do_%s has already called reply_with_error */\n" name;
6096            pr "    goto done;\n";
6097            pr "\n"
6098        | RBufferOut _ ->
6099            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6100            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6101            pr "   */\n";
6102            pr "  if (size == 1 && r == %s)\n" error_code;
6103            pr "    /* do_%s has already called reply_with_error */\n" name;
6104            pr "    goto done;\n";
6105            pr "\n"
6106       );
6107
6108       (* If there are any FileOut parameters, then the impl must
6109        * send its own reply.
6110        *)
6111       let no_reply =
6112         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6113       if no_reply then
6114         pr "  /* do_%s has already sent a reply */\n" name
6115       else (
6116         match fst style with
6117         | RErr -> pr "  reply (NULL, NULL);\n"
6118         | RInt n | RInt64 n | RBool n ->
6119             pr "  struct guestfs_%s_ret ret;\n" name;
6120             pr "  ret.%s = r;\n" n;
6121             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6122               name
6123         | RConstString _ | RConstOptString _ ->
6124             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6125         | RString n ->
6126             pr "  struct guestfs_%s_ret ret;\n" name;
6127             pr "  ret.%s = r;\n" n;
6128             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6129               name;
6130             pr "  free (r);\n"
6131         | RStringList n | RHashtable n ->
6132             pr "  struct guestfs_%s_ret ret;\n" name;
6133             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6134             pr "  ret.%s.%s_val = r;\n" n n;
6135             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6136               name;
6137             pr "  free_strings (r);\n"
6138         | RStruct (n, _) ->
6139             pr "  struct guestfs_%s_ret ret;\n" name;
6140             pr "  ret.%s = *r;\n" n;
6141             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6142               name;
6143             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6144               name
6145         | RStructList (n, _) ->
6146             pr "  struct guestfs_%s_ret ret;\n" name;
6147             pr "  ret.%s = *r;\n" n;
6148             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6149               name;
6150             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6151               name
6152         | RBufferOut n ->
6153             pr "  struct guestfs_%s_ret ret;\n" name;
6154             pr "  ret.%s.%s_val = r;\n" n n;
6155             pr "  ret.%s.%s_len = size;\n" n n;
6156             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6157               name;
6158             pr "  free (r);\n"
6159       );
6160
6161       (* Free the args. *)
6162       (match snd style with
6163        | [] ->
6164            pr "done: ;\n";
6165        | _ ->
6166            pr "done:\n";
6167            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6168              name
6169       );
6170
6171       pr "}\n\n";
6172   ) daemon_functions;
6173
6174   (* Dispatch function. *)
6175   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6176   pr "{\n";
6177   pr "  switch (proc_nr) {\n";
6178
6179   List.iter (
6180     fun (name, style, _, _, _, _, _) ->
6181       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6182       pr "      %s_stub (xdr_in);\n" name;
6183       pr "      break;\n"
6184   ) daemon_functions;
6185
6186   pr "    default:\n";
6187   pr "      reply_with_error (\"dispatch_incoming_message: unknown procedure number %%d, set LIBGUESTFS_PATH to point to the matching libguestfs appliance directory\", proc_nr);\n";
6188   pr "  }\n";
6189   pr "}\n";
6190   pr "\n";
6191
6192   (* LVM columns and tokenization functions. *)
6193   (* XXX This generates crap code.  We should rethink how we
6194    * do this parsing.
6195    *)
6196   List.iter (
6197     function
6198     | typ, cols ->
6199         pr "static const char *lvm_%s_cols = \"%s\";\n"
6200           typ (String.concat "," (List.map fst cols));
6201         pr "\n";
6202
6203         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6204         pr "{\n";
6205         pr "  char *tok, *p, *next;\n";
6206         pr "  int i, j;\n";
6207         pr "\n";
6208         (*
6209           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6210           pr "\n";
6211         *)
6212         pr "  if (!str) {\n";
6213         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6214         pr "    return -1;\n";
6215         pr "  }\n";
6216         pr "  if (!*str || c_isspace (*str)) {\n";
6217         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6218         pr "    return -1;\n";
6219         pr "  }\n";
6220         pr "  tok = str;\n";
6221         List.iter (
6222           fun (name, coltype) ->
6223             pr "  if (!tok) {\n";
6224             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6225             pr "    return -1;\n";
6226             pr "  }\n";
6227             pr "  p = strchrnul (tok, ',');\n";
6228             pr "  if (*p) next = p+1; else next = NULL;\n";
6229             pr "  *p = '\\0';\n";
6230             (match coltype with
6231              | FString ->
6232                  pr "  r->%s = strdup (tok);\n" name;
6233                  pr "  if (r->%s == NULL) {\n" name;
6234                  pr "    perror (\"strdup\");\n";
6235                  pr "    return -1;\n";
6236                  pr "  }\n"
6237              | FUUID ->
6238                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6239                  pr "    if (tok[j] == '\\0') {\n";
6240                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6241                  pr "      return -1;\n";
6242                  pr "    } else if (tok[j] != '-')\n";
6243                  pr "      r->%s[i++] = tok[j];\n" name;
6244                  pr "  }\n";
6245              | FBytes ->
6246                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6247                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6248                  pr "    return -1;\n";
6249                  pr "  }\n";
6250              | FInt64 ->
6251                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6252                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6253                  pr "    return -1;\n";
6254                  pr "  }\n";
6255              | FOptPercent ->
6256                  pr "  if (tok[0] == '\\0')\n";
6257                  pr "    r->%s = -1;\n" name;
6258                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6259                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6260                  pr "    return -1;\n";
6261                  pr "  }\n";
6262              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6263                  assert false (* can never be an LVM column *)
6264             );
6265             pr "  tok = next;\n";
6266         ) cols;
6267
6268         pr "  if (tok != NULL) {\n";
6269         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6270         pr "    return -1;\n";
6271         pr "  }\n";
6272         pr "  return 0;\n";
6273         pr "}\n";
6274         pr "\n";
6275
6276         pr "guestfs_int_lvm_%s_list *\n" typ;
6277         pr "parse_command_line_%ss (void)\n" typ;
6278         pr "{\n";
6279         pr "  char *out, *err;\n";
6280         pr "  char *p, *pend;\n";
6281         pr "  int r, i;\n";
6282         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6283         pr "  void *newp;\n";
6284         pr "\n";
6285         pr "  ret = malloc (sizeof *ret);\n";
6286         pr "  if (!ret) {\n";
6287         pr "    reply_with_perror (\"malloc\");\n";
6288         pr "    return NULL;\n";
6289         pr "  }\n";
6290         pr "\n";
6291         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6292         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6293         pr "\n";
6294         pr "  r = command (&out, &err,\n";
6295         pr "           \"lvm\", \"%ss\",\n" typ;
6296         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6297         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6298         pr "  if (r == -1) {\n";
6299         pr "    reply_with_error (\"%%s\", err);\n";
6300         pr "    free (out);\n";
6301         pr "    free (err);\n";
6302         pr "    free (ret);\n";
6303         pr "    return NULL;\n";
6304         pr "  }\n";
6305         pr "\n";
6306         pr "  free (err);\n";
6307         pr "\n";
6308         pr "  /* Tokenize each line of the output. */\n";
6309         pr "  p = out;\n";
6310         pr "  i = 0;\n";
6311         pr "  while (p) {\n";
6312         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6313         pr "    if (pend) {\n";
6314         pr "      *pend = '\\0';\n";
6315         pr "      pend++;\n";
6316         pr "    }\n";
6317         pr "\n";
6318         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6319         pr "      p++;\n";
6320         pr "\n";
6321         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6322         pr "      p = pend;\n";
6323         pr "      continue;\n";
6324         pr "    }\n";
6325         pr "\n";
6326         pr "    /* Allocate some space to store this next entry. */\n";
6327         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6328         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6329         pr "    if (newp == NULL) {\n";
6330         pr "      reply_with_perror (\"realloc\");\n";
6331         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6332         pr "      free (ret);\n";
6333         pr "      free (out);\n";
6334         pr "      return NULL;\n";
6335         pr "    }\n";
6336         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6337         pr "\n";
6338         pr "    /* Tokenize the next entry. */\n";
6339         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6340         pr "    if (r == -1) {\n";
6341         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6342         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6343         pr "      free (ret);\n";
6344         pr "      free (out);\n";
6345         pr "      return NULL;\n";
6346         pr "    }\n";
6347         pr "\n";
6348         pr "    ++i;\n";
6349         pr "    p = pend;\n";
6350         pr "  }\n";
6351         pr "\n";
6352         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6353         pr "\n";
6354         pr "  free (out);\n";
6355         pr "  return ret;\n";
6356         pr "}\n"
6357
6358   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6359
6360 (* Generate a list of function names, for debugging in the daemon.. *)
6361 and generate_daemon_names () =
6362   generate_header CStyle GPLv2plus;
6363
6364   pr "#include <config.h>\n";
6365   pr "\n";
6366   pr "#include \"daemon.h\"\n";
6367   pr "\n";
6368
6369   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6370   pr "const char *function_names[] = {\n";
6371   List.iter (
6372     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6373   ) daemon_functions;
6374   pr "};\n";
6375
6376 (* Generate the optional groups for the daemon to implement
6377  * guestfs_available.
6378  *)
6379 and generate_daemon_optgroups_c () =
6380   generate_header CStyle GPLv2plus;
6381
6382   pr "#include <config.h>\n";
6383   pr "\n";
6384   pr "#include \"daemon.h\"\n";
6385   pr "#include \"optgroups.h\"\n";
6386   pr "\n";
6387
6388   pr "struct optgroup optgroups[] = {\n";
6389   List.iter (
6390     fun (group, _) ->
6391       pr "  { \"%s\", optgroup_%s_available },\n" group group
6392   ) optgroups;
6393   pr "  { NULL, NULL }\n";
6394   pr "};\n"
6395
6396 and generate_daemon_optgroups_h () =
6397   generate_header CStyle GPLv2plus;
6398
6399   List.iter (
6400     fun (group, _) ->
6401       pr "extern int optgroup_%s_available (void);\n" group
6402   ) optgroups
6403
6404 (* Generate the tests. *)
6405 and generate_tests () =
6406   generate_header CStyle GPLv2plus;
6407
6408   pr "\
6409 #include <stdio.h>
6410 #include <stdlib.h>
6411 #include <string.h>
6412 #include <unistd.h>
6413 #include <sys/types.h>
6414 #include <fcntl.h>
6415
6416 #include \"guestfs.h\"
6417 #include \"guestfs-internal.h\"
6418
6419 static guestfs_h *g;
6420 static int suppress_error = 0;
6421
6422 static void print_error (guestfs_h *g, void *data, const char *msg)
6423 {
6424   if (!suppress_error)
6425     fprintf (stderr, \"%%s\\n\", msg);
6426 }
6427
6428 /* FIXME: nearly identical code appears in fish.c */
6429 static void print_strings (char *const *argv)
6430 {
6431   int argc;
6432
6433   for (argc = 0; argv[argc] != NULL; ++argc)
6434     printf (\"\\t%%s\\n\", argv[argc]);
6435 }
6436
6437 /*
6438 static void print_table (char const *const *argv)
6439 {
6440   int i;
6441
6442   for (i = 0; argv[i] != NULL; i += 2)
6443     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6444 }
6445 */
6446
6447 ";
6448
6449   (* Generate a list of commands which are not tested anywhere. *)
6450   pr "static void no_test_warnings (void)\n";
6451   pr "{\n";
6452
6453   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6454   List.iter (
6455     fun (_, _, _, _, tests, _, _) ->
6456       let tests = filter_map (
6457         function
6458         | (_, (Always|If _|Unless _), test) -> Some test
6459         | (_, Disabled, _) -> None
6460       ) tests in
6461       let seq = List.concat (List.map seq_of_test tests) in
6462       let cmds_tested = List.map List.hd seq in
6463       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6464   ) all_functions;
6465
6466   List.iter (
6467     fun (name, _, _, _, _, _, _) ->
6468       if not (Hashtbl.mem hash name) then
6469         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6470   ) all_functions;
6471
6472   pr "}\n";
6473   pr "\n";
6474
6475   (* Generate the actual tests.  Note that we generate the tests
6476    * in reverse order, deliberately, so that (in general) the
6477    * newest tests run first.  This makes it quicker and easier to
6478    * debug them.
6479    *)
6480   let test_names =
6481     List.map (
6482       fun (name, _, _, flags, tests, _, _) ->
6483         mapi (generate_one_test name flags) tests
6484     ) (List.rev all_functions) in
6485   let test_names = List.concat test_names in
6486   let nr_tests = List.length test_names in
6487
6488   pr "\
6489 int main (int argc, char *argv[])
6490 {
6491   char c = 0;
6492   unsigned long int n_failed = 0;
6493   const char *filename;
6494   int fd;
6495   int nr_tests, test_num = 0;
6496
6497   setbuf (stdout, NULL);
6498
6499   no_test_warnings ();
6500
6501   g = guestfs_create ();
6502   if (g == NULL) {
6503     printf (\"guestfs_create FAILED\\n\");
6504     exit (EXIT_FAILURE);
6505   }
6506
6507   guestfs_set_error_handler (g, print_error, NULL);
6508
6509   guestfs_set_path (g, \"../appliance\");
6510
6511   filename = \"test1.img\";
6512   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6513   if (fd == -1) {
6514     perror (filename);
6515     exit (EXIT_FAILURE);
6516   }
6517   if (lseek (fd, %d, SEEK_SET) == -1) {
6518     perror (\"lseek\");
6519     close (fd);
6520     unlink (filename);
6521     exit (EXIT_FAILURE);
6522   }
6523   if (write (fd, &c, 1) == -1) {
6524     perror (\"write\");
6525     close (fd);
6526     unlink (filename);
6527     exit (EXIT_FAILURE);
6528   }
6529   if (close (fd) == -1) {
6530     perror (filename);
6531     unlink (filename);
6532     exit (EXIT_FAILURE);
6533   }
6534   if (guestfs_add_drive (g, filename) == -1) {
6535     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6536     exit (EXIT_FAILURE);
6537   }
6538
6539   filename = \"test2.img\";
6540   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6541   if (fd == -1) {
6542     perror (filename);
6543     exit (EXIT_FAILURE);
6544   }
6545   if (lseek (fd, %d, SEEK_SET) == -1) {
6546     perror (\"lseek\");
6547     close (fd);
6548     unlink (filename);
6549     exit (EXIT_FAILURE);
6550   }
6551   if (write (fd, &c, 1) == -1) {
6552     perror (\"write\");
6553     close (fd);
6554     unlink (filename);
6555     exit (EXIT_FAILURE);
6556   }
6557   if (close (fd) == -1) {
6558     perror (filename);
6559     unlink (filename);
6560     exit (EXIT_FAILURE);
6561   }
6562   if (guestfs_add_drive (g, filename) == -1) {
6563     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6564     exit (EXIT_FAILURE);
6565   }
6566
6567   filename = \"test3.img\";
6568   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6569   if (fd == -1) {
6570     perror (filename);
6571     exit (EXIT_FAILURE);
6572   }
6573   if (lseek (fd, %d, SEEK_SET) == -1) {
6574     perror (\"lseek\");
6575     close (fd);
6576     unlink (filename);
6577     exit (EXIT_FAILURE);
6578   }
6579   if (write (fd, &c, 1) == -1) {
6580     perror (\"write\");
6581     close (fd);
6582     unlink (filename);
6583     exit (EXIT_FAILURE);
6584   }
6585   if (close (fd) == -1) {
6586     perror (filename);
6587     unlink (filename);
6588     exit (EXIT_FAILURE);
6589   }
6590   if (guestfs_add_drive (g, filename) == -1) {
6591     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6592     exit (EXIT_FAILURE);
6593   }
6594
6595   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6596     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6597     exit (EXIT_FAILURE);
6598   }
6599
6600   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6601   alarm (600);
6602
6603   if (guestfs_launch (g) == -1) {
6604     printf (\"guestfs_launch FAILED\\n\");
6605     exit (EXIT_FAILURE);
6606   }
6607
6608   /* Cancel previous alarm. */
6609   alarm (0);
6610
6611   nr_tests = %d;
6612
6613 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6614
6615   iteri (
6616     fun i test_name ->
6617       pr "  test_num++;\n";
6618       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6619       pr "  if (%s () == -1) {\n" test_name;
6620       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6621       pr "    n_failed++;\n";
6622       pr "  }\n";
6623   ) test_names;
6624   pr "\n";
6625
6626   pr "  guestfs_close (g);\n";
6627   pr "  unlink (\"test1.img\");\n";
6628   pr "  unlink (\"test2.img\");\n";
6629   pr "  unlink (\"test3.img\");\n";
6630   pr "\n";
6631
6632   pr "  if (n_failed > 0) {\n";
6633   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6634   pr "    exit (EXIT_FAILURE);\n";
6635   pr "  }\n";
6636   pr "\n";
6637
6638   pr "  exit (EXIT_SUCCESS);\n";
6639   pr "}\n"
6640
6641 and generate_one_test name flags i (init, prereq, test) =
6642   let test_name = sprintf "test_%s_%d" name i in
6643
6644   pr "\
6645 static int %s_skip (void)
6646 {
6647   const char *str;
6648
6649   str = getenv (\"TEST_ONLY\");
6650   if (str)
6651     return strstr (str, \"%s\") == NULL;
6652   str = getenv (\"SKIP_%s\");
6653   if (str && STREQ (str, \"1\")) return 1;
6654   str = getenv (\"SKIP_TEST_%s\");
6655   if (str && STREQ (str, \"1\")) return 1;
6656   return 0;
6657 }
6658
6659 " test_name name (String.uppercase test_name) (String.uppercase name);
6660
6661   (match prereq with
6662    | Disabled | Always -> ()
6663    | If code | Unless code ->
6664        pr "static int %s_prereq (void)\n" test_name;
6665        pr "{\n";
6666        pr "  %s\n" code;
6667        pr "}\n";
6668        pr "\n";
6669   );
6670
6671   pr "\
6672 static int %s (void)
6673 {
6674   if (%s_skip ()) {
6675     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6676     return 0;
6677   }
6678
6679 " test_name test_name test_name;
6680
6681   (* Optional functions should only be tested if the relevant
6682    * support is available in the daemon.
6683    *)
6684   List.iter (
6685     function
6686     | Optional group ->
6687         pr "  {\n";
6688         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6689         pr "    int r;\n";
6690         pr "    suppress_error = 1;\n";
6691         pr "    r = guestfs_available (g, (char **) groups);\n";
6692         pr "    suppress_error = 0;\n";
6693         pr "    if (r == -1) {\n";
6694         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6695         pr "      return 0;\n";
6696         pr "    }\n";
6697         pr "  }\n";
6698     | _ -> ()
6699   ) flags;
6700
6701   (match prereq with
6702    | Disabled ->
6703        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6704    | If _ ->
6705        pr "  if (! %s_prereq ()) {\n" test_name;
6706        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6707        pr "    return 0;\n";
6708        pr "  }\n";
6709        pr "\n";
6710        generate_one_test_body name i test_name init test;
6711    | Unless _ ->
6712        pr "  if (%s_prereq ()) {\n" test_name;
6713        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6714        pr "    return 0;\n";
6715        pr "  }\n";
6716        pr "\n";
6717        generate_one_test_body name i test_name init test;
6718    | Always ->
6719        generate_one_test_body name i test_name init test
6720   );
6721
6722   pr "  return 0;\n";
6723   pr "}\n";
6724   pr "\n";
6725   test_name
6726
6727 and generate_one_test_body name i test_name init test =
6728   (match init with
6729    | InitNone (* XXX at some point, InitNone and InitEmpty became
6730                * folded together as the same thing.  Really we should
6731                * make InitNone do nothing at all, but the tests may
6732                * need to be checked to make sure this is OK.
6733                *)
6734    | InitEmpty ->
6735        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6736        List.iter (generate_test_command_call test_name)
6737          [["blockdev_setrw"; "/dev/sda"];
6738           ["umount_all"];
6739           ["lvm_remove_all"]]
6740    | InitPartition ->
6741        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6742        List.iter (generate_test_command_call test_name)
6743          [["blockdev_setrw"; "/dev/sda"];
6744           ["umount_all"];
6745           ["lvm_remove_all"];
6746           ["part_disk"; "/dev/sda"; "mbr"]]
6747    | InitBasicFS ->
6748        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6749        List.iter (generate_test_command_call test_name)
6750          [["blockdev_setrw"; "/dev/sda"];
6751           ["umount_all"];
6752           ["lvm_remove_all"];
6753           ["part_disk"; "/dev/sda"; "mbr"];
6754           ["mkfs"; "ext2"; "/dev/sda1"];
6755           ["mount_options"; ""; "/dev/sda1"; "/"]]
6756    | InitBasicFSonLVM ->
6757        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6758          test_name;
6759        List.iter (generate_test_command_call test_name)
6760          [["blockdev_setrw"; "/dev/sda"];
6761           ["umount_all"];
6762           ["lvm_remove_all"];
6763           ["part_disk"; "/dev/sda"; "mbr"];
6764           ["pvcreate"; "/dev/sda1"];
6765           ["vgcreate"; "VG"; "/dev/sda1"];
6766           ["lvcreate"; "LV"; "VG"; "8"];
6767           ["mkfs"; "ext2"; "/dev/VG/LV"];
6768           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6769    | InitISOFS ->
6770        pr "  /* InitISOFS for %s */\n" test_name;
6771        List.iter (generate_test_command_call test_name)
6772          [["blockdev_setrw"; "/dev/sda"];
6773           ["umount_all"];
6774           ["lvm_remove_all"];
6775           ["mount_ro"; "/dev/sdd"; "/"]]
6776   );
6777
6778   let get_seq_last = function
6779     | [] ->
6780         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6781           test_name
6782     | seq ->
6783         let seq = List.rev seq in
6784         List.rev (List.tl seq), List.hd seq
6785   in
6786
6787   match test with
6788   | TestRun seq ->
6789       pr "  /* TestRun for %s (%d) */\n" name i;
6790       List.iter (generate_test_command_call test_name) seq
6791   | TestOutput (seq, expected) ->
6792       pr "  /* TestOutput for %s (%d) */\n" name i;
6793       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6794       let seq, last = get_seq_last seq in
6795       let test () =
6796         pr "    if (STRNEQ (r, expected)) {\n";
6797         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6798         pr "      return -1;\n";
6799         pr "    }\n"
6800       in
6801       List.iter (generate_test_command_call test_name) seq;
6802       generate_test_command_call ~test test_name last
6803   | TestOutputList (seq, expected) ->
6804       pr "  /* TestOutputList for %s (%d) */\n" name i;
6805       let seq, last = get_seq_last seq in
6806       let test () =
6807         iteri (
6808           fun i str ->
6809             pr "    if (!r[%d]) {\n" i;
6810             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6811             pr "      print_strings (r);\n";
6812             pr "      return -1;\n";
6813             pr "    }\n";
6814             pr "    {\n";
6815             pr "      const char *expected = \"%s\";\n" (c_quote str);
6816             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6817             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6818             pr "        return -1;\n";
6819             pr "      }\n";
6820             pr "    }\n"
6821         ) expected;
6822         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6823         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6824           test_name;
6825         pr "      print_strings (r);\n";
6826         pr "      return -1;\n";
6827         pr "    }\n"
6828       in
6829       List.iter (generate_test_command_call test_name) seq;
6830       generate_test_command_call ~test test_name last
6831   | TestOutputListOfDevices (seq, expected) ->
6832       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6833       let seq, last = get_seq_last seq in
6834       let test () =
6835         iteri (
6836           fun i str ->
6837             pr "    if (!r[%d]) {\n" i;
6838             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6839             pr "      print_strings (r);\n";
6840             pr "      return -1;\n";
6841             pr "    }\n";
6842             pr "    {\n";
6843             pr "      const char *expected = \"%s\";\n" (c_quote str);
6844             pr "      r[%d][5] = 's';\n" i;
6845             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6846             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6847             pr "        return -1;\n";
6848             pr "      }\n";
6849             pr "    }\n"
6850         ) expected;
6851         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6852         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6853           test_name;
6854         pr "      print_strings (r);\n";
6855         pr "      return -1;\n";
6856         pr "    }\n"
6857       in
6858       List.iter (generate_test_command_call test_name) seq;
6859       generate_test_command_call ~test test_name last
6860   | TestOutputInt (seq, expected) ->
6861       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6862       let seq, last = get_seq_last seq in
6863       let test () =
6864         pr "    if (r != %d) {\n" expected;
6865         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6866           test_name expected;
6867         pr "               (int) r);\n";
6868         pr "      return -1;\n";
6869         pr "    }\n"
6870       in
6871       List.iter (generate_test_command_call test_name) seq;
6872       generate_test_command_call ~test test_name last
6873   | TestOutputIntOp (seq, op, expected) ->
6874       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6875       let seq, last = get_seq_last seq in
6876       let test () =
6877         pr "    if (! (r %s %d)) {\n" op expected;
6878         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6879           test_name op expected;
6880         pr "               (int) r);\n";
6881         pr "      return -1;\n";
6882         pr "    }\n"
6883       in
6884       List.iter (generate_test_command_call test_name) seq;
6885       generate_test_command_call ~test test_name last
6886   | TestOutputTrue seq ->
6887       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6888       let seq, last = get_seq_last seq in
6889       let test () =
6890         pr "    if (!r) {\n";
6891         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6892           test_name;
6893         pr "      return -1;\n";
6894         pr "    }\n"
6895       in
6896       List.iter (generate_test_command_call test_name) seq;
6897       generate_test_command_call ~test test_name last
6898   | TestOutputFalse seq ->
6899       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6900       let seq, last = get_seq_last seq in
6901       let test () =
6902         pr "    if (r) {\n";
6903         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6904           test_name;
6905         pr "      return -1;\n";
6906         pr "    }\n"
6907       in
6908       List.iter (generate_test_command_call test_name) seq;
6909       generate_test_command_call ~test test_name last
6910   | TestOutputLength (seq, expected) ->
6911       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6912       let seq, last = get_seq_last seq in
6913       let test () =
6914         pr "    int j;\n";
6915         pr "    for (j = 0; j < %d; ++j)\n" expected;
6916         pr "      if (r[j] == NULL) {\n";
6917         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6918           test_name;
6919         pr "        print_strings (r);\n";
6920         pr "        return -1;\n";
6921         pr "      }\n";
6922         pr "    if (r[j] != NULL) {\n";
6923         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6924           test_name;
6925         pr "      print_strings (r);\n";
6926         pr "      return -1;\n";
6927         pr "    }\n"
6928       in
6929       List.iter (generate_test_command_call test_name) seq;
6930       generate_test_command_call ~test test_name last
6931   | TestOutputBuffer (seq, expected) ->
6932       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6933       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6934       let seq, last = get_seq_last seq in
6935       let len = String.length expected in
6936       let test () =
6937         pr "    if (size != %d) {\n" len;
6938         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6939         pr "      return -1;\n";
6940         pr "    }\n";
6941         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6942         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6943         pr "      return -1;\n";
6944         pr "    }\n"
6945       in
6946       List.iter (generate_test_command_call test_name) seq;
6947       generate_test_command_call ~test test_name last
6948   | TestOutputStruct (seq, checks) ->
6949       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6950       let seq, last = get_seq_last seq in
6951       let test () =
6952         List.iter (
6953           function
6954           | CompareWithInt (field, expected) ->
6955               pr "    if (r->%s != %d) {\n" field expected;
6956               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6957                 test_name field expected;
6958               pr "               (int) r->%s);\n" field;
6959               pr "      return -1;\n";
6960               pr "    }\n"
6961           | CompareWithIntOp (field, op, expected) ->
6962               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6963               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6964                 test_name field op expected;
6965               pr "               (int) r->%s);\n" field;
6966               pr "      return -1;\n";
6967               pr "    }\n"
6968           | CompareWithString (field, expected) ->
6969               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6970               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6971                 test_name field expected;
6972               pr "               r->%s);\n" field;
6973               pr "      return -1;\n";
6974               pr "    }\n"
6975           | CompareFieldsIntEq (field1, field2) ->
6976               pr "    if (r->%s != r->%s) {\n" field1 field2;
6977               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6978                 test_name field1 field2;
6979               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6980               pr "      return -1;\n";
6981               pr "    }\n"
6982           | CompareFieldsStrEq (field1, field2) ->
6983               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6984               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6985                 test_name field1 field2;
6986               pr "               r->%s, r->%s);\n" field1 field2;
6987               pr "      return -1;\n";
6988               pr "    }\n"
6989         ) checks
6990       in
6991       List.iter (generate_test_command_call test_name) seq;
6992       generate_test_command_call ~test test_name last
6993   | TestLastFail seq ->
6994       pr "  /* TestLastFail for %s (%d) */\n" name i;
6995       let seq, last = get_seq_last seq in
6996       List.iter (generate_test_command_call test_name) seq;
6997       generate_test_command_call test_name ~expect_error:true last
6998
6999 (* Generate the code to run a command, leaving the result in 'r'.
7000  * If you expect to get an error then you should set expect_error:true.
7001  *)
7002 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7003   match cmd with
7004   | [] -> assert false
7005   | name :: args ->
7006       (* Look up the command to find out what args/ret it has. *)
7007       let style =
7008         try
7009           let _, style, _, _, _, _, _ =
7010             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7011           style
7012         with Not_found ->
7013           failwithf "%s: in test, command %s was not found" test_name name in
7014
7015       if List.length (snd style) <> List.length args then
7016         failwithf "%s: in test, wrong number of args given to %s"
7017           test_name name;
7018
7019       pr "  {\n";
7020
7021       List.iter (
7022         function
7023         | OptString n, "NULL" -> ()
7024         | Pathname n, arg
7025         | Device n, arg
7026         | Dev_or_Path n, arg
7027         | String n, arg
7028         | OptString n, arg ->
7029             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7030         | Int _, _
7031         | Int64 _, _
7032         | Bool _, _
7033         | FileIn _, _ | FileOut _, _ -> ()
7034         | StringList n, "" | DeviceList n, "" ->
7035             pr "    const char *const %s[1] = { NULL };\n" n
7036         | StringList n, arg | DeviceList n, arg ->
7037             let strs = string_split " " arg in
7038             iteri (
7039               fun i str ->
7040                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7041             ) strs;
7042             pr "    const char *const %s[] = {\n" n;
7043             iteri (
7044               fun i _ -> pr "      %s_%d,\n" n i
7045             ) strs;
7046             pr "      NULL\n";
7047             pr "    };\n";
7048       ) (List.combine (snd style) args);
7049
7050       let error_code =
7051         match fst style with
7052         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7053         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7054         | RConstString _ | RConstOptString _ ->
7055             pr "    const char *r;\n"; "NULL"
7056         | RString _ -> pr "    char *r;\n"; "NULL"
7057         | RStringList _ | RHashtable _ ->
7058             pr "    char **r;\n";
7059             pr "    int i;\n";
7060             "NULL"
7061         | RStruct (_, typ) ->
7062             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7063         | RStructList (_, typ) ->
7064             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7065         | RBufferOut _ ->
7066             pr "    char *r;\n";
7067             pr "    size_t size;\n";
7068             "NULL" in
7069
7070       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7071       pr "    r = guestfs_%s (g" name;
7072
7073       (* Generate the parameters. *)
7074       List.iter (
7075         function
7076         | OptString _, "NULL" -> pr ", NULL"
7077         | Pathname n, _
7078         | Device n, _ | Dev_or_Path n, _
7079         | String n, _
7080         | OptString n, _ ->
7081             pr ", %s" n
7082         | FileIn _, arg | FileOut _, arg ->
7083             pr ", \"%s\"" (c_quote arg)
7084         | StringList n, _ | DeviceList n, _ ->
7085             pr ", (char **) %s" n
7086         | Int _, arg ->
7087             let i =
7088               try int_of_string arg
7089               with Failure "int_of_string" ->
7090                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7091             pr ", %d" i
7092         | Int64 _, arg ->
7093             let i =
7094               try Int64.of_string arg
7095               with Failure "int_of_string" ->
7096                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7097             pr ", %Ld" i
7098         | Bool _, arg ->
7099             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7100       ) (List.combine (snd style) args);
7101
7102       (match fst style with
7103        | RBufferOut _ -> pr ", &size"
7104        | _ -> ()
7105       );
7106
7107       pr ");\n";
7108
7109       if not expect_error then
7110         pr "    if (r == %s)\n" error_code
7111       else
7112         pr "    if (r != %s)\n" error_code;
7113       pr "      return -1;\n";
7114
7115       (* Insert the test code. *)
7116       (match test with
7117        | None -> ()
7118        | Some f -> f ()
7119       );
7120
7121       (match fst style with
7122        | RErr | RInt _ | RInt64 _ | RBool _
7123        | RConstString _ | RConstOptString _ -> ()
7124        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7125        | RStringList _ | RHashtable _ ->
7126            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7127            pr "      free (r[i]);\n";
7128            pr "    free (r);\n"
7129        | RStruct (_, typ) ->
7130            pr "    guestfs_free_%s (r);\n" typ
7131        | RStructList (_, typ) ->
7132            pr "    guestfs_free_%s_list (r);\n" typ
7133       );
7134
7135       pr "  }\n"
7136
7137 and c_quote str =
7138   let str = replace_str str "\r" "\\r" in
7139   let str = replace_str str "\n" "\\n" in
7140   let str = replace_str str "\t" "\\t" in
7141   let str = replace_str str "\000" "\\0" in
7142   str
7143
7144 (* Generate a lot of different functions for guestfish. *)
7145 and generate_fish_cmds () =
7146   generate_header CStyle GPLv2plus;
7147
7148   let all_functions =
7149     List.filter (
7150       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7151     ) all_functions in
7152   let all_functions_sorted =
7153     List.filter (
7154       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7155     ) all_functions_sorted in
7156
7157   pr "#include <config.h>\n";
7158   pr "\n";
7159   pr "#include <stdio.h>\n";
7160   pr "#include <stdlib.h>\n";
7161   pr "#include <string.h>\n";
7162   pr "#include <inttypes.h>\n";
7163   pr "\n";
7164   pr "#include <guestfs.h>\n";
7165   pr "#include \"c-ctype.h\"\n";
7166   pr "#include \"full-write.h\"\n";
7167   pr "#include \"xstrtol.h\"\n";
7168   pr "#include \"fish.h\"\n";
7169   pr "\n";
7170
7171   (* list_commands function, which implements guestfish -h *)
7172   pr "void list_commands (void)\n";
7173   pr "{\n";
7174   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7175   pr "  list_builtin_commands ();\n";
7176   List.iter (
7177     fun (name, _, _, flags, _, shortdesc, _) ->
7178       let name = replace_char name '_' '-' in
7179       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7180         name shortdesc
7181   ) all_functions_sorted;
7182   pr "  printf (\"    %%s\\n\",";
7183   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7184   pr "}\n";
7185   pr "\n";
7186
7187   (* display_command function, which implements guestfish -h cmd *)
7188   pr "void display_command (const char *cmd)\n";
7189   pr "{\n";
7190   List.iter (
7191     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7192       let name2 = replace_char name '_' '-' in
7193       let alias =
7194         try find_map (function FishAlias n -> Some n | _ -> None) flags
7195         with Not_found -> name in
7196       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7197       let synopsis =
7198         match snd style with
7199         | [] -> name2
7200         | args ->
7201             sprintf "%s %s"
7202               name2 (String.concat " " (List.map name_of_argt args)) in
7203
7204       let warnings =
7205         if List.mem ProtocolLimitWarning flags then
7206           ("\n\n" ^ protocol_limit_warning)
7207         else "" in
7208
7209       (* For DangerWillRobinson commands, we should probably have
7210        * guestfish prompt before allowing you to use them (especially
7211        * in interactive mode). XXX
7212        *)
7213       let warnings =
7214         warnings ^
7215           if List.mem DangerWillRobinson flags then
7216             ("\n\n" ^ danger_will_robinson)
7217           else "" in
7218
7219       let warnings =
7220         warnings ^
7221           match deprecation_notice flags with
7222           | None -> ""
7223           | Some txt -> "\n\n" ^ txt in
7224
7225       let describe_alias =
7226         if name <> alias then
7227           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7228         else "" in
7229
7230       pr "  if (";
7231       pr "STRCASEEQ (cmd, \"%s\")" name;
7232       if name <> name2 then
7233         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7234       if name <> alias then
7235         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7236       pr ")\n";
7237       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7238         name2 shortdesc
7239         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7240          "=head1 DESCRIPTION\n\n" ^
7241          longdesc ^ warnings ^ describe_alias);
7242       pr "  else\n"
7243   ) all_functions;
7244   pr "    display_builtin_command (cmd);\n";
7245   pr "}\n";
7246   pr "\n";
7247
7248   let emit_print_list_function typ =
7249     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7250       typ typ typ;
7251     pr "{\n";
7252     pr "  unsigned int i;\n";
7253     pr "\n";
7254     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7255     pr "    printf (\"[%%d] = {\\n\", i);\n";
7256     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7257     pr "    printf (\"}\\n\");\n";
7258     pr "  }\n";
7259     pr "}\n";
7260     pr "\n";
7261   in
7262
7263   (* print_* functions *)
7264   List.iter (
7265     fun (typ, cols) ->
7266       let needs_i =
7267         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7268
7269       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7270       pr "{\n";
7271       if needs_i then (
7272         pr "  unsigned int i;\n";
7273         pr "\n"
7274       );
7275       List.iter (
7276         function
7277         | name, FString ->
7278             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7279         | name, FUUID ->
7280             pr "  printf (\"%%s%s: \", indent);\n" name;
7281             pr "  for (i = 0; i < 32; ++i)\n";
7282             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7283             pr "  printf (\"\\n\");\n"
7284         | name, FBuffer ->
7285             pr "  printf (\"%%s%s: \", indent);\n" name;
7286             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7287             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7288             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7289             pr "    else\n";
7290             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7291             pr "  printf (\"\\n\");\n"
7292         | name, (FUInt64|FBytes) ->
7293             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7294               name typ name
7295         | name, FInt64 ->
7296             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7297               name typ name
7298         | name, FUInt32 ->
7299             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7300               name typ name
7301         | name, FInt32 ->
7302             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7303               name typ name
7304         | name, FChar ->
7305             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7306               name typ name
7307         | name, FOptPercent ->
7308             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7309               typ name name typ name;
7310             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7311       ) cols;
7312       pr "}\n";
7313       pr "\n";
7314   ) structs;
7315
7316   (* Emit a print_TYPE_list function definition only if that function is used. *)
7317   List.iter (
7318     function
7319     | typ, (RStructListOnly | RStructAndList) ->
7320         (* generate the function for typ *)
7321         emit_print_list_function typ
7322     | typ, _ -> () (* empty *)
7323   ) (rstructs_used_by all_functions);
7324
7325   (* Emit a print_TYPE function definition only if that function is used. *)
7326   List.iter (
7327     function
7328     | typ, (RStructOnly | RStructAndList) ->
7329         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7330         pr "{\n";
7331         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7332         pr "}\n";
7333         pr "\n";
7334     | typ, _ -> () (* empty *)
7335   ) (rstructs_used_by all_functions);
7336
7337   (* run_<action> actions *)
7338   List.iter (
7339     fun (name, style, _, flags, _, _, _) ->
7340       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7341       pr "{\n";
7342       (match fst style with
7343        | RErr
7344        | RInt _
7345        | RBool _ -> pr "  int r;\n"
7346        | RInt64 _ -> pr "  int64_t r;\n"
7347        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7348        | RString _ -> pr "  char *r;\n"
7349        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7350        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7351        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7352        | RBufferOut _ ->
7353            pr "  char *r;\n";
7354            pr "  size_t size;\n";
7355       );
7356       List.iter (
7357         function
7358         | Device n
7359         | String n
7360         | OptString n
7361         | FileIn n
7362         | FileOut n -> pr "  const char *%s;\n" n
7363         | Pathname n
7364         | Dev_or_Path n -> pr "  char *%s;\n" n
7365         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7366         | Bool n -> pr "  int %s;\n" n
7367         | Int n -> pr "  int %s;\n" n
7368         | Int64 n -> pr "  int64_t %s;\n" n
7369       ) (snd style);
7370
7371       (* Check and convert parameters. *)
7372       let argc_expected = List.length (snd style) in
7373       pr "  if (argc != %d) {\n" argc_expected;
7374       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7375         argc_expected;
7376       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7377       pr "    return -1;\n";
7378       pr "  }\n";
7379
7380       let parse_integer fn fntyp rtyp range name i =
7381         pr "  {\n";
7382         pr "    strtol_error xerr;\n";
7383         pr "    %s r;\n" fntyp;
7384         pr "\n";
7385         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7386         pr "    if (xerr != LONGINT_OK) {\n";
7387         pr "      fprintf (stderr,\n";
7388         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7389         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7390         pr "      return -1;\n";
7391         pr "    }\n";
7392         (match range with
7393          | None -> ()
7394          | Some (min, max, comment) ->
7395              pr "    /* %s */\n" comment;
7396              pr "    if (r < %s || r > %s) {\n" min max;
7397              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7398                name;
7399              pr "      return -1;\n";
7400              pr "    }\n";
7401              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7402         );
7403         pr "    %s = r;\n" name;
7404         pr "  }\n";
7405       in
7406
7407       iteri (
7408         fun i ->
7409           function
7410           | Device name
7411           | String name ->
7412               pr "  %s = argv[%d];\n" name i
7413           | Pathname name
7414           | Dev_or_Path name ->
7415               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7416               pr "  if (%s == NULL) return -1;\n" name
7417           | OptString name ->
7418               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7419                 name i i
7420           | FileIn name ->
7421               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7422                 name i i
7423           | FileOut name ->
7424               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7425                 name i i
7426           | StringList name | DeviceList name ->
7427               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7428               pr "  if (%s == NULL) return -1;\n" name;
7429           | Bool name ->
7430               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7431           | Int name ->
7432               let range =
7433                 let min = "(-(2LL<<30))"
7434                 and max = "((2LL<<30)-1)"
7435                 and comment =
7436                   "The Int type in the generator is a signed 31 bit int." in
7437                 Some (min, max, comment) in
7438               parse_integer "xstrtoll" "long long" "int" range name i
7439           | Int64 name ->
7440               parse_integer "xstrtoll" "long long" "int64_t" None name i
7441       ) (snd style);
7442
7443       (* Call C API function. *)
7444       let fn =
7445         try find_map (function FishAction n -> Some n | _ -> None) flags
7446         with Not_found -> sprintf "guestfs_%s" name in
7447       pr "  r = %s " fn;
7448       generate_c_call_args ~handle:"g" style;
7449       pr ";\n";
7450
7451       List.iter (
7452         function
7453         | Device name | String name
7454         | OptString name | FileIn name | FileOut name | Bool name
7455         | Int name | Int64 name -> ()
7456         | Pathname name | Dev_or_Path name ->
7457             pr "  free (%s);\n" name
7458         | StringList name | DeviceList name ->
7459             pr "  free_strings (%s);\n" name
7460       ) (snd style);
7461
7462       (* Any output flags? *)
7463       let fish_output =
7464         let flags = filter_map (
7465           function FishOutput flag -> Some flag | _ -> None
7466         ) flags in
7467         match flags with
7468         | [] -> None
7469         | [f] -> Some f
7470         | _ ->
7471             failwithf "%s: more than one FishOutput flag is not allowed" name in
7472
7473       (* Check return value for errors and display command results. *)
7474       (match fst style with
7475        | RErr -> pr "  return r;\n"
7476        | RInt _ ->
7477            pr "  if (r == -1) return -1;\n";
7478            (match fish_output with
7479             | None ->
7480                 pr "  printf (\"%%d\\n\", r);\n";
7481             | Some FishOutputOctal ->
7482                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7483             | Some FishOutputHexadecimal ->
7484                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7485            pr "  return 0;\n"
7486        | RInt64 _ ->
7487            pr "  if (r == -1) return -1;\n";
7488            (match fish_output with
7489             | None ->
7490                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7491             | Some FishOutputOctal ->
7492                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7493             | Some FishOutputHexadecimal ->
7494                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7495            pr "  return 0;\n"
7496        | RBool _ ->
7497            pr "  if (r == -1) return -1;\n";
7498            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7499            pr "  return 0;\n"
7500        | RConstString _ ->
7501            pr "  if (r == NULL) return -1;\n";
7502            pr "  printf (\"%%s\\n\", r);\n";
7503            pr "  return 0;\n"
7504        | RConstOptString _ ->
7505            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7506            pr "  return 0;\n"
7507        | RString _ ->
7508            pr "  if (r == NULL) return -1;\n";
7509            pr "  printf (\"%%s\\n\", r);\n";
7510            pr "  free (r);\n";
7511            pr "  return 0;\n"
7512        | RStringList _ ->
7513            pr "  if (r == NULL) return -1;\n";
7514            pr "  print_strings (r);\n";
7515            pr "  free_strings (r);\n";
7516            pr "  return 0;\n"
7517        | RStruct (_, typ) ->
7518            pr "  if (r == NULL) return -1;\n";
7519            pr "  print_%s (r);\n" typ;
7520            pr "  guestfs_free_%s (r);\n" typ;
7521            pr "  return 0;\n"
7522        | RStructList (_, typ) ->
7523            pr "  if (r == NULL) return -1;\n";
7524            pr "  print_%s_list (r);\n" typ;
7525            pr "  guestfs_free_%s_list (r);\n" typ;
7526            pr "  return 0;\n"
7527        | RHashtable _ ->
7528            pr "  if (r == NULL) return -1;\n";
7529            pr "  print_table (r);\n";
7530            pr "  free_strings (r);\n";
7531            pr "  return 0;\n"
7532        | RBufferOut _ ->
7533            pr "  if (r == NULL) return -1;\n";
7534            pr "  if (full_write (1, r, size) != size) {\n";
7535            pr "    perror (\"write\");\n";
7536            pr "    free (r);\n";
7537            pr "    return -1;\n";
7538            pr "  }\n";
7539            pr "  free (r);\n";
7540            pr "  return 0;\n"
7541       );
7542       pr "}\n";
7543       pr "\n"
7544   ) all_functions;
7545
7546   (* run_action function *)
7547   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7548   pr "{\n";
7549   List.iter (
7550     fun (name, _, _, flags, _, _, _) ->
7551       let name2 = replace_char name '_' '-' in
7552       let alias =
7553         try find_map (function FishAlias n -> Some n | _ -> None) flags
7554         with Not_found -> name in
7555       pr "  if (";
7556       pr "STRCASEEQ (cmd, \"%s\")" name;
7557       if name <> name2 then
7558         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7559       if name <> alias then
7560         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7561       pr ")\n";
7562       pr "    return run_%s (cmd, argc, argv);\n" name;
7563       pr "  else\n";
7564   ) all_functions;
7565   pr "    {\n";
7566   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7567   pr "      if (command_num == 1)\n";
7568   pr "        extended_help_message ();\n";
7569   pr "      return -1;\n";
7570   pr "    }\n";
7571   pr "  return 0;\n";
7572   pr "}\n";
7573   pr "\n"
7574
7575 (* Readline completion for guestfish. *)
7576 and generate_fish_completion () =
7577   generate_header CStyle GPLv2plus;
7578
7579   let all_functions =
7580     List.filter (
7581       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7582     ) all_functions in
7583
7584   pr "\
7585 #include <config.h>
7586
7587 #include <stdio.h>
7588 #include <stdlib.h>
7589 #include <string.h>
7590
7591 #ifdef HAVE_LIBREADLINE
7592 #include <readline/readline.h>
7593 #endif
7594
7595 #include \"fish.h\"
7596
7597 #ifdef HAVE_LIBREADLINE
7598
7599 static const char *const commands[] = {
7600   BUILTIN_COMMANDS_FOR_COMPLETION,
7601 ";
7602
7603   (* Get the commands, including the aliases.  They don't need to be
7604    * sorted - the generator() function just does a dumb linear search.
7605    *)
7606   let commands =
7607     List.map (
7608       fun (name, _, _, flags, _, _, _) ->
7609         let name2 = replace_char name '_' '-' in
7610         let alias =
7611           try find_map (function FishAlias n -> Some n | _ -> None) flags
7612           with Not_found -> name in
7613
7614         if name <> alias then [name2; alias] else [name2]
7615     ) all_functions in
7616   let commands = List.flatten commands in
7617
7618   List.iter (pr "  \"%s\",\n") commands;
7619
7620   pr "  NULL
7621 };
7622
7623 static char *
7624 generator (const char *text, int state)
7625 {
7626   static int index, len;
7627   const char *name;
7628
7629   if (!state) {
7630     index = 0;
7631     len = strlen (text);
7632   }
7633
7634   rl_attempted_completion_over = 1;
7635
7636   while ((name = commands[index]) != NULL) {
7637     index++;
7638     if (STRCASEEQLEN (name, text, len))
7639       return strdup (name);
7640   }
7641
7642   return NULL;
7643 }
7644
7645 #endif /* HAVE_LIBREADLINE */
7646
7647 #ifdef HAVE_RL_COMPLETION_MATCHES
7648 #define RL_COMPLETION_MATCHES rl_completion_matches
7649 #else
7650 #ifdef HAVE_COMPLETION_MATCHES
7651 #define RL_COMPLETION_MATCHES completion_matches
7652 #endif
7653 #endif /* else just fail if we don't have either symbol */
7654
7655 char **
7656 do_completion (const char *text, int start, int end)
7657 {
7658   char **matches = NULL;
7659
7660 #ifdef HAVE_LIBREADLINE
7661   rl_completion_append_character = ' ';
7662
7663   if (start == 0)
7664     matches = RL_COMPLETION_MATCHES (text, generator);
7665   else if (complete_dest_paths)
7666     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7667 #endif
7668
7669   return matches;
7670 }
7671 ";
7672
7673 (* Generate the POD documentation for guestfish. *)
7674 and generate_fish_actions_pod () =
7675   let all_functions_sorted =
7676     List.filter (
7677       fun (_, _, _, flags, _, _, _) ->
7678         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7679     ) all_functions_sorted in
7680
7681   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7682
7683   List.iter (
7684     fun (name, style, _, flags, _, _, longdesc) ->
7685       let longdesc =
7686         Str.global_substitute rex (
7687           fun s ->
7688             let sub =
7689               try Str.matched_group 1 s
7690               with Not_found ->
7691                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7692             "C<" ^ replace_char sub '_' '-' ^ ">"
7693         ) longdesc in
7694       let name = replace_char name '_' '-' in
7695       let alias =
7696         try find_map (function FishAlias n -> Some n | _ -> None) flags
7697         with Not_found -> name in
7698
7699       pr "=head2 %s" name;
7700       if name <> alias then
7701         pr " | %s" alias;
7702       pr "\n";
7703       pr "\n";
7704       pr " %s" name;
7705       List.iter (
7706         function
7707         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7708         | OptString n -> pr " %s" n
7709         | StringList n | DeviceList n -> pr " '%s ...'" n
7710         | Bool _ -> pr " true|false"
7711         | Int n -> pr " %s" n
7712         | Int64 n -> pr " %s" n
7713         | FileIn n | FileOut n -> pr " (%s|-)" n
7714       ) (snd style);
7715       pr "\n";
7716       pr "\n";
7717       pr "%s\n\n" longdesc;
7718
7719       if List.exists (function FileIn _ | FileOut _ -> true
7720                       | _ -> false) (snd style) then
7721         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7722
7723       if List.mem ProtocolLimitWarning flags then
7724         pr "%s\n\n" protocol_limit_warning;
7725
7726       if List.mem DangerWillRobinson flags then
7727         pr "%s\n\n" danger_will_robinson;
7728
7729       match deprecation_notice flags with
7730       | None -> ()
7731       | Some txt -> pr "%s\n\n" txt
7732   ) all_functions_sorted
7733
7734 (* Generate a C function prototype. *)
7735 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7736     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7737     ?(prefix = "")
7738     ?handle name style =
7739   if extern then pr "extern ";
7740   if static then pr "static ";
7741   (match fst style with
7742    | RErr -> pr "int "
7743    | RInt _ -> pr "int "
7744    | RInt64 _ -> pr "int64_t "
7745    | RBool _ -> pr "int "
7746    | RConstString _ | RConstOptString _ -> pr "const char *"
7747    | RString _ | RBufferOut _ -> pr "char *"
7748    | RStringList _ | RHashtable _ -> pr "char **"
7749    | RStruct (_, typ) ->
7750        if not in_daemon then pr "struct guestfs_%s *" typ
7751        else pr "guestfs_int_%s *" typ
7752    | RStructList (_, typ) ->
7753        if not in_daemon then pr "struct guestfs_%s_list *" typ
7754        else pr "guestfs_int_%s_list *" typ
7755   );
7756   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7757   pr "%s%s (" prefix name;
7758   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7759     pr "void"
7760   else (
7761     let comma = ref false in
7762     (match handle with
7763      | None -> ()
7764      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7765     );
7766     let next () =
7767       if !comma then (
7768         if single_line then pr ", " else pr ",\n\t\t"
7769       );
7770       comma := true
7771     in
7772     List.iter (
7773       function
7774       | Pathname n
7775       | Device n | Dev_or_Path n
7776       | String n
7777       | OptString n ->
7778           next ();
7779           pr "const char *%s" n
7780       | StringList n | DeviceList n ->
7781           next ();
7782           pr "char *const *%s" n
7783       | Bool n -> next (); pr "int %s" n
7784       | Int n -> next (); pr "int %s" n
7785       | Int64 n -> next (); pr "int64_t %s" n
7786       | FileIn n
7787       | FileOut n ->
7788           if not in_daemon then (next (); pr "const char *%s" n)
7789     ) (snd style);
7790     if is_RBufferOut then (next (); pr "size_t *size_r");
7791   );
7792   pr ")";
7793   if semicolon then pr ";";
7794   if newline then pr "\n"
7795
7796 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7797 and generate_c_call_args ?handle ?(decl = false) style =
7798   pr "(";
7799   let comma = ref false in
7800   let next () =
7801     if !comma then pr ", ";
7802     comma := true
7803   in
7804   (match handle with
7805    | None -> ()
7806    | Some handle -> pr "%s" handle; comma := true
7807   );
7808   List.iter (
7809     fun arg ->
7810       next ();
7811       pr "%s" (name_of_argt arg)
7812   ) (snd style);
7813   (* For RBufferOut calls, add implicit &size parameter. *)
7814   if not decl then (
7815     match fst style with
7816     | RBufferOut _ ->
7817         next ();
7818         pr "&size"
7819     | _ -> ()
7820   );
7821   pr ")"
7822
7823 (* Generate the OCaml bindings interface. *)
7824 and generate_ocaml_mli () =
7825   generate_header OCamlStyle LGPLv2plus;
7826
7827   pr "\
7828 (** For API documentation you should refer to the C API
7829     in the guestfs(3) manual page.  The OCaml API uses almost
7830     exactly the same calls. *)
7831
7832 type t
7833 (** A [guestfs_h] handle. *)
7834
7835 exception Error of string
7836 (** This exception is raised when there is an error. *)
7837
7838 exception Handle_closed of string
7839 (** This exception is raised if you use a {!Guestfs.t} handle
7840     after calling {!close} on it.  The string is the name of
7841     the function. *)
7842
7843 val create : unit -> t
7844 (** Create a {!Guestfs.t} handle. *)
7845
7846 val close : t -> unit
7847 (** Close the {!Guestfs.t} handle and free up all resources used
7848     by it immediately.
7849
7850     Handles are closed by the garbage collector when they become
7851     unreferenced, but callers can call this in order to provide
7852     predictable cleanup. *)
7853
7854 ";
7855   generate_ocaml_structure_decls ();
7856
7857   (* The actions. *)
7858   List.iter (
7859     fun (name, style, _, _, _, shortdesc, _) ->
7860       generate_ocaml_prototype name style;
7861       pr "(** %s *)\n" shortdesc;
7862       pr "\n"
7863   ) all_functions_sorted
7864
7865 (* Generate the OCaml bindings implementation. *)
7866 and generate_ocaml_ml () =
7867   generate_header OCamlStyle LGPLv2plus;
7868
7869   pr "\
7870 type t
7871
7872 exception Error of string
7873 exception Handle_closed of string
7874
7875 external create : unit -> t = \"ocaml_guestfs_create\"
7876 external close : t -> unit = \"ocaml_guestfs_close\"
7877
7878 (* Give the exceptions names, so they can be raised from the C code. *)
7879 let () =
7880   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7881   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7882
7883 ";
7884
7885   generate_ocaml_structure_decls ();
7886
7887   (* The actions. *)
7888   List.iter (
7889     fun (name, style, _, _, _, shortdesc, _) ->
7890       generate_ocaml_prototype ~is_external:true name style;
7891   ) all_functions_sorted
7892
7893 (* Generate the OCaml bindings C implementation. *)
7894 and generate_ocaml_c () =
7895   generate_header CStyle LGPLv2plus;
7896
7897   pr "\
7898 #include <stdio.h>
7899 #include <stdlib.h>
7900 #include <string.h>
7901
7902 #include <caml/config.h>
7903 #include <caml/alloc.h>
7904 #include <caml/callback.h>
7905 #include <caml/fail.h>
7906 #include <caml/memory.h>
7907 #include <caml/mlvalues.h>
7908 #include <caml/signals.h>
7909
7910 #include <guestfs.h>
7911
7912 #include \"guestfs_c.h\"
7913
7914 /* Copy a hashtable of string pairs into an assoc-list.  We return
7915  * the list in reverse order, but hashtables aren't supposed to be
7916  * ordered anyway.
7917  */
7918 static CAMLprim value
7919 copy_table (char * const * argv)
7920 {
7921   CAMLparam0 ();
7922   CAMLlocal5 (rv, pairv, kv, vv, cons);
7923   int i;
7924
7925   rv = Val_int (0);
7926   for (i = 0; argv[i] != NULL; i += 2) {
7927     kv = caml_copy_string (argv[i]);
7928     vv = caml_copy_string (argv[i+1]);
7929     pairv = caml_alloc (2, 0);
7930     Store_field (pairv, 0, kv);
7931     Store_field (pairv, 1, vv);
7932     cons = caml_alloc (2, 0);
7933     Store_field (cons, 1, rv);
7934     rv = cons;
7935     Store_field (cons, 0, pairv);
7936   }
7937
7938   CAMLreturn (rv);
7939 }
7940
7941 ";
7942
7943   (* Struct copy functions. *)
7944
7945   let emit_ocaml_copy_list_function typ =
7946     pr "static CAMLprim value\n";
7947     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7948     pr "{\n";
7949     pr "  CAMLparam0 ();\n";
7950     pr "  CAMLlocal2 (rv, v);\n";
7951     pr "  unsigned int i;\n";
7952     pr "\n";
7953     pr "  if (%ss->len == 0)\n" typ;
7954     pr "    CAMLreturn (Atom (0));\n";
7955     pr "  else {\n";
7956     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7957     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7958     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7959     pr "      caml_modify (&Field (rv, i), v);\n";
7960     pr "    }\n";
7961     pr "    CAMLreturn (rv);\n";
7962     pr "  }\n";
7963     pr "}\n";
7964     pr "\n";
7965   in
7966
7967   List.iter (
7968     fun (typ, cols) ->
7969       let has_optpercent_col =
7970         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7971
7972       pr "static CAMLprim value\n";
7973       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7974       pr "{\n";
7975       pr "  CAMLparam0 ();\n";
7976       if has_optpercent_col then
7977         pr "  CAMLlocal3 (rv, v, v2);\n"
7978       else
7979         pr "  CAMLlocal2 (rv, v);\n";
7980       pr "\n";
7981       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7982       iteri (
7983         fun i col ->
7984           (match col with
7985            | name, FString ->
7986                pr "  v = caml_copy_string (%s->%s);\n" typ name
7987            | name, FBuffer ->
7988                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7989                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7990                  typ name typ name
7991            | name, FUUID ->
7992                pr "  v = caml_alloc_string (32);\n";
7993                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7994            | name, (FBytes|FInt64|FUInt64) ->
7995                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7996            | name, (FInt32|FUInt32) ->
7997                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7998            | name, FOptPercent ->
7999                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8000                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8001                pr "    v = caml_alloc (1, 0);\n";
8002                pr "    Store_field (v, 0, v2);\n";
8003                pr "  } else /* None */\n";
8004                pr "    v = Val_int (0);\n";
8005            | name, FChar ->
8006                pr "  v = Val_int (%s->%s);\n" typ name
8007           );
8008           pr "  Store_field (rv, %d, v);\n" i
8009       ) cols;
8010       pr "  CAMLreturn (rv);\n";
8011       pr "}\n";
8012       pr "\n";
8013   ) structs;
8014
8015   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8016   List.iter (
8017     function
8018     | typ, (RStructListOnly | RStructAndList) ->
8019         (* generate the function for typ *)
8020         emit_ocaml_copy_list_function typ
8021     | typ, _ -> () (* empty *)
8022   ) (rstructs_used_by all_functions);
8023
8024   (* The wrappers. *)
8025   List.iter (
8026     fun (name, style, _, _, _, _, _) ->
8027       pr "/* Automatically generated wrapper for function\n";
8028       pr " * ";
8029       generate_ocaml_prototype name style;
8030       pr " */\n";
8031       pr "\n";
8032
8033       let params =
8034         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8035
8036       let needs_extra_vs =
8037         match fst style with RConstOptString _ -> true | _ -> false in
8038
8039       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8040       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8041       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8042       pr "\n";
8043
8044       pr "CAMLprim value\n";
8045       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8046       List.iter (pr ", value %s") (List.tl params);
8047       pr ")\n";
8048       pr "{\n";
8049
8050       (match params with
8051        | [p1; p2; p3; p4; p5] ->
8052            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8053        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8054            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8055            pr "  CAMLxparam%d (%s);\n"
8056              (List.length rest) (String.concat ", " rest)
8057        | ps ->
8058            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8059       );
8060       if not needs_extra_vs then
8061         pr "  CAMLlocal1 (rv);\n"
8062       else
8063         pr "  CAMLlocal3 (rv, v, v2);\n";
8064       pr "\n";
8065
8066       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8067       pr "  if (g == NULL)\n";
8068       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8069       pr "\n";
8070
8071       List.iter (
8072         function
8073         | Pathname n
8074         | Device n | Dev_or_Path n
8075         | String n
8076         | FileIn n
8077         | FileOut n ->
8078             pr "  const char *%s = String_val (%sv);\n" n n
8079         | OptString n ->
8080             pr "  const char *%s =\n" n;
8081             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8082               n n
8083         | StringList n | DeviceList n ->
8084             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8085         | Bool n ->
8086             pr "  int %s = Bool_val (%sv);\n" n n
8087         | Int n ->
8088             pr "  int %s = Int_val (%sv);\n" n n
8089         | Int64 n ->
8090             pr "  int64_t %s = Int64_val (%sv);\n" n n
8091       ) (snd style);
8092       let error_code =
8093         match fst style with
8094         | RErr -> pr "  int r;\n"; "-1"
8095         | RInt _ -> pr "  int r;\n"; "-1"
8096         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8097         | RBool _ -> pr "  int r;\n"; "-1"
8098         | RConstString _ | RConstOptString _ ->
8099             pr "  const char *r;\n"; "NULL"
8100         | RString _ -> pr "  char *r;\n"; "NULL"
8101         | RStringList _ ->
8102             pr "  int i;\n";
8103             pr "  char **r;\n";
8104             "NULL"
8105         | RStruct (_, typ) ->
8106             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8107         | RStructList (_, typ) ->
8108             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8109         | RHashtable _ ->
8110             pr "  int i;\n";
8111             pr "  char **r;\n";
8112             "NULL"
8113         | RBufferOut _ ->
8114             pr "  char *r;\n";
8115             pr "  size_t size;\n";
8116             "NULL" in
8117       pr "\n";
8118
8119       pr "  caml_enter_blocking_section ();\n";
8120       pr "  r = guestfs_%s " name;
8121       generate_c_call_args ~handle:"g" style;
8122       pr ";\n";
8123       pr "  caml_leave_blocking_section ();\n";
8124
8125       List.iter (
8126         function
8127         | StringList n | DeviceList n ->
8128             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8129         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8130         | Bool _ | Int _ | Int64 _
8131         | FileIn _ | FileOut _ -> ()
8132       ) (snd style);
8133
8134       pr "  if (r == %s)\n" error_code;
8135       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8136       pr "\n";
8137
8138       (match fst style with
8139        | RErr -> pr "  rv = Val_unit;\n"
8140        | RInt _ -> pr "  rv = Val_int (r);\n"
8141        | RInt64 _ ->
8142            pr "  rv = caml_copy_int64 (r);\n"
8143        | RBool _ -> pr "  rv = Val_bool (r);\n"
8144        | RConstString _ ->
8145            pr "  rv = caml_copy_string (r);\n"
8146        | RConstOptString _ ->
8147            pr "  if (r) { /* Some string */\n";
8148            pr "    v = caml_alloc (1, 0);\n";
8149            pr "    v2 = caml_copy_string (r);\n";
8150            pr "    Store_field (v, 0, v2);\n";
8151            pr "  } else /* None */\n";
8152            pr "    v = Val_int (0);\n";
8153        | RString _ ->
8154            pr "  rv = caml_copy_string (r);\n";
8155            pr "  free (r);\n"
8156        | RStringList _ ->
8157            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8158            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8159            pr "  free (r);\n"
8160        | RStruct (_, typ) ->
8161            pr "  rv = copy_%s (r);\n" typ;
8162            pr "  guestfs_free_%s (r);\n" typ;
8163        | RStructList (_, typ) ->
8164            pr "  rv = copy_%s_list (r);\n" typ;
8165            pr "  guestfs_free_%s_list (r);\n" typ;
8166        | RHashtable _ ->
8167            pr "  rv = copy_table (r);\n";
8168            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8169            pr "  free (r);\n";
8170        | RBufferOut _ ->
8171            pr "  rv = caml_alloc_string (size);\n";
8172            pr "  memcpy (String_val (rv), r, size);\n";
8173       );
8174
8175       pr "  CAMLreturn (rv);\n";
8176       pr "}\n";
8177       pr "\n";
8178
8179       if List.length params > 5 then (
8180         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8181         pr "CAMLprim value ";
8182         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8183         pr "CAMLprim value\n";
8184         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8185         pr "{\n";
8186         pr "  return ocaml_guestfs_%s (argv[0]" name;
8187         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8188         pr ");\n";
8189         pr "}\n";
8190         pr "\n"
8191       )
8192   ) all_functions_sorted
8193
8194 and generate_ocaml_structure_decls () =
8195   List.iter (
8196     fun (typ, cols) ->
8197       pr "type %s = {\n" typ;
8198       List.iter (
8199         function
8200         | name, FString -> pr "  %s : string;\n" name
8201         | name, FBuffer -> pr "  %s : string;\n" name
8202         | name, FUUID -> pr "  %s : string;\n" name
8203         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8204         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8205         | name, FChar -> pr "  %s : char;\n" name
8206         | name, FOptPercent -> pr "  %s : float option;\n" name
8207       ) cols;
8208       pr "}\n";
8209       pr "\n"
8210   ) structs
8211
8212 and generate_ocaml_prototype ?(is_external = false) name style =
8213   if is_external then pr "external " else pr "val ";
8214   pr "%s : t -> " name;
8215   List.iter (
8216     function
8217     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
8218     | OptString _ -> pr "string option -> "
8219     | StringList _ | DeviceList _ -> pr "string array -> "
8220     | Bool _ -> pr "bool -> "
8221     | Int _ -> pr "int -> "
8222     | Int64 _ -> pr "int64 -> "
8223   ) (snd style);
8224   (match fst style with
8225    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8226    | RInt _ -> pr "int"
8227    | RInt64 _ -> pr "int64"
8228    | RBool _ -> pr "bool"
8229    | RConstString _ -> pr "string"
8230    | RConstOptString _ -> pr "string option"
8231    | RString _ | RBufferOut _ -> pr "string"
8232    | RStringList _ -> pr "string array"
8233    | RStruct (_, typ) -> pr "%s" typ
8234    | RStructList (_, typ) -> pr "%s array" typ
8235    | RHashtable _ -> pr "(string * string) list"
8236   );
8237   if is_external then (
8238     pr " = ";
8239     if List.length (snd style) + 1 > 5 then
8240       pr "\"ocaml_guestfs_%s_byte\" " name;
8241     pr "\"ocaml_guestfs_%s\"" name
8242   );
8243   pr "\n"
8244
8245 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8246 and generate_perl_xs () =
8247   generate_header CStyle LGPLv2plus;
8248
8249   pr "\
8250 #include \"EXTERN.h\"
8251 #include \"perl.h\"
8252 #include \"XSUB.h\"
8253
8254 #include <guestfs.h>
8255
8256 #ifndef PRId64
8257 #define PRId64 \"lld\"
8258 #endif
8259
8260 static SV *
8261 my_newSVll(long long val) {
8262 #ifdef USE_64_BIT_ALL
8263   return newSViv(val);
8264 #else
8265   char buf[100];
8266   int len;
8267   len = snprintf(buf, 100, \"%%\" PRId64, val);
8268   return newSVpv(buf, len);
8269 #endif
8270 }
8271
8272 #ifndef PRIu64
8273 #define PRIu64 \"llu\"
8274 #endif
8275
8276 static SV *
8277 my_newSVull(unsigned long long val) {
8278 #ifdef USE_64_BIT_ALL
8279   return newSVuv(val);
8280 #else
8281   char buf[100];
8282   int len;
8283   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8284   return newSVpv(buf, len);
8285 #endif
8286 }
8287
8288 /* http://www.perlmonks.org/?node_id=680842 */
8289 static char **
8290 XS_unpack_charPtrPtr (SV *arg) {
8291   char **ret;
8292   AV *av;
8293   I32 i;
8294
8295   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8296     croak (\"array reference expected\");
8297
8298   av = (AV *)SvRV (arg);
8299   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8300   if (!ret)
8301     croak (\"malloc failed\");
8302
8303   for (i = 0; i <= av_len (av); i++) {
8304     SV **elem = av_fetch (av, i, 0);
8305
8306     if (!elem || !*elem)
8307       croak (\"missing element in list\");
8308
8309     ret[i] = SvPV_nolen (*elem);
8310   }
8311
8312   ret[i] = NULL;
8313
8314   return ret;
8315 }
8316
8317 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8318
8319 PROTOTYPES: ENABLE
8320
8321 guestfs_h *
8322 _create ()
8323    CODE:
8324       RETVAL = guestfs_create ();
8325       if (!RETVAL)
8326         croak (\"could not create guestfs handle\");
8327       guestfs_set_error_handler (RETVAL, NULL, NULL);
8328  OUTPUT:
8329       RETVAL
8330
8331 void
8332 DESTROY (g)
8333       guestfs_h *g;
8334  PPCODE:
8335       guestfs_close (g);
8336
8337 ";
8338
8339   List.iter (
8340     fun (name, style, _, _, _, _, _) ->
8341       (match fst style with
8342        | RErr -> pr "void\n"
8343        | RInt _ -> pr "SV *\n"
8344        | RInt64 _ -> pr "SV *\n"
8345        | RBool _ -> pr "SV *\n"
8346        | RConstString _ -> pr "SV *\n"
8347        | RConstOptString _ -> pr "SV *\n"
8348        | RString _ -> pr "SV *\n"
8349        | RBufferOut _ -> pr "SV *\n"
8350        | RStringList _
8351        | RStruct _ | RStructList _
8352        | RHashtable _ ->
8353            pr "void\n" (* all lists returned implictly on the stack *)
8354       );
8355       (* Call and arguments. *)
8356       pr "%s " name;
8357       generate_c_call_args ~handle:"g" ~decl:true style;
8358       pr "\n";
8359       pr "      guestfs_h *g;\n";
8360       iteri (
8361         fun i ->
8362           function
8363           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8364               pr "      char *%s;\n" n
8365           | OptString n ->
8366               (* http://www.perlmonks.org/?node_id=554277
8367                * Note that the implicit handle argument means we have
8368                * to add 1 to the ST(x) operator.
8369                *)
8370               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8371           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8372           | Bool n -> pr "      int %s;\n" n
8373           | Int n -> pr "      int %s;\n" n
8374           | Int64 n -> pr "      int64_t %s;\n" n
8375       ) (snd style);
8376
8377       let do_cleanups () =
8378         List.iter (
8379           function
8380           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8381           | Bool _ | Int _ | Int64 _
8382           | FileIn _ | FileOut _ -> ()
8383           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8384         ) (snd style)
8385       in
8386
8387       (* Code. *)
8388       (match fst style with
8389        | RErr ->
8390            pr "PREINIT:\n";
8391            pr "      int r;\n";
8392            pr " PPCODE:\n";
8393            pr "      r = guestfs_%s " name;
8394            generate_c_call_args ~handle:"g" style;
8395            pr ";\n";
8396            do_cleanups ();
8397            pr "      if (r == -1)\n";
8398            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8399        | RInt n
8400        | RBool n ->
8401            pr "PREINIT:\n";
8402            pr "      int %s;\n" n;
8403            pr "   CODE:\n";
8404            pr "      %s = guestfs_%s " n name;
8405            generate_c_call_args ~handle:"g" style;
8406            pr ";\n";
8407            do_cleanups ();
8408            pr "      if (%s == -1)\n" n;
8409            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8410            pr "      RETVAL = newSViv (%s);\n" n;
8411            pr " OUTPUT:\n";
8412            pr "      RETVAL\n"
8413        | RInt64 n ->
8414            pr "PREINIT:\n";
8415            pr "      int64_t %s;\n" n;
8416            pr "   CODE:\n";
8417            pr "      %s = guestfs_%s " n name;
8418            generate_c_call_args ~handle:"g" style;
8419            pr ";\n";
8420            do_cleanups ();
8421            pr "      if (%s == -1)\n" n;
8422            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8423            pr "      RETVAL = my_newSVll (%s);\n" n;
8424            pr " OUTPUT:\n";
8425            pr "      RETVAL\n"
8426        | RConstString n ->
8427            pr "PREINIT:\n";
8428            pr "      const char *%s;\n" n;
8429            pr "   CODE:\n";
8430            pr "      %s = guestfs_%s " n name;
8431            generate_c_call_args ~handle:"g" style;
8432            pr ";\n";
8433            do_cleanups ();
8434            pr "      if (%s == NULL)\n" n;
8435            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8436            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8437            pr " OUTPUT:\n";
8438            pr "      RETVAL\n"
8439        | RConstOptString n ->
8440            pr "PREINIT:\n";
8441            pr "      const char *%s;\n" n;
8442            pr "   CODE:\n";
8443            pr "      %s = guestfs_%s " n name;
8444            generate_c_call_args ~handle:"g" style;
8445            pr ";\n";
8446            do_cleanups ();
8447            pr "      if (%s == NULL)\n" n;
8448            pr "        RETVAL = &PL_sv_undef;\n";
8449            pr "      else\n";
8450            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8451            pr " OUTPUT:\n";
8452            pr "      RETVAL\n"
8453        | RString n ->
8454            pr "PREINIT:\n";
8455            pr "      char *%s;\n" n;
8456            pr "   CODE:\n";
8457            pr "      %s = guestfs_%s " n name;
8458            generate_c_call_args ~handle:"g" style;
8459            pr ";\n";
8460            do_cleanups ();
8461            pr "      if (%s == NULL)\n" n;
8462            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8463            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8464            pr "      free (%s);\n" n;
8465            pr " OUTPUT:\n";
8466            pr "      RETVAL\n"
8467        | RStringList n | RHashtable n ->
8468            pr "PREINIT:\n";
8469            pr "      char **%s;\n" n;
8470            pr "      int i, n;\n";
8471            pr " PPCODE:\n";
8472            pr "      %s = guestfs_%s " n name;
8473            generate_c_call_args ~handle:"g" style;
8474            pr ";\n";
8475            do_cleanups ();
8476            pr "      if (%s == NULL)\n" n;
8477            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8478            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8479            pr "      EXTEND (SP, n);\n";
8480            pr "      for (i = 0; i < n; ++i) {\n";
8481            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8482            pr "        free (%s[i]);\n" n;
8483            pr "      }\n";
8484            pr "      free (%s);\n" n;
8485        | RStruct (n, typ) ->
8486            let cols = cols_of_struct typ in
8487            generate_perl_struct_code typ cols name style n do_cleanups
8488        | RStructList (n, typ) ->
8489            let cols = cols_of_struct typ in
8490            generate_perl_struct_list_code typ cols name style n do_cleanups
8491        | RBufferOut n ->
8492            pr "PREINIT:\n";
8493            pr "      char *%s;\n" n;
8494            pr "      size_t size;\n";
8495            pr "   CODE:\n";
8496            pr "      %s = guestfs_%s " n name;
8497            generate_c_call_args ~handle:"g" style;
8498            pr ";\n";
8499            do_cleanups ();
8500            pr "      if (%s == NULL)\n" n;
8501            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8502            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8503            pr "      free (%s);\n" n;
8504            pr " OUTPUT:\n";
8505            pr "      RETVAL\n"
8506       );
8507
8508       pr "\n"
8509   ) all_functions
8510
8511 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8512   pr "PREINIT:\n";
8513   pr "      struct guestfs_%s_list *%s;\n" typ n;
8514   pr "      int i;\n";
8515   pr "      HV *hv;\n";
8516   pr " PPCODE:\n";
8517   pr "      %s = guestfs_%s " n name;
8518   generate_c_call_args ~handle:"g" style;
8519   pr ";\n";
8520   do_cleanups ();
8521   pr "      if (%s == NULL)\n" n;
8522   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8523   pr "      EXTEND (SP, %s->len);\n" n;
8524   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8525   pr "        hv = newHV ();\n";
8526   List.iter (
8527     function
8528     | name, FString ->
8529         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8530           name (String.length name) n name
8531     | name, FUUID ->
8532         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8533           name (String.length name) n name
8534     | name, FBuffer ->
8535         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8536           name (String.length name) n name n name
8537     | name, (FBytes|FUInt64) ->
8538         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8539           name (String.length name) n name
8540     | name, FInt64 ->
8541         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8542           name (String.length name) n name
8543     | name, (FInt32|FUInt32) ->
8544         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8545           name (String.length name) n name
8546     | name, FChar ->
8547         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8548           name (String.length name) n name
8549     | name, FOptPercent ->
8550         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8551           name (String.length name) n name
8552   ) cols;
8553   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8554   pr "      }\n";
8555   pr "      guestfs_free_%s_list (%s);\n" typ n
8556
8557 and generate_perl_struct_code typ cols name style n do_cleanups =
8558   pr "PREINIT:\n";
8559   pr "      struct guestfs_%s *%s;\n" typ n;
8560   pr " PPCODE:\n";
8561   pr "      %s = guestfs_%s " n name;
8562   generate_c_call_args ~handle:"g" style;
8563   pr ";\n";
8564   do_cleanups ();
8565   pr "      if (%s == NULL)\n" n;
8566   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8567   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8568   List.iter (
8569     fun ((name, _) as col) ->
8570       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8571
8572       match col with
8573       | name, FString ->
8574           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8575             n name
8576       | name, FBuffer ->
8577           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8578             n name n name
8579       | name, FUUID ->
8580           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8581             n name
8582       | name, (FBytes|FUInt64) ->
8583           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8584             n name
8585       | name, FInt64 ->
8586           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8587             n name
8588       | name, (FInt32|FUInt32) ->
8589           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8590             n name
8591       | name, FChar ->
8592           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8593             n name
8594       | name, FOptPercent ->
8595           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8596             n name
8597   ) cols;
8598   pr "      free (%s);\n" n
8599
8600 (* Generate Sys/Guestfs.pm. *)
8601 and generate_perl_pm () =
8602   generate_header HashStyle LGPLv2plus;
8603
8604   pr "\
8605 =pod
8606
8607 =head1 NAME
8608
8609 Sys::Guestfs - Perl bindings for libguestfs
8610
8611 =head1 SYNOPSIS
8612
8613  use Sys::Guestfs;
8614
8615  my $h = Sys::Guestfs->new ();
8616  $h->add_drive ('guest.img');
8617  $h->launch ();
8618  $h->mount ('/dev/sda1', '/');
8619  $h->touch ('/hello');
8620  $h->sync ();
8621
8622 =head1 DESCRIPTION
8623
8624 The C<Sys::Guestfs> module provides a Perl XS binding to the
8625 libguestfs API for examining and modifying virtual machine
8626 disk images.
8627
8628 Amongst the things this is good for: making batch configuration
8629 changes to guests, getting disk used/free statistics (see also:
8630 virt-df), migrating between virtualization systems (see also:
8631 virt-p2v), performing partial backups, performing partial guest
8632 clones, cloning guests and changing registry/UUID/hostname info, and
8633 much else besides.
8634
8635 Libguestfs uses Linux kernel and qemu code, and can access any type of
8636 guest filesystem that Linux and qemu can, including but not limited
8637 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8638 schemes, qcow, qcow2, vmdk.
8639
8640 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8641 LVs, what filesystem is in each LV, etc.).  It can also run commands
8642 in the context of the guest.  Also you can access filesystems over
8643 FUSE.
8644
8645 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8646 functions for using libguestfs from Perl, including integration
8647 with libvirt.
8648
8649 =head1 ERRORS
8650
8651 All errors turn into calls to C<croak> (see L<Carp(3)>).
8652
8653 =head1 METHODS
8654
8655 =over 4
8656
8657 =cut
8658
8659 package Sys::Guestfs;
8660
8661 use strict;
8662 use warnings;
8663
8664 require XSLoader;
8665 XSLoader::load ('Sys::Guestfs');
8666
8667 =item $h = Sys::Guestfs->new ();
8668
8669 Create a new guestfs handle.
8670
8671 =cut
8672
8673 sub new {
8674   my $proto = shift;
8675   my $class = ref ($proto) || $proto;
8676
8677   my $self = Sys::Guestfs::_create ();
8678   bless $self, $class;
8679   return $self;
8680 }
8681
8682 ";
8683
8684   (* Actions.  We only need to print documentation for these as
8685    * they are pulled in from the XS code automatically.
8686    *)
8687   List.iter (
8688     fun (name, style, _, flags, _, _, longdesc) ->
8689       if not (List.mem NotInDocs flags) then (
8690         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8691         pr "=item ";
8692         generate_perl_prototype name style;
8693         pr "\n\n";
8694         pr "%s\n\n" longdesc;
8695         if List.mem ProtocolLimitWarning flags then
8696           pr "%s\n\n" protocol_limit_warning;
8697         if List.mem DangerWillRobinson flags then
8698           pr "%s\n\n" danger_will_robinson;
8699         match deprecation_notice flags with
8700         | None -> ()
8701         | Some txt -> pr "%s\n\n" txt
8702       )
8703   ) all_functions_sorted;
8704
8705   (* End of file. *)
8706   pr "\
8707 =cut
8708
8709 1;
8710
8711 =back
8712
8713 =head1 COPYRIGHT
8714
8715 Copyright (C) %s Red Hat Inc.
8716
8717 =head1 LICENSE
8718
8719 Please see the file COPYING.LIB for the full license.
8720
8721 =head1 SEE ALSO
8722
8723 L<guestfs(3)>,
8724 L<guestfish(1)>,
8725 L<http://libguestfs.org>,
8726 L<Sys::Guestfs::Lib(3)>.
8727
8728 =cut
8729 " copyright_years
8730
8731 and generate_perl_prototype name style =
8732   (match fst style with
8733    | RErr -> ()
8734    | RBool n
8735    | RInt n
8736    | RInt64 n
8737    | RConstString n
8738    | RConstOptString n
8739    | RString n
8740    | RBufferOut n -> pr "$%s = " n
8741    | RStruct (n,_)
8742    | RHashtable n -> pr "%%%s = " n
8743    | RStringList n
8744    | RStructList (n,_) -> pr "@%s = " n
8745   );
8746   pr "$h->%s (" name;
8747   let comma = ref false in
8748   List.iter (
8749     fun arg ->
8750       if !comma then pr ", ";
8751       comma := true;
8752       match arg with
8753       | Pathname n | Device n | Dev_or_Path n | String n
8754       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8755           pr "$%s" n
8756       | StringList n | DeviceList n ->
8757           pr "\\@%s" n
8758   ) (snd style);
8759   pr ");"
8760
8761 (* Generate Python C module. *)
8762 and generate_python_c () =
8763   generate_header CStyle LGPLv2plus;
8764
8765   pr "\
8766 #include <Python.h>
8767
8768 #include <stdio.h>
8769 #include <stdlib.h>
8770 #include <assert.h>
8771
8772 #include \"guestfs.h\"
8773
8774 typedef struct {
8775   PyObject_HEAD
8776   guestfs_h *g;
8777 } Pyguestfs_Object;
8778
8779 static guestfs_h *
8780 get_handle (PyObject *obj)
8781 {
8782   assert (obj);
8783   assert (obj != Py_None);
8784   return ((Pyguestfs_Object *) obj)->g;
8785 }
8786
8787 static PyObject *
8788 put_handle (guestfs_h *g)
8789 {
8790   assert (g);
8791   return
8792     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8793 }
8794
8795 /* This list should be freed (but not the strings) after use. */
8796 static char **
8797 get_string_list (PyObject *obj)
8798 {
8799   int i, len;
8800   char **r;
8801
8802   assert (obj);
8803
8804   if (!PyList_Check (obj)) {
8805     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8806     return NULL;
8807   }
8808
8809   len = PyList_Size (obj);
8810   r = malloc (sizeof (char *) * (len+1));
8811   if (r == NULL) {
8812     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8813     return NULL;
8814   }
8815
8816   for (i = 0; i < len; ++i)
8817     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8818   r[len] = NULL;
8819
8820   return r;
8821 }
8822
8823 static PyObject *
8824 put_string_list (char * const * const argv)
8825 {
8826   PyObject *list;
8827   int argc, i;
8828
8829   for (argc = 0; argv[argc] != NULL; ++argc)
8830     ;
8831
8832   list = PyList_New (argc);
8833   for (i = 0; i < argc; ++i)
8834     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8835
8836   return list;
8837 }
8838
8839 static PyObject *
8840 put_table (char * const * const argv)
8841 {
8842   PyObject *list, *item;
8843   int argc, i;
8844
8845   for (argc = 0; argv[argc] != NULL; ++argc)
8846     ;
8847
8848   list = PyList_New (argc >> 1);
8849   for (i = 0; i < argc; i += 2) {
8850     item = PyTuple_New (2);
8851     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8852     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8853     PyList_SetItem (list, i >> 1, item);
8854   }
8855
8856   return list;
8857 }
8858
8859 static void
8860 free_strings (char **argv)
8861 {
8862   int argc;
8863
8864   for (argc = 0; argv[argc] != NULL; ++argc)
8865     free (argv[argc]);
8866   free (argv);
8867 }
8868
8869 static PyObject *
8870 py_guestfs_create (PyObject *self, PyObject *args)
8871 {
8872   guestfs_h *g;
8873
8874   g = guestfs_create ();
8875   if (g == NULL) {
8876     PyErr_SetString (PyExc_RuntimeError,
8877                      \"guestfs.create: failed to allocate handle\");
8878     return NULL;
8879   }
8880   guestfs_set_error_handler (g, NULL, NULL);
8881   return put_handle (g);
8882 }
8883
8884 static PyObject *
8885 py_guestfs_close (PyObject *self, PyObject *args)
8886 {
8887   PyObject *py_g;
8888   guestfs_h *g;
8889
8890   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8891     return NULL;
8892   g = get_handle (py_g);
8893
8894   guestfs_close (g);
8895
8896   Py_INCREF (Py_None);
8897   return Py_None;
8898 }
8899
8900 ";
8901
8902   let emit_put_list_function typ =
8903     pr "static PyObject *\n";
8904     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8905     pr "{\n";
8906     pr "  PyObject *list;\n";
8907     pr "  int i;\n";
8908     pr "\n";
8909     pr "  list = PyList_New (%ss->len);\n" typ;
8910     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8911     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8912     pr "  return list;\n";
8913     pr "};\n";
8914     pr "\n"
8915   in
8916
8917   (* Structures, turned into Python dictionaries. *)
8918   List.iter (
8919     fun (typ, cols) ->
8920       pr "static PyObject *\n";
8921       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8922       pr "{\n";
8923       pr "  PyObject *dict;\n";
8924       pr "\n";
8925       pr "  dict = PyDict_New ();\n";
8926       List.iter (
8927         function
8928         | name, FString ->
8929             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8930             pr "                        PyString_FromString (%s->%s));\n"
8931               typ name
8932         | name, FBuffer ->
8933             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8934             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8935               typ name typ name
8936         | name, FUUID ->
8937             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8938             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8939               typ name
8940         | name, (FBytes|FUInt64) ->
8941             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8942             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8943               typ name
8944         | name, FInt64 ->
8945             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8946             pr "                        PyLong_FromLongLong (%s->%s));\n"
8947               typ name
8948         | name, FUInt32 ->
8949             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8950             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8951               typ name
8952         | name, FInt32 ->
8953             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8954             pr "                        PyLong_FromLong (%s->%s));\n"
8955               typ name
8956         | name, FOptPercent ->
8957             pr "  if (%s->%s >= 0)\n" typ name;
8958             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8959             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8960               typ name;
8961             pr "  else {\n";
8962             pr "    Py_INCREF (Py_None);\n";
8963             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8964             pr "  }\n"
8965         | name, FChar ->
8966             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8967             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8968       ) cols;
8969       pr "  return dict;\n";
8970       pr "};\n";
8971       pr "\n";
8972
8973   ) structs;
8974
8975   (* Emit a put_TYPE_list function definition only if that function is used. *)
8976   List.iter (
8977     function
8978     | typ, (RStructListOnly | RStructAndList) ->
8979         (* generate the function for typ *)
8980         emit_put_list_function typ
8981     | typ, _ -> () (* empty *)
8982   ) (rstructs_used_by all_functions);
8983
8984   (* Python wrapper functions. *)
8985   List.iter (
8986     fun (name, style, _, _, _, _, _) ->
8987       pr "static PyObject *\n";
8988       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8989       pr "{\n";
8990
8991       pr "  PyObject *py_g;\n";
8992       pr "  guestfs_h *g;\n";
8993       pr "  PyObject *py_r;\n";
8994
8995       let error_code =
8996         match fst style with
8997         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8998         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8999         | RConstString _ | RConstOptString _ ->
9000             pr "  const char *r;\n"; "NULL"
9001         | RString _ -> pr "  char *r;\n"; "NULL"
9002         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9003         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9004         | RStructList (_, typ) ->
9005             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9006         | RBufferOut _ ->
9007             pr "  char *r;\n";
9008             pr "  size_t size;\n";
9009             "NULL" in
9010
9011       List.iter (
9012         function
9013         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9014             pr "  const char *%s;\n" n
9015         | OptString n -> pr "  const char *%s;\n" n
9016         | StringList n | DeviceList n ->
9017             pr "  PyObject *py_%s;\n" n;
9018             pr "  char **%s;\n" n
9019         | Bool n -> pr "  int %s;\n" n
9020         | Int n -> pr "  int %s;\n" n
9021         | Int64 n -> pr "  long long %s;\n" n
9022       ) (snd style);
9023
9024       pr "\n";
9025
9026       (* Convert the parameters. *)
9027       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9028       List.iter (
9029         function
9030         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9031         | OptString _ -> pr "z"
9032         | StringList _ | DeviceList _ -> pr "O"
9033         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9034         | Int _ -> pr "i"
9035         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9036                              * emulate C's int/long/long long in Python?
9037                              *)
9038       ) (snd style);
9039       pr ":guestfs_%s\",\n" name;
9040       pr "                         &py_g";
9041       List.iter (
9042         function
9043         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9044         | OptString n -> pr ", &%s" n
9045         | StringList n | DeviceList n -> pr ", &py_%s" n
9046         | Bool n -> pr ", &%s" n
9047         | Int n -> pr ", &%s" n
9048         | Int64 n -> pr ", &%s" n
9049       ) (snd style);
9050
9051       pr "))\n";
9052       pr "    return NULL;\n";
9053
9054       pr "  g = get_handle (py_g);\n";
9055       List.iter (
9056         function
9057         | Pathname _ | Device _ | Dev_or_Path _ | String _
9058         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9059         | StringList n | DeviceList n ->
9060             pr "  %s = get_string_list (py_%s);\n" n n;
9061             pr "  if (!%s) return NULL;\n" n
9062       ) (snd style);
9063
9064       pr "\n";
9065
9066       pr "  r = guestfs_%s " name;
9067       generate_c_call_args ~handle:"g" style;
9068       pr ";\n";
9069
9070       List.iter (
9071         function
9072         | Pathname _ | Device _ | Dev_or_Path _ | String _
9073         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9074         | StringList n | DeviceList n ->
9075             pr "  free (%s);\n" n
9076       ) (snd style);
9077
9078       pr "  if (r == %s) {\n" error_code;
9079       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9080       pr "    return NULL;\n";
9081       pr "  }\n";
9082       pr "\n";
9083
9084       (match fst style with
9085        | RErr ->
9086            pr "  Py_INCREF (Py_None);\n";
9087            pr "  py_r = Py_None;\n"
9088        | RInt _
9089        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9090        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9091        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9092        | RConstOptString _ ->
9093            pr "  if (r)\n";
9094            pr "    py_r = PyString_FromString (r);\n";
9095            pr "  else {\n";
9096            pr "    Py_INCREF (Py_None);\n";
9097            pr "    py_r = Py_None;\n";
9098            pr "  }\n"
9099        | RString _ ->
9100            pr "  py_r = PyString_FromString (r);\n";
9101            pr "  free (r);\n"
9102        | RStringList _ ->
9103            pr "  py_r = put_string_list (r);\n";
9104            pr "  free_strings (r);\n"
9105        | RStruct (_, typ) ->
9106            pr "  py_r = put_%s (r);\n" typ;
9107            pr "  guestfs_free_%s (r);\n" typ
9108        | RStructList (_, typ) ->
9109            pr "  py_r = put_%s_list (r);\n" typ;
9110            pr "  guestfs_free_%s_list (r);\n" typ
9111        | RHashtable n ->
9112            pr "  py_r = put_table (r);\n";
9113            pr "  free_strings (r);\n"
9114        | RBufferOut _ ->
9115            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9116            pr "  free (r);\n"
9117       );
9118
9119       pr "  return py_r;\n";
9120       pr "}\n";
9121       pr "\n"
9122   ) all_functions;
9123
9124   (* Table of functions. *)
9125   pr "static PyMethodDef methods[] = {\n";
9126   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9127   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9128   List.iter (
9129     fun (name, _, _, _, _, _, _) ->
9130       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9131         name name
9132   ) all_functions;
9133   pr "  { NULL, NULL, 0, NULL }\n";
9134   pr "};\n";
9135   pr "\n";
9136
9137   (* Init function. *)
9138   pr "\
9139 void
9140 initlibguestfsmod (void)
9141 {
9142   static int initialized = 0;
9143
9144   if (initialized) return;
9145   Py_InitModule ((char *) \"libguestfsmod\", methods);
9146   initialized = 1;
9147 }
9148 "
9149
9150 (* Generate Python module. *)
9151 and generate_python_py () =
9152   generate_header HashStyle LGPLv2plus;
9153
9154   pr "\
9155 u\"\"\"Python bindings for libguestfs
9156
9157 import guestfs
9158 g = guestfs.GuestFS ()
9159 g.add_drive (\"guest.img\")
9160 g.launch ()
9161 parts = g.list_partitions ()
9162
9163 The guestfs module provides a Python binding to the libguestfs API
9164 for examining and modifying virtual machine disk images.
9165
9166 Amongst the things this is good for: making batch configuration
9167 changes to guests, getting disk used/free statistics (see also:
9168 virt-df), migrating between virtualization systems (see also:
9169 virt-p2v), performing partial backups, performing partial guest
9170 clones, cloning guests and changing registry/UUID/hostname info, and
9171 much else besides.
9172
9173 Libguestfs uses Linux kernel and qemu code, and can access any type of
9174 guest filesystem that Linux and qemu can, including but not limited
9175 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9176 schemes, qcow, qcow2, vmdk.
9177
9178 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9179 LVs, what filesystem is in each LV, etc.).  It can also run commands
9180 in the context of the guest.  Also you can access filesystems over
9181 FUSE.
9182
9183 Errors which happen while using the API are turned into Python
9184 RuntimeError exceptions.
9185
9186 To create a guestfs handle you usually have to perform the following
9187 sequence of calls:
9188
9189 # Create the handle, call add_drive at least once, and possibly
9190 # several times if the guest has multiple block devices:
9191 g = guestfs.GuestFS ()
9192 g.add_drive (\"guest.img\")
9193
9194 # Launch the qemu subprocess and wait for it to become ready:
9195 g.launch ()
9196
9197 # Now you can issue commands, for example:
9198 logvols = g.lvs ()
9199
9200 \"\"\"
9201
9202 import libguestfsmod
9203
9204 class GuestFS:
9205     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9206
9207     def __init__ (self):
9208         \"\"\"Create a new libguestfs handle.\"\"\"
9209         self._o = libguestfsmod.create ()
9210
9211     def __del__ (self):
9212         libguestfsmod.close (self._o)
9213
9214 ";
9215
9216   List.iter (
9217     fun (name, style, _, flags, _, _, longdesc) ->
9218       pr "    def %s " name;
9219       generate_py_call_args ~handle:"self" (snd style);
9220       pr ":\n";
9221
9222       if not (List.mem NotInDocs flags) then (
9223         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9224         let doc =
9225           match fst style with
9226           | RErr | RInt _ | RInt64 _ | RBool _
9227           | RConstOptString _ | RConstString _
9228           | RString _ | RBufferOut _ -> doc
9229           | RStringList _ ->
9230               doc ^ "\n\nThis function returns a list of strings."
9231           | RStruct (_, typ) ->
9232               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9233           | RStructList (_, typ) ->
9234               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9235           | RHashtable _ ->
9236               doc ^ "\n\nThis function returns a dictionary." in
9237         let doc =
9238           if List.mem ProtocolLimitWarning flags then
9239             doc ^ "\n\n" ^ protocol_limit_warning
9240           else doc in
9241         let doc =
9242           if List.mem DangerWillRobinson flags then
9243             doc ^ "\n\n" ^ danger_will_robinson
9244           else doc in
9245         let doc =
9246           match deprecation_notice flags with
9247           | None -> doc
9248           | Some txt -> doc ^ "\n\n" ^ txt in
9249         let doc = pod2text ~width:60 name doc in
9250         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9251         let doc = String.concat "\n        " doc in
9252         pr "        u\"\"\"%s\"\"\"\n" doc;
9253       );
9254       pr "        return libguestfsmod.%s " name;
9255       generate_py_call_args ~handle:"self._o" (snd style);
9256       pr "\n";
9257       pr "\n";
9258   ) all_functions
9259
9260 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9261 and generate_py_call_args ~handle args =
9262   pr "(%s" handle;
9263   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9264   pr ")"
9265
9266 (* Useful if you need the longdesc POD text as plain text.  Returns a
9267  * list of lines.
9268  *
9269  * Because this is very slow (the slowest part of autogeneration),
9270  * we memoize the results.
9271  *)
9272 and pod2text ~width name longdesc =
9273   let key = width, name, longdesc in
9274   try Hashtbl.find pod2text_memo key
9275   with Not_found ->
9276     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9277     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9278     close_out chan;
9279     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9280     let chan = open_process_in cmd in
9281     let lines = ref [] in
9282     let rec loop i =
9283       let line = input_line chan in
9284       if i = 1 then             (* discard the first line of output *)
9285         loop (i+1)
9286       else (
9287         let line = triml line in
9288         lines := line :: !lines;
9289         loop (i+1)
9290       ) in
9291     let lines = try loop 1 with End_of_file -> List.rev !lines in
9292     unlink filename;
9293     (match close_process_in chan with
9294      | WEXITED 0 -> ()
9295      | WEXITED i ->
9296          failwithf "pod2text: process exited with non-zero status (%d)" i
9297      | WSIGNALED i | WSTOPPED i ->
9298          failwithf "pod2text: process signalled or stopped by signal %d" i
9299     );
9300     Hashtbl.add pod2text_memo key lines;
9301     pod2text_memo_updated ();
9302     lines
9303
9304 (* Generate ruby bindings. *)
9305 and generate_ruby_c () =
9306   generate_header CStyle LGPLv2plus;
9307
9308   pr "\
9309 #include <stdio.h>
9310 #include <stdlib.h>
9311
9312 #include <ruby.h>
9313
9314 #include \"guestfs.h\"
9315
9316 #include \"extconf.h\"
9317
9318 /* For Ruby < 1.9 */
9319 #ifndef RARRAY_LEN
9320 #define RARRAY_LEN(r) (RARRAY((r))->len)
9321 #endif
9322
9323 static VALUE m_guestfs;                 /* guestfs module */
9324 static VALUE c_guestfs;                 /* guestfs_h handle */
9325 static VALUE e_Error;                   /* used for all errors */
9326
9327 static void ruby_guestfs_free (void *p)
9328 {
9329   if (!p) return;
9330   guestfs_close ((guestfs_h *) p);
9331 }
9332
9333 static VALUE ruby_guestfs_create (VALUE m)
9334 {
9335   guestfs_h *g;
9336
9337   g = guestfs_create ();
9338   if (!g)
9339     rb_raise (e_Error, \"failed to create guestfs handle\");
9340
9341   /* Don't print error messages to stderr by default. */
9342   guestfs_set_error_handler (g, NULL, NULL);
9343
9344   /* Wrap it, and make sure the close function is called when the
9345    * handle goes away.
9346    */
9347   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9348 }
9349
9350 static VALUE ruby_guestfs_close (VALUE gv)
9351 {
9352   guestfs_h *g;
9353   Data_Get_Struct (gv, guestfs_h, g);
9354
9355   ruby_guestfs_free (g);
9356   DATA_PTR (gv) = NULL;
9357
9358   return Qnil;
9359 }
9360
9361 ";
9362
9363   List.iter (
9364     fun (name, style, _, _, _, _, _) ->
9365       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9366       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9367       pr ")\n";
9368       pr "{\n";
9369       pr "  guestfs_h *g;\n";
9370       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9371       pr "  if (!g)\n";
9372       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9373         name;
9374       pr "\n";
9375
9376       List.iter (
9377         function
9378         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9379             pr "  Check_Type (%sv, T_STRING);\n" n;
9380             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9381             pr "  if (!%s)\n" n;
9382             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9383             pr "              \"%s\", \"%s\");\n" n name
9384         | OptString n ->
9385             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9386         | StringList n | DeviceList n ->
9387             pr "  char **%s;\n" n;
9388             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9389             pr "  {\n";
9390             pr "    int i, len;\n";
9391             pr "    len = RARRAY_LEN (%sv);\n" n;
9392             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9393               n;
9394             pr "    for (i = 0; i < len; ++i) {\n";
9395             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9396             pr "      %s[i] = StringValueCStr (v);\n" n;
9397             pr "    }\n";
9398             pr "    %s[len] = NULL;\n" n;
9399             pr "  }\n";
9400         | Bool n ->
9401             pr "  int %s = RTEST (%sv);\n" n n
9402         | Int n ->
9403             pr "  int %s = NUM2INT (%sv);\n" n n
9404         | Int64 n ->
9405             pr "  long long %s = NUM2LL (%sv);\n" n n
9406       ) (snd style);
9407       pr "\n";
9408
9409       let error_code =
9410         match fst style with
9411         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9412         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9413         | RConstString _ | RConstOptString _ ->
9414             pr "  const char *r;\n"; "NULL"
9415         | RString _ -> pr "  char *r;\n"; "NULL"
9416         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9417         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9418         | RStructList (_, typ) ->
9419             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9420         | RBufferOut _ ->
9421             pr "  char *r;\n";
9422             pr "  size_t size;\n";
9423             "NULL" in
9424       pr "\n";
9425
9426       pr "  r = guestfs_%s " name;
9427       generate_c_call_args ~handle:"g" style;
9428       pr ";\n";
9429
9430       List.iter (
9431         function
9432         | Pathname _ | Device _ | Dev_or_Path _ | String _
9433         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9434         | StringList n | DeviceList n ->
9435             pr "  free (%s);\n" n
9436       ) (snd style);
9437
9438       pr "  if (r == %s)\n" error_code;
9439       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9440       pr "\n";
9441
9442       (match fst style with
9443        | RErr ->
9444            pr "  return Qnil;\n"
9445        | RInt _ | RBool _ ->
9446            pr "  return INT2NUM (r);\n"
9447        | RInt64 _ ->
9448            pr "  return ULL2NUM (r);\n"
9449        | RConstString _ ->
9450            pr "  return rb_str_new2 (r);\n";
9451        | RConstOptString _ ->
9452            pr "  if (r)\n";
9453            pr "    return rb_str_new2 (r);\n";
9454            pr "  else\n";
9455            pr "    return Qnil;\n";
9456        | RString _ ->
9457            pr "  VALUE rv = rb_str_new2 (r);\n";
9458            pr "  free (r);\n";
9459            pr "  return rv;\n";
9460        | RStringList _ ->
9461            pr "  int i, len = 0;\n";
9462            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9463            pr "  VALUE rv = rb_ary_new2 (len);\n";
9464            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9465            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9466            pr "    free (r[i]);\n";
9467            pr "  }\n";
9468            pr "  free (r);\n";
9469            pr "  return rv;\n"
9470        | RStruct (_, typ) ->
9471            let cols = cols_of_struct typ in
9472            generate_ruby_struct_code typ cols
9473        | RStructList (_, typ) ->
9474            let cols = cols_of_struct typ in
9475            generate_ruby_struct_list_code typ cols
9476        | RHashtable _ ->
9477            pr "  VALUE rv = rb_hash_new ();\n";
9478            pr "  int i;\n";
9479            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9480            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9481            pr "    free (r[i]);\n";
9482            pr "    free (r[i+1]);\n";
9483            pr "  }\n";
9484            pr "  free (r);\n";
9485            pr "  return rv;\n"
9486        | RBufferOut _ ->
9487            pr "  VALUE rv = rb_str_new (r, size);\n";
9488            pr "  free (r);\n";
9489            pr "  return rv;\n";
9490       );
9491
9492       pr "}\n";
9493       pr "\n"
9494   ) all_functions;
9495
9496   pr "\
9497 /* Initialize the module. */
9498 void Init__guestfs ()
9499 {
9500   m_guestfs = rb_define_module (\"Guestfs\");
9501   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9502   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9503
9504   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9505   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9506
9507 ";
9508   (* Define the rest of the methods. *)
9509   List.iter (
9510     fun (name, style, _, _, _, _, _) ->
9511       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9512       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9513   ) all_functions;
9514
9515   pr "}\n"
9516
9517 (* Ruby code to return a struct. *)
9518 and generate_ruby_struct_code typ cols =
9519   pr "  VALUE rv = rb_hash_new ();\n";
9520   List.iter (
9521     function
9522     | name, FString ->
9523         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9524     | name, FBuffer ->
9525         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9526     | name, FUUID ->
9527         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9528     | name, (FBytes|FUInt64) ->
9529         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9530     | name, FInt64 ->
9531         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9532     | name, FUInt32 ->
9533         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9534     | name, FInt32 ->
9535         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9536     | name, FOptPercent ->
9537         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9538     | name, FChar -> (* XXX wrong? *)
9539         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9540   ) cols;
9541   pr "  guestfs_free_%s (r);\n" typ;
9542   pr "  return rv;\n"
9543
9544 (* Ruby code to return a struct list. *)
9545 and generate_ruby_struct_list_code typ cols =
9546   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9547   pr "  int i;\n";
9548   pr "  for (i = 0; i < r->len; ++i) {\n";
9549   pr "    VALUE hv = rb_hash_new ();\n";
9550   List.iter (
9551     function
9552     | name, FString ->
9553         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9554     | name, FBuffer ->
9555         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
9556     | name, FUUID ->
9557         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9558     | name, (FBytes|FUInt64) ->
9559         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9560     | name, FInt64 ->
9561         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9562     | name, FUInt32 ->
9563         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9564     | name, FInt32 ->
9565         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9566     | name, FOptPercent ->
9567         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9568     | name, FChar -> (* XXX wrong? *)
9569         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9570   ) cols;
9571   pr "    rb_ary_push (rv, hv);\n";
9572   pr "  }\n";
9573   pr "  guestfs_free_%s_list (r);\n" typ;
9574   pr "  return rv;\n"
9575
9576 (* Generate Java bindings GuestFS.java file. *)
9577 and generate_java_java () =
9578   generate_header CStyle LGPLv2plus;
9579
9580   pr "\
9581 package com.redhat.et.libguestfs;
9582
9583 import java.util.HashMap;
9584 import com.redhat.et.libguestfs.LibGuestFSException;
9585 import com.redhat.et.libguestfs.PV;
9586 import com.redhat.et.libguestfs.VG;
9587 import com.redhat.et.libguestfs.LV;
9588 import com.redhat.et.libguestfs.Stat;
9589 import com.redhat.et.libguestfs.StatVFS;
9590 import com.redhat.et.libguestfs.IntBool;
9591 import com.redhat.et.libguestfs.Dirent;
9592
9593 /**
9594  * The GuestFS object is a libguestfs handle.
9595  *
9596  * @author rjones
9597  */
9598 public class GuestFS {
9599   // Load the native code.
9600   static {
9601     System.loadLibrary (\"guestfs_jni\");
9602   }
9603
9604   /**
9605    * The native guestfs_h pointer.
9606    */
9607   long g;
9608
9609   /**
9610    * Create a libguestfs handle.
9611    *
9612    * @throws LibGuestFSException
9613    */
9614   public GuestFS () throws LibGuestFSException
9615   {
9616     g = _create ();
9617   }
9618   private native long _create () throws LibGuestFSException;
9619
9620   /**
9621    * Close a libguestfs handle.
9622    *
9623    * You can also leave handles to be collected by the garbage
9624    * collector, but this method ensures that the resources used
9625    * by the handle are freed up immediately.  If you call any
9626    * other methods after closing the handle, you will get an
9627    * exception.
9628    *
9629    * @throws LibGuestFSException
9630    */
9631   public void close () throws LibGuestFSException
9632   {
9633     if (g != 0)
9634       _close (g);
9635     g = 0;
9636   }
9637   private native void _close (long g) throws LibGuestFSException;
9638
9639   public void finalize () throws LibGuestFSException
9640   {
9641     close ();
9642   }
9643
9644 ";
9645
9646   List.iter (
9647     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9648       if not (List.mem NotInDocs flags); then (
9649         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9650         let doc =
9651           if List.mem ProtocolLimitWarning flags then
9652             doc ^ "\n\n" ^ protocol_limit_warning
9653           else doc in
9654         let doc =
9655           if List.mem DangerWillRobinson flags then
9656             doc ^ "\n\n" ^ danger_will_robinson
9657           else doc in
9658         let doc =
9659           match deprecation_notice flags with
9660           | None -> doc
9661           | Some txt -> doc ^ "\n\n" ^ txt in
9662         let doc = pod2text ~width:60 name doc in
9663         let doc = List.map (            (* RHBZ#501883 *)
9664           function
9665           | "" -> "<p>"
9666           | nonempty -> nonempty
9667         ) doc in
9668         let doc = String.concat "\n   * " doc in
9669
9670         pr "  /**\n";
9671         pr "   * %s\n" shortdesc;
9672         pr "   * <p>\n";
9673         pr "   * %s\n" doc;
9674         pr "   * @throws LibGuestFSException\n";
9675         pr "   */\n";
9676         pr "  ";
9677       );
9678       generate_java_prototype ~public:true ~semicolon:false name style;
9679       pr "\n";
9680       pr "  {\n";
9681       pr "    if (g == 0)\n";
9682       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9683         name;
9684       pr "    ";
9685       if fst style <> RErr then pr "return ";
9686       pr "_%s " name;
9687       generate_java_call_args ~handle:"g" (snd style);
9688       pr ";\n";
9689       pr "  }\n";
9690       pr "  ";
9691       generate_java_prototype ~privat:true ~native:true name style;
9692       pr "\n";
9693       pr "\n";
9694   ) all_functions;
9695
9696   pr "}\n"
9697
9698 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9699 and generate_java_call_args ~handle args =
9700   pr "(%s" handle;
9701   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9702   pr ")"
9703
9704 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9705     ?(semicolon=true) name style =
9706   if privat then pr "private ";
9707   if public then pr "public ";
9708   if native then pr "native ";
9709
9710   (* return type *)
9711   (match fst style with
9712    | RErr -> pr "void ";
9713    | RInt _ -> pr "int ";
9714    | RInt64 _ -> pr "long ";
9715    | RBool _ -> pr "boolean ";
9716    | RConstString _ | RConstOptString _ | RString _
9717    | RBufferOut _ -> pr "String ";
9718    | RStringList _ -> pr "String[] ";
9719    | RStruct (_, typ) ->
9720        let name = java_name_of_struct typ in
9721        pr "%s " name;
9722    | RStructList (_, typ) ->
9723        let name = java_name_of_struct typ in
9724        pr "%s[] " name;
9725    | RHashtable _ -> pr "HashMap<String,String> ";
9726   );
9727
9728   if native then pr "_%s " name else pr "%s " name;
9729   pr "(";
9730   let needs_comma = ref false in
9731   if native then (
9732     pr "long g";
9733     needs_comma := true
9734   );
9735
9736   (* args *)
9737   List.iter (
9738     fun arg ->
9739       if !needs_comma then pr ", ";
9740       needs_comma := true;
9741
9742       match arg with
9743       | Pathname n
9744       | Device n | Dev_or_Path n
9745       | String n
9746       | OptString n
9747       | FileIn n
9748       | FileOut n ->
9749           pr "String %s" n
9750       | StringList n | DeviceList n ->
9751           pr "String[] %s" n
9752       | Bool n ->
9753           pr "boolean %s" n
9754       | Int n ->
9755           pr "int %s" n
9756       | Int64 n ->
9757           pr "long %s" n
9758   ) (snd style);
9759
9760   pr ")\n";
9761   pr "    throws LibGuestFSException";
9762   if semicolon then pr ";"
9763
9764 and generate_java_struct jtyp cols () =
9765   generate_header CStyle LGPLv2plus;
9766
9767   pr "\
9768 package com.redhat.et.libguestfs;
9769
9770 /**
9771  * Libguestfs %s structure.
9772  *
9773  * @author rjones
9774  * @see GuestFS
9775  */
9776 public class %s {
9777 " jtyp jtyp;
9778
9779   List.iter (
9780     function
9781     | name, FString
9782     | name, FUUID
9783     | name, FBuffer -> pr "  public String %s;\n" name
9784     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9785     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9786     | name, FChar -> pr "  public char %s;\n" name
9787     | name, FOptPercent ->
9788         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9789         pr "  public float %s;\n" name
9790   ) cols;
9791
9792   pr "}\n"
9793
9794 and generate_java_c () =
9795   generate_header CStyle LGPLv2plus;
9796
9797   pr "\
9798 #include <stdio.h>
9799 #include <stdlib.h>
9800 #include <string.h>
9801
9802 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9803 #include \"guestfs.h\"
9804
9805 /* Note that this function returns.  The exception is not thrown
9806  * until after the wrapper function returns.
9807  */
9808 static void
9809 throw_exception (JNIEnv *env, const char *msg)
9810 {
9811   jclass cl;
9812   cl = (*env)->FindClass (env,
9813                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9814   (*env)->ThrowNew (env, cl, msg);
9815 }
9816
9817 JNIEXPORT jlong JNICALL
9818 Java_com_redhat_et_libguestfs_GuestFS__1create
9819   (JNIEnv *env, jobject obj)
9820 {
9821   guestfs_h *g;
9822
9823   g = guestfs_create ();
9824   if (g == NULL) {
9825     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9826     return 0;
9827   }
9828   guestfs_set_error_handler (g, NULL, NULL);
9829   return (jlong) (long) g;
9830 }
9831
9832 JNIEXPORT void JNICALL
9833 Java_com_redhat_et_libguestfs_GuestFS__1close
9834   (JNIEnv *env, jobject obj, jlong jg)
9835 {
9836   guestfs_h *g = (guestfs_h *) (long) jg;
9837   guestfs_close (g);
9838 }
9839
9840 ";
9841
9842   List.iter (
9843     fun (name, style, _, _, _, _, _) ->
9844       pr "JNIEXPORT ";
9845       (match fst style with
9846        | RErr -> pr "void ";
9847        | RInt _ -> pr "jint ";
9848        | RInt64 _ -> pr "jlong ";
9849        | RBool _ -> pr "jboolean ";
9850        | RConstString _ | RConstOptString _ | RString _
9851        | RBufferOut _ -> pr "jstring ";
9852        | RStruct _ | RHashtable _ ->
9853            pr "jobject ";
9854        | RStringList _ | RStructList _ ->
9855            pr "jobjectArray ";
9856       );
9857       pr "JNICALL\n";
9858       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9859       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9860       pr "\n";
9861       pr "  (JNIEnv *env, jobject obj, jlong jg";
9862       List.iter (
9863         function
9864         | Pathname n
9865         | Device n | Dev_or_Path n
9866         | String n
9867         | OptString n
9868         | FileIn n
9869         | FileOut n ->
9870             pr ", jstring j%s" n
9871         | StringList n | DeviceList n ->
9872             pr ", jobjectArray j%s" n
9873         | Bool n ->
9874             pr ", jboolean j%s" n
9875         | Int n ->
9876             pr ", jint j%s" n
9877         | Int64 n ->
9878             pr ", jlong j%s" n
9879       ) (snd style);
9880       pr ")\n";
9881       pr "{\n";
9882       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9883       let error_code, no_ret =
9884         match fst style with
9885         | RErr -> pr "  int r;\n"; "-1", ""
9886         | RBool _
9887         | RInt _ -> pr "  int r;\n"; "-1", "0"
9888         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9889         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9890         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9891         | RString _ ->
9892             pr "  jstring jr;\n";
9893             pr "  char *r;\n"; "NULL", "NULL"
9894         | RStringList _ ->
9895             pr "  jobjectArray jr;\n";
9896             pr "  int r_len;\n";
9897             pr "  jclass cl;\n";
9898             pr "  jstring jstr;\n";
9899             pr "  char **r;\n"; "NULL", "NULL"
9900         | RStruct (_, typ) ->
9901             pr "  jobject jr;\n";
9902             pr "  jclass cl;\n";
9903             pr "  jfieldID fl;\n";
9904             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9905         | RStructList (_, typ) ->
9906             pr "  jobjectArray jr;\n";
9907             pr "  jclass cl;\n";
9908             pr "  jfieldID fl;\n";
9909             pr "  jobject jfl;\n";
9910             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9911         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9912         | RBufferOut _ ->
9913             pr "  jstring jr;\n";
9914             pr "  char *r;\n";
9915             pr "  size_t size;\n";
9916             "NULL", "NULL" in
9917       List.iter (
9918         function
9919         | Pathname n
9920         | Device n | Dev_or_Path n
9921         | String n
9922         | OptString n
9923         | FileIn n
9924         | FileOut n ->
9925             pr "  const char *%s;\n" n
9926         | StringList n | DeviceList n ->
9927             pr "  int %s_len;\n" n;
9928             pr "  const char **%s;\n" n
9929         | Bool n
9930         | Int n ->
9931             pr "  int %s;\n" n
9932         | Int64 n ->
9933             pr "  int64_t %s;\n" n
9934       ) (snd style);
9935
9936       let needs_i =
9937         (match fst style with
9938          | RStringList _ | RStructList _ -> true
9939          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9940          | RConstOptString _
9941          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9942           List.exists (function
9943                        | StringList _ -> true
9944                        | DeviceList _ -> true
9945                        | _ -> false) (snd style) in
9946       if needs_i then
9947         pr "  int i;\n";
9948
9949       pr "\n";
9950
9951       (* Get the parameters. *)
9952       List.iter (
9953         function
9954         | Pathname n
9955         | Device n | Dev_or_Path n
9956         | String n
9957         | FileIn n
9958         | FileOut n ->
9959             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9960         | OptString n ->
9961             (* This is completely undocumented, but Java null becomes
9962              * a NULL parameter.
9963              *)
9964             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9965         | StringList n | DeviceList n ->
9966             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9967             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9968             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9969             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9970               n;
9971             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9972             pr "  }\n";
9973             pr "  %s[%s_len] = NULL;\n" n n;
9974         | Bool n
9975         | Int n
9976         | Int64 n ->
9977             pr "  %s = j%s;\n" n n
9978       ) (snd style);
9979
9980       (* Make the call. *)
9981       pr "  r = guestfs_%s " name;
9982       generate_c_call_args ~handle:"g" style;
9983       pr ";\n";
9984
9985       (* Release the parameters. *)
9986       List.iter (
9987         function
9988         | Pathname n
9989         | Device n | Dev_or_Path n
9990         | String n
9991         | FileIn n
9992         | FileOut n ->
9993             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9994         | OptString n ->
9995             pr "  if (j%s)\n" n;
9996             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9997         | StringList n | DeviceList n ->
9998             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9999             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10000               n;
10001             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10002             pr "  }\n";
10003             pr "  free (%s);\n" n
10004         | Bool n
10005         | Int n
10006         | Int64 n -> ()
10007       ) (snd style);
10008
10009       (* Check for errors. *)
10010       pr "  if (r == %s) {\n" error_code;
10011       pr "    throw_exception (env, guestfs_last_error (g));\n";
10012       pr "    return %s;\n" no_ret;
10013       pr "  }\n";
10014
10015       (* Return value. *)
10016       (match fst style with
10017        | RErr -> ()
10018        | RInt _ -> pr "  return (jint) r;\n"
10019        | RBool _ -> pr "  return (jboolean) r;\n"
10020        | RInt64 _ -> pr "  return (jlong) r;\n"
10021        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10022        | RConstOptString _ ->
10023            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10024        | RString _ ->
10025            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10026            pr "  free (r);\n";
10027            pr "  return jr;\n"
10028        | RStringList _ ->
10029            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10030            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10031            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10032            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10033            pr "  for (i = 0; i < r_len; ++i) {\n";
10034            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10035            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10036            pr "    free (r[i]);\n";
10037            pr "  }\n";
10038            pr "  free (r);\n";
10039            pr "  return jr;\n"
10040        | RStruct (_, typ) ->
10041            let jtyp = java_name_of_struct typ in
10042            let cols = cols_of_struct typ in
10043            generate_java_struct_return typ jtyp cols
10044        | RStructList (_, typ) ->
10045            let jtyp = java_name_of_struct typ in
10046            let cols = cols_of_struct typ in
10047            generate_java_struct_list_return typ jtyp cols
10048        | RHashtable _ ->
10049            (* XXX *)
10050            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10051            pr "  return NULL;\n"
10052        | RBufferOut _ ->
10053            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10054            pr "  free (r);\n";
10055            pr "  return jr;\n"
10056       );
10057
10058       pr "}\n";
10059       pr "\n"
10060   ) all_functions
10061
10062 and generate_java_struct_return typ jtyp cols =
10063   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10064   pr "  jr = (*env)->AllocObject (env, cl);\n";
10065   List.iter (
10066     function
10067     | name, FString ->
10068         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10069         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10070     | name, FUUID ->
10071         pr "  {\n";
10072         pr "    char s[33];\n";
10073         pr "    memcpy (s, r->%s, 32);\n" name;
10074         pr "    s[32] = 0;\n";
10075         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10076         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10077         pr "  }\n";
10078     | name, FBuffer ->
10079         pr "  {\n";
10080         pr "    int len = r->%s_len;\n" name;
10081         pr "    char s[len+1];\n";
10082         pr "    memcpy (s, r->%s, len);\n" name;
10083         pr "    s[len] = 0;\n";
10084         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10085         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10086         pr "  }\n";
10087     | name, (FBytes|FUInt64|FInt64) ->
10088         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10089         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10090     | name, (FUInt32|FInt32) ->
10091         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10092         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10093     | name, FOptPercent ->
10094         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10095         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10096     | name, FChar ->
10097         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10098         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10099   ) cols;
10100   pr "  free (r);\n";
10101   pr "  return jr;\n"
10102
10103 and generate_java_struct_list_return typ jtyp cols =
10104   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10105   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10106   pr "  for (i = 0; i < r->len; ++i) {\n";
10107   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10108   List.iter (
10109     function
10110     | name, FString ->
10111         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10112         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10113     | name, FUUID ->
10114         pr "    {\n";
10115         pr "      char s[33];\n";
10116         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10117         pr "      s[32] = 0;\n";
10118         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10119         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10120         pr "    }\n";
10121     | name, FBuffer ->
10122         pr "    {\n";
10123         pr "      int len = r->val[i].%s_len;\n" name;
10124         pr "      char s[len+1];\n";
10125         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10126         pr "      s[len] = 0;\n";
10127         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10128         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10129         pr "    }\n";
10130     | name, (FBytes|FUInt64|FInt64) ->
10131         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10132         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10133     | name, (FUInt32|FInt32) ->
10134         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10135         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10136     | name, FOptPercent ->
10137         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10138         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10139     | name, FChar ->
10140         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10141         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10142   ) cols;
10143   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10144   pr "  }\n";
10145   pr "  guestfs_free_%s_list (r);\n" typ;
10146   pr "  return jr;\n"
10147
10148 and generate_java_makefile_inc () =
10149   generate_header HashStyle GPLv2plus;
10150
10151   pr "java_built_sources = \\\n";
10152   List.iter (
10153     fun (typ, jtyp) ->
10154         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10155   ) java_structs;
10156   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10157
10158 and generate_haskell_hs () =
10159   generate_header HaskellStyle LGPLv2plus;
10160
10161   (* XXX We only know how to generate partial FFI for Haskell
10162    * at the moment.  Please help out!
10163    *)
10164   let can_generate style =
10165     match style with
10166     | RErr, _
10167     | RInt _, _
10168     | RInt64 _, _ -> true
10169     | RBool _, _
10170     | RConstString _, _
10171     | RConstOptString _, _
10172     | RString _, _
10173     | RStringList _, _
10174     | RStruct _, _
10175     | RStructList _, _
10176     | RHashtable _, _
10177     | RBufferOut _, _ -> false in
10178
10179   pr "\
10180 {-# INCLUDE <guestfs.h> #-}
10181 {-# LANGUAGE ForeignFunctionInterface #-}
10182
10183 module Guestfs (
10184   create";
10185
10186   (* List out the names of the actions we want to export. *)
10187   List.iter (
10188     fun (name, style, _, _, _, _, _) ->
10189       if can_generate style then pr ",\n  %s" name
10190   ) all_functions;
10191
10192   pr "
10193   ) where
10194
10195 -- Unfortunately some symbols duplicate ones already present
10196 -- in Prelude.  We don't know which, so we hard-code a list
10197 -- here.
10198 import Prelude hiding (truncate)
10199
10200 import Foreign
10201 import Foreign.C
10202 import Foreign.C.Types
10203 import IO
10204 import Control.Exception
10205 import Data.Typeable
10206
10207 data GuestfsS = GuestfsS            -- represents the opaque C struct
10208 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10209 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10210
10211 -- XXX define properly later XXX
10212 data PV = PV
10213 data VG = VG
10214 data LV = LV
10215 data IntBool = IntBool
10216 data Stat = Stat
10217 data StatVFS = StatVFS
10218 data Hashtable = Hashtable
10219
10220 foreign import ccall unsafe \"guestfs_create\" c_create
10221   :: IO GuestfsP
10222 foreign import ccall unsafe \"&guestfs_close\" c_close
10223   :: FunPtr (GuestfsP -> IO ())
10224 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10225   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10226
10227 create :: IO GuestfsH
10228 create = do
10229   p <- c_create
10230   c_set_error_handler p nullPtr nullPtr
10231   h <- newForeignPtr c_close p
10232   return h
10233
10234 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10235   :: GuestfsP -> IO CString
10236
10237 -- last_error :: GuestfsH -> IO (Maybe String)
10238 -- last_error h = do
10239 --   str <- withForeignPtr h (\\p -> c_last_error p)
10240 --   maybePeek peekCString str
10241
10242 last_error :: GuestfsH -> IO (String)
10243 last_error h = do
10244   str <- withForeignPtr h (\\p -> c_last_error p)
10245   if (str == nullPtr)
10246     then return \"no error\"
10247     else peekCString str
10248
10249 ";
10250
10251   (* Generate wrappers for each foreign function. *)
10252   List.iter (
10253     fun (name, style, _, _, _, _, _) ->
10254       if can_generate style then (
10255         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10256         pr "  :: ";
10257         generate_haskell_prototype ~handle:"GuestfsP" style;
10258         pr "\n";
10259         pr "\n";
10260         pr "%s :: " name;
10261         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10262         pr "\n";
10263         pr "%s %s = do\n" name
10264           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10265         pr "  r <- ";
10266         (* Convert pointer arguments using with* functions. *)
10267         List.iter (
10268           function
10269           | FileIn n
10270           | FileOut n
10271           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10272           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10273           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10274           | Bool _ | Int _ | Int64 _ -> ()
10275         ) (snd style);
10276         (* Convert integer arguments. *)
10277         let args =
10278           List.map (
10279             function
10280             | Bool n -> sprintf "(fromBool %s)" n
10281             | Int n -> sprintf "(fromIntegral %s)" n
10282             | Int64 n -> sprintf "(fromIntegral %s)" n
10283             | FileIn n | FileOut n
10284             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10285           ) (snd style) in
10286         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10287           (String.concat " " ("p" :: args));
10288         (match fst style with
10289          | RErr | RInt _ | RInt64 _ | RBool _ ->
10290              pr "  if (r == -1)\n";
10291              pr "    then do\n";
10292              pr "      err <- last_error h\n";
10293              pr "      fail err\n";
10294          | RConstString _ | RConstOptString _ | RString _
10295          | RStringList _ | RStruct _
10296          | RStructList _ | RHashtable _ | RBufferOut _ ->
10297              pr "  if (r == nullPtr)\n";
10298              pr "    then do\n";
10299              pr "      err <- last_error h\n";
10300              pr "      fail err\n";
10301         );
10302         (match fst style with
10303          | RErr ->
10304              pr "    else return ()\n"
10305          | RInt _ ->
10306              pr "    else return (fromIntegral r)\n"
10307          | RInt64 _ ->
10308              pr "    else return (fromIntegral r)\n"
10309          | RBool _ ->
10310              pr "    else return (toBool r)\n"
10311          | RConstString _
10312          | RConstOptString _
10313          | RString _
10314          | RStringList _
10315          | RStruct _
10316          | RStructList _
10317          | RHashtable _
10318          | RBufferOut _ ->
10319              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10320         );
10321         pr "\n";
10322       )
10323   ) all_functions
10324
10325 and generate_haskell_prototype ~handle ?(hs = false) style =
10326   pr "%s -> " handle;
10327   let string = if hs then "String" else "CString" in
10328   let int = if hs then "Int" else "CInt" in
10329   let bool = if hs then "Bool" else "CInt" in
10330   let int64 = if hs then "Integer" else "Int64" in
10331   List.iter (
10332     fun arg ->
10333       (match arg with
10334        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10335        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10336        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10337        | Bool _ -> pr "%s" bool
10338        | Int _ -> pr "%s" int
10339        | Int64 _ -> pr "%s" int
10340        | FileIn _ -> pr "%s" string
10341        | FileOut _ -> pr "%s" string
10342       );
10343       pr " -> ";
10344   ) (snd style);
10345   pr "IO (";
10346   (match fst style with
10347    | RErr -> if not hs then pr "CInt"
10348    | RInt _ -> pr "%s" int
10349    | RInt64 _ -> pr "%s" int64
10350    | RBool _ -> pr "%s" bool
10351    | RConstString _ -> pr "%s" string
10352    | RConstOptString _ -> pr "Maybe %s" string
10353    | RString _ -> pr "%s" string
10354    | RStringList _ -> pr "[%s]" string
10355    | RStruct (_, typ) ->
10356        let name = java_name_of_struct typ in
10357        pr "%s" name
10358    | RStructList (_, typ) ->
10359        let name = java_name_of_struct typ in
10360        pr "[%s]" name
10361    | RHashtable _ -> pr "Hashtable"
10362    | RBufferOut _ -> pr "%s" string
10363   );
10364   pr ")"
10365
10366 and generate_csharp () =
10367   generate_header CPlusPlusStyle LGPLv2plus;
10368
10369   (* XXX Make this configurable by the C# assembly users. *)
10370   let library = "libguestfs.so.0" in
10371
10372   pr "\
10373 // These C# bindings are highly experimental at present.
10374 //
10375 // Firstly they only work on Linux (ie. Mono).  In order to get them
10376 // to work on Windows (ie. .Net) you would need to port the library
10377 // itself to Windows first.
10378 //
10379 // The second issue is that some calls are known to be incorrect and
10380 // can cause Mono to segfault.  Particularly: calls which pass or
10381 // return string[], or return any structure value.  This is because
10382 // we haven't worked out the correct way to do this from C#.
10383 //
10384 // The third issue is that when compiling you get a lot of warnings.
10385 // We are not sure whether the warnings are important or not.
10386 //
10387 // Fourthly we do not routinely build or test these bindings as part
10388 // of the make && make check cycle, which means that regressions might
10389 // go unnoticed.
10390 //
10391 // Suggestions and patches are welcome.
10392
10393 // To compile:
10394 //
10395 // gmcs Libguestfs.cs
10396 // mono Libguestfs.exe
10397 //
10398 // (You'll probably want to add a Test class / static main function
10399 // otherwise this won't do anything useful).
10400
10401 using System;
10402 using System.IO;
10403 using System.Runtime.InteropServices;
10404 using System.Runtime.Serialization;
10405 using System.Collections;
10406
10407 namespace Guestfs
10408 {
10409   class Error : System.ApplicationException
10410   {
10411     public Error (string message) : base (message) {}
10412     protected Error (SerializationInfo info, StreamingContext context) {}
10413   }
10414
10415   class Guestfs
10416   {
10417     IntPtr _handle;
10418
10419     [DllImport (\"%s\")]
10420     static extern IntPtr guestfs_create ();
10421
10422     public Guestfs ()
10423     {
10424       _handle = guestfs_create ();
10425       if (_handle == IntPtr.Zero)
10426         throw new Error (\"could not create guestfs handle\");
10427     }
10428
10429     [DllImport (\"%s\")]
10430     static extern void guestfs_close (IntPtr h);
10431
10432     ~Guestfs ()
10433     {
10434       guestfs_close (_handle);
10435     }
10436
10437     [DllImport (\"%s\")]
10438     static extern string guestfs_last_error (IntPtr h);
10439
10440 " library library library;
10441
10442   (* Generate C# structure bindings.  We prefix struct names with
10443    * underscore because C# cannot have conflicting struct names and
10444    * method names (eg. "class stat" and "stat").
10445    *)
10446   List.iter (
10447     fun (typ, cols) ->
10448       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10449       pr "    public class _%s {\n" typ;
10450       List.iter (
10451         function
10452         | name, FChar -> pr "      char %s;\n" name
10453         | name, FString -> pr "      string %s;\n" name
10454         | name, FBuffer ->
10455             pr "      uint %s_len;\n" name;
10456             pr "      string %s;\n" name
10457         | name, FUUID ->
10458             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10459             pr "      string %s;\n" name
10460         | name, FUInt32 -> pr "      uint %s;\n" name
10461         | name, FInt32 -> pr "      int %s;\n" name
10462         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10463         | name, FInt64 -> pr "      long %s;\n" name
10464         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10465       ) cols;
10466       pr "    }\n";
10467       pr "\n"
10468   ) structs;
10469
10470   (* Generate C# function bindings. *)
10471   List.iter (
10472     fun (name, style, _, _, _, shortdesc, _) ->
10473       let rec csharp_return_type () =
10474         match fst style with
10475         | RErr -> "void"
10476         | RBool n -> "bool"
10477         | RInt n -> "int"
10478         | RInt64 n -> "long"
10479         | RConstString n
10480         | RConstOptString n
10481         | RString n
10482         | RBufferOut n -> "string"
10483         | RStruct (_,n) -> "_" ^ n
10484         | RHashtable n -> "Hashtable"
10485         | RStringList n -> "string[]"
10486         | RStructList (_,n) -> sprintf "_%s[]" n
10487
10488       and c_return_type () =
10489         match fst style with
10490         | RErr
10491         | RBool _
10492         | RInt _ -> "int"
10493         | RInt64 _ -> "long"
10494         | RConstString _
10495         | RConstOptString _
10496         | RString _
10497         | RBufferOut _ -> "string"
10498         | RStruct (_,n) -> "_" ^ n
10499         | RHashtable _
10500         | RStringList _ -> "string[]"
10501         | RStructList (_,n) -> sprintf "_%s[]" n
10502
10503       and c_error_comparison () =
10504         match fst style with
10505         | RErr
10506         | RBool _
10507         | RInt _
10508         | RInt64 _ -> "== -1"
10509         | RConstString _
10510         | RConstOptString _
10511         | RString _
10512         | RBufferOut _
10513         | RStruct (_,_)
10514         | RHashtable _
10515         | RStringList _
10516         | RStructList (_,_) -> "== null"
10517
10518       and generate_extern_prototype () =
10519         pr "    static extern %s guestfs_%s (IntPtr h"
10520           (c_return_type ()) name;
10521         List.iter (
10522           function
10523           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10524           | FileIn n | FileOut n ->
10525               pr ", [In] string %s" n
10526           | StringList n | DeviceList n ->
10527               pr ", [In] string[] %s" n
10528           | Bool n ->
10529               pr ", bool %s" n
10530           | Int n ->
10531               pr ", int %s" n
10532           | Int64 n ->
10533               pr ", long %s" n
10534         ) (snd style);
10535         pr ");\n"
10536
10537       and generate_public_prototype () =
10538         pr "    public %s %s (" (csharp_return_type ()) name;
10539         let comma = ref false in
10540         let next () =
10541           if !comma then pr ", ";
10542           comma := true
10543         in
10544         List.iter (
10545           function
10546           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10547           | FileIn n | FileOut n ->
10548               next (); pr "string %s" n
10549           | StringList n | DeviceList n ->
10550               next (); pr "string[] %s" n
10551           | Bool n ->
10552               next (); pr "bool %s" n
10553           | Int n ->
10554               next (); pr "int %s" n
10555           | Int64 n ->
10556               next (); pr "long %s" n
10557         ) (snd style);
10558         pr ")\n"
10559
10560       and generate_call () =
10561         pr "guestfs_%s (_handle" name;
10562         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10563         pr ");\n";
10564       in
10565
10566       pr "    [DllImport (\"%s\")]\n" library;
10567       generate_extern_prototype ();
10568       pr "\n";
10569       pr "    /// <summary>\n";
10570       pr "    /// %s\n" shortdesc;
10571       pr "    /// </summary>\n";
10572       generate_public_prototype ();
10573       pr "    {\n";
10574       pr "      %s r;\n" (c_return_type ());
10575       pr "      r = ";
10576       generate_call ();
10577       pr "      if (r %s)\n" (c_error_comparison ());
10578       pr "        throw new Error (guestfs_last_error (_handle));\n";
10579       (match fst style with
10580        | RErr -> ()
10581        | RBool _ ->
10582            pr "      return r != 0 ? true : false;\n"
10583        | RHashtable _ ->
10584            pr "      Hashtable rr = new Hashtable ();\n";
10585            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10586            pr "        rr.Add (r[i], r[i+1]);\n";
10587            pr "      return rr;\n"
10588        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10589        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10590        | RStructList _ ->
10591            pr "      return r;\n"
10592       );
10593       pr "    }\n";
10594       pr "\n";
10595   ) all_functions_sorted;
10596
10597   pr "  }
10598 }
10599 "
10600
10601 and generate_bindtests () =
10602   generate_header CStyle LGPLv2plus;
10603
10604   pr "\
10605 #include <stdio.h>
10606 #include <stdlib.h>
10607 #include <inttypes.h>
10608 #include <string.h>
10609
10610 #include \"guestfs.h\"
10611 #include \"guestfs-internal.h\"
10612 #include \"guestfs-internal-actions.h\"
10613 #include \"guestfs_protocol.h\"
10614
10615 #define error guestfs_error
10616 #define safe_calloc guestfs_safe_calloc
10617 #define safe_malloc guestfs_safe_malloc
10618
10619 static void
10620 print_strings (char *const *argv)
10621 {
10622   int argc;
10623
10624   printf (\"[\");
10625   for (argc = 0; argv[argc] != NULL; ++argc) {
10626     if (argc > 0) printf (\", \");
10627     printf (\"\\\"%%s\\\"\", argv[argc]);
10628   }
10629   printf (\"]\\n\");
10630 }
10631
10632 /* The test0 function prints its parameters to stdout. */
10633 ";
10634
10635   let test0, tests =
10636     match test_functions with
10637     | [] -> assert false
10638     | test0 :: tests -> test0, tests in
10639
10640   let () =
10641     let (name, style, _, _, _, _, _) = test0 in
10642     generate_prototype ~extern:false ~semicolon:false ~newline:true
10643       ~handle:"g" ~prefix:"guestfs__" name style;
10644     pr "{\n";
10645     List.iter (
10646       function
10647       | Pathname n
10648       | Device n | Dev_or_Path n
10649       | String n
10650       | FileIn n
10651       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10652       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10653       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10654       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10655       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10656       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10657     ) (snd style);
10658     pr "  /* Java changes stdout line buffering so we need this: */\n";
10659     pr "  fflush (stdout);\n";
10660     pr "  return 0;\n";
10661     pr "}\n";
10662     pr "\n" in
10663
10664   List.iter (
10665     fun (name, style, _, _, _, _, _) ->
10666       if String.sub name (String.length name - 3) 3 <> "err" then (
10667         pr "/* Test normal return. */\n";
10668         generate_prototype ~extern:false ~semicolon:false ~newline:true
10669           ~handle:"g" ~prefix:"guestfs__" name style;
10670         pr "{\n";
10671         (match fst style with
10672          | RErr ->
10673              pr "  return 0;\n"
10674          | RInt _ ->
10675              pr "  int r;\n";
10676              pr "  sscanf (val, \"%%d\", &r);\n";
10677              pr "  return r;\n"
10678          | RInt64 _ ->
10679              pr "  int64_t r;\n";
10680              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10681              pr "  return r;\n"
10682          | RBool _ ->
10683              pr "  return STREQ (val, \"true\");\n"
10684          | RConstString _
10685          | RConstOptString _ ->
10686              (* Can't return the input string here.  Return a static
10687               * string so we ensure we get a segfault if the caller
10688               * tries to free it.
10689               *)
10690              pr "  return \"static string\";\n"
10691          | RString _ ->
10692              pr "  return strdup (val);\n"
10693          | RStringList _ ->
10694              pr "  char **strs;\n";
10695              pr "  int n, i;\n";
10696              pr "  sscanf (val, \"%%d\", &n);\n";
10697              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10698              pr "  for (i = 0; i < n; ++i) {\n";
10699              pr "    strs[i] = safe_malloc (g, 16);\n";
10700              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10701              pr "  }\n";
10702              pr "  strs[n] = NULL;\n";
10703              pr "  return strs;\n"
10704          | RStruct (_, typ) ->
10705              pr "  struct guestfs_%s *r;\n" typ;
10706              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10707              pr "  return r;\n"
10708          | RStructList (_, typ) ->
10709              pr "  struct guestfs_%s_list *r;\n" typ;
10710              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10711              pr "  sscanf (val, \"%%d\", &r->len);\n";
10712              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10713              pr "  return r;\n"
10714          | RHashtable _ ->
10715              pr "  char **strs;\n";
10716              pr "  int n, i;\n";
10717              pr "  sscanf (val, \"%%d\", &n);\n";
10718              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10719              pr "  for (i = 0; i < n; ++i) {\n";
10720              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10721              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10722              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10723              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10724              pr "  }\n";
10725              pr "  strs[n*2] = NULL;\n";
10726              pr "  return strs;\n"
10727          | RBufferOut _ ->
10728              pr "  return strdup (val);\n"
10729         );
10730         pr "}\n";
10731         pr "\n"
10732       ) else (
10733         pr "/* Test error return. */\n";
10734         generate_prototype ~extern:false ~semicolon:false ~newline:true
10735           ~handle:"g" ~prefix:"guestfs__" name style;
10736         pr "{\n";
10737         pr "  error (g, \"error\");\n";
10738         (match fst style with
10739          | RErr | RInt _ | RInt64 _ | RBool _ ->
10740              pr "  return -1;\n"
10741          | RConstString _ | RConstOptString _
10742          | RString _ | RStringList _ | RStruct _
10743          | RStructList _
10744          | RHashtable _
10745          | RBufferOut _ ->
10746              pr "  return NULL;\n"
10747         );
10748         pr "}\n";
10749         pr "\n"
10750       )
10751   ) tests
10752
10753 and generate_ocaml_bindtests () =
10754   generate_header OCamlStyle GPLv2plus;
10755
10756   pr "\
10757 let () =
10758   let g = Guestfs.create () in
10759 ";
10760
10761   let mkargs args =
10762     String.concat " " (
10763       List.map (
10764         function
10765         | CallString s -> "\"" ^ s ^ "\""
10766         | CallOptString None -> "None"
10767         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10768         | CallStringList xs ->
10769             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10770         | CallInt i when i >= 0 -> string_of_int i
10771         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10772         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10773         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10774         | CallBool b -> string_of_bool b
10775       ) args
10776     )
10777   in
10778
10779   generate_lang_bindtests (
10780     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10781   );
10782
10783   pr "print_endline \"EOF\"\n"
10784
10785 and generate_perl_bindtests () =
10786   pr "#!/usr/bin/perl -w\n";
10787   generate_header HashStyle GPLv2plus;
10788
10789   pr "\
10790 use strict;
10791
10792 use Sys::Guestfs;
10793
10794 my $g = Sys::Guestfs->new ();
10795 ";
10796
10797   let mkargs args =
10798     String.concat ", " (
10799       List.map (
10800         function
10801         | CallString s -> "\"" ^ s ^ "\""
10802         | CallOptString None -> "undef"
10803         | CallOptString (Some s) -> sprintf "\"%s\"" s
10804         | CallStringList xs ->
10805             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10806         | CallInt i -> string_of_int i
10807         | CallInt64 i -> Int64.to_string i
10808         | CallBool b -> if b then "1" else "0"
10809       ) args
10810     )
10811   in
10812
10813   generate_lang_bindtests (
10814     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10815   );
10816
10817   pr "print \"EOF\\n\"\n"
10818
10819 and generate_python_bindtests () =
10820   generate_header HashStyle GPLv2plus;
10821
10822   pr "\
10823 import guestfs
10824
10825 g = guestfs.GuestFS ()
10826 ";
10827
10828   let mkargs args =
10829     String.concat ", " (
10830       List.map (
10831         function
10832         | CallString s -> "\"" ^ s ^ "\""
10833         | CallOptString None -> "None"
10834         | CallOptString (Some s) -> sprintf "\"%s\"" s
10835         | CallStringList xs ->
10836             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10837         | CallInt i -> string_of_int i
10838         | CallInt64 i -> Int64.to_string i
10839         | CallBool b -> if b then "1" else "0"
10840       ) args
10841     )
10842   in
10843
10844   generate_lang_bindtests (
10845     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10846   );
10847
10848   pr "print \"EOF\"\n"
10849
10850 and generate_ruby_bindtests () =
10851   generate_header HashStyle GPLv2plus;
10852
10853   pr "\
10854 require 'guestfs'
10855
10856 g = Guestfs::create()
10857 ";
10858
10859   let mkargs args =
10860     String.concat ", " (
10861       List.map (
10862         function
10863         | CallString s -> "\"" ^ s ^ "\""
10864         | CallOptString None -> "nil"
10865         | CallOptString (Some s) -> sprintf "\"%s\"" s
10866         | CallStringList xs ->
10867             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10868         | CallInt i -> string_of_int i
10869         | CallInt64 i -> Int64.to_string i
10870         | CallBool b -> string_of_bool b
10871       ) args
10872     )
10873   in
10874
10875   generate_lang_bindtests (
10876     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10877   );
10878
10879   pr "print \"EOF\\n\"\n"
10880
10881 and generate_java_bindtests () =
10882   generate_header CStyle GPLv2plus;
10883
10884   pr "\
10885 import com.redhat.et.libguestfs.*;
10886
10887 public class Bindtests {
10888     public static void main (String[] argv)
10889     {
10890         try {
10891             GuestFS g = new GuestFS ();
10892 ";
10893
10894   let mkargs args =
10895     String.concat ", " (
10896       List.map (
10897         function
10898         | CallString s -> "\"" ^ s ^ "\""
10899         | CallOptString None -> "null"
10900         | CallOptString (Some s) -> sprintf "\"%s\"" s
10901         | CallStringList xs ->
10902             "new String[]{" ^
10903               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10904         | CallInt i -> string_of_int i
10905         | CallInt64 i -> Int64.to_string i
10906         | CallBool b -> string_of_bool b
10907       ) args
10908     )
10909   in
10910
10911   generate_lang_bindtests (
10912     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10913   );
10914
10915   pr "
10916             System.out.println (\"EOF\");
10917         }
10918         catch (Exception exn) {
10919             System.err.println (exn);
10920             System.exit (1);
10921         }
10922     }
10923 }
10924 "
10925
10926 and generate_haskell_bindtests () =
10927   generate_header HaskellStyle GPLv2plus;
10928
10929   pr "\
10930 module Bindtests where
10931 import qualified Guestfs
10932
10933 main = do
10934   g <- Guestfs.create
10935 ";
10936
10937   let mkargs args =
10938     String.concat " " (
10939       List.map (
10940         function
10941         | CallString s -> "\"" ^ s ^ "\""
10942         | CallOptString None -> "Nothing"
10943         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10944         | CallStringList xs ->
10945             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10946         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10947         | CallInt i -> string_of_int i
10948         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10949         | CallInt64 i -> Int64.to_string i
10950         | CallBool true -> "True"
10951         | CallBool false -> "False"
10952       ) args
10953     )
10954   in
10955
10956   generate_lang_bindtests (
10957     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10958   );
10959
10960   pr "  putStrLn \"EOF\"\n"
10961
10962 (* Language-independent bindings tests - we do it this way to
10963  * ensure there is parity in testing bindings across all languages.
10964  *)
10965 and generate_lang_bindtests call =
10966   call "test0" [CallString "abc"; CallOptString (Some "def");
10967                 CallStringList []; CallBool false;
10968                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10969   call "test0" [CallString "abc"; CallOptString None;
10970                 CallStringList []; CallBool false;
10971                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10972   call "test0" [CallString ""; CallOptString (Some "def");
10973                 CallStringList []; CallBool false;
10974                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10975   call "test0" [CallString ""; CallOptString (Some "");
10976                 CallStringList []; CallBool false;
10977                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10978   call "test0" [CallString "abc"; CallOptString (Some "def");
10979                 CallStringList ["1"]; CallBool false;
10980                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10981   call "test0" [CallString "abc"; CallOptString (Some "def");
10982                 CallStringList ["1"; "2"]; CallBool false;
10983                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10984   call "test0" [CallString "abc"; CallOptString (Some "def");
10985                 CallStringList ["1"]; CallBool true;
10986                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10987   call "test0" [CallString "abc"; CallOptString (Some "def");
10988                 CallStringList ["1"]; CallBool false;
10989                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10990   call "test0" [CallString "abc"; CallOptString (Some "def");
10991                 CallStringList ["1"]; CallBool false;
10992                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10993   call "test0" [CallString "abc"; CallOptString (Some "def");
10994                 CallStringList ["1"]; CallBool false;
10995                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10996   call "test0" [CallString "abc"; CallOptString (Some "def");
10997                 CallStringList ["1"]; CallBool false;
10998                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10999   call "test0" [CallString "abc"; CallOptString (Some "def");
11000                 CallStringList ["1"]; CallBool false;
11001                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
11002   call "test0" [CallString "abc"; CallOptString (Some "def");
11003                 CallStringList ["1"]; CallBool false;
11004                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
11005
11006 (* XXX Add here tests of the return and error functions. *)
11007
11008 (* Code to generator bindings for virt-inspector.  Currently only
11009  * implemented for OCaml code (for virt-p2v 2.0).
11010  *)
11011 let rng_input = "inspector/virt-inspector.rng"
11012
11013 (* Read the input file and parse it into internal structures.  This is
11014  * by no means a complete RELAX NG parser, but is just enough to be
11015  * able to parse the specific input file.
11016  *)
11017 type rng =
11018   | Element of string * rng list        (* <element name=name/> *)
11019   | Attribute of string * rng list        (* <attribute name=name/> *)
11020   | Interleave of rng list                (* <interleave/> *)
11021   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11022   | OneOrMore of rng                        (* <oneOrMore/> *)
11023   | Optional of rng                        (* <optional/> *)
11024   | Choice of string list                (* <choice><value/>*</choice> *)
11025   | Value of string                        (* <value>str</value> *)
11026   | Text                                (* <text/> *)
11027
11028 let rec string_of_rng = function
11029   | Element (name, xs) ->
11030       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11031   | Attribute (name, xs) ->
11032       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11033   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11034   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11035   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11036   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11037   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11038   | Value value -> "Value \"" ^ value ^ "\""
11039   | Text -> "Text"
11040
11041 and string_of_rng_list xs =
11042   String.concat ", " (List.map string_of_rng xs)
11043
11044 let rec parse_rng ?defines context = function
11045   | [] -> []
11046   | Xml.Element ("element", ["name", name], children) :: rest ->
11047       Element (name, parse_rng ?defines context children)
11048       :: parse_rng ?defines context rest
11049   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11050       Attribute (name, parse_rng ?defines context children)
11051       :: parse_rng ?defines context rest
11052   | Xml.Element ("interleave", [], children) :: rest ->
11053       Interleave (parse_rng ?defines context children)
11054       :: parse_rng ?defines context rest
11055   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11056       let rng = parse_rng ?defines context [child] in
11057       (match rng with
11058        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11059        | _ ->
11060            failwithf "%s: <zeroOrMore> contains more than one child element"
11061              context
11062       )
11063   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11064       let rng = parse_rng ?defines context [child] in
11065       (match rng with
11066        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11067        | _ ->
11068            failwithf "%s: <oneOrMore> contains more than one child element"
11069              context
11070       )
11071   | Xml.Element ("optional", [], [child]) :: rest ->
11072       let rng = parse_rng ?defines context [child] in
11073       (match rng with
11074        | [child] -> Optional child :: parse_rng ?defines context rest
11075        | _ ->
11076            failwithf "%s: <optional> contains more than one child element"
11077              context
11078       )
11079   | Xml.Element ("choice", [], children) :: rest ->
11080       let values = List.map (
11081         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11082         | _ ->
11083             failwithf "%s: can't handle anything except <value> in <choice>"
11084               context
11085       ) children in
11086       Choice values
11087       :: parse_rng ?defines context rest
11088   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11089       Value value :: parse_rng ?defines context rest
11090   | Xml.Element ("text", [], []) :: rest ->
11091       Text :: parse_rng ?defines context rest
11092   | Xml.Element ("ref", ["name", name], []) :: rest ->
11093       (* Look up the reference.  Because of limitations in this parser,
11094        * we can't handle arbitrarily nested <ref> yet.  You can only
11095        * use <ref> from inside <start>.
11096        *)
11097       (match defines with
11098        | None ->
11099            failwithf "%s: contains <ref>, but no refs are defined yet" context
11100        | Some map ->
11101            let rng = StringMap.find name map in
11102            rng @ parse_rng ?defines context rest
11103       )
11104   | x :: _ ->
11105       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11106
11107 let grammar =
11108   let xml = Xml.parse_file rng_input in
11109   match xml with
11110   | Xml.Element ("grammar", _,
11111                  Xml.Element ("start", _, gram) :: defines) ->
11112       (* The <define/> elements are referenced in the <start> section,
11113        * so build a map of those first.
11114        *)
11115       let defines = List.fold_left (
11116         fun map ->
11117           function Xml.Element ("define", ["name", name], defn) ->
11118             StringMap.add name defn map
11119           | _ ->
11120               failwithf "%s: expected <define name=name/>" rng_input
11121       ) StringMap.empty defines in
11122       let defines = StringMap.mapi parse_rng defines in
11123
11124       (* Parse the <start> clause, passing the defines. *)
11125       parse_rng ~defines "<start>" gram
11126   | _ ->
11127       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11128         rng_input
11129
11130 let name_of_field = function
11131   | Element (name, _) | Attribute (name, _)
11132   | ZeroOrMore (Element (name, _))
11133   | OneOrMore (Element (name, _))
11134   | Optional (Element (name, _)) -> name
11135   | Optional (Attribute (name, _)) -> name
11136   | Text -> (* an unnamed field in an element *)
11137       "data"
11138   | rng ->
11139       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11140
11141 (* At the moment this function only generates OCaml types.  However we
11142  * should parameterize it later so it can generate types/structs in a
11143  * variety of languages.
11144  *)
11145 let generate_types xs =
11146   (* A simple type is one that can be printed out directly, eg.
11147    * "string option".  A complex type is one which has a name and has
11148    * to be defined via another toplevel definition, eg. a struct.
11149    *
11150    * generate_type generates code for either simple or complex types.
11151    * In the simple case, it returns the string ("string option").  In
11152    * the complex case, it returns the name ("mountpoint").  In the
11153    * complex case it has to print out the definition before returning,
11154    * so it should only be called when we are at the beginning of a
11155    * new line (BOL context).
11156    *)
11157   let rec generate_type = function
11158     | Text ->                                (* string *)
11159         "string", true
11160     | Choice values ->                        (* [`val1|`val2|...] *)
11161         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11162     | ZeroOrMore rng ->                        (* <rng> list *)
11163         let t, is_simple = generate_type rng in
11164         t ^ " list (* 0 or more *)", is_simple
11165     | OneOrMore rng ->                        (* <rng> list *)
11166         let t, is_simple = generate_type rng in
11167         t ^ " list (* 1 or more *)", is_simple
11168                                         (* virt-inspector hack: bool *)
11169     | Optional (Attribute (name, [Value "1"])) ->
11170         "bool", true
11171     | Optional rng ->                        (* <rng> list *)
11172         let t, is_simple = generate_type rng in
11173         t ^ " option", is_simple
11174                                         (* type name = { fields ... } *)
11175     | Element (name, fields) when is_attrs_interleave fields ->
11176         generate_type_struct name (get_attrs_interleave fields)
11177     | Element (name, [field])                (* type name = field *)
11178     | Attribute (name, [field]) ->
11179         let t, is_simple = generate_type field in
11180         if is_simple then (t, true)
11181         else (
11182           pr "type %s = %s\n" name t;
11183           name, false
11184         )
11185     | Element (name, fields) ->              (* type name = { fields ... } *)
11186         generate_type_struct name fields
11187     | rng ->
11188         failwithf "generate_type failed at: %s" (string_of_rng rng)
11189
11190   and is_attrs_interleave = function
11191     | [Interleave _] -> true
11192     | Attribute _ :: fields -> is_attrs_interleave fields
11193     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11194     | _ -> false
11195
11196   and get_attrs_interleave = function
11197     | [Interleave fields] -> fields
11198     | ((Attribute _) as field) :: fields
11199     | ((Optional (Attribute _)) as field) :: fields ->
11200         field :: get_attrs_interleave fields
11201     | _ -> assert false
11202
11203   and generate_types xs =
11204     List.iter (fun x -> ignore (generate_type x)) xs
11205
11206   and generate_type_struct name fields =
11207     (* Calculate the types of the fields first.  We have to do this
11208      * before printing anything so we are still in BOL context.
11209      *)
11210     let types = List.map fst (List.map generate_type fields) in
11211
11212     (* Special case of a struct containing just a string and another
11213      * field.  Turn it into an assoc list.
11214      *)
11215     match types with
11216     | ["string"; other] ->
11217         let fname1, fname2 =
11218           match fields with
11219           | [f1; f2] -> name_of_field f1, name_of_field f2
11220           | _ -> assert false in
11221         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11222         name, false
11223
11224     | types ->
11225         pr "type %s = {\n" name;
11226         List.iter (
11227           fun (field, ftype) ->
11228             let fname = name_of_field field in
11229             pr "  %s_%s : %s;\n" name fname ftype
11230         ) (List.combine fields types);
11231         pr "}\n";
11232         (* Return the name of this type, and
11233          * false because it's not a simple type.
11234          *)
11235         name, false
11236   in
11237
11238   generate_types xs
11239
11240 let generate_parsers xs =
11241   (* As for generate_type above, generate_parser makes a parser for
11242    * some type, and returns the name of the parser it has generated.
11243    * Because it (may) need to print something, it should always be
11244    * called in BOL context.
11245    *)
11246   let rec generate_parser = function
11247     | Text ->                                (* string *)
11248         "string_child_or_empty"
11249     | Choice values ->                        (* [`val1|`val2|...] *)
11250         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11251           (String.concat "|"
11252              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11253     | ZeroOrMore rng ->                        (* <rng> list *)
11254         let pa = generate_parser rng in
11255         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11256     | OneOrMore rng ->                        (* <rng> list *)
11257         let pa = generate_parser rng in
11258         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11259                                         (* virt-inspector hack: bool *)
11260     | Optional (Attribute (name, [Value "1"])) ->
11261         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11262     | Optional rng ->                        (* <rng> list *)
11263         let pa = generate_parser rng in
11264         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11265                                         (* type name = { fields ... } *)
11266     | Element (name, fields) when is_attrs_interleave fields ->
11267         generate_parser_struct name (get_attrs_interleave fields)
11268     | Element (name, [field]) ->        (* type name = field *)
11269         let pa = generate_parser field in
11270         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11271         pr "let %s =\n" parser_name;
11272         pr "  %s\n" pa;
11273         pr "let parse_%s = %s\n" name parser_name;
11274         parser_name
11275     | Attribute (name, [field]) ->
11276         let pa = generate_parser field in
11277         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11278         pr "let %s =\n" parser_name;
11279         pr "  %s\n" pa;
11280         pr "let parse_%s = %s\n" name parser_name;
11281         parser_name
11282     | Element (name, fields) ->              (* type name = { fields ... } *)
11283         generate_parser_struct name ([], fields)
11284     | rng ->
11285         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11286
11287   and is_attrs_interleave = function
11288     | [Interleave _] -> true
11289     | Attribute _ :: fields -> is_attrs_interleave fields
11290     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11291     | _ -> false
11292
11293   and get_attrs_interleave = function
11294     | [Interleave fields] -> [], fields
11295     | ((Attribute _) as field) :: fields
11296     | ((Optional (Attribute _)) as field) :: fields ->
11297         let attrs, interleaves = get_attrs_interleave fields in
11298         (field :: attrs), interleaves
11299     | _ -> assert false
11300
11301   and generate_parsers xs =
11302     List.iter (fun x -> ignore (generate_parser x)) xs
11303
11304   and generate_parser_struct name (attrs, interleaves) =
11305     (* Generate parsers for the fields first.  We have to do this
11306      * before printing anything so we are still in BOL context.
11307      *)
11308     let fields = attrs @ interleaves in
11309     let pas = List.map generate_parser fields in
11310
11311     (* Generate an intermediate tuple from all the fields first.
11312      * If the type is just a string + another field, then we will
11313      * return this directly, otherwise it is turned into a record.
11314      *
11315      * RELAX NG note: This code treats <interleave> and plain lists of
11316      * fields the same.  In other words, it doesn't bother enforcing
11317      * any ordering of fields in the XML.
11318      *)
11319     pr "let parse_%s x =\n" name;
11320     pr "  let t = (\n    ";
11321     let comma = ref false in
11322     List.iter (
11323       fun x ->
11324         if !comma then pr ",\n    ";
11325         comma := true;
11326         match x with
11327         | Optional (Attribute (fname, [field])), pa ->
11328             pr "%s x" pa
11329         | Optional (Element (fname, [field])), pa ->
11330             pr "%s (optional_child %S x)" pa fname
11331         | Attribute (fname, [Text]), _ ->
11332             pr "attribute %S x" fname
11333         | (ZeroOrMore _ | OneOrMore _), pa ->
11334             pr "%s x" pa
11335         | Text, pa ->
11336             pr "%s x" pa
11337         | (field, pa) ->
11338             let fname = name_of_field field in
11339             pr "%s (child %S x)" pa fname
11340     ) (List.combine fields pas);
11341     pr "\n  ) in\n";
11342
11343     (match fields with
11344      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11345          pr "  t\n"
11346
11347      | _ ->
11348          pr "  (Obj.magic t : %s)\n" name
11349 (*
11350          List.iter (
11351            function
11352            | (Optional (Attribute (fname, [field])), pa) ->
11353                pr "  %s_%s =\n" name fname;
11354                pr "    %s x;\n" pa
11355            | (Optional (Element (fname, [field])), pa) ->
11356                pr "  %s_%s =\n" name fname;
11357                pr "    (let x = optional_child %S x in\n" fname;
11358                pr "     %s x);\n" pa
11359            | (field, pa) ->
11360                let fname = name_of_field field in
11361                pr "  %s_%s =\n" name fname;
11362                pr "    (let x = child %S x in\n" fname;
11363                pr "     %s x);\n" pa
11364          ) (List.combine fields pas);
11365          pr "}\n"
11366 *)
11367     );
11368     sprintf "parse_%s" name
11369   in
11370
11371   generate_parsers xs
11372
11373 (* Generate ocaml/guestfs_inspector.mli. *)
11374 let generate_ocaml_inspector_mli () =
11375   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11376
11377   pr "\
11378 (** This is an OCaml language binding to the external [virt-inspector]
11379     program.
11380
11381     For more information, please read the man page [virt-inspector(1)].
11382 *)
11383
11384 ";
11385
11386   generate_types grammar;
11387   pr "(** The nested information returned from the {!inspect} function. *)\n";
11388   pr "\n";
11389
11390   pr "\
11391 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11392 (** To inspect a libvirt domain called [name], pass a singleton
11393     list: [inspect [name]].  When using libvirt only, you may
11394     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11395
11396     To inspect a disk image or images, pass a list of the filenames
11397     of the disk images: [inspect filenames]
11398
11399     This function inspects the given guest or disk images and
11400     returns a list of operating system(s) found and a large amount
11401     of information about them.  In the vast majority of cases,
11402     a virtual machine only contains a single operating system.
11403
11404     If the optional [~xml] parameter is given, then this function
11405     skips running the external virt-inspector program and just
11406     parses the given XML directly (which is expected to be XML
11407     produced from a previous run of virt-inspector).  The list of
11408     names and connect URI are ignored in this case.
11409
11410     This function can throw a wide variety of exceptions, for example
11411     if the external virt-inspector program cannot be found, or if
11412     it doesn't generate valid XML.
11413 *)
11414 "
11415
11416 (* Generate ocaml/guestfs_inspector.ml. *)
11417 let generate_ocaml_inspector_ml () =
11418   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11419
11420   pr "open Unix\n";
11421   pr "\n";
11422
11423   generate_types grammar;
11424   pr "\n";
11425
11426   pr "\
11427 (* Misc functions which are used by the parser code below. *)
11428 let first_child = function
11429   | Xml.Element (_, _, c::_) -> c
11430   | Xml.Element (name, _, []) ->
11431       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11432   | Xml.PCData str ->
11433       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11434
11435 let string_child_or_empty = function
11436   | Xml.Element (_, _, [Xml.PCData s]) -> s
11437   | Xml.Element (_, _, []) -> \"\"
11438   | Xml.Element (x, _, _) ->
11439       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11440                 x ^ \" instead\")
11441   | Xml.PCData str ->
11442       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11443
11444 let optional_child name xml =
11445   let children = Xml.children xml in
11446   try
11447     Some (List.find (function
11448                      | Xml.Element (n, _, _) when n = name -> true
11449                      | _ -> false) children)
11450   with
11451     Not_found -> None
11452
11453 let child name xml =
11454   match optional_child name xml with
11455   | Some c -> c
11456   | None ->
11457       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11458
11459 let attribute name xml =
11460   try Xml.attrib xml name
11461   with Xml.No_attribute _ ->
11462     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11463
11464 ";
11465
11466   generate_parsers grammar;
11467   pr "\n";
11468
11469   pr "\
11470 (* Run external virt-inspector, then use parser to parse the XML. *)
11471 let inspect ?connect ?xml names =
11472   let xml =
11473     match xml with
11474     | None ->
11475         if names = [] then invalid_arg \"inspect: no names given\";
11476         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11477           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11478           names in
11479         let cmd = List.map Filename.quote cmd in
11480         let cmd = String.concat \" \" cmd in
11481         let chan = open_process_in cmd in
11482         let xml = Xml.parse_in chan in
11483         (match close_process_in chan with
11484          | WEXITED 0 -> ()
11485          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11486          | WSIGNALED i | WSTOPPED i ->
11487              failwith (\"external virt-inspector command died or stopped on sig \" ^
11488                        string_of_int i)
11489         );
11490         xml
11491     | Some doc ->
11492         Xml.parse_string doc in
11493   parse_operatingsystems xml
11494 "
11495
11496 (* This is used to generate the src/MAX_PROC_NR file which
11497  * contains the maximum procedure number, a surrogate for the
11498  * ABI version number.  See src/Makefile.am for the details.
11499  *)
11500 and generate_max_proc_nr () =
11501   let proc_nrs = List.map (
11502     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11503   ) daemon_functions in
11504
11505   let max_proc_nr = List.fold_left max 0 proc_nrs in
11506
11507   pr "%d\n" max_proc_nr
11508
11509 let output_to filename k =
11510   let filename_new = filename ^ ".new" in
11511   chan := open_out filename_new;
11512   k ();
11513   close_out !chan;
11514   chan := Pervasives.stdout;
11515
11516   (* Is the new file different from the current file? *)
11517   if Sys.file_exists filename && files_equal filename filename_new then
11518     unlink filename_new                 (* same, so skip it *)
11519   else (
11520     (* different, overwrite old one *)
11521     (try chmod filename 0o644 with Unix_error _ -> ());
11522     rename filename_new filename;
11523     chmod filename 0o444;
11524     printf "written %s\n%!" filename;
11525   )
11526
11527 let perror msg = function
11528   | Unix_error (err, _, _) ->
11529       eprintf "%s: %s\n" msg (error_message err)
11530   | exn ->
11531       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11532
11533 (* Main program. *)
11534 let () =
11535   let lock_fd =
11536     try openfile "HACKING" [O_RDWR] 0
11537     with
11538     | Unix_error (ENOENT, _, _) ->
11539         eprintf "\
11540 You are probably running this from the wrong directory.
11541 Run it from the top source directory using the command
11542   src/generator.ml
11543 ";
11544         exit 1
11545     | exn ->
11546         perror "open: HACKING" exn;
11547         exit 1 in
11548
11549   (* Acquire a lock so parallel builds won't try to run the generator
11550    * twice at the same time.  Subsequent builds will wait for the first
11551    * one to finish.  Note the lock is released implicitly when the
11552    * program exits.
11553    *)
11554   (try lockf lock_fd F_LOCK 1
11555    with exn ->
11556      perror "lock: HACKING" exn;
11557      exit 1);
11558
11559   check_functions ();
11560
11561   output_to "src/guestfs_protocol.x" generate_xdr;
11562   output_to "src/guestfs-structs.h" generate_structs_h;
11563   output_to "src/guestfs-actions.h" generate_actions_h;
11564   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11565   output_to "src/guestfs-actions.c" generate_client_actions;
11566   output_to "src/guestfs-bindtests.c" generate_bindtests;
11567   output_to "src/guestfs-structs.pod" generate_structs_pod;
11568   output_to "src/guestfs-actions.pod" generate_actions_pod;
11569   output_to "src/guestfs-availability.pod" generate_availability_pod;
11570   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11571   output_to "src/libguestfs.syms" generate_linker_script;
11572   output_to "daemon/actions.h" generate_daemon_actions_h;
11573   output_to "daemon/stubs.c" generate_daemon_actions;
11574   output_to "daemon/names.c" generate_daemon_names;
11575   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11576   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11577   output_to "capitests/tests.c" generate_tests;
11578   output_to "fish/cmds.c" generate_fish_cmds;
11579   output_to "fish/completion.c" generate_fish_completion;
11580   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11581   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11582   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11583   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11584   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11585   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11586   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11587   output_to "perl/Guestfs.xs" generate_perl_xs;
11588   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11589   output_to "perl/bindtests.pl" generate_perl_bindtests;
11590   output_to "python/guestfs-py.c" generate_python_c;
11591   output_to "python/guestfs.py" generate_python_py;
11592   output_to "python/bindtests.py" generate_python_bindtests;
11593   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11594   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11595   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11596
11597   List.iter (
11598     fun (typ, jtyp) ->
11599       let cols = cols_of_struct typ in
11600       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11601       output_to filename (generate_java_struct jtyp cols);
11602   ) java_structs;
11603
11604   output_to "java/Makefile.inc" generate_java_makefile_inc;
11605   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11606   output_to "java/Bindtests.java" generate_java_bindtests;
11607   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11608   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11609   output_to "csharp/Libguestfs.cs" generate_csharp;
11610
11611   (* Always generate this file last, and unconditionally.  It's used
11612    * by the Makefile to know when we must re-run the generator.
11613    *)
11614   let chan = open_out "src/stamp-generator" in
11615   fprintf chan "1\n";
11616   close_out chan;
11617
11618   printf "generated %d lines of code\n" !lines