New APIs: findfs-label and findfs-uuid
[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     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <const char *, size_t> pair.
169      * Most other languages have a string type which can contain
170      * ASCII NUL.  We use whatever type is appropriate for each
171      * language.
172      * Buffers are limited by the total message size.  To transfer
173      * large blocks of data, use FileIn/FileOut parameters instead.
174      * To return an arbitrary buffer, use RBufferOut.
175      *)
176   | BufferIn of string
177     (* Key material / passphrase.  Eventually we should treat this
178      * as sensitive and mlock it into physical RAM.  However this
179      * is highly complex because of all the places that XDR-encoded
180      * strings can end up.  So currently the only difference from
181      * 'String' is the way that guestfish requests these parameters
182      * from the user.
183      *)
184   | Key of string
185
186 type flags =
187   | ProtocolLimitWarning  (* display warning about protocol size limits *)
188   | DangerWillRobinson    (* flags particularly dangerous commands *)
189   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
190   | FishOutput of fish_output_t (* how to display output in guestfish *)
191   | NotInFish             (* do not export via guestfish *)
192   | NotInDocs             (* do not add this function to documentation *)
193   | DeprecatedBy of string (* function is deprecated, use .. instead *)
194   | Optional of string    (* function is part of an optional group *)
195
196 and fish_output_t =
197   | FishOutputOctal       (* for int return, print in octal *)
198   | FishOutputHexadecimal (* for int return, print in hex *)
199
200 (* You can supply zero or as many tests as you want per API call.
201  *
202  * Note that the test environment has 3 block devices, of size 500MB,
203  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
204  * a fourth ISO block device with some known files on it (/dev/sdd).
205  *
206  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
207  * Number of cylinders was 63 for IDE emulated disks with precisely
208  * the same size.  How exactly this is calculated is a mystery.
209  *
210  * The ISO block device (/dev/sdd) comes from images/test.iso.
211  *
212  * To be able to run the tests in a reasonable amount of time,
213  * the virtual machine and block devices are reused between tests.
214  * So don't try testing kill_subprocess :-x
215  *
216  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
217  *
218  * Don't assume anything about the previous contents of the block
219  * devices.  Use 'Init*' to create some initial scenarios.
220  *
221  * You can add a prerequisite clause to any individual test.  This
222  * is a run-time check, which, if it fails, causes the test to be
223  * skipped.  Useful if testing a command which might not work on
224  * all variations of libguestfs builds.  A test that has prerequisite
225  * of 'Always' is run unconditionally.
226  *
227  * In addition, packagers can skip individual tests by setting the
228  * environment variables:     eg:
229  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
230  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
231  *)
232 type tests = (test_init * test_prereq * test) list
233 and test =
234     (* Run the command sequence and just expect nothing to fail. *)
235   | TestRun of seq
236
237     (* Run the command sequence and expect the output of the final
238      * command to be the string.
239      *)
240   | TestOutput of seq * string
241
242     (* Run the command sequence and expect the output of the final
243      * command to be the list of strings.
244      *)
245   | TestOutputList of seq * string list
246
247     (* Run the command sequence and expect the output of the final
248      * command to be the list of block devices (could be either
249      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
250      * character of each string).
251      *)
252   | TestOutputListOfDevices of seq * string list
253
254     (* Run the command sequence and expect the output of the final
255      * command to be the integer.
256      *)
257   | TestOutputInt of seq * int
258
259     (* Run the command sequence and expect the output of the final
260      * command to be <op> <int>, eg. ">=", "1".
261      *)
262   | TestOutputIntOp of seq * string * int
263
264     (* Run the command sequence and expect the output of the final
265      * command to be a true value (!= 0 or != NULL).
266      *)
267   | TestOutputTrue of seq
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a false value (== 0 or == NULL, but not an error).
271      *)
272   | TestOutputFalse of seq
273
274     (* Run the command sequence and expect the output of the final
275      * command to be a list of the given length (but don't care about
276      * content).
277      *)
278   | TestOutputLength of seq * int
279
280     (* Run the command sequence and expect the output of the final
281      * command to be a buffer (RBufferOut), ie. string + size.
282      *)
283   | TestOutputBuffer of seq * string
284
285     (* Run the command sequence and expect the output of the final
286      * command to be a structure.
287      *)
288   | TestOutputStruct of seq * test_field_compare list
289
290     (* Run the command sequence and expect the final command (only)
291      * to fail.
292      *)
293   | TestLastFail of seq
294
295 and test_field_compare =
296   | CompareWithInt of string * int
297   | CompareWithIntOp of string * string * int
298   | CompareWithString of string * string
299   | CompareFieldsIntEq of string * string
300   | CompareFieldsStrEq of string * string
301
302 (* Test prerequisites. *)
303 and test_prereq =
304     (* Test always runs. *)
305   | Always
306
307     (* Test is currently disabled - eg. it fails, or it tests some
308      * unimplemented feature.
309      *)
310   | Disabled
311
312     (* 'string' is some C code (a function body) that should return
313      * true or false.  The test will run if the code returns true.
314      *)
315   | If of string
316
317     (* As for 'If' but the test runs _unless_ the code returns true. *)
318   | Unless of string
319
320     (* Run the test only if 'string' is available in the daemon. *)
321   | IfAvailable of string
322
323 (* Some initial scenarios for testing. *)
324 and test_init =
325     (* Do nothing, block devices could contain random stuff including
326      * LVM PVs, and some filesystems might be mounted.  This is usually
327      * a bad idea.
328      *)
329   | InitNone
330
331     (* Block devices are empty and no filesystems are mounted. *)
332   | InitEmpty
333
334     (* /dev/sda contains a single partition /dev/sda1, with random
335      * content.  /dev/sdb and /dev/sdc may have random content.
336      * No LVM.
337      *)
338   | InitPartition
339
340     (* /dev/sda contains a single partition /dev/sda1, which is formatted
341      * as ext2, empty [except for lost+found] and mounted on /.
342      * /dev/sdb and /dev/sdc may have random content.
343      * No LVM.
344      *)
345   | InitBasicFS
346
347     (* /dev/sda:
348      *   /dev/sda1 (is a PV):
349      *     /dev/VG/LV (size 8MB):
350      *       formatted as ext2, empty [except for lost+found], mounted on /
351      * /dev/sdb and /dev/sdc may have random content.
352      *)
353   | InitBasicFSonLVM
354
355     (* /dev/sdd (the ISO, see images/ directory in source)
356      * is mounted on /
357      *)
358   | InitISOFS
359
360 (* Sequence of commands for testing. *)
361 and seq = cmd list
362 and cmd = string list
363
364 (* Note about long descriptions: When referring to another
365  * action, use the format C<guestfs_other> (ie. the full name of
366  * the C function).  This will be replaced as appropriate in other
367  * language bindings.
368  *
369  * Apart from that, long descriptions are just perldoc paragraphs.
370  *)
371
372 (* Generate a random UUID (used in tests). *)
373 let uuidgen () =
374   let chan = open_process_in "uuidgen" in
375   let uuid = input_line chan in
376   (match close_process_in chan with
377    | WEXITED 0 -> ()
378    | WEXITED _ ->
379        failwith "uuidgen: process exited with non-zero status"
380    | WSIGNALED _ | WSTOPPED _ ->
381        failwith "uuidgen: process signalled or stopped by signal"
382   );
383   uuid
384
385 (* These test functions are used in the language binding tests. *)
386
387 let test_all_args = [
388   String "str";
389   OptString "optstr";
390   StringList "strlist";
391   Bool "b";
392   Int "integer";
393   Int64 "integer64";
394   FileIn "filein";
395   FileOut "fileout";
396   BufferIn "bufferin";
397 ]
398
399 let test_all_rets = [
400   (* except for RErr, which is tested thoroughly elsewhere *)
401   "test0rint",         RInt "valout";
402   "test0rint64",       RInt64 "valout";
403   "test0rbool",        RBool "valout";
404   "test0rconststring", RConstString "valout";
405   "test0rconstoptstring", RConstOptString "valout";
406   "test0rstring",      RString "valout";
407   "test0rstringlist",  RStringList "valout";
408   "test0rstruct",      RStruct ("valout", "lvm_pv");
409   "test0rstructlist",  RStructList ("valout", "lvm_pv");
410   "test0rhashtable",   RHashtable "valout";
411 ]
412
413 let test_functions = [
414   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
415    [],
416    "internal test function - do not use",
417    "\
418 This is an internal test function which is used to test whether
419 the automatically generated bindings can handle every possible
420 parameter type correctly.
421
422 It echos the contents of each parameter to stdout.
423
424 You probably don't want to call this function.");
425 ] @ List.flatten (
426   List.map (
427     fun (name, ret) ->
428       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
429         [],
430         "internal test function - do not use",
431         "\
432 This is an internal test function which is used to test whether
433 the automatically generated bindings can handle every possible
434 return type correctly.
435
436 It converts string C<val> to the return type.
437
438 You probably don't want to call this function.");
439        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
440         [],
441         "internal test function - do not use",
442         "\
443 This is an internal test function which is used to test whether
444 the automatically generated bindings can handle every possible
445 return type correctly.
446
447 This function always returns an error.
448
449 You probably don't want to call this function.")]
450   ) test_all_rets
451 )
452
453 (* non_daemon_functions are any functions which don't get processed
454  * in the daemon, eg. functions for setting and getting local
455  * configuration values.
456  *)
457
458 let non_daemon_functions = test_functions @ [
459   ("launch", (RErr, []), -1, [FishAlias "run"],
460    [],
461    "launch the qemu subprocess",
462    "\
463 Internally libguestfs is implemented by running a virtual machine
464 using L<qemu(1)>.
465
466 You should call this after configuring the handle
467 (eg. adding drives) but before performing any actions.");
468
469   ("wait_ready", (RErr, []), -1, [NotInFish],
470    [],
471    "wait until the qemu subprocess launches (no op)",
472    "\
473 This function is a no op.
474
475 In versions of the API E<lt> 1.0.71 you had to call this function
476 just after calling C<guestfs_launch> to wait for the launch
477 to complete.  However this is no longer necessary because
478 C<guestfs_launch> now does the waiting.
479
480 If you see any calls to this function in code then you can just
481 remove them, unless you want to retain compatibility with older
482 versions of the API.");
483
484   ("kill_subprocess", (RErr, []), -1, [],
485    [],
486    "kill the qemu subprocess",
487    "\
488 This kills the qemu subprocess.  You should never need to call this.");
489
490   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
491    [],
492    "add an image to examine or modify",
493    "\
494 This function adds a virtual machine disk image C<filename> to the
495 guest.  The first time you call this function, the disk appears as IDE
496 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
497 so on.
498
499 You don't necessarily need to be root when using libguestfs.  However
500 you obviously do need sufficient permissions to access the filename
501 for whatever operations you want to perform (ie. read access if you
502 just want to read the image or write access if you want to modify the
503 image).
504
505 This is equivalent to the qemu parameter
506 C<-drive file=filename,cache=off,if=...>.
507
508 C<cache=off> is omitted in cases where it is not supported by
509 the underlying filesystem.
510
511 C<if=...> is set at compile time by the configuration option
512 C<./configure --with-drive-if=...>.  In the rare case where you
513 might need to change this at run time, use C<guestfs_add_drive_with_if>
514 or C<guestfs_add_drive_ro_with_if>.
515
516 Note that this call checks for the existence of C<filename>.  This
517 stops you from specifying other types of drive which are supported
518 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
519 the general C<guestfs_config> call instead.");
520
521   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
522    [],
523    "add a CD-ROM disk image to examine",
524    "\
525 This function adds a virtual CD-ROM disk image to the guest.
526
527 This is equivalent to the qemu parameter C<-cdrom filename>.
528
529 Notes:
530
531 =over 4
532
533 =item *
534
535 This call checks for the existence of C<filename>.  This
536 stops you from specifying other types of drive which are supported
537 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
538 the general C<guestfs_config> call instead.
539
540 =item *
541
542 If you just want to add an ISO file (often you use this as an
543 efficient way to transfer large files into the guest), then you
544 should probably use C<guestfs_add_drive_ro> instead.
545
546 =back");
547
548   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
549    [],
550    "add a drive in snapshot mode (read-only)",
551    "\
552 This adds a drive in snapshot mode, making it effectively
553 read-only.
554
555 Note that writes to the device are allowed, and will be seen for
556 the duration of the guestfs handle, but they are written
557 to a temporary file which is discarded as soon as the guestfs
558 handle is closed.  We don't currently have any method to enable
559 changes to be committed, although qemu can support this.
560
561 This is equivalent to the qemu parameter
562 C<-drive file=filename,snapshot=on,if=...>.
563
564 C<if=...> is set at compile time by the configuration option
565 C<./configure --with-drive-if=...>.  In the rare case where you
566 might need to change this at run time, use C<guestfs_add_drive_with_if>
567 or C<guestfs_add_drive_ro_with_if>.
568
569 Note that this call checks for the existence of C<filename>.  This
570 stops you from specifying other types of drive which are supported
571 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
572 the general C<guestfs_config> call instead.");
573
574   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
575    [],
576    "add qemu parameters",
577    "\
578 This can be used to add arbitrary qemu command line parameters
579 of the form C<-param value>.  Actually it's not quite arbitrary - we
580 prevent you from setting some parameters which would interfere with
581 parameters that we use.
582
583 The first character of C<param> string must be a C<-> (dash).
584
585 C<value> can be NULL.");
586
587   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
588    [],
589    "set the qemu binary",
590    "\
591 Set the qemu binary that we will use.
592
593 The default is chosen when the library was compiled by the
594 configure script.
595
596 You can also override this by setting the C<LIBGUESTFS_QEMU>
597 environment variable.
598
599 Setting C<qemu> to C<NULL> restores the default qemu binary.
600
601 Note that you should call this function as early as possible
602 after creating the handle.  This is because some pre-launch
603 operations depend on testing qemu features (by running C<qemu -help>).
604 If the qemu binary changes, we don't retest features, and
605 so you might see inconsistent results.  Using the environment
606 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
607 the qemu binary at the same time as the handle is created.");
608
609   ("get_qemu", (RConstString "qemu", []), -1, [],
610    [InitNone, Always, TestRun (
611       [["get_qemu"]])],
612    "get the qemu binary",
613    "\
614 Return the current qemu binary.
615
616 This is always non-NULL.  If it wasn't set already, then this will
617 return the default qemu binary name.");
618
619   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
620    [],
621    "set the search path",
622    "\
623 Set the path that libguestfs searches for kernel and initrd.img.
624
625 The default is C<$libdir/guestfs> unless overridden by setting
626 C<LIBGUESTFS_PATH> environment variable.
627
628 Setting C<path> to C<NULL> restores the default path.");
629
630   ("get_path", (RConstString "path", []), -1, [],
631    [InitNone, Always, TestRun (
632       [["get_path"]])],
633    "get the search path",
634    "\
635 Return the current search path.
636
637 This is always non-NULL.  If it wasn't set already, then this will
638 return the default path.");
639
640   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
641    [],
642    "add options to kernel command line",
643    "\
644 This function is used to add additional options to the
645 guest kernel command line.
646
647 The default is C<NULL> unless overridden by setting
648 C<LIBGUESTFS_APPEND> environment variable.
649
650 Setting C<append> to C<NULL> means I<no> additional options
651 are passed (libguestfs always adds a few of its own).");
652
653   ("get_append", (RConstOptString "append", []), -1, [],
654    (* This cannot be tested with the current framework.  The
655     * function can return NULL in normal operations, which the
656     * test framework interprets as an error.
657     *)
658    [],
659    "get the additional kernel options",
660    "\
661 Return the additional kernel options which are added to the
662 guest kernel command line.
663
664 If C<NULL> then no options are added.");
665
666   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
667    [],
668    "set autosync mode",
669    "\
670 If C<autosync> is true, this enables autosync.  Libguestfs will make a
671 best effort attempt to run C<guestfs_umount_all> followed by
672 C<guestfs_sync> when the handle is closed
673 (also if the program exits without closing handles).
674
675 This is disabled by default (except in guestfish where it is
676 enabled by default).");
677
678   ("get_autosync", (RBool "autosync", []), -1, [],
679    [InitNone, Always, TestRun (
680       [["get_autosync"]])],
681    "get autosync mode",
682    "\
683 Get the autosync flag.");
684
685   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
686    [],
687    "set verbose mode",
688    "\
689 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
690
691 Verbose messages are disabled unless the environment variable
692 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
693
694   ("get_verbose", (RBool "verbose", []), -1, [],
695    [],
696    "get verbose mode",
697    "\
698 This returns the verbose messages flag.");
699
700   ("is_ready", (RBool "ready", []), -1, [],
701    [InitNone, Always, TestOutputTrue (
702       [["is_ready"]])],
703    "is ready to accept commands",
704    "\
705 This returns true iff this handle is ready to accept commands
706 (in the C<READY> state).
707
708 For more information on states, see L<guestfs(3)>.");
709
710   ("is_config", (RBool "config", []), -1, [],
711    [InitNone, Always, TestOutputFalse (
712       [["is_config"]])],
713    "is in configuration state",
714    "\
715 This returns true iff this handle is being configured
716 (in the C<CONFIG> state).
717
718 For more information on states, see L<guestfs(3)>.");
719
720   ("is_launching", (RBool "launching", []), -1, [],
721    [InitNone, Always, TestOutputFalse (
722       [["is_launching"]])],
723    "is launching subprocess",
724    "\
725 This returns true iff this handle is launching the subprocess
726 (in the C<LAUNCHING> state).
727
728 For more information on states, see L<guestfs(3)>.");
729
730   ("is_busy", (RBool "busy", []), -1, [],
731    [InitNone, Always, TestOutputFalse (
732       [["is_busy"]])],
733    "is busy processing a command",
734    "\
735 This returns true iff this handle is busy processing a command
736 (in the C<BUSY> state).
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("get_state", (RInt "state", []), -1, [],
741    [],
742    "get the current state",
743    "\
744 This returns the current state as an opaque integer.  This is
745 only useful for printing debug and internal error messages.
746
747 For more information on states, see L<guestfs(3)>.");
748
749   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
750    [InitNone, Always, TestOutputInt (
751       [["set_memsize"; "500"];
752        ["get_memsize"]], 500)],
753    "set memory allocated to the qemu subprocess",
754    "\
755 This sets the memory size in megabytes allocated to the
756 qemu subprocess.  This only has any effect if called before
757 C<guestfs_launch>.
758
759 You can also change this by setting the environment
760 variable C<LIBGUESTFS_MEMSIZE> before the handle is
761 created.
762
763 For more information on the architecture of libguestfs,
764 see L<guestfs(3)>.");
765
766   ("get_memsize", (RInt "memsize", []), -1, [],
767    [InitNone, Always, TestOutputIntOp (
768       [["get_memsize"]], ">=", 256)],
769    "get memory allocated to the qemu subprocess",
770    "\
771 This gets the memory size in megabytes allocated to the
772 qemu subprocess.
773
774 If C<guestfs_set_memsize> was not called
775 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
776 then this returns the compiled-in default value for memsize.
777
778 For more information on the architecture of libguestfs,
779 see L<guestfs(3)>.");
780
781   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
782    [InitNone, Always, TestOutputIntOp (
783       [["get_pid"]], ">=", 1)],
784    "get PID of qemu subprocess",
785    "\
786 Return the process ID of the qemu subprocess.  If there is no
787 qemu subprocess, then this will return an error.
788
789 This is an internal call used for debugging and testing.");
790
791   ("version", (RStruct ("version", "version"), []), -1, [],
792    [InitNone, Always, TestOutputStruct (
793       [["version"]], [CompareWithInt ("major", 1)])],
794    "get the library version number",
795    "\
796 Return the libguestfs version number that the program is linked
797 against.
798
799 Note that because of dynamic linking this is not necessarily
800 the version of libguestfs that you compiled against.  You can
801 compile the program, and then at runtime dynamically link
802 against a completely different C<libguestfs.so> library.
803
804 This call was added in version C<1.0.58>.  In previous
805 versions of libguestfs there was no way to get the version
806 number.  From C code you can use dynamic linker functions
807 to find out if this symbol exists (if it doesn't, then
808 it's an earlier version).
809
810 The call returns a structure with four elements.  The first
811 three (C<major>, C<minor> and C<release>) are numbers and
812 correspond to the usual version triplet.  The fourth element
813 (C<extra>) is a string and is normally empty, but may be
814 used for distro-specific information.
815
816 To construct the original version string:
817 C<$major.$minor.$release$extra>
818
819 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
820
821 I<Note:> Don't use this call to test for availability
822 of features.  In enterprise distributions we backport
823 features from later versions into earlier versions,
824 making this an unreliable way to test for features.
825 Use C<guestfs_available> instead.");
826
827   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
828    [InitNone, Always, TestOutputTrue (
829       [["set_selinux"; "true"];
830        ["get_selinux"]])],
831    "set SELinux enabled or disabled at appliance boot",
832    "\
833 This sets the selinux flag that is passed to the appliance
834 at boot time.  The default is C<selinux=0> (disabled).
835
836 Note that if SELinux is enabled, it is always in
837 Permissive mode (C<enforcing=0>).
838
839 For more information on the architecture of libguestfs,
840 see L<guestfs(3)>.");
841
842   ("get_selinux", (RBool "selinux", []), -1, [],
843    [],
844    "get SELinux enabled flag",
845    "\
846 This returns the current setting of the selinux flag which
847 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
848
849 For more information on the architecture of libguestfs,
850 see L<guestfs(3)>.");
851
852   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
853    [InitNone, Always, TestOutputFalse (
854       [["set_trace"; "false"];
855        ["get_trace"]])],
856    "enable or disable command traces",
857    "\
858 If the command trace flag is set to 1, then commands are
859 printed on stderr before they are executed in a format
860 which is very similar to the one used by guestfish.  In
861 other words, you can run a program with this enabled, and
862 you will get out a script which you can feed to guestfish
863 to perform the same set of actions.
864
865 If you want to trace C API calls into libguestfs (and
866 other libraries) then possibly a better way is to use
867 the external ltrace(1) command.
868
869 Command traces are disabled unless the environment variable
870 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
871
872   ("get_trace", (RBool "trace", []), -1, [],
873    [],
874    "get command trace enabled flag",
875    "\
876 Return the command trace flag.");
877
878   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
879    [InitNone, Always, TestOutputFalse (
880       [["set_direct"; "false"];
881        ["get_direct"]])],
882    "enable or disable direct appliance mode",
883    "\
884 If the direct appliance mode flag is enabled, then stdin and
885 stdout are passed directly through to the appliance once it
886 is launched.
887
888 One consequence of this is that log messages aren't caught
889 by the library and handled by C<guestfs_set_log_message_callback>,
890 but go straight to stdout.
891
892 You probably don't want to use this unless you know what you
893 are doing.
894
895 The default is disabled.");
896
897   ("get_direct", (RBool "direct", []), -1, [],
898    [],
899    "get direct appliance mode flag",
900    "\
901 Return the direct appliance mode flag.");
902
903   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
904    [InitNone, Always, TestOutputTrue (
905       [["set_recovery_proc"; "true"];
906        ["get_recovery_proc"]])],
907    "enable or disable the recovery process",
908    "\
909 If this is called with the parameter C<false> then
910 C<guestfs_launch> does not create a recovery process.  The
911 purpose of the recovery process is to stop runaway qemu
912 processes in the case where the main program aborts abruptly.
913
914 This only has any effect if called before C<guestfs_launch>,
915 and the default is true.
916
917 About the only time when you would want to disable this is
918 if the main process will fork itself into the background
919 (\"daemonize\" itself).  In this case the recovery process
920 thinks that the main program has disappeared and so kills
921 qemu, which is not very helpful.");
922
923   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
924    [],
925    "get recovery process enabled flag",
926    "\
927 Return the recovery process enabled flag.");
928
929   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
930    [],
931    "add a drive specifying the QEMU block emulation to use",
932    "\
933 This is the same as C<guestfs_add_drive> but it allows you
934 to specify the QEMU interface emulation to use at run time.");
935
936   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
937    [],
938    "add a drive read-only specifying the QEMU block emulation to use",
939    "\
940 This is the same as C<guestfs_add_drive_ro> but it allows you
941 to specify the QEMU interface emulation to use at run time.");
942
943   ("file_architecture", (RString "arch", [Pathname "filename"]), -1, [],
944    [InitISOFS, Always, TestOutput (
945       [["file_architecture"; "/bin-i586-dynamic"]], "i386");
946     InitISOFS, Always, TestOutput (
947       [["file_architecture"; "/bin-sparc-dynamic"]], "sparc");
948     InitISOFS, Always, TestOutput (
949       [["file_architecture"; "/bin-win32.exe"]], "i386");
950     InitISOFS, Always, TestOutput (
951       [["file_architecture"; "/bin-win64.exe"]], "x86_64");
952     InitISOFS, Always, TestOutput (
953       [["file_architecture"; "/bin-x86_64-dynamic"]], "x86_64");
954     InitISOFS, Always, TestOutput (
955       [["file_architecture"; "/lib-i586.so"]], "i386");
956     InitISOFS, Always, TestOutput (
957       [["file_architecture"; "/lib-sparc.so"]], "sparc");
958     InitISOFS, Always, TestOutput (
959       [["file_architecture"; "/lib-win32.dll"]], "i386");
960     InitISOFS, Always, TestOutput (
961       [["file_architecture"; "/lib-win64.dll"]], "x86_64");
962     InitISOFS, Always, TestOutput (
963       [["file_architecture"; "/lib-x86_64.so"]], "x86_64");
964     InitISOFS, Always, TestOutput (
965       [["file_architecture"; "/initrd-x86_64.img"]], "x86_64");
966     InitISOFS, Always, TestOutput (
967       [["file_architecture"; "/initrd-x86_64.img.gz"]], "x86_64");],
968    "detect the architecture of a binary file",
969    "\
970 This detects the architecture of the binary C<filename>,
971 and returns it if known.
972
973 Currently defined architectures are:
974
975 =over 4
976
977 =item \"i386\"
978
979 This string is returned for all 32 bit i386, i486, i586, i686 binaries
980 irrespective of the precise processor requirements of the binary.
981
982 =item \"x86_64\"
983
984 64 bit x86-64.
985
986 =item \"sparc\"
987
988 32 bit SPARC.
989
990 =item \"sparc64\"
991
992 64 bit SPARC V9 and above.
993
994 =item \"ia64\"
995
996 Intel Itanium.
997
998 =item \"ppc\"
999
1000 32 bit Power PC.
1001
1002 =item \"ppc64\"
1003
1004 64 bit Power PC.
1005
1006 =back
1007
1008 Libguestfs may return other architecture strings in future.
1009
1010 The function works on at least the following types of files:
1011
1012 =over 4
1013
1014 =item *
1015
1016 many types of Un*x and Linux binary
1017
1018 =item *
1019
1020 many types of Un*x and Linux shared library
1021
1022 =item *
1023
1024 Windows Win32 and Win64 binaries
1025
1026 =item *
1027
1028 Windows Win32 and Win64 DLLs
1029
1030 Win32 binaries and DLLs return C<i386>.
1031
1032 Win64 binaries and DLLs return C<x86_64>.
1033
1034 =item *
1035
1036 Linux kernel modules
1037
1038 =item *
1039
1040 Linux new-style initrd images
1041
1042 =item *
1043
1044 some non-x86 Linux vmlinuz kernels
1045
1046 =back
1047
1048 What it can't do currently:
1049
1050 =over 4
1051
1052 =item *
1053
1054 static libraries (libfoo.a)
1055
1056 =item *
1057
1058 Linux old-style initrd as compressed ext2 filesystem (RHEL 3)
1059
1060 =item *
1061
1062 x86 Linux vmlinuz kernels
1063
1064 x86 vmlinuz images (bzImage format) consist of a mix of 16-, 32- and
1065 compressed code, and are horribly hard to unpack.  If you want to find
1066 the architecture of a kernel, use the architecture of the associated
1067 initrd or kernel module(s) instead.
1068
1069 =back");
1070
1071 ]
1072
1073 (* daemon_functions are any functions which cause some action
1074  * to take place in the daemon.
1075  *)
1076
1077 let daemon_functions = [
1078   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
1079    [InitEmpty, Always, TestOutput (
1080       [["part_disk"; "/dev/sda"; "mbr"];
1081        ["mkfs"; "ext2"; "/dev/sda1"];
1082        ["mount"; "/dev/sda1"; "/"];
1083        ["write"; "/new"; "new file contents"];
1084        ["cat"; "/new"]], "new file contents")],
1085    "mount a guest disk at a position in the filesystem",
1086    "\
1087 Mount a guest disk at a position in the filesystem.  Block devices
1088 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
1089 the guest.  If those block devices contain partitions, they will have
1090 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
1091 names can be used.
1092
1093 The rules are the same as for L<mount(2)>:  A filesystem must
1094 first be mounted on C</> before others can be mounted.  Other
1095 filesystems can only be mounted on directories which already
1096 exist.
1097
1098 The mounted filesystem is writable, if we have sufficient permissions
1099 on the underlying device.
1100
1101 B<Important note:>
1102 When you use this call, the filesystem options C<sync> and C<noatime>
1103 are set implicitly.  This was originally done because we thought it
1104 would improve reliability, but it turns out that I<-o sync> has a
1105 very large negative performance impact and negligible effect on
1106 reliability.  Therefore we recommend that you avoid using
1107 C<guestfs_mount> in any code that needs performance, and instead
1108 use C<guestfs_mount_options> (use an empty string for the first
1109 parameter if you don't want any options).");
1110
1111   ("sync", (RErr, []), 2, [],
1112    [ InitEmpty, Always, TestRun [["sync"]]],
1113    "sync disks, writes are flushed through to the disk image",
1114    "\
1115 This syncs the disk, so that any writes are flushed through to the
1116 underlying disk image.
1117
1118 You should always call this if you have modified a disk image, before
1119 closing the handle.");
1120
1121   ("touch", (RErr, [Pathname "path"]), 3, [],
1122    [InitBasicFS, Always, TestOutputTrue (
1123       [["touch"; "/new"];
1124        ["exists"; "/new"]])],
1125    "update file timestamps or create a new file",
1126    "\
1127 Touch acts like the L<touch(1)> command.  It can be used to
1128 update the timestamps on a file, or, if the file does not exist,
1129 to create a new zero-length file.
1130
1131 This command only works on regular files, and will fail on other
1132 file types such as directories, symbolic links, block special etc.");
1133
1134   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
1135    [InitISOFS, Always, TestOutput (
1136       [["cat"; "/known-2"]], "abcdef\n")],
1137    "list the contents of a file",
1138    "\
1139 Return the contents of the file named C<path>.
1140
1141 Note that this function cannot correctly handle binary files
1142 (specifically, files containing C<\\0> character which is treated
1143 as end of string).  For those you need to use the C<guestfs_read_file>
1144 or C<guestfs_download> functions which have a more complex interface.");
1145
1146   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1147    [], (* XXX Tricky to test because it depends on the exact format
1148         * of the 'ls -l' command, which changes between F10 and F11.
1149         *)
1150    "list the files in a directory (long format)",
1151    "\
1152 List the files in C<directory> (relative to the root directory,
1153 there is no cwd) in the format of 'ls -la'.
1154
1155 This command is mostly useful for interactive sessions.  It
1156 is I<not> intended that you try to parse the output string.");
1157
1158   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1159    [InitBasicFS, Always, TestOutputList (
1160       [["touch"; "/new"];
1161        ["touch"; "/newer"];
1162        ["touch"; "/newest"];
1163        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1164    "list the files in a directory",
1165    "\
1166 List the files in C<directory> (relative to the root directory,
1167 there is no cwd).  The '.' and '..' entries are not returned, but
1168 hidden files are shown.
1169
1170 This command is mostly useful for interactive sessions.  Programs
1171 should probably use C<guestfs_readdir> instead.");
1172
1173   ("list_devices", (RStringList "devices", []), 7, [],
1174    [InitEmpty, Always, TestOutputListOfDevices (
1175       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1176    "list the block devices",
1177    "\
1178 List all the block devices.
1179
1180 The full block device names are returned, eg. C</dev/sda>");
1181
1182   ("list_partitions", (RStringList "partitions", []), 8, [],
1183    [InitBasicFS, Always, TestOutputListOfDevices (
1184       [["list_partitions"]], ["/dev/sda1"]);
1185     InitEmpty, Always, TestOutputListOfDevices (
1186       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1187        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1188    "list the partitions",
1189    "\
1190 List all the partitions detected on all block devices.
1191
1192 The full partition device names are returned, eg. C</dev/sda1>
1193
1194 This does not return logical volumes.  For that you will need to
1195 call C<guestfs_lvs>.");
1196
1197   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1198    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1199       [["pvs"]], ["/dev/sda1"]);
1200     InitEmpty, Always, TestOutputListOfDevices (
1201       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1202        ["pvcreate"; "/dev/sda1"];
1203        ["pvcreate"; "/dev/sda2"];
1204        ["pvcreate"; "/dev/sda3"];
1205        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1206    "list the LVM physical volumes (PVs)",
1207    "\
1208 List all the physical volumes detected.  This is the equivalent
1209 of the L<pvs(8)> command.
1210
1211 This returns a list of just the device names that contain
1212 PVs (eg. C</dev/sda2>).
1213
1214 See also C<guestfs_pvs_full>.");
1215
1216   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1217    [InitBasicFSonLVM, Always, TestOutputList (
1218       [["vgs"]], ["VG"]);
1219     InitEmpty, Always, TestOutputList (
1220       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1221        ["pvcreate"; "/dev/sda1"];
1222        ["pvcreate"; "/dev/sda2"];
1223        ["pvcreate"; "/dev/sda3"];
1224        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1225        ["vgcreate"; "VG2"; "/dev/sda3"];
1226        ["vgs"]], ["VG1"; "VG2"])],
1227    "list the LVM volume groups (VGs)",
1228    "\
1229 List all the volumes groups detected.  This is the equivalent
1230 of the L<vgs(8)> command.
1231
1232 This returns a list of just the volume group names that were
1233 detected (eg. C<VolGroup00>).
1234
1235 See also C<guestfs_vgs_full>.");
1236
1237   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1238    [InitBasicFSonLVM, Always, TestOutputList (
1239       [["lvs"]], ["/dev/VG/LV"]);
1240     InitEmpty, Always, TestOutputList (
1241       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1242        ["pvcreate"; "/dev/sda1"];
1243        ["pvcreate"; "/dev/sda2"];
1244        ["pvcreate"; "/dev/sda3"];
1245        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1246        ["vgcreate"; "VG2"; "/dev/sda3"];
1247        ["lvcreate"; "LV1"; "VG1"; "50"];
1248        ["lvcreate"; "LV2"; "VG1"; "50"];
1249        ["lvcreate"; "LV3"; "VG2"; "50"];
1250        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1251    "list the LVM logical volumes (LVs)",
1252    "\
1253 List all the logical volumes detected.  This is the equivalent
1254 of the L<lvs(8)> command.
1255
1256 This returns a list of the logical volume device names
1257 (eg. C</dev/VolGroup00/LogVol00>).
1258
1259 See also C<guestfs_lvs_full>.");
1260
1261   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1262    [], (* XXX how to test? *)
1263    "list the LVM physical volumes (PVs)",
1264    "\
1265 List all the physical volumes detected.  This is the equivalent
1266 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1267
1268   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1269    [], (* XXX how to test? *)
1270    "list the LVM volume groups (VGs)",
1271    "\
1272 List all the volumes groups detected.  This is the equivalent
1273 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1274
1275   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1276    [], (* XXX how to test? *)
1277    "list the LVM logical volumes (LVs)",
1278    "\
1279 List all the logical volumes detected.  This is the equivalent
1280 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1281
1282   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1283    [InitISOFS, Always, TestOutputList (
1284       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1285     InitISOFS, Always, TestOutputList (
1286       [["read_lines"; "/empty"]], [])],
1287    "read file as lines",
1288    "\
1289 Return the contents of the file named C<path>.
1290
1291 The file contents are returned as a list of lines.  Trailing
1292 C<LF> and C<CRLF> character sequences are I<not> returned.
1293
1294 Note that this function cannot correctly handle binary files
1295 (specifically, files containing C<\\0> character which is treated
1296 as end of line).  For those you need to use the C<guestfs_read_file>
1297 function which has a more complex interface.");
1298
1299   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1300    [], (* XXX Augeas code needs tests. *)
1301    "create a new Augeas handle",
1302    "\
1303 Create a new Augeas handle for editing configuration files.
1304 If there was any previous Augeas handle associated with this
1305 guestfs session, then it is closed.
1306
1307 You must call this before using any other C<guestfs_aug_*>
1308 commands.
1309
1310 C<root> is the filesystem root.  C<root> must not be NULL,
1311 use C</> instead.
1312
1313 The flags are the same as the flags defined in
1314 E<lt>augeas.hE<gt>, the logical I<or> of the following
1315 integers:
1316
1317 =over 4
1318
1319 =item C<AUG_SAVE_BACKUP> = 1
1320
1321 Keep the original file with a C<.augsave> extension.
1322
1323 =item C<AUG_SAVE_NEWFILE> = 2
1324
1325 Save changes into a file with extension C<.augnew>, and
1326 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1327
1328 =item C<AUG_TYPE_CHECK> = 4
1329
1330 Typecheck lenses (can be expensive).
1331
1332 =item C<AUG_NO_STDINC> = 8
1333
1334 Do not use standard load path for modules.
1335
1336 =item C<AUG_SAVE_NOOP> = 16
1337
1338 Make save a no-op, just record what would have been changed.
1339
1340 =item C<AUG_NO_LOAD> = 32
1341
1342 Do not load the tree in C<guestfs_aug_init>.
1343
1344 =back
1345
1346 To close the handle, you can call C<guestfs_aug_close>.
1347
1348 To find out more about Augeas, see L<http://augeas.net/>.");
1349
1350   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1351    [], (* XXX Augeas code needs tests. *)
1352    "close the current Augeas handle",
1353    "\
1354 Close the current Augeas handle and free up any resources
1355 used by it.  After calling this, you have to call
1356 C<guestfs_aug_init> again before you can use any other
1357 Augeas functions.");
1358
1359   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1360    [], (* XXX Augeas code needs tests. *)
1361    "define an Augeas variable",
1362    "\
1363 Defines an Augeas variable C<name> whose value is the result
1364 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1365 undefined.
1366
1367 On success this returns the number of nodes in C<expr>, or
1368 C<0> if C<expr> evaluates to something which is not a nodeset.");
1369
1370   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1371    [], (* XXX Augeas code needs tests. *)
1372    "define an Augeas node",
1373    "\
1374 Defines a variable C<name> whose value is the result of
1375 evaluating C<expr>.
1376
1377 If C<expr> evaluates to an empty nodeset, a node is created,
1378 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1379 C<name> will be the nodeset containing that single node.
1380
1381 On success this returns a pair containing the
1382 number of nodes in the nodeset, and a boolean flag
1383 if a node was created.");
1384
1385   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1386    [], (* XXX Augeas code needs tests. *)
1387    "look up the value of an Augeas path",
1388    "\
1389 Look up the value associated with C<path>.  If C<path>
1390 matches exactly one node, the C<value> is returned.");
1391
1392   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1393    [], (* XXX Augeas code needs tests. *)
1394    "set Augeas path to value",
1395    "\
1396 Set the value associated with C<path> to C<val>.
1397
1398 In the Augeas API, it is possible to clear a node by setting
1399 the value to NULL.  Due to an oversight in the libguestfs API
1400 you cannot do that with this call.  Instead you must use the
1401 C<guestfs_aug_clear> call.");
1402
1403   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1404    [], (* XXX Augeas code needs tests. *)
1405    "insert a sibling Augeas node",
1406    "\
1407 Create a new sibling C<label> for C<path>, inserting it into
1408 the tree before or after C<path> (depending on the boolean
1409 flag C<before>).
1410
1411 C<path> must match exactly one existing node in the tree, and
1412 C<label> must be a label, ie. not contain C</>, C<*> or end
1413 with a bracketed index C<[N]>.");
1414
1415   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1416    [], (* XXX Augeas code needs tests. *)
1417    "remove an Augeas path",
1418    "\
1419 Remove C<path> and all of its children.
1420
1421 On success this returns the number of entries which were removed.");
1422
1423   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1424    [], (* XXX Augeas code needs tests. *)
1425    "move Augeas node",
1426    "\
1427 Move the node C<src> to C<dest>.  C<src> must match exactly
1428 one node.  C<dest> is overwritten if it exists.");
1429
1430   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1431    [], (* XXX Augeas code needs tests. *)
1432    "return Augeas nodes which match augpath",
1433    "\
1434 Returns a list of paths which match the path expression C<path>.
1435 The returned paths are sufficiently qualified so that they match
1436 exactly one node in the current tree.");
1437
1438   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1439    [], (* XXX Augeas code needs tests. *)
1440    "write all pending Augeas changes to disk",
1441    "\
1442 This writes all pending changes to disk.
1443
1444 The flags which were passed to C<guestfs_aug_init> affect exactly
1445 how files are saved.");
1446
1447   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1448    [], (* XXX Augeas code needs tests. *)
1449    "load files into the tree",
1450    "\
1451 Load files into the tree.
1452
1453 See C<aug_load> in the Augeas documentation for the full gory
1454 details.");
1455
1456   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1457    [], (* XXX Augeas code needs tests. *)
1458    "list Augeas nodes under augpath",
1459    "\
1460 This is just a shortcut for listing C<guestfs_aug_match>
1461 C<path/*> and sorting the resulting nodes into alphabetical order.");
1462
1463   ("rm", (RErr, [Pathname "path"]), 29, [],
1464    [InitBasicFS, Always, TestRun
1465       [["touch"; "/new"];
1466        ["rm"; "/new"]];
1467     InitBasicFS, Always, TestLastFail
1468       [["rm"; "/new"]];
1469     InitBasicFS, Always, TestLastFail
1470       [["mkdir"; "/new"];
1471        ["rm"; "/new"]]],
1472    "remove a file",
1473    "\
1474 Remove the single file C<path>.");
1475
1476   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1477    [InitBasicFS, Always, TestRun
1478       [["mkdir"; "/new"];
1479        ["rmdir"; "/new"]];
1480     InitBasicFS, Always, TestLastFail
1481       [["rmdir"; "/new"]];
1482     InitBasicFS, Always, TestLastFail
1483       [["touch"; "/new"];
1484        ["rmdir"; "/new"]]],
1485    "remove a directory",
1486    "\
1487 Remove the single directory C<path>.");
1488
1489   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1490    [InitBasicFS, Always, TestOutputFalse
1491       [["mkdir"; "/new"];
1492        ["mkdir"; "/new/foo"];
1493        ["touch"; "/new/foo/bar"];
1494        ["rm_rf"; "/new"];
1495        ["exists"; "/new"]]],
1496    "remove a file or directory recursively",
1497    "\
1498 Remove the file or directory C<path>, recursively removing the
1499 contents if its a directory.  This is like the C<rm -rf> shell
1500 command.");
1501
1502   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1503    [InitBasicFS, Always, TestOutputTrue
1504       [["mkdir"; "/new"];
1505        ["is_dir"; "/new"]];
1506     InitBasicFS, Always, TestLastFail
1507       [["mkdir"; "/new/foo/bar"]]],
1508    "create a directory",
1509    "\
1510 Create a directory named C<path>.");
1511
1512   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1513    [InitBasicFS, Always, TestOutputTrue
1514       [["mkdir_p"; "/new/foo/bar"];
1515        ["is_dir"; "/new/foo/bar"]];
1516     InitBasicFS, Always, TestOutputTrue
1517       [["mkdir_p"; "/new/foo/bar"];
1518        ["is_dir"; "/new/foo"]];
1519     InitBasicFS, Always, TestOutputTrue
1520       [["mkdir_p"; "/new/foo/bar"];
1521        ["is_dir"; "/new"]];
1522     (* Regression tests for RHBZ#503133: *)
1523     InitBasicFS, Always, TestRun
1524       [["mkdir"; "/new"];
1525        ["mkdir_p"; "/new"]];
1526     InitBasicFS, Always, TestLastFail
1527       [["touch"; "/new"];
1528        ["mkdir_p"; "/new"]]],
1529    "create a directory and parents",
1530    "\
1531 Create a directory named C<path>, creating any parent directories
1532 as necessary.  This is like the C<mkdir -p> shell command.");
1533
1534   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1535    [], (* XXX Need stat command to test *)
1536    "change file mode",
1537    "\
1538 Change the mode (permissions) of C<path> to C<mode>.  Only
1539 numeric modes are supported.
1540
1541 I<Note>: When using this command from guestfish, C<mode>
1542 by default would be decimal, unless you prefix it with
1543 C<0> to get octal, ie. use C<0700> not C<700>.
1544
1545 The mode actually set is affected by the umask.");
1546
1547   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1548    [], (* XXX Need stat command to test *)
1549    "change file owner and group",
1550    "\
1551 Change the file owner to C<owner> and group to C<group>.
1552
1553 Only numeric uid and gid are supported.  If you want to use
1554 names, you will need to locate and parse the password file
1555 yourself (Augeas support makes this relatively easy).");
1556
1557   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1558    [InitISOFS, Always, TestOutputTrue (
1559       [["exists"; "/empty"]]);
1560     InitISOFS, Always, TestOutputTrue (
1561       [["exists"; "/directory"]])],
1562    "test if file or directory exists",
1563    "\
1564 This returns C<true> if and only if there is a file, directory
1565 (or anything) with the given C<path> name.
1566
1567 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1568
1569   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1570    [InitISOFS, Always, TestOutputTrue (
1571       [["is_file"; "/known-1"]]);
1572     InitISOFS, Always, TestOutputFalse (
1573       [["is_file"; "/directory"]])],
1574    "test if file exists",
1575    "\
1576 This returns C<true> if and only if there is a file
1577 with the given C<path> name.  Note that it returns false for
1578 other objects like directories.
1579
1580 See also C<guestfs_stat>.");
1581
1582   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1583    [InitISOFS, Always, TestOutputFalse (
1584       [["is_dir"; "/known-3"]]);
1585     InitISOFS, Always, TestOutputTrue (
1586       [["is_dir"; "/directory"]])],
1587    "test if file exists",
1588    "\
1589 This returns C<true> if and only if there is a directory
1590 with the given C<path> name.  Note that it returns false for
1591 other objects like files.
1592
1593 See also C<guestfs_stat>.");
1594
1595   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1596    [InitEmpty, Always, TestOutputListOfDevices (
1597       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1598        ["pvcreate"; "/dev/sda1"];
1599        ["pvcreate"; "/dev/sda2"];
1600        ["pvcreate"; "/dev/sda3"];
1601        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1602    "create an LVM physical volume",
1603    "\
1604 This creates an LVM physical volume on the named C<device>,
1605 where C<device> should usually be a partition name such
1606 as C</dev/sda1>.");
1607
1608   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1609    [InitEmpty, Always, TestOutputList (
1610       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1611        ["pvcreate"; "/dev/sda1"];
1612        ["pvcreate"; "/dev/sda2"];
1613        ["pvcreate"; "/dev/sda3"];
1614        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1615        ["vgcreate"; "VG2"; "/dev/sda3"];
1616        ["vgs"]], ["VG1"; "VG2"])],
1617    "create an LVM volume group",
1618    "\
1619 This creates an LVM volume group called C<volgroup>
1620 from the non-empty list of physical volumes C<physvols>.");
1621
1622   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1623    [InitEmpty, Always, TestOutputList (
1624       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1625        ["pvcreate"; "/dev/sda1"];
1626        ["pvcreate"; "/dev/sda2"];
1627        ["pvcreate"; "/dev/sda3"];
1628        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1629        ["vgcreate"; "VG2"; "/dev/sda3"];
1630        ["lvcreate"; "LV1"; "VG1"; "50"];
1631        ["lvcreate"; "LV2"; "VG1"; "50"];
1632        ["lvcreate"; "LV3"; "VG2"; "50"];
1633        ["lvcreate"; "LV4"; "VG2"; "50"];
1634        ["lvcreate"; "LV5"; "VG2"; "50"];
1635        ["lvs"]],
1636       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1637        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1638    "create an LVM logical volume",
1639    "\
1640 This creates an LVM logical volume called C<logvol>
1641 on the volume group C<volgroup>, with C<size> megabytes.");
1642
1643   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1644    [InitEmpty, Always, TestOutput (
1645       [["part_disk"; "/dev/sda"; "mbr"];
1646        ["mkfs"; "ext2"; "/dev/sda1"];
1647        ["mount_options"; ""; "/dev/sda1"; "/"];
1648        ["write"; "/new"; "new file contents"];
1649        ["cat"; "/new"]], "new file contents")],
1650    "make a filesystem",
1651    "\
1652 This creates a filesystem on C<device> (usually a partition
1653 or LVM logical volume).  The filesystem type is C<fstype>, for
1654 example C<ext3>.");
1655
1656   ("sfdisk", (RErr, [Device "device";
1657                      Int "cyls"; Int "heads"; Int "sectors";
1658                      StringList "lines"]), 43, [DangerWillRobinson],
1659    [],
1660    "create partitions on a block device",
1661    "\
1662 This is a direct interface to the L<sfdisk(8)> program for creating
1663 partitions on block devices.
1664
1665 C<device> should be a block device, for example C</dev/sda>.
1666
1667 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1668 and sectors on the device, which are passed directly to sfdisk as
1669 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1670 of these, then the corresponding parameter is omitted.  Usually for
1671 'large' disks, you can just pass C<0> for these, but for small
1672 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1673 out the right geometry and you will need to tell it.
1674
1675 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1676 information refer to the L<sfdisk(8)> manpage.
1677
1678 To create a single partition occupying the whole disk, you would
1679 pass C<lines> as a single element list, when the single element being
1680 the string C<,> (comma).
1681
1682 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1683 C<guestfs_part_init>");
1684
1685   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1686    (* Regression test for RHBZ#597135. *)
1687    [InitBasicFS, Always, TestLastFail
1688       [["write_file"; "/new"; "abc"; "10000"]]],
1689    "create a file",
1690    "\
1691 This call creates a file called C<path>.  The contents of the
1692 file is the string C<content> (which can contain any 8 bit data),
1693 with length C<size>.
1694
1695 As a special case, if C<size> is C<0>
1696 then the length is calculated using C<strlen> (so in this case
1697 the content cannot contain embedded ASCII NULs).
1698
1699 I<NB.> Owing to a bug, writing content containing ASCII NUL
1700 characters does I<not> work, even if the length is specified.");
1701
1702   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1703    [InitEmpty, Always, TestOutputListOfDevices (
1704       [["part_disk"; "/dev/sda"; "mbr"];
1705        ["mkfs"; "ext2"; "/dev/sda1"];
1706        ["mount_options"; ""; "/dev/sda1"; "/"];
1707        ["mounts"]], ["/dev/sda1"]);
1708     InitEmpty, Always, TestOutputList (
1709       [["part_disk"; "/dev/sda"; "mbr"];
1710        ["mkfs"; "ext2"; "/dev/sda1"];
1711        ["mount_options"; ""; "/dev/sda1"; "/"];
1712        ["umount"; "/"];
1713        ["mounts"]], [])],
1714    "unmount a filesystem",
1715    "\
1716 This unmounts the given filesystem.  The filesystem may be
1717 specified either by its mountpoint (path) or the device which
1718 contains the filesystem.");
1719
1720   ("mounts", (RStringList "devices", []), 46, [],
1721    [InitBasicFS, Always, TestOutputListOfDevices (
1722       [["mounts"]], ["/dev/sda1"])],
1723    "show mounted filesystems",
1724    "\
1725 This returns the list of currently mounted filesystems.  It returns
1726 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1727
1728 Some internal mounts are not shown.
1729
1730 See also: C<guestfs_mountpoints>");
1731
1732   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1733    [InitBasicFS, Always, TestOutputList (
1734       [["umount_all"];
1735        ["mounts"]], []);
1736     (* check that umount_all can unmount nested mounts correctly: *)
1737     InitEmpty, Always, TestOutputList (
1738       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1739        ["mkfs"; "ext2"; "/dev/sda1"];
1740        ["mkfs"; "ext2"; "/dev/sda2"];
1741        ["mkfs"; "ext2"; "/dev/sda3"];
1742        ["mount_options"; ""; "/dev/sda1"; "/"];
1743        ["mkdir"; "/mp1"];
1744        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1745        ["mkdir"; "/mp1/mp2"];
1746        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1747        ["mkdir"; "/mp1/mp2/mp3"];
1748        ["umount_all"];
1749        ["mounts"]], [])],
1750    "unmount all filesystems",
1751    "\
1752 This unmounts all mounted filesystems.
1753
1754 Some internal mounts are not unmounted by this call.");
1755
1756   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1757    [],
1758    "remove all LVM LVs, VGs and PVs",
1759    "\
1760 This command removes all LVM logical volumes, volume groups
1761 and physical volumes.");
1762
1763   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1764    [InitISOFS, Always, TestOutput (
1765       [["file"; "/empty"]], "empty");
1766     InitISOFS, Always, TestOutput (
1767       [["file"; "/known-1"]], "ASCII text");
1768     InitISOFS, Always, TestLastFail (
1769       [["file"; "/notexists"]]);
1770     InitISOFS, Always, TestOutput (
1771       [["file"; "/abssymlink"]], "symbolic link");
1772     InitISOFS, Always, TestOutput (
1773       [["file"; "/directory"]], "directory")],
1774    "determine file type",
1775    "\
1776 This call uses the standard L<file(1)> command to determine
1777 the type or contents of the file.
1778
1779 This call will also transparently look inside various types
1780 of compressed file.
1781
1782 The exact command which runs is C<file -zb path>.  Note in
1783 particular that the filename is not prepended to the output
1784 (the C<-b> option).
1785
1786 This command can also be used on C</dev/> devices
1787 (and partitions, LV names).  You can for example use this
1788 to determine if a device contains a filesystem, although
1789 it's usually better to use C<guestfs_vfs_type>.
1790
1791 If the C<path> does not begin with C</dev/> then
1792 this command only works for the content of regular files.
1793 For other file types (directory, symbolic link etc) it
1794 will just return the string C<directory> etc.");
1795
1796   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1797    [InitBasicFS, Always, TestOutput (
1798       [["upload"; "test-command"; "/test-command"];
1799        ["chmod"; "0o755"; "/test-command"];
1800        ["command"; "/test-command 1"]], "Result1");
1801     InitBasicFS, Always, TestOutput (
1802       [["upload"; "test-command"; "/test-command"];
1803        ["chmod"; "0o755"; "/test-command"];
1804        ["command"; "/test-command 2"]], "Result2\n");
1805     InitBasicFS, Always, TestOutput (
1806       [["upload"; "test-command"; "/test-command"];
1807        ["chmod"; "0o755"; "/test-command"];
1808        ["command"; "/test-command 3"]], "\nResult3");
1809     InitBasicFS, Always, TestOutput (
1810       [["upload"; "test-command"; "/test-command"];
1811        ["chmod"; "0o755"; "/test-command"];
1812        ["command"; "/test-command 4"]], "\nResult4\n");
1813     InitBasicFS, Always, TestOutput (
1814       [["upload"; "test-command"; "/test-command"];
1815        ["chmod"; "0o755"; "/test-command"];
1816        ["command"; "/test-command 5"]], "\nResult5\n\n");
1817     InitBasicFS, Always, TestOutput (
1818       [["upload"; "test-command"; "/test-command"];
1819        ["chmod"; "0o755"; "/test-command"];
1820        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1821     InitBasicFS, Always, TestOutput (
1822       [["upload"; "test-command"; "/test-command"];
1823        ["chmod"; "0o755"; "/test-command"];
1824        ["command"; "/test-command 7"]], "");
1825     InitBasicFS, Always, TestOutput (
1826       [["upload"; "test-command"; "/test-command"];
1827        ["chmod"; "0o755"; "/test-command"];
1828        ["command"; "/test-command 8"]], "\n");
1829     InitBasicFS, Always, TestOutput (
1830       [["upload"; "test-command"; "/test-command"];
1831        ["chmod"; "0o755"; "/test-command"];
1832        ["command"; "/test-command 9"]], "\n\n");
1833     InitBasicFS, Always, TestOutput (
1834       [["upload"; "test-command"; "/test-command"];
1835        ["chmod"; "0o755"; "/test-command"];
1836        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1837     InitBasicFS, Always, TestOutput (
1838       [["upload"; "test-command"; "/test-command"];
1839        ["chmod"; "0o755"; "/test-command"];
1840        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1841     InitBasicFS, Always, TestLastFail (
1842       [["upload"; "test-command"; "/test-command"];
1843        ["chmod"; "0o755"; "/test-command"];
1844        ["command"; "/test-command"]])],
1845    "run a command from the guest filesystem",
1846    "\
1847 This call runs a command from the guest filesystem.  The
1848 filesystem must be mounted, and must contain a compatible
1849 operating system (ie. something Linux, with the same
1850 or compatible processor architecture).
1851
1852 The single parameter is an argv-style list of arguments.
1853 The first element is the name of the program to run.
1854 Subsequent elements are parameters.  The list must be
1855 non-empty (ie. must contain a program name).  Note that
1856 the command runs directly, and is I<not> invoked via
1857 the shell (see C<guestfs_sh>).
1858
1859 The return value is anything printed to I<stdout> by
1860 the command.
1861
1862 If the command returns a non-zero exit status, then
1863 this function returns an error message.  The error message
1864 string is the content of I<stderr> from the command.
1865
1866 The C<$PATH> environment variable will contain at least
1867 C</usr/bin> and C</bin>.  If you require a program from
1868 another location, you should provide the full path in the
1869 first parameter.
1870
1871 Shared libraries and data files required by the program
1872 must be available on filesystems which are mounted in the
1873 correct places.  It is the caller's responsibility to ensure
1874 all filesystems that are needed are mounted at the right
1875 locations.");
1876
1877   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1878    [InitBasicFS, Always, TestOutputList (
1879       [["upload"; "test-command"; "/test-command"];
1880        ["chmod"; "0o755"; "/test-command"];
1881        ["command_lines"; "/test-command 1"]], ["Result1"]);
1882     InitBasicFS, Always, TestOutputList (
1883       [["upload"; "test-command"; "/test-command"];
1884        ["chmod"; "0o755"; "/test-command"];
1885        ["command_lines"; "/test-command 2"]], ["Result2"]);
1886     InitBasicFS, Always, TestOutputList (
1887       [["upload"; "test-command"; "/test-command"];
1888        ["chmod"; "0o755"; "/test-command"];
1889        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1890     InitBasicFS, Always, TestOutputList (
1891       [["upload"; "test-command"; "/test-command"];
1892        ["chmod"; "0o755"; "/test-command"];
1893        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1894     InitBasicFS, Always, TestOutputList (
1895       [["upload"; "test-command"; "/test-command"];
1896        ["chmod"; "0o755"; "/test-command"];
1897        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1898     InitBasicFS, Always, TestOutputList (
1899       [["upload"; "test-command"; "/test-command"];
1900        ["chmod"; "0o755"; "/test-command"];
1901        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1902     InitBasicFS, Always, TestOutputList (
1903       [["upload"; "test-command"; "/test-command"];
1904        ["chmod"; "0o755"; "/test-command"];
1905        ["command_lines"; "/test-command 7"]], []);
1906     InitBasicFS, Always, TestOutputList (
1907       [["upload"; "test-command"; "/test-command"];
1908        ["chmod"; "0o755"; "/test-command"];
1909        ["command_lines"; "/test-command 8"]], [""]);
1910     InitBasicFS, Always, TestOutputList (
1911       [["upload"; "test-command"; "/test-command"];
1912        ["chmod"; "0o755"; "/test-command"];
1913        ["command_lines"; "/test-command 9"]], ["";""]);
1914     InitBasicFS, Always, TestOutputList (
1915       [["upload"; "test-command"; "/test-command"];
1916        ["chmod"; "0o755"; "/test-command"];
1917        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1918     InitBasicFS, Always, TestOutputList (
1919       [["upload"; "test-command"; "/test-command"];
1920        ["chmod"; "0o755"; "/test-command"];
1921        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1922    "run a command, returning lines",
1923    "\
1924 This is the same as C<guestfs_command>, but splits the
1925 result into a list of lines.
1926
1927 See also: C<guestfs_sh_lines>");
1928
1929   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1930    [InitISOFS, Always, TestOutputStruct (
1931       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1932    "get file information",
1933    "\
1934 Returns file information for the given C<path>.
1935
1936 This is the same as the C<stat(2)> system call.");
1937
1938   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1939    [InitISOFS, Always, TestOutputStruct (
1940       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1941    "get file information for a symbolic link",
1942    "\
1943 Returns file information for the given C<path>.
1944
1945 This is the same as C<guestfs_stat> except that if C<path>
1946 is a symbolic link, then the link is stat-ed, not the file it
1947 refers to.
1948
1949 This is the same as the C<lstat(2)> system call.");
1950
1951   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1952    [InitISOFS, Always, TestOutputStruct (
1953       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1954    "get file system statistics",
1955    "\
1956 Returns file system statistics for any mounted file system.
1957 C<path> should be a file or directory in the mounted file system
1958 (typically it is the mount point itself, but it doesn't need to be).
1959
1960 This is the same as the C<statvfs(2)> system call.");
1961
1962   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1963    [], (* XXX test *)
1964    "get ext2/ext3/ext4 superblock details",
1965    "\
1966 This returns the contents of the ext2, ext3 or ext4 filesystem
1967 superblock on C<device>.
1968
1969 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1970 manpage for more details.  The list of fields returned isn't
1971 clearly defined, and depends on both the version of C<tune2fs>
1972 that libguestfs was built against, and the filesystem itself.");
1973
1974   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1975    [InitEmpty, Always, TestOutputTrue (
1976       [["blockdev_setro"; "/dev/sda"];
1977        ["blockdev_getro"; "/dev/sda"]])],
1978    "set block device to read-only",
1979    "\
1980 Sets the block device named C<device> to read-only.
1981
1982 This uses the L<blockdev(8)> command.");
1983
1984   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1985    [InitEmpty, Always, TestOutputFalse (
1986       [["blockdev_setrw"; "/dev/sda"];
1987        ["blockdev_getro"; "/dev/sda"]])],
1988    "set block device to read-write",
1989    "\
1990 Sets the block device named C<device> to read-write.
1991
1992 This uses the L<blockdev(8)> command.");
1993
1994   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1995    [InitEmpty, Always, TestOutputTrue (
1996       [["blockdev_setro"; "/dev/sda"];
1997        ["blockdev_getro"; "/dev/sda"]])],
1998    "is block device set to read-only",
1999    "\
2000 Returns a boolean indicating if the block device is read-only
2001 (true if read-only, false if not).
2002
2003 This uses the L<blockdev(8)> command.");
2004
2005   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
2006    [InitEmpty, Always, TestOutputInt (
2007       [["blockdev_getss"; "/dev/sda"]], 512)],
2008    "get sectorsize of block device",
2009    "\
2010 This returns the size of sectors on a block device.
2011 Usually 512, but can be larger for modern devices.
2012
2013 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
2014 for that).
2015
2016 This uses the L<blockdev(8)> command.");
2017
2018   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
2019    [InitEmpty, Always, TestOutputInt (
2020       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
2021    "get blocksize of block device",
2022    "\
2023 This returns the block size of a device.
2024
2025 (Note this is different from both I<size in blocks> and
2026 I<filesystem block size>).
2027
2028 This uses the L<blockdev(8)> command.");
2029
2030   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
2031    [], (* XXX test *)
2032    "set blocksize of block device",
2033    "\
2034 This sets the block size of a device.
2035
2036 (Note this is different from both I<size in blocks> and
2037 I<filesystem block size>).
2038
2039 This uses the L<blockdev(8)> command.");
2040
2041   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
2042    [InitEmpty, Always, TestOutputInt (
2043       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
2044    "get total size of device in 512-byte sectors",
2045    "\
2046 This returns the size of the device in units of 512-byte sectors
2047 (even if the sectorsize isn't 512 bytes ... weird).
2048
2049 See also C<guestfs_blockdev_getss> for the real sector size of
2050 the device, and C<guestfs_blockdev_getsize64> for the more
2051 useful I<size in bytes>.
2052
2053 This uses the L<blockdev(8)> command.");
2054
2055   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
2056    [InitEmpty, Always, TestOutputInt (
2057       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
2058    "get total size of device in bytes",
2059    "\
2060 This returns the size of the device in bytes.
2061
2062 See also C<guestfs_blockdev_getsz>.
2063
2064 This uses the L<blockdev(8)> command.");
2065
2066   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
2067    [InitEmpty, Always, TestRun
2068       [["blockdev_flushbufs"; "/dev/sda"]]],
2069    "flush device buffers",
2070    "\
2071 This tells the kernel to flush internal buffers associated
2072 with C<device>.
2073
2074 This uses the L<blockdev(8)> command.");
2075
2076   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
2077    [InitEmpty, Always, TestRun
2078       [["blockdev_rereadpt"; "/dev/sda"]]],
2079    "reread partition table",
2080    "\
2081 Reread the partition table on C<device>.
2082
2083 This uses the L<blockdev(8)> command.");
2084
2085   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
2086    [InitBasicFS, Always, TestOutput (
2087       (* Pick a file from cwd which isn't likely to change. *)
2088       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
2089        ["checksum"; "md5"; "/COPYING.LIB"]],
2090       Digest.to_hex (Digest.file "COPYING.LIB"))],
2091    "upload a file from the local machine",
2092    "\
2093 Upload local file C<filename> to C<remotefilename> on the
2094 filesystem.
2095
2096 C<filename> can also be a named pipe.
2097
2098 See also C<guestfs_download>.");
2099
2100   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
2101    [InitBasicFS, Always, TestOutput (
2102       (* Pick a file from cwd which isn't likely to change. *)
2103       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
2104        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
2105        ["upload"; "testdownload.tmp"; "/upload"];
2106        ["checksum"; "md5"; "/upload"]],
2107       Digest.to_hex (Digest.file "COPYING.LIB"))],
2108    "download a file to the local machine",
2109    "\
2110 Download file C<remotefilename> and save it as C<filename>
2111 on the local machine.
2112
2113 C<filename> can also be a named pipe.
2114
2115 See also C<guestfs_upload>, C<guestfs_cat>.");
2116
2117   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
2118    [InitISOFS, Always, TestOutput (
2119       [["checksum"; "crc"; "/known-3"]], "2891671662");
2120     InitISOFS, Always, TestLastFail (
2121       [["checksum"; "crc"; "/notexists"]]);
2122     InitISOFS, Always, TestOutput (
2123       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
2124     InitISOFS, Always, TestOutput (
2125       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
2126     InitISOFS, Always, TestOutput (
2127       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
2128     InitISOFS, Always, TestOutput (
2129       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
2130     InitISOFS, Always, TestOutput (
2131       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
2132     InitISOFS, Always, TestOutput (
2133       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
2134     (* Test for RHBZ#579608, absolute symbolic links. *)
2135     InitISOFS, Always, TestOutput (
2136       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2137    "compute MD5, SHAx or CRC checksum of file",
2138    "\
2139 This call computes the MD5, SHAx or CRC checksum of the
2140 file named C<path>.
2141
2142 The type of checksum to compute is given by the C<csumtype>
2143 parameter which must have one of the following values:
2144
2145 =over 4
2146
2147 =item C<crc>
2148
2149 Compute the cyclic redundancy check (CRC) specified by POSIX
2150 for the C<cksum> command.
2151
2152 =item C<md5>
2153
2154 Compute the MD5 hash (using the C<md5sum> program).
2155
2156 =item C<sha1>
2157
2158 Compute the SHA1 hash (using the C<sha1sum> program).
2159
2160 =item C<sha224>
2161
2162 Compute the SHA224 hash (using the C<sha224sum> program).
2163
2164 =item C<sha256>
2165
2166 Compute the SHA256 hash (using the C<sha256sum> program).
2167
2168 =item C<sha384>
2169
2170 Compute the SHA384 hash (using the C<sha384sum> program).
2171
2172 =item C<sha512>
2173
2174 Compute the SHA512 hash (using the C<sha512sum> program).
2175
2176 =back
2177
2178 The checksum is returned as a printable string.
2179
2180 To get the checksum for a device, use C<guestfs_checksum_device>.
2181
2182 To get the checksums for many files, use C<guestfs_checksums_out>.");
2183
2184   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2185    [InitBasicFS, Always, TestOutput (
2186       [["tar_in"; "../images/helloworld.tar"; "/"];
2187        ["cat"; "/hello"]], "hello\n")],
2188    "unpack tarfile to directory",
2189    "\
2190 This command uploads and unpacks local file C<tarfile> (an
2191 I<uncompressed> tar file) into C<directory>.
2192
2193 To upload a compressed tarball, use C<guestfs_tgz_in>
2194 or C<guestfs_txz_in>.");
2195
2196   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2197    [],
2198    "pack directory into tarfile",
2199    "\
2200 This command packs the contents of C<directory> and downloads
2201 it to local file C<tarfile>.
2202
2203 To download a compressed tarball, use C<guestfs_tgz_out>
2204 or C<guestfs_txz_out>.");
2205
2206   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2207    [InitBasicFS, Always, TestOutput (
2208       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2209        ["cat"; "/hello"]], "hello\n")],
2210    "unpack compressed tarball to directory",
2211    "\
2212 This command uploads and unpacks local file C<tarball> (a
2213 I<gzip compressed> tar file) into C<directory>.
2214
2215 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2216
2217   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2218    [],
2219    "pack directory into compressed tarball",
2220    "\
2221 This command packs the contents of C<directory> and downloads
2222 it to local file C<tarball>.
2223
2224 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2225
2226   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2227    [InitBasicFS, Always, TestLastFail (
2228       [["umount"; "/"];
2229        ["mount_ro"; "/dev/sda1"; "/"];
2230        ["touch"; "/new"]]);
2231     InitBasicFS, Always, TestOutput (
2232       [["write"; "/new"; "data"];
2233        ["umount"; "/"];
2234        ["mount_ro"; "/dev/sda1"; "/"];
2235        ["cat"; "/new"]], "data")],
2236    "mount a guest disk, read-only",
2237    "\
2238 This is the same as the C<guestfs_mount> command, but it
2239 mounts the filesystem with the read-only (I<-o ro>) flag.");
2240
2241   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2242    [],
2243    "mount a guest disk with mount options",
2244    "\
2245 This is the same as the C<guestfs_mount> command, but it
2246 allows you to set the mount options as for the
2247 L<mount(8)> I<-o> flag.
2248
2249 If the C<options> parameter is an empty string, then
2250 no options are passed (all options default to whatever
2251 the filesystem uses).");
2252
2253   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2254    [],
2255    "mount a guest disk with mount options and vfstype",
2256    "\
2257 This is the same as the C<guestfs_mount> command, but it
2258 allows you to set both the mount options and the vfstype
2259 as for the L<mount(8)> I<-o> and I<-t> flags.");
2260
2261   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2262    [],
2263    "debugging and internals",
2264    "\
2265 The C<guestfs_debug> command exposes some internals of
2266 C<guestfsd> (the guestfs daemon) that runs inside the
2267 qemu subprocess.
2268
2269 There is no comprehensive help for this command.  You have
2270 to look at the file C<daemon/debug.c> in the libguestfs source
2271 to find out what you can do.");
2272
2273   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2274    [InitEmpty, Always, TestOutputList (
2275       [["part_disk"; "/dev/sda"; "mbr"];
2276        ["pvcreate"; "/dev/sda1"];
2277        ["vgcreate"; "VG"; "/dev/sda1"];
2278        ["lvcreate"; "LV1"; "VG"; "50"];
2279        ["lvcreate"; "LV2"; "VG"; "50"];
2280        ["lvremove"; "/dev/VG/LV1"];
2281        ["lvs"]], ["/dev/VG/LV2"]);
2282     InitEmpty, Always, TestOutputList (
2283       [["part_disk"; "/dev/sda"; "mbr"];
2284        ["pvcreate"; "/dev/sda1"];
2285        ["vgcreate"; "VG"; "/dev/sda1"];
2286        ["lvcreate"; "LV1"; "VG"; "50"];
2287        ["lvcreate"; "LV2"; "VG"; "50"];
2288        ["lvremove"; "/dev/VG"];
2289        ["lvs"]], []);
2290     InitEmpty, Always, TestOutputList (
2291       [["part_disk"; "/dev/sda"; "mbr"];
2292        ["pvcreate"; "/dev/sda1"];
2293        ["vgcreate"; "VG"; "/dev/sda1"];
2294        ["lvcreate"; "LV1"; "VG"; "50"];
2295        ["lvcreate"; "LV2"; "VG"; "50"];
2296        ["lvremove"; "/dev/VG"];
2297        ["vgs"]], ["VG"])],
2298    "remove an LVM logical volume",
2299    "\
2300 Remove an LVM logical volume C<device>, where C<device> is
2301 the path to the LV, such as C</dev/VG/LV>.
2302
2303 You can also remove all LVs in a volume group by specifying
2304 the VG name, C</dev/VG>.");
2305
2306   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2307    [InitEmpty, Always, TestOutputList (
2308       [["part_disk"; "/dev/sda"; "mbr"];
2309        ["pvcreate"; "/dev/sda1"];
2310        ["vgcreate"; "VG"; "/dev/sda1"];
2311        ["lvcreate"; "LV1"; "VG"; "50"];
2312        ["lvcreate"; "LV2"; "VG"; "50"];
2313        ["vgremove"; "VG"];
2314        ["lvs"]], []);
2315     InitEmpty, Always, TestOutputList (
2316       [["part_disk"; "/dev/sda"; "mbr"];
2317        ["pvcreate"; "/dev/sda1"];
2318        ["vgcreate"; "VG"; "/dev/sda1"];
2319        ["lvcreate"; "LV1"; "VG"; "50"];
2320        ["lvcreate"; "LV2"; "VG"; "50"];
2321        ["vgremove"; "VG"];
2322        ["vgs"]], [])],
2323    "remove an LVM volume group",
2324    "\
2325 Remove an LVM volume group C<vgname>, (for example C<VG>).
2326
2327 This also forcibly removes all logical volumes in the volume
2328 group (if any).");
2329
2330   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2331    [InitEmpty, Always, TestOutputListOfDevices (
2332       [["part_disk"; "/dev/sda"; "mbr"];
2333        ["pvcreate"; "/dev/sda1"];
2334        ["vgcreate"; "VG"; "/dev/sda1"];
2335        ["lvcreate"; "LV1"; "VG"; "50"];
2336        ["lvcreate"; "LV2"; "VG"; "50"];
2337        ["vgremove"; "VG"];
2338        ["pvremove"; "/dev/sda1"];
2339        ["lvs"]], []);
2340     InitEmpty, Always, TestOutputListOfDevices (
2341       [["part_disk"; "/dev/sda"; "mbr"];
2342        ["pvcreate"; "/dev/sda1"];
2343        ["vgcreate"; "VG"; "/dev/sda1"];
2344        ["lvcreate"; "LV1"; "VG"; "50"];
2345        ["lvcreate"; "LV2"; "VG"; "50"];
2346        ["vgremove"; "VG"];
2347        ["pvremove"; "/dev/sda1"];
2348        ["vgs"]], []);
2349     InitEmpty, Always, TestOutputListOfDevices (
2350       [["part_disk"; "/dev/sda"; "mbr"];
2351        ["pvcreate"; "/dev/sda1"];
2352        ["vgcreate"; "VG"; "/dev/sda1"];
2353        ["lvcreate"; "LV1"; "VG"; "50"];
2354        ["lvcreate"; "LV2"; "VG"; "50"];
2355        ["vgremove"; "VG"];
2356        ["pvremove"; "/dev/sda1"];
2357        ["pvs"]], [])],
2358    "remove an LVM physical volume",
2359    "\
2360 This wipes a physical volume C<device> so that LVM will no longer
2361 recognise it.
2362
2363 The implementation uses the C<pvremove> command which refuses to
2364 wipe physical volumes that contain any volume groups, so you have
2365 to remove those first.");
2366
2367   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2368    [InitBasicFS, Always, TestOutput (
2369       [["set_e2label"; "/dev/sda1"; "testlabel"];
2370        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2371    "set the ext2/3/4 filesystem label",
2372    "\
2373 This sets the ext2/3/4 filesystem label of the filesystem on
2374 C<device> to C<label>.  Filesystem labels are limited to
2375 16 characters.
2376
2377 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2378 to return the existing label on a filesystem.");
2379
2380   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2381    [],
2382    "get the ext2/3/4 filesystem label",
2383    "\
2384 This returns the ext2/3/4 filesystem label of the filesystem on
2385 C<device>.");
2386
2387   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2388    (let uuid = uuidgen () in
2389     [InitBasicFS, Always, TestOutput (
2390        [["set_e2uuid"; "/dev/sda1"; uuid];
2391         ["get_e2uuid"; "/dev/sda1"]], uuid);
2392      InitBasicFS, Always, TestOutput (
2393        [["set_e2uuid"; "/dev/sda1"; "clear"];
2394         ["get_e2uuid"; "/dev/sda1"]], "");
2395      (* We can't predict what UUIDs will be, so just check the commands run. *)
2396      InitBasicFS, Always, TestRun (
2397        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2398      InitBasicFS, Always, TestRun (
2399        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2400    "set the ext2/3/4 filesystem UUID",
2401    "\
2402 This sets the ext2/3/4 filesystem UUID of the filesystem on
2403 C<device> to C<uuid>.  The format of the UUID and alternatives
2404 such as C<clear>, C<random> and C<time> are described in the
2405 L<tune2fs(8)> manpage.
2406
2407 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2408 to return the existing UUID of a filesystem.");
2409
2410   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2411    (* Regression test for RHBZ#597112. *)
2412    (let uuid = uuidgen () in
2413     [InitBasicFS, Always, TestOutput (
2414        [["mke2journal"; "1024"; "/dev/sdb"];
2415         ["set_e2uuid"; "/dev/sdb"; uuid];
2416         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2417    "get the ext2/3/4 filesystem UUID",
2418    "\
2419 This returns the ext2/3/4 filesystem UUID of the filesystem on
2420 C<device>.");
2421
2422   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2423    [InitBasicFS, Always, TestOutputInt (
2424       [["umount"; "/dev/sda1"];
2425        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2426     InitBasicFS, Always, TestOutputInt (
2427       [["umount"; "/dev/sda1"];
2428        ["zero"; "/dev/sda1"];
2429        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2430    "run the filesystem checker",
2431    "\
2432 This runs the filesystem checker (fsck) on C<device> which
2433 should have filesystem type C<fstype>.
2434
2435 The returned integer is the status.  See L<fsck(8)> for the
2436 list of status codes from C<fsck>.
2437
2438 Notes:
2439
2440 =over 4
2441
2442 =item *
2443
2444 Multiple status codes can be summed together.
2445
2446 =item *
2447
2448 A non-zero return code can mean \"success\", for example if
2449 errors have been corrected on the filesystem.
2450
2451 =item *
2452
2453 Checking or repairing NTFS volumes is not supported
2454 (by linux-ntfs).
2455
2456 =back
2457
2458 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2459
2460   ("zero", (RErr, [Device "device"]), 85, [],
2461    [InitBasicFS, Always, TestOutput (
2462       [["umount"; "/dev/sda1"];
2463        ["zero"; "/dev/sda1"];
2464        ["file"; "/dev/sda1"]], "data")],
2465    "write zeroes to the device",
2466    "\
2467 This command writes zeroes over the first few blocks of C<device>.
2468
2469 How many blocks are zeroed isn't specified (but it's I<not> enough
2470 to securely wipe the device).  It should be sufficient to remove
2471 any partition tables, filesystem superblocks and so on.
2472
2473 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2474
2475   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2476    (* See:
2477     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2478     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2479     *)
2480    [InitBasicFS, Always, TestOutputTrue (
2481       [["mkdir_p"; "/boot/grub"];
2482        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2483        ["grub_install"; "/"; "/dev/vda"];
2484        ["is_dir"; "/boot"]])],
2485    "install GRUB",
2486    "\
2487 This command installs GRUB (the Grand Unified Bootloader) on
2488 C<device>, with the root directory being C<root>.
2489
2490 Note: If grub-install reports the error
2491 \"No suitable drive was found in the generated device map.\"
2492 it may be that you need to create a C</boot/grub/device.map>
2493 file first that contains the mapping between grub device names
2494 and Linux device names.  It is usually sufficient to create
2495 a file containing:
2496
2497  (hd0) /dev/vda
2498
2499 replacing C</dev/vda> with the name of the installation device.");
2500
2501   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2502    [InitBasicFS, Always, TestOutput (
2503       [["write"; "/old"; "file content"];
2504        ["cp"; "/old"; "/new"];
2505        ["cat"; "/new"]], "file content");
2506     InitBasicFS, Always, TestOutputTrue (
2507       [["write"; "/old"; "file content"];
2508        ["cp"; "/old"; "/new"];
2509        ["is_file"; "/old"]]);
2510     InitBasicFS, Always, TestOutput (
2511       [["write"; "/old"; "file content"];
2512        ["mkdir"; "/dir"];
2513        ["cp"; "/old"; "/dir/new"];
2514        ["cat"; "/dir/new"]], "file content")],
2515    "copy a file",
2516    "\
2517 This copies a file from C<src> to C<dest> where C<dest> is
2518 either a destination filename or destination directory.");
2519
2520   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2521    [InitBasicFS, Always, TestOutput (
2522       [["mkdir"; "/olddir"];
2523        ["mkdir"; "/newdir"];
2524        ["write"; "/olddir/file"; "file content"];
2525        ["cp_a"; "/olddir"; "/newdir"];
2526        ["cat"; "/newdir/olddir/file"]], "file content")],
2527    "copy a file or directory recursively",
2528    "\
2529 This copies a file or directory from C<src> to C<dest>
2530 recursively using the C<cp -a> command.");
2531
2532   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2533    [InitBasicFS, Always, TestOutput (
2534       [["write"; "/old"; "file content"];
2535        ["mv"; "/old"; "/new"];
2536        ["cat"; "/new"]], "file content");
2537     InitBasicFS, Always, TestOutputFalse (
2538       [["write"; "/old"; "file content"];
2539        ["mv"; "/old"; "/new"];
2540        ["is_file"; "/old"]])],
2541    "move a file",
2542    "\
2543 This moves a file from C<src> to C<dest> where C<dest> is
2544 either a destination filename or destination directory.");
2545
2546   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2547    [InitEmpty, Always, TestRun (
2548       [["drop_caches"; "3"]])],
2549    "drop kernel page cache, dentries and inodes",
2550    "\
2551 This instructs the guest kernel to drop its page cache,
2552 and/or dentries and inode caches.  The parameter C<whattodrop>
2553 tells the kernel what precisely to drop, see
2554 L<http://linux-mm.org/Drop_Caches>
2555
2556 Setting C<whattodrop> to 3 should drop everything.
2557
2558 This automatically calls L<sync(2)> before the operation,
2559 so that the maximum guest memory is freed.");
2560
2561   ("dmesg", (RString "kmsgs", []), 91, [],
2562    [InitEmpty, Always, TestRun (
2563       [["dmesg"]])],
2564    "return kernel messages",
2565    "\
2566 This returns the kernel messages (C<dmesg> output) from
2567 the guest kernel.  This is sometimes useful for extended
2568 debugging of problems.
2569
2570 Another way to get the same information is to enable
2571 verbose messages with C<guestfs_set_verbose> or by setting
2572 the environment variable C<LIBGUESTFS_DEBUG=1> before
2573 running the program.");
2574
2575   ("ping_daemon", (RErr, []), 92, [],
2576    [InitEmpty, Always, TestRun (
2577       [["ping_daemon"]])],
2578    "ping the guest daemon",
2579    "\
2580 This is a test probe into the guestfs daemon running inside
2581 the qemu subprocess.  Calling this function checks that the
2582 daemon responds to the ping message, without affecting the daemon
2583 or attached block device(s) in any other way.");
2584
2585   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2586    [InitBasicFS, Always, TestOutputTrue (
2587       [["write"; "/file1"; "contents of a file"];
2588        ["cp"; "/file1"; "/file2"];
2589        ["equal"; "/file1"; "/file2"]]);
2590     InitBasicFS, Always, TestOutputFalse (
2591       [["write"; "/file1"; "contents of a file"];
2592        ["write"; "/file2"; "contents of another file"];
2593        ["equal"; "/file1"; "/file2"]]);
2594     InitBasicFS, Always, TestLastFail (
2595       [["equal"; "/file1"; "/file2"]])],
2596    "test if two files have equal contents",
2597    "\
2598 This compares the two files C<file1> and C<file2> and returns
2599 true if their content is exactly equal, or false otherwise.
2600
2601 The external L<cmp(1)> program is used for the comparison.");
2602
2603   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2604    [InitISOFS, Always, TestOutputList (
2605       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2606     InitISOFS, Always, TestOutputList (
2607       [["strings"; "/empty"]], []);
2608     (* Test for RHBZ#579608, absolute symbolic links. *)
2609     InitISOFS, Always, TestRun (
2610       [["strings"; "/abssymlink"]])],
2611    "print the printable strings in a file",
2612    "\
2613 This runs the L<strings(1)> command on a file and returns
2614 the list of printable strings found.");
2615
2616   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2617    [InitISOFS, Always, TestOutputList (
2618       [["strings_e"; "b"; "/known-5"]], []);
2619     InitBasicFS, Always, TestOutputList (
2620       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2621        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2622    "print the printable strings in a file",
2623    "\
2624 This is like the C<guestfs_strings> command, but allows you to
2625 specify the encoding of strings that are looked for in
2626 the source file C<path>.
2627
2628 Allowed encodings are:
2629
2630 =over 4
2631
2632 =item s
2633
2634 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2635 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2636
2637 =item S
2638
2639 Single 8-bit-byte characters.
2640
2641 =item b
2642
2643 16-bit big endian strings such as those encoded in
2644 UTF-16BE or UCS-2BE.
2645
2646 =item l (lower case letter L)
2647
2648 16-bit little endian such as UTF-16LE and UCS-2LE.
2649 This is useful for examining binaries in Windows guests.
2650
2651 =item B
2652
2653 32-bit big endian such as UCS-4BE.
2654
2655 =item L
2656
2657 32-bit little endian such as UCS-4LE.
2658
2659 =back
2660
2661 The returned strings are transcoded to UTF-8.");
2662
2663   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2664    [InitISOFS, Always, TestOutput (
2665       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2666     (* Test for RHBZ#501888c2 regression which caused large hexdump
2667      * commands to segfault.
2668      *)
2669     InitISOFS, Always, TestRun (
2670       [["hexdump"; "/100krandom"]]);
2671     (* Test for RHBZ#579608, absolute symbolic links. *)
2672     InitISOFS, Always, TestRun (
2673       [["hexdump"; "/abssymlink"]])],
2674    "dump a file in hexadecimal",
2675    "\
2676 This runs C<hexdump -C> on the given C<path>.  The result is
2677 the human-readable, canonical hex dump of the file.");
2678
2679   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2680    [InitNone, Always, TestOutput (
2681       [["part_disk"; "/dev/sda"; "mbr"];
2682        ["mkfs"; "ext3"; "/dev/sda1"];
2683        ["mount_options"; ""; "/dev/sda1"; "/"];
2684        ["write"; "/new"; "test file"];
2685        ["umount"; "/dev/sda1"];
2686        ["zerofree"; "/dev/sda1"];
2687        ["mount_options"; ""; "/dev/sda1"; "/"];
2688        ["cat"; "/new"]], "test file")],
2689    "zero unused inodes and disk blocks on ext2/3 filesystem",
2690    "\
2691 This runs the I<zerofree> program on C<device>.  This program
2692 claims to zero unused inodes and disk blocks on an ext2/3
2693 filesystem, thus making it possible to compress the filesystem
2694 more effectively.
2695
2696 You should B<not> run this program if the filesystem is
2697 mounted.
2698
2699 It is possible that using this program can damage the filesystem
2700 or data on the filesystem.");
2701
2702   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2703    [],
2704    "resize an LVM physical volume",
2705    "\
2706 This resizes (expands or shrinks) an existing LVM physical
2707 volume to match the new size of the underlying device.");
2708
2709   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2710                        Int "cyls"; Int "heads"; Int "sectors";
2711                        String "line"]), 99, [DangerWillRobinson],
2712    [],
2713    "modify a single partition on a block device",
2714    "\
2715 This runs L<sfdisk(8)> option to modify just the single
2716 partition C<n> (note: C<n> counts from 1).
2717
2718 For other parameters, see C<guestfs_sfdisk>.  You should usually
2719 pass C<0> for the cyls/heads/sectors parameters.
2720
2721 See also: C<guestfs_part_add>");
2722
2723   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2724    [],
2725    "display the partition table",
2726    "\
2727 This displays the partition table on C<device>, in the
2728 human-readable output of the L<sfdisk(8)> command.  It is
2729 not intended to be parsed.
2730
2731 See also: C<guestfs_part_list>");
2732
2733   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2734    [],
2735    "display the kernel geometry",
2736    "\
2737 This displays the kernel's idea of the geometry of C<device>.
2738
2739 The result is in human-readable format, and not designed to
2740 be parsed.");
2741
2742   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2743    [],
2744    "display the disk geometry from the partition table",
2745    "\
2746 This displays the disk geometry of C<device> read from the
2747 partition table.  Especially in the case where the underlying
2748 block device has been resized, this can be different from the
2749 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2750
2751 The result is in human-readable format, and not designed to
2752 be parsed.");
2753
2754   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2755    [],
2756    "activate or deactivate all volume groups",
2757    "\
2758 This command activates or (if C<activate> is false) deactivates
2759 all logical volumes in all volume groups.
2760 If activated, then they are made known to the
2761 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2762 then those devices disappear.
2763
2764 This command is the same as running C<vgchange -a y|n>");
2765
2766   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2767    [],
2768    "activate or deactivate some volume groups",
2769    "\
2770 This command activates or (if C<activate> is false) deactivates
2771 all logical volumes in the listed volume groups C<volgroups>.
2772 If activated, then they are made known to the
2773 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2774 then those devices disappear.
2775
2776 This command is the same as running C<vgchange -a y|n volgroups...>
2777
2778 Note that if C<volgroups> is an empty list then B<all> volume groups
2779 are activated or deactivated.");
2780
2781   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2782    [InitNone, Always, TestOutput (
2783       [["part_disk"; "/dev/sda"; "mbr"];
2784        ["pvcreate"; "/dev/sda1"];
2785        ["vgcreate"; "VG"; "/dev/sda1"];
2786        ["lvcreate"; "LV"; "VG"; "10"];
2787        ["mkfs"; "ext2"; "/dev/VG/LV"];
2788        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2789        ["write"; "/new"; "test content"];
2790        ["umount"; "/"];
2791        ["lvresize"; "/dev/VG/LV"; "20"];
2792        ["e2fsck_f"; "/dev/VG/LV"];
2793        ["resize2fs"; "/dev/VG/LV"];
2794        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2795        ["cat"; "/new"]], "test content");
2796     InitNone, Always, TestRun (
2797       (* Make an LV smaller to test RHBZ#587484. *)
2798       [["part_disk"; "/dev/sda"; "mbr"];
2799        ["pvcreate"; "/dev/sda1"];
2800        ["vgcreate"; "VG"; "/dev/sda1"];
2801        ["lvcreate"; "LV"; "VG"; "20"];
2802        ["lvresize"; "/dev/VG/LV"; "10"]])],
2803    "resize an LVM logical volume",
2804    "\
2805 This resizes (expands or shrinks) an existing LVM logical
2806 volume to C<mbytes>.  When reducing, data in the reduced part
2807 is lost.");
2808
2809   ("resize2fs", (RErr, [Device "device"]), 106, [],
2810    [], (* lvresize tests this *)
2811    "resize an ext2, ext3 or ext4 filesystem",
2812    "\
2813 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2814 the underlying device.
2815
2816 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2817 on the C<device> before calling this command.  For unknown reasons
2818 C<resize2fs> sometimes gives an error about this and sometimes not.
2819 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2820 calling this function.");
2821
2822   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2823    [InitBasicFS, Always, TestOutputList (
2824       [["find"; "/"]], ["lost+found"]);
2825     InitBasicFS, Always, TestOutputList (
2826       [["touch"; "/a"];
2827        ["mkdir"; "/b"];
2828        ["touch"; "/b/c"];
2829        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2830     InitBasicFS, Always, TestOutputList (
2831       [["mkdir_p"; "/a/b/c"];
2832        ["touch"; "/a/b/c/d"];
2833        ["find"; "/a/b/"]], ["c"; "c/d"])],
2834    "find all files and directories",
2835    "\
2836 This command lists out all files and directories, recursively,
2837 starting at C<directory>.  It is essentially equivalent to
2838 running the shell command C<find directory -print> but some
2839 post-processing happens on the output, described below.
2840
2841 This returns a list of strings I<without any prefix>.  Thus
2842 if the directory structure was:
2843
2844  /tmp/a
2845  /tmp/b
2846  /tmp/c/d
2847
2848 then the returned list from C<guestfs_find> C</tmp> would be
2849 4 elements:
2850
2851  a
2852  b
2853  c
2854  c/d
2855
2856 If C<directory> is not a directory, then this command returns
2857 an error.
2858
2859 The returned list is sorted.
2860
2861 See also C<guestfs_find0>.");
2862
2863   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2864    [], (* lvresize tests this *)
2865    "check an ext2/ext3 filesystem",
2866    "\
2867 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2868 filesystem checker on C<device>, noninteractively (C<-p>),
2869 even if the filesystem appears to be clean (C<-f>).
2870
2871 This command is only needed because of C<guestfs_resize2fs>
2872 (q.v.).  Normally you should use C<guestfs_fsck>.");
2873
2874   ("sleep", (RErr, [Int "secs"]), 109, [],
2875    [InitNone, Always, TestRun (
2876       [["sleep"; "1"]])],
2877    "sleep for some seconds",
2878    "\
2879 Sleep for C<secs> seconds.");
2880
2881   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2882    [InitNone, Always, TestOutputInt (
2883       [["part_disk"; "/dev/sda"; "mbr"];
2884        ["mkfs"; "ntfs"; "/dev/sda1"];
2885        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2886     InitNone, Always, TestOutputInt (
2887       [["part_disk"; "/dev/sda"; "mbr"];
2888        ["mkfs"; "ext2"; "/dev/sda1"];
2889        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2890    "probe NTFS volume",
2891    "\
2892 This command runs the L<ntfs-3g.probe(8)> command which probes
2893 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2894 be mounted read-write, and some cannot be mounted at all).
2895
2896 C<rw> is a boolean flag.  Set it to true if you want to test
2897 if the volume can be mounted read-write.  Set it to false if
2898 you want to test if the volume can be mounted read-only.
2899
2900 The return value is an integer which C<0> if the operation
2901 would succeed, or some non-zero value documented in the
2902 L<ntfs-3g.probe(8)> manual page.");
2903
2904   ("sh", (RString "output", [String "command"]), 111, [],
2905    [], (* XXX needs tests *)
2906    "run a command via the shell",
2907    "\
2908 This call runs a command from the guest filesystem via the
2909 guest's C</bin/sh>.
2910
2911 This is like C<guestfs_command>, but passes the command to:
2912
2913  /bin/sh -c \"command\"
2914
2915 Depending on the guest's shell, this usually results in
2916 wildcards being expanded, shell expressions being interpolated
2917 and so on.
2918
2919 All the provisos about C<guestfs_command> apply to this call.");
2920
2921   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2922    [], (* XXX needs tests *)
2923    "run a command via the shell returning lines",
2924    "\
2925 This is the same as C<guestfs_sh>, but splits the result
2926 into a list of lines.
2927
2928 See also: C<guestfs_command_lines>");
2929
2930   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2931    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2932     * code in stubs.c, since all valid glob patterns must start with "/".
2933     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2934     *)
2935    [InitBasicFS, Always, TestOutputList (
2936       [["mkdir_p"; "/a/b/c"];
2937        ["touch"; "/a/b/c/d"];
2938        ["touch"; "/a/b/c/e"];
2939        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2940     InitBasicFS, Always, TestOutputList (
2941       [["mkdir_p"; "/a/b/c"];
2942        ["touch"; "/a/b/c/d"];
2943        ["touch"; "/a/b/c/e"];
2944        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2945     InitBasicFS, Always, TestOutputList (
2946       [["mkdir_p"; "/a/b/c"];
2947        ["touch"; "/a/b/c/d"];
2948        ["touch"; "/a/b/c/e"];
2949        ["glob_expand"; "/a/*/x/*"]], [])],
2950    "expand a wildcard path",
2951    "\
2952 This command searches for all the pathnames matching
2953 C<pattern> according to the wildcard expansion rules
2954 used by the shell.
2955
2956 If no paths match, then this returns an empty list
2957 (note: not an error).
2958
2959 It is just a wrapper around the C L<glob(3)> function
2960 with flags C<GLOB_MARK|GLOB_BRACE>.
2961 See that manual page for more details.");
2962
2963   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2964    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2965       [["scrub_device"; "/dev/sdc"]])],
2966    "scrub (securely wipe) a device",
2967    "\
2968 This command writes patterns over C<device> to make data retrieval
2969 more difficult.
2970
2971 It is an interface to the L<scrub(1)> program.  See that
2972 manual page for more details.");
2973
2974   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2975    [InitBasicFS, Always, TestRun (
2976       [["write"; "/file"; "content"];
2977        ["scrub_file"; "/file"]])],
2978    "scrub (securely wipe) a file",
2979    "\
2980 This command writes patterns over a file to make data retrieval
2981 more difficult.
2982
2983 The file is I<removed> after scrubbing.
2984
2985 It is an interface to the L<scrub(1)> program.  See that
2986 manual page for more details.");
2987
2988   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2989    [], (* XXX needs testing *)
2990    "scrub (securely wipe) free space",
2991    "\
2992 This command creates the directory C<dir> and then fills it
2993 with files until the filesystem is full, and scrubs the files
2994 as for C<guestfs_scrub_file>, and deletes them.
2995 The intention is to scrub any free space on the partition
2996 containing C<dir>.
2997
2998 It is an interface to the L<scrub(1)> program.  See that
2999 manual page for more details.");
3000
3001   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
3002    [InitBasicFS, Always, TestRun (
3003       [["mkdir"; "/tmp"];
3004        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
3005    "create a temporary directory",
3006    "\
3007 This command creates a temporary directory.  The
3008 C<template> parameter should be a full pathname for the
3009 temporary directory name with the final six characters being
3010 \"XXXXXX\".
3011
3012 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
3013 the second one being suitable for Windows filesystems.
3014
3015 The name of the temporary directory that was created
3016 is returned.
3017
3018 The temporary directory is created with mode 0700
3019 and is owned by root.
3020
3021 The caller is responsible for deleting the temporary
3022 directory and its contents after use.
3023
3024 See also: L<mkdtemp(3)>");
3025
3026   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
3027    [InitISOFS, Always, TestOutputInt (
3028       [["wc_l"; "/10klines"]], 10000);
3029     (* Test for RHBZ#579608, absolute symbolic links. *)
3030     InitISOFS, Always, TestOutputInt (
3031       [["wc_l"; "/abssymlink"]], 10000)],
3032    "count lines in a file",
3033    "\
3034 This command counts the lines in a file, using the
3035 C<wc -l> external command.");
3036
3037   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
3038    [InitISOFS, Always, TestOutputInt (
3039       [["wc_w"; "/10klines"]], 10000)],
3040    "count words in a file",
3041    "\
3042 This command counts the words in a file, using the
3043 C<wc -w> external command.");
3044
3045   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
3046    [InitISOFS, Always, TestOutputInt (
3047       [["wc_c"; "/100kallspaces"]], 102400)],
3048    "count characters in a file",
3049    "\
3050 This command counts the characters in a file, using the
3051 C<wc -c> external command.");
3052
3053   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
3054    [InitISOFS, Always, TestOutputList (
3055       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
3056     (* Test for RHBZ#579608, absolute symbolic links. *)
3057     InitISOFS, Always, TestOutputList (
3058       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
3059    "return first 10 lines of a file",
3060    "\
3061 This command returns up to the first 10 lines of a file as
3062 a list of strings.");
3063
3064   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
3065    [InitISOFS, Always, TestOutputList (
3066       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
3067     InitISOFS, Always, TestOutputList (
3068       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
3069     InitISOFS, Always, TestOutputList (
3070       [["head_n"; "0"; "/10klines"]], [])],
3071    "return first N lines of a file",
3072    "\
3073 If the parameter C<nrlines> is a positive number, this returns the first
3074 C<nrlines> lines of the file C<path>.
3075
3076 If the parameter C<nrlines> is a negative number, this returns lines
3077 from the file C<path>, excluding the last C<nrlines> lines.
3078
3079 If the parameter C<nrlines> is zero, this returns an empty list.");
3080
3081   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
3082    [InitISOFS, Always, TestOutputList (
3083       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
3084    "return last 10 lines of a file",
3085    "\
3086 This command returns up to the last 10 lines of a file as
3087 a list of strings.");
3088
3089   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
3090    [InitISOFS, Always, TestOutputList (
3091       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
3092     InitISOFS, Always, TestOutputList (
3093       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
3094     InitISOFS, Always, TestOutputList (
3095       [["tail_n"; "0"; "/10klines"]], [])],
3096    "return last N lines of a file",
3097    "\
3098 If the parameter C<nrlines> is a positive number, this returns the last
3099 C<nrlines> lines of the file C<path>.
3100
3101 If the parameter C<nrlines> is a negative number, this returns lines
3102 from the file C<path>, starting with the C<-nrlines>th line.
3103
3104 If the parameter C<nrlines> is zero, this returns an empty list.");
3105
3106   ("df", (RString "output", []), 125, [],
3107    [], (* XXX Tricky to test because it depends on the exact format
3108         * of the 'df' command and other imponderables.
3109         *)
3110    "report file system disk space usage",
3111    "\
3112 This command runs the C<df> command to report disk space used.
3113
3114 This command is mostly useful for interactive sessions.  It
3115 is I<not> intended that you try to parse the output string.
3116 Use C<statvfs> from programs.");
3117
3118   ("df_h", (RString "output", []), 126, [],
3119    [], (* XXX Tricky to test because it depends on the exact format
3120         * of the 'df' command and other imponderables.
3121         *)
3122    "report file system disk space usage (human readable)",
3123    "\
3124 This command runs the C<df -h> command to report disk space used
3125 in human-readable format.
3126
3127 This command is mostly useful for interactive sessions.  It
3128 is I<not> intended that you try to parse the output string.
3129 Use C<statvfs> from programs.");
3130
3131   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
3132    [InitISOFS, Always, TestOutputInt (
3133       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
3134    "estimate file space usage",
3135    "\
3136 This command runs the C<du -s> command to estimate file space
3137 usage for C<path>.
3138
3139 C<path> can be a file or a directory.  If C<path> is a directory
3140 then the estimate includes the contents of the directory and all
3141 subdirectories (recursively).
3142
3143 The result is the estimated size in I<kilobytes>
3144 (ie. units of 1024 bytes).");
3145
3146   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3147    [InitISOFS, Always, TestOutputList (
3148       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3149    "list files in an initrd",
3150    "\
3151 This command lists out files contained in an initrd.
3152
3153 The files are listed without any initial C</> character.  The
3154 files are listed in the order they appear (not necessarily
3155 alphabetical).  Directory names are listed as separate items.
3156
3157 Old Linux kernels (2.4 and earlier) used a compressed ext2
3158 filesystem as initrd.  We I<only> support the newer initramfs
3159 format (compressed cpio files).");
3160
3161   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3162    [],
3163    "mount a file using the loop device",
3164    "\
3165 This command lets you mount C<file> (a filesystem image
3166 in a file) on a mount point.  It is entirely equivalent to
3167 the command C<mount -o loop file mountpoint>.");
3168
3169   ("mkswap", (RErr, [Device "device"]), 130, [],
3170    [InitEmpty, Always, TestRun (
3171       [["part_disk"; "/dev/sda"; "mbr"];
3172        ["mkswap"; "/dev/sda1"]])],
3173    "create a swap partition",
3174    "\
3175 Create a swap partition on C<device>.");
3176
3177   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3178    [InitEmpty, Always, TestRun (
3179       [["part_disk"; "/dev/sda"; "mbr"];
3180        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3181    "create a swap partition with a label",
3182    "\
3183 Create a swap partition on C<device> with label C<label>.
3184
3185 Note that you cannot attach a swap label to a block device
3186 (eg. C</dev/sda>), just to a partition.  This appears to be
3187 a limitation of the kernel or swap tools.");
3188
3189   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3190    (let uuid = uuidgen () in
3191     [InitEmpty, Always, TestRun (
3192        [["part_disk"; "/dev/sda"; "mbr"];
3193         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3194    "create a swap partition with an explicit UUID",
3195    "\
3196 Create a swap partition on C<device> with UUID C<uuid>.");
3197
3198   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3199    [InitBasicFS, Always, TestOutputStruct (
3200       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3201        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3202        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3203     InitBasicFS, Always, TestOutputStruct (
3204       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3205        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3206    "make block, character or FIFO devices",
3207    "\
3208 This call creates block or character special devices, or
3209 named pipes (FIFOs).
3210
3211 The C<mode> parameter should be the mode, using the standard
3212 constants.  C<devmajor> and C<devminor> are the
3213 device major and minor numbers, only used when creating block
3214 and character special devices.
3215
3216 Note that, just like L<mknod(2)>, the mode must be bitwise
3217 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3218 just creates a regular file).  These constants are
3219 available in the standard Linux header files, or you can use
3220 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3221 which are wrappers around this command which bitwise OR
3222 in the appropriate constant for you.
3223
3224 The mode actually set is affected by the umask.");
3225
3226   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3227    [InitBasicFS, Always, TestOutputStruct (
3228       [["mkfifo"; "0o777"; "/node"];
3229        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3230    "make FIFO (named pipe)",
3231    "\
3232 This call creates a FIFO (named pipe) called C<path> with
3233 mode C<mode>.  It is just a convenient wrapper around
3234 C<guestfs_mknod>.
3235
3236 The mode actually set is affected by the umask.");
3237
3238   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3239    [InitBasicFS, Always, TestOutputStruct (
3240       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3241        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3242    "make block device node",
3243    "\
3244 This call creates a block device node called C<path> with
3245 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3246 It is just a convenient wrapper around C<guestfs_mknod>.
3247
3248 The mode actually set is affected by the umask.");
3249
3250   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3251    [InitBasicFS, Always, TestOutputStruct (
3252       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3253        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3254    "make char device node",
3255    "\
3256 This call creates a char device node called C<path> with
3257 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3258 It is just a convenient wrapper around C<guestfs_mknod>.
3259
3260 The mode actually set is affected by the umask.");
3261
3262   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3263    [InitEmpty, Always, TestOutputInt (
3264       [["umask"; "0o22"]], 0o22)],
3265    "set file mode creation mask (umask)",
3266    "\
3267 This function sets the mask used for creating new files and
3268 device nodes to C<mask & 0777>.
3269
3270 Typical umask values would be C<022> which creates new files
3271 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3272 C<002> which creates new files with permissions like
3273 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3274
3275 The default umask is C<022>.  This is important because it
3276 means that directories and device nodes will be created with
3277 C<0644> or C<0755> mode even if you specify C<0777>.
3278
3279 See also C<guestfs_get_umask>,
3280 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3281
3282 This call returns the previous umask.");
3283
3284   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3285    [],
3286    "read directories entries",
3287    "\
3288 This returns the list of directory entries in directory C<dir>.
3289
3290 All entries in the directory are returned, including C<.> and
3291 C<..>.  The entries are I<not> sorted, but returned in the same
3292 order as the underlying filesystem.
3293
3294 Also this call returns basic file type information about each
3295 file.  The C<ftyp> field will contain one of the following characters:
3296
3297 =over 4
3298
3299 =item 'b'
3300
3301 Block special
3302
3303 =item 'c'
3304
3305 Char special
3306
3307 =item 'd'
3308
3309 Directory
3310
3311 =item 'f'
3312
3313 FIFO (named pipe)
3314
3315 =item 'l'
3316
3317 Symbolic link
3318
3319 =item 'r'
3320
3321 Regular file
3322
3323 =item 's'
3324
3325 Socket
3326
3327 =item 'u'
3328
3329 Unknown file type
3330
3331 =item '?'
3332
3333 The L<readdir(3)> call returned a C<d_type> field with an
3334 unexpected value
3335
3336 =back
3337
3338 This function is primarily intended for use by programs.  To
3339 get a simple list of names, use C<guestfs_ls>.  To get a printable
3340 directory for human consumption, use C<guestfs_ll>.");
3341
3342   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3343    [],
3344    "create partitions on a block device",
3345    "\
3346 This is a simplified interface to the C<guestfs_sfdisk>
3347 command, where partition sizes are specified in megabytes
3348 only (rounded to the nearest cylinder) and you don't need
3349 to specify the cyls, heads and sectors parameters which
3350 were rarely if ever used anyway.
3351
3352 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3353 and C<guestfs_part_disk>");
3354
3355   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3356    [],
3357    "determine file type inside a compressed file",
3358    "\
3359 This command runs C<file> after first decompressing C<path>
3360 using C<method>.
3361
3362 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3363
3364 Since 1.0.63, use C<guestfs_file> instead which can now
3365 process compressed files.");
3366
3367   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3368    [],
3369    "list extended attributes of a file or directory",
3370    "\
3371 This call lists the extended attributes of the file or directory
3372 C<path>.
3373
3374 At the system call level, this is a combination of the
3375 L<listxattr(2)> and L<getxattr(2)> calls.
3376
3377 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3378
3379   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3380    [],
3381    "list extended attributes of a file or directory",
3382    "\
3383 This is the same as C<guestfs_getxattrs>, but if C<path>
3384 is a symbolic link, then it returns the extended attributes
3385 of the link itself.");
3386
3387   ("setxattr", (RErr, [String "xattr";
3388                        String "val"; Int "vallen"; (* will be BufferIn *)
3389                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3390    [],
3391    "set extended attribute of a file or directory",
3392    "\
3393 This call sets the extended attribute named C<xattr>
3394 of the file C<path> to the value C<val> (of length C<vallen>).
3395 The value is arbitrary 8 bit data.
3396
3397 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3398
3399   ("lsetxattr", (RErr, [String "xattr";
3400                         String "val"; Int "vallen"; (* will be BufferIn *)
3401                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3402    [],
3403    "set extended attribute of a file or directory",
3404    "\
3405 This is the same as C<guestfs_setxattr>, but if C<path>
3406 is a symbolic link, then it sets an extended attribute
3407 of the link itself.");
3408
3409   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3410    [],
3411    "remove extended attribute of a file or directory",
3412    "\
3413 This call removes the extended attribute named C<xattr>
3414 of the file C<path>.
3415
3416 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3417
3418   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3419    [],
3420    "remove extended attribute of a file or directory",
3421    "\
3422 This is the same as C<guestfs_removexattr>, but if C<path>
3423 is a symbolic link, then it removes an extended attribute
3424 of the link itself.");
3425
3426   ("mountpoints", (RHashtable "mps", []), 147, [],
3427    [],
3428    "show mountpoints",
3429    "\
3430 This call is similar to C<guestfs_mounts>.  That call returns
3431 a list of devices.  This one returns a hash table (map) of
3432 device name to directory where the device is mounted.");
3433
3434   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3435    (* This is a special case: while you would expect a parameter
3436     * of type "Pathname", that doesn't work, because it implies
3437     * NEED_ROOT in the generated calling code in stubs.c, and
3438     * this function cannot use NEED_ROOT.
3439     *)
3440    [],
3441    "create a mountpoint",
3442    "\
3443 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3444 specialized calls that can be used to create extra mountpoints
3445 before mounting the first filesystem.
3446
3447 These calls are I<only> necessary in some very limited circumstances,
3448 mainly the case where you want to mount a mix of unrelated and/or
3449 read-only filesystems together.
3450
3451 For example, live CDs often contain a \"Russian doll\" nest of
3452 filesystems, an ISO outer layer, with a squashfs image inside, with
3453 an ext2/3 image inside that.  You can unpack this as follows
3454 in guestfish:
3455
3456  add-ro Fedora-11-i686-Live.iso
3457  run
3458  mkmountpoint /cd
3459  mkmountpoint /squash
3460  mkmountpoint /ext3
3461  mount /dev/sda /cd
3462  mount-loop /cd/LiveOS/squashfs.img /squash
3463  mount-loop /squash/LiveOS/ext3fs.img /ext3
3464
3465 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3466
3467   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3468    [],
3469    "remove a mountpoint",
3470    "\
3471 This calls removes a mountpoint that was previously created
3472 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3473 for full details.");
3474
3475   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3476    [InitISOFS, Always, TestOutputBuffer (
3477       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3478     (* Test various near large, large and too large files (RHBZ#589039). *)
3479     InitBasicFS, Always, TestLastFail (
3480       [["touch"; "/a"];
3481        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3482        ["read_file"; "/a"]]);
3483     InitBasicFS, Always, TestLastFail (
3484       [["touch"; "/a"];
3485        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3486        ["read_file"; "/a"]]);
3487     InitBasicFS, Always, TestLastFail (
3488       [["touch"; "/a"];
3489        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3490        ["read_file"; "/a"]])],
3491    "read a file",
3492    "\
3493 This calls returns the contents of the file C<path> as a
3494 buffer.
3495
3496 Unlike C<guestfs_cat>, this function can correctly
3497 handle files that contain embedded ASCII NUL characters.
3498 However unlike C<guestfs_download>, this function is limited
3499 in the total size of file that can be handled.");
3500
3501   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3502    [InitISOFS, Always, TestOutputList (
3503       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3504     InitISOFS, Always, TestOutputList (
3505       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3506     (* Test for RHBZ#579608, absolute symbolic links. *)
3507     InitISOFS, Always, TestOutputList (
3508       [["grep"; "nomatch"; "/abssymlink"]], [])],
3509    "return lines matching a pattern",
3510    "\
3511 This calls the external C<grep> program and returns the
3512 matching lines.");
3513
3514   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3515    [InitISOFS, Always, TestOutputList (
3516       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3517    "return lines matching a pattern",
3518    "\
3519 This calls the external C<egrep> program and returns the
3520 matching lines.");
3521
3522   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3523    [InitISOFS, Always, TestOutputList (
3524       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3525    "return lines matching a pattern",
3526    "\
3527 This calls the external C<fgrep> program and returns the
3528 matching lines.");
3529
3530   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3531    [InitISOFS, Always, TestOutputList (
3532       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3533    "return lines matching a pattern",
3534    "\
3535 This calls the external C<grep -i> program and returns the
3536 matching lines.");
3537
3538   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3539    [InitISOFS, Always, TestOutputList (
3540       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3541    "return lines matching a pattern",
3542    "\
3543 This calls the external C<egrep -i> program and returns the
3544 matching lines.");
3545
3546   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3547    [InitISOFS, Always, TestOutputList (
3548       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3549    "return lines matching a pattern",
3550    "\
3551 This calls the external C<fgrep -i> program and returns the
3552 matching lines.");
3553
3554   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3555    [InitISOFS, Always, TestOutputList (
3556       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3557    "return lines matching a pattern",
3558    "\
3559 This calls the external C<zgrep> program and returns the
3560 matching lines.");
3561
3562   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3563    [InitISOFS, Always, TestOutputList (
3564       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3565    "return lines matching a pattern",
3566    "\
3567 This calls the external C<zegrep> program and returns the
3568 matching lines.");
3569
3570   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3571    [InitISOFS, Always, TestOutputList (
3572       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3573    "return lines matching a pattern",
3574    "\
3575 This calls the external C<zfgrep> program and returns the
3576 matching lines.");
3577
3578   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3579    [InitISOFS, Always, TestOutputList (
3580       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3581    "return lines matching a pattern",
3582    "\
3583 This calls the external C<zgrep -i> program and returns the
3584 matching lines.");
3585
3586   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3587    [InitISOFS, Always, TestOutputList (
3588       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3589    "return lines matching a pattern",
3590    "\
3591 This calls the external C<zegrep -i> program and returns the
3592 matching lines.");
3593
3594   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3595    [InitISOFS, Always, TestOutputList (
3596       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3597    "return lines matching a pattern",
3598    "\
3599 This calls the external C<zfgrep -i> program and returns the
3600 matching lines.");
3601
3602   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3603    [InitISOFS, Always, TestOutput (
3604       [["realpath"; "/../directory"]], "/directory")],
3605    "canonicalized absolute pathname",
3606    "\
3607 Return the canonicalized absolute pathname of C<path>.  The
3608 returned path has no C<.>, C<..> or symbolic link path elements.");
3609
3610   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3611    [InitBasicFS, Always, TestOutputStruct (
3612       [["touch"; "/a"];
3613        ["ln"; "/a"; "/b"];
3614        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3615    "create a hard link",
3616    "\
3617 This command creates a hard link using the C<ln> command.");
3618
3619   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3620    [InitBasicFS, Always, TestOutputStruct (
3621       [["touch"; "/a"];
3622        ["touch"; "/b"];
3623        ["ln_f"; "/a"; "/b"];
3624        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3625    "create a hard link",
3626    "\
3627 This command creates a hard link using the C<ln -f> command.
3628 The C<-f> option removes the link (C<linkname>) if it exists already.");
3629
3630   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3631    [InitBasicFS, Always, TestOutputStruct (
3632       [["touch"; "/a"];
3633        ["ln_s"; "a"; "/b"];
3634        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3635    "create a symbolic link",
3636    "\
3637 This command creates a symbolic link using the C<ln -s> command.");
3638
3639   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3640    [InitBasicFS, Always, TestOutput (
3641       [["mkdir_p"; "/a/b"];
3642        ["touch"; "/a/b/c"];
3643        ["ln_sf"; "../d"; "/a/b/c"];
3644        ["readlink"; "/a/b/c"]], "../d")],
3645    "create a symbolic link",
3646    "\
3647 This command creates a symbolic link using the C<ln -sf> command,
3648 The C<-f> option removes the link (C<linkname>) if it exists already.");
3649
3650   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3651    [] (* XXX tested above *),
3652    "read the target of a symbolic link",
3653    "\
3654 This command reads the target of a symbolic link.");
3655
3656   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3657    [InitBasicFS, Always, TestOutputStruct (
3658       [["fallocate"; "/a"; "1000000"];
3659        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3660    "preallocate a file in the guest filesystem",
3661    "\
3662 This command preallocates a file (containing zero bytes) named
3663 C<path> of size C<len> bytes.  If the file exists already, it
3664 is overwritten.
3665
3666 Do not confuse this with the guestfish-specific
3667 C<alloc> command which allocates a file in the host and
3668 attaches it as a device.");
3669
3670   ("swapon_device", (RErr, [Device "device"]), 170, [],
3671    [InitPartition, Always, TestRun (
3672       [["mkswap"; "/dev/sda1"];
3673        ["swapon_device"; "/dev/sda1"];
3674        ["swapoff_device"; "/dev/sda1"]])],
3675    "enable swap on device",
3676    "\
3677 This command enables the libguestfs appliance to use the
3678 swap device or partition named C<device>.  The increased
3679 memory is made available for all commands, for example
3680 those run using C<guestfs_command> or C<guestfs_sh>.
3681
3682 Note that you should not swap to existing guest swap
3683 partitions unless you know what you are doing.  They may
3684 contain hibernation information, or other information that
3685 the guest doesn't want you to trash.  You also risk leaking
3686 information about the host to the guest this way.  Instead,
3687 attach a new host device to the guest and swap on that.");
3688
3689   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3690    [], (* XXX tested by swapon_device *)
3691    "disable swap on device",
3692    "\
3693 This command disables the libguestfs appliance swap
3694 device or partition named C<device>.
3695 See C<guestfs_swapon_device>.");
3696
3697   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3698    [InitBasicFS, Always, TestRun (
3699       [["fallocate"; "/swap"; "8388608"];
3700        ["mkswap_file"; "/swap"];
3701        ["swapon_file"; "/swap"];
3702        ["swapoff_file"; "/swap"]])],
3703    "enable swap on file",
3704    "\
3705 This command enables swap to a file.
3706 See C<guestfs_swapon_device> for other notes.");
3707
3708   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3709    [], (* XXX tested by swapon_file *)
3710    "disable swap on file",
3711    "\
3712 This command disables the libguestfs appliance swap on file.");
3713
3714   ("swapon_label", (RErr, [String "label"]), 174, [],
3715    [InitEmpty, Always, TestRun (
3716       [["part_disk"; "/dev/sdb"; "mbr"];
3717        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3718        ["swapon_label"; "swapit"];
3719        ["swapoff_label"; "swapit"];
3720        ["zero"; "/dev/sdb"];
3721        ["blockdev_rereadpt"; "/dev/sdb"]])],
3722    "enable swap on labeled swap partition",
3723    "\
3724 This command enables swap to a labeled swap partition.
3725 See C<guestfs_swapon_device> for other notes.");
3726
3727   ("swapoff_label", (RErr, [String "label"]), 175, [],
3728    [], (* XXX tested by swapon_label *)
3729    "disable swap on labeled swap partition",
3730    "\
3731 This command disables the libguestfs appliance swap on
3732 labeled swap partition.");
3733
3734   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3735    (let uuid = uuidgen () in
3736     [InitEmpty, Always, TestRun (
3737        [["mkswap_U"; uuid; "/dev/sdb"];
3738         ["swapon_uuid"; uuid];
3739         ["swapoff_uuid"; uuid]])]),
3740    "enable swap on swap partition by UUID",
3741    "\
3742 This command enables swap to a swap partition with the given UUID.
3743 See C<guestfs_swapon_device> for other notes.");
3744
3745   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3746    [], (* XXX tested by swapon_uuid *)
3747    "disable swap on swap partition by UUID",
3748    "\
3749 This command disables the libguestfs appliance swap partition
3750 with the given UUID.");
3751
3752   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3753    [InitBasicFS, Always, TestRun (
3754       [["fallocate"; "/swap"; "8388608"];
3755        ["mkswap_file"; "/swap"]])],
3756    "create a swap file",
3757    "\
3758 Create a swap file.
3759
3760 This command just writes a swap file signature to an existing
3761 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3762
3763   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3764    [InitISOFS, Always, TestRun (
3765       [["inotify_init"; "0"]])],
3766    "create an inotify handle",
3767    "\
3768 This command creates a new inotify handle.
3769 The inotify subsystem can be used to notify events which happen to
3770 objects in the guest filesystem.
3771
3772 C<maxevents> is the maximum number of events which will be
3773 queued up between calls to C<guestfs_inotify_read> or
3774 C<guestfs_inotify_files>.
3775 If this is passed as C<0>, then the kernel (or previously set)
3776 default is used.  For Linux 2.6.29 the default was 16384 events.
3777 Beyond this limit, the kernel throws away events, but records
3778 the fact that it threw them away by setting a flag
3779 C<IN_Q_OVERFLOW> in the returned structure list (see
3780 C<guestfs_inotify_read>).
3781
3782 Before any events are generated, you have to add some
3783 watches to the internal watch list.  See:
3784 C<guestfs_inotify_add_watch>,
3785 C<guestfs_inotify_rm_watch> and
3786 C<guestfs_inotify_watch_all>.
3787
3788 Queued up events should be read periodically by calling
3789 C<guestfs_inotify_read>
3790 (or C<guestfs_inotify_files> which is just a helpful
3791 wrapper around C<guestfs_inotify_read>).  If you don't
3792 read the events out often enough then you risk the internal
3793 queue overflowing.
3794
3795 The handle should be closed after use by calling
3796 C<guestfs_inotify_close>.  This also removes any
3797 watches automatically.
3798
3799 See also L<inotify(7)> for an overview of the inotify interface
3800 as exposed by the Linux kernel, which is roughly what we expose
3801 via libguestfs.  Note that there is one global inotify handle
3802 per libguestfs instance.");
3803
3804   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3805    [InitBasicFS, Always, TestOutputList (
3806       [["inotify_init"; "0"];
3807        ["inotify_add_watch"; "/"; "1073741823"];
3808        ["touch"; "/a"];
3809        ["touch"; "/b"];
3810        ["inotify_files"]], ["a"; "b"])],
3811    "add an inotify watch",
3812    "\
3813 Watch C<path> for the events listed in C<mask>.
3814
3815 Note that if C<path> is a directory then events within that
3816 directory are watched, but this does I<not> happen recursively
3817 (in subdirectories).
3818
3819 Note for non-C or non-Linux callers: the inotify events are
3820 defined by the Linux kernel ABI and are listed in
3821 C</usr/include/sys/inotify.h>.");
3822
3823   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3824    [],
3825    "remove an inotify watch",
3826    "\
3827 Remove a previously defined inotify watch.
3828 See C<guestfs_inotify_add_watch>.");
3829
3830   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3831    [],
3832    "return list of inotify events",
3833    "\
3834 Return the complete queue of events that have happened
3835 since the previous read call.
3836
3837 If no events have happened, this returns an empty list.
3838
3839 I<Note>: In order to make sure that all events have been
3840 read, you must call this function repeatedly until it
3841 returns an empty list.  The reason is that the call will
3842 read events up to the maximum appliance-to-host message
3843 size and leave remaining events in the queue.");
3844
3845   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3846    [],
3847    "return list of watched files that had events",
3848    "\
3849 This function is a helpful wrapper around C<guestfs_inotify_read>
3850 which just returns a list of pathnames of objects that were
3851 touched.  The returned pathnames are sorted and deduplicated.");
3852
3853   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3854    [],
3855    "close the inotify handle",
3856    "\
3857 This closes the inotify handle which was previously
3858 opened by inotify_init.  It removes all watches, throws
3859 away any pending events, and deallocates all resources.");
3860
3861   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3862    [],
3863    "set SELinux security context",
3864    "\
3865 This sets the SELinux security context of the daemon
3866 to the string C<context>.
3867
3868 See the documentation about SELINUX in L<guestfs(3)>.");
3869
3870   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3871    [],
3872    "get SELinux security context",
3873    "\
3874 This gets the SELinux security context of the daemon.
3875
3876 See the documentation about SELINUX in L<guestfs(3)>,
3877 and C<guestfs_setcon>");
3878
3879   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3880    [InitEmpty, Always, TestOutput (
3881       [["part_disk"; "/dev/sda"; "mbr"];
3882        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3883        ["mount_options"; ""; "/dev/sda1"; "/"];
3884        ["write"; "/new"; "new file contents"];
3885        ["cat"; "/new"]], "new file contents");
3886     InitEmpty, Always, TestRun (
3887       [["part_disk"; "/dev/sda"; "mbr"];
3888        ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3889     InitEmpty, Always, TestLastFail (
3890       [["part_disk"; "/dev/sda"; "mbr"];
3891        ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3892     InitEmpty, Always, TestLastFail (
3893       [["part_disk"; "/dev/sda"; "mbr"];
3894        ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3895     InitEmpty, IfAvailable "ntfsprogs", TestRun (
3896       [["part_disk"; "/dev/sda"; "mbr"];
3897        ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3898    "make a filesystem with block size",
3899    "\
3900 This call is similar to C<guestfs_mkfs>, but it allows you to
3901 control the block size of the resulting filesystem.  Supported
3902 block sizes depend on the filesystem type, but typically they
3903 are C<1024>, C<2048> or C<4096> only.
3904
3905 For VFAT and NTFS the C<blocksize> parameter is treated as
3906 the requested cluster size.");
3907
3908   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3909    [InitEmpty, Always, TestOutput (
3910       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3911        ["mke2journal"; "4096"; "/dev/sda1"];
3912        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3913        ["mount_options"; ""; "/dev/sda2"; "/"];
3914        ["write"; "/new"; "new file contents"];
3915        ["cat"; "/new"]], "new file contents")],
3916    "make ext2/3/4 external journal",
3917    "\
3918 This creates an ext2 external journal on C<device>.  It is equivalent
3919 to the command:
3920
3921  mke2fs -O journal_dev -b blocksize device");
3922
3923   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3924    [InitEmpty, Always, TestOutput (
3925       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3926        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3927        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3928        ["mount_options"; ""; "/dev/sda2"; "/"];
3929        ["write"; "/new"; "new file contents"];
3930        ["cat"; "/new"]], "new file contents")],
3931    "make ext2/3/4 external journal with label",
3932    "\
3933 This creates an ext2 external journal on C<device> with label C<label>.");
3934
3935   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3936    (let uuid = uuidgen () in
3937     [InitEmpty, Always, TestOutput (
3938        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3939         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3940         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3941         ["mount_options"; ""; "/dev/sda2"; "/"];
3942         ["write"; "/new"; "new file contents"];
3943         ["cat"; "/new"]], "new file contents")]),
3944    "make ext2/3/4 external journal with UUID",
3945    "\
3946 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3947
3948   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3949    [],
3950    "make ext2/3/4 filesystem with external journal",
3951    "\
3952 This creates an ext2/3/4 filesystem on C<device> with
3953 an external journal on C<journal>.  It is equivalent
3954 to the command:
3955
3956  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3957
3958 See also C<guestfs_mke2journal>.");
3959
3960   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3961    [],
3962    "make ext2/3/4 filesystem with external journal",
3963    "\
3964 This creates an ext2/3/4 filesystem on C<device> with
3965 an external journal on the journal labeled C<label>.
3966
3967 See also C<guestfs_mke2journal_L>.");
3968
3969   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3970    [],
3971    "make ext2/3/4 filesystem with external journal",
3972    "\
3973 This creates an ext2/3/4 filesystem on C<device> with
3974 an external journal on the journal with UUID C<uuid>.
3975
3976 See also C<guestfs_mke2journal_U>.");
3977
3978   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3979    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3980    "load a kernel module",
3981    "\
3982 This loads a kernel module in the appliance.
3983
3984 The kernel module must have been whitelisted when libguestfs
3985 was built (see C<appliance/kmod.whitelist.in> in the source).");
3986
3987   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3988    [InitNone, Always, TestOutput (
3989       [["echo_daemon"; "This is a test"]], "This is a test"
3990     )],
3991    "echo arguments back to the client",
3992    "\
3993 This command concatenates the list of C<words> passed with single spaces
3994 between them and returns the resulting string.
3995
3996 You can use this command to test the connection through to the daemon.
3997
3998 See also C<guestfs_ping_daemon>.");
3999
4000   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
4001    [], (* There is a regression test for this. *)
4002    "find all files and directories, returning NUL-separated list",
4003    "\
4004 This command lists out all files and directories, recursively,
4005 starting at C<directory>, placing the resulting list in the
4006 external file called C<files>.
4007
4008 This command works the same way as C<guestfs_find> with the
4009 following exceptions:
4010
4011 =over 4
4012
4013 =item *
4014
4015 The resulting list is written to an external file.
4016
4017 =item *
4018
4019 Items (filenames) in the result are separated
4020 by C<\\0> characters.  See L<find(1)> option I<-print0>.
4021
4022 =item *
4023
4024 This command is not limited in the number of names that it
4025 can return.
4026
4027 =item *
4028
4029 The result list is not sorted.
4030
4031 =back");
4032
4033   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
4034    [InitISOFS, Always, TestOutput (
4035       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
4036     InitISOFS, Always, TestOutput (
4037       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
4038     InitISOFS, Always, TestOutput (
4039       [["case_sensitive_path"; "/Known-1"]], "/known-1");
4040     InitISOFS, Always, TestLastFail (
4041       [["case_sensitive_path"; "/Known-1/"]]);
4042     InitBasicFS, Always, TestOutput (
4043       [["mkdir"; "/a"];
4044        ["mkdir"; "/a/bbb"];
4045        ["touch"; "/a/bbb/c"];
4046        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
4047     InitBasicFS, Always, TestOutput (
4048       [["mkdir"; "/a"];
4049        ["mkdir"; "/a/bbb"];
4050        ["touch"; "/a/bbb/c"];
4051        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
4052     InitBasicFS, Always, TestLastFail (
4053       [["mkdir"; "/a"];
4054        ["mkdir"; "/a/bbb"];
4055        ["touch"; "/a/bbb/c"];
4056        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
4057    "return true path on case-insensitive filesystem",
4058    "\
4059 This can be used to resolve case insensitive paths on
4060 a filesystem which is case sensitive.  The use case is
4061 to resolve paths which you have read from Windows configuration
4062 files or the Windows Registry, to the true path.
4063
4064 The command handles a peculiarity of the Linux ntfs-3g
4065 filesystem driver (and probably others), which is that although
4066 the underlying filesystem is case-insensitive, the driver
4067 exports the filesystem to Linux as case-sensitive.
4068
4069 One consequence of this is that special directories such
4070 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
4071 (or other things) depending on the precise details of how
4072 they were created.  In Windows itself this would not be
4073 a problem.
4074
4075 Bug or feature?  You decide:
4076 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
4077
4078 This function resolves the true case of each element in the
4079 path and returns the case-sensitive path.
4080
4081 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
4082 might return C<\"/WINDOWS/system32\"> (the exact return value
4083 would depend on details of how the directories were originally
4084 created under Windows).
4085
4086 I<Note>:
4087 This function does not handle drive names, backslashes etc.
4088
4089 See also C<guestfs_realpath>.");
4090
4091   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
4092    [InitBasicFS, Always, TestOutput (
4093       [["vfs_type"; "/dev/sda1"]], "ext2")],
4094    "get the Linux VFS type corresponding to a mounted device",
4095    "\
4096 This command gets the filesystem type corresponding to
4097 the filesystem on C<device>.
4098
4099 For most filesystems, the result is the name of the Linux
4100 VFS module which would be used to mount this filesystem
4101 if you mounted it without specifying the filesystem type.
4102 For example a string such as C<ext3> or C<ntfs>.");
4103
4104   ("truncate", (RErr, [Pathname "path"]), 199, [],
4105    [InitBasicFS, Always, TestOutputStruct (
4106       [["write"; "/test"; "some stuff so size is not zero"];
4107        ["truncate"; "/test"];
4108        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
4109    "truncate a file to zero size",
4110    "\
4111 This command truncates C<path> to a zero-length file.  The
4112 file must exist already.");
4113
4114   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
4115    [InitBasicFS, Always, TestOutputStruct (
4116       [["touch"; "/test"];
4117        ["truncate_size"; "/test"; "1000"];
4118        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
4119    "truncate a file to a particular size",
4120    "\
4121 This command truncates C<path> to size C<size> bytes.  The file
4122 must exist already.
4123
4124 If the current file size is less than C<size> then
4125 the file is extended to the required size with zero bytes.
4126 This creates a sparse file (ie. disk blocks are not allocated
4127 for the file until you write to it).  To create a non-sparse
4128 file of zeroes, use C<guestfs_fallocate64> instead.");
4129
4130   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
4131    [InitBasicFS, Always, TestOutputStruct (
4132       [["touch"; "/test"];
4133        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
4134        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
4135    "set timestamp of a file with nanosecond precision",
4136    "\
4137 This command sets the timestamps of a file with nanosecond
4138 precision.
4139
4140 C<atsecs, atnsecs> are the last access time (atime) in secs and
4141 nanoseconds from the epoch.
4142
4143 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4144 secs and nanoseconds from the epoch.
4145
4146 If the C<*nsecs> field contains the special value C<-1> then
4147 the corresponding timestamp is set to the current time.  (The
4148 C<*secs> field is ignored in this case).
4149
4150 If the C<*nsecs> field contains the special value C<-2> then
4151 the corresponding timestamp is left unchanged.  (The
4152 C<*secs> field is ignored in this case).");
4153
4154   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4155    [InitBasicFS, Always, TestOutputStruct (
4156       [["mkdir_mode"; "/test"; "0o111"];
4157        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4158    "create a directory with a particular mode",
4159    "\
4160 This command creates a directory, setting the initial permissions
4161 of the directory to C<mode>.
4162
4163 For common Linux filesystems, the actual mode which is set will
4164 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
4165 interpret the mode in other ways.
4166
4167 See also C<guestfs_mkdir>, C<guestfs_umask>");
4168
4169   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4170    [], (* XXX *)
4171    "change file owner and group",
4172    "\
4173 Change the file owner to C<owner> and group to C<group>.
4174 This is like C<guestfs_chown> but if C<path> is a symlink then
4175 the link itself is changed, not the target.
4176
4177 Only numeric uid and gid are supported.  If you want to use
4178 names, you will need to locate and parse the password file
4179 yourself (Augeas support makes this relatively easy).");
4180
4181   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4182    [], (* XXX *)
4183    "lstat on multiple files",
4184    "\
4185 This call allows you to perform the C<guestfs_lstat> operation
4186 on multiple files, where all files are in the directory C<path>.
4187 C<names> is the list of files from this directory.
4188
4189 On return you get a list of stat structs, with a one-to-one
4190 correspondence to the C<names> list.  If any name did not exist
4191 or could not be lstat'd, then the C<ino> field of that structure
4192 is set to C<-1>.
4193
4194 This call is intended for programs that want to efficiently
4195 list a directory contents without making many round-trips.
4196 See also C<guestfs_lxattrlist> for a similarly efficient call
4197 for getting extended attributes.  Very long directory listings
4198 might cause the protocol message size to be exceeded, causing
4199 this call to fail.  The caller must split up such requests
4200 into smaller groups of names.");
4201
4202   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4203    [], (* XXX *)
4204    "lgetxattr on multiple files",
4205    "\
4206 This call allows you to get the extended attributes
4207 of multiple files, where all files are in the directory C<path>.
4208 C<names> is the list of files from this directory.
4209
4210 On return you get a flat list of xattr structs which must be
4211 interpreted sequentially.  The first xattr struct always has a zero-length
4212 C<attrname>.  C<attrval> in this struct is zero-length
4213 to indicate there was an error doing C<lgetxattr> for this
4214 file, I<or> is a C string which is a decimal number
4215 (the number of following attributes for this file, which could
4216 be C<\"0\">).  Then after the first xattr struct are the
4217 zero or more attributes for the first named file.
4218 This repeats for the second and subsequent files.
4219
4220 This call is intended for programs that want to efficiently
4221 list a directory contents without making many round-trips.
4222 See also C<guestfs_lstatlist> for a similarly efficient call
4223 for getting standard stats.  Very long directory listings
4224 might cause the protocol message size to be exceeded, causing
4225 this call to fail.  The caller must split up such requests
4226 into smaller groups of names.");
4227
4228   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4229    [], (* XXX *)
4230    "readlink on multiple files",
4231    "\
4232 This call allows you to do a C<readlink> operation
4233 on multiple files, where all files are in the directory C<path>.
4234 C<names> is the list of files from this directory.
4235
4236 On return you get a list of strings, with a one-to-one
4237 correspondence to the C<names> list.  Each string is the
4238 value of the symbolic link.
4239
4240 If the C<readlink(2)> operation fails on any name, then
4241 the corresponding result string is the empty string C<\"\">.
4242 However the whole operation is completed even if there
4243 were C<readlink(2)> errors, and so you can call this
4244 function with names where you don't know if they are
4245 symbolic links already (albeit slightly less efficient).
4246
4247 This call is intended for programs that want to efficiently
4248 list a directory contents without making many round-trips.
4249 Very long directory listings might cause the protocol
4250 message size to be exceeded, causing
4251 this call to fail.  The caller must split up such requests
4252 into smaller groups of names.");
4253
4254   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4255    [InitISOFS, Always, TestOutputBuffer (
4256       [["pread"; "/known-4"; "1"; "3"]], "\n");
4257     InitISOFS, Always, TestOutputBuffer (
4258       [["pread"; "/empty"; "0"; "100"]], "")],
4259    "read part of a file",
4260    "\
4261 This command lets you read part of a file.  It reads C<count>
4262 bytes of the file, starting at C<offset>, from file C<path>.
4263
4264 This may read fewer bytes than requested.  For further details
4265 see the L<pread(2)> system call.
4266
4267 See also C<guestfs_pwrite>.");
4268
4269   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4270    [InitEmpty, Always, TestRun (
4271       [["part_init"; "/dev/sda"; "gpt"]])],
4272    "create an empty partition table",
4273    "\
4274 This creates an empty partition table on C<device> of one of the
4275 partition types listed below.  Usually C<parttype> should be
4276 either C<msdos> or C<gpt> (for large disks).
4277
4278 Initially there are no partitions.  Following this, you should
4279 call C<guestfs_part_add> for each partition required.
4280
4281 Possible values for C<parttype> are:
4282
4283 =over 4
4284
4285 =item B<efi> | B<gpt>
4286
4287 Intel EFI / GPT partition table.
4288
4289 This is recommended for >= 2 TB partitions that will be accessed
4290 from Linux and Intel-based Mac OS X.  It also has limited backwards
4291 compatibility with the C<mbr> format.
4292
4293 =item B<mbr> | B<msdos>
4294
4295 The standard PC \"Master Boot Record\" (MBR) format used
4296 by MS-DOS and Windows.  This partition type will B<only> work
4297 for device sizes up to 2 TB.  For large disks we recommend
4298 using C<gpt>.
4299
4300 =back
4301
4302 Other partition table types that may work but are not
4303 supported include:
4304
4305 =over 4
4306
4307 =item B<aix>
4308
4309 AIX disk labels.
4310
4311 =item B<amiga> | B<rdb>
4312
4313 Amiga \"Rigid Disk Block\" format.
4314
4315 =item B<bsd>
4316
4317 BSD disk labels.
4318
4319 =item B<dasd>
4320
4321 DASD, used on IBM mainframes.
4322
4323 =item B<dvh>
4324
4325 MIPS/SGI volumes.
4326
4327 =item B<mac>
4328
4329 Old Mac partition format.  Modern Macs use C<gpt>.
4330
4331 =item B<pc98>
4332
4333 NEC PC-98 format, common in Japan apparently.
4334
4335 =item B<sun>
4336
4337 Sun disk labels.
4338
4339 =back");
4340
4341   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4342    [InitEmpty, Always, TestRun (
4343       [["part_init"; "/dev/sda"; "mbr"];
4344        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4345     InitEmpty, Always, TestRun (
4346       [["part_init"; "/dev/sda"; "gpt"];
4347        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4348        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4349     InitEmpty, Always, TestRun (
4350       [["part_init"; "/dev/sda"; "mbr"];
4351        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4352        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4353        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4354        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4355    "add a partition to the device",
4356    "\
4357 This command adds a partition to C<device>.  If there is no partition
4358 table on the device, call C<guestfs_part_init> first.
4359
4360 The C<prlogex> parameter is the type of partition.  Normally you
4361 should pass C<p> or C<primary> here, but MBR partition tables also
4362 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4363 types.
4364
4365 C<startsect> and C<endsect> are the start and end of the partition
4366 in I<sectors>.  C<endsect> may be negative, which means it counts
4367 backwards from the end of the disk (C<-1> is the last sector).
4368
4369 Creating a partition which covers the whole disk is not so easy.
4370 Use C<guestfs_part_disk> to do that.");
4371
4372   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4373    [InitEmpty, Always, TestRun (
4374       [["part_disk"; "/dev/sda"; "mbr"]]);
4375     InitEmpty, Always, TestRun (
4376       [["part_disk"; "/dev/sda"; "gpt"]])],
4377    "partition whole disk with a single primary partition",
4378    "\
4379 This command is simply a combination of C<guestfs_part_init>
4380 followed by C<guestfs_part_add> to create a single primary partition
4381 covering the whole disk.
4382
4383 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4384 but other possible values are described in C<guestfs_part_init>.");
4385
4386   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4387    [InitEmpty, Always, TestRun (
4388       [["part_disk"; "/dev/sda"; "mbr"];
4389        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4390    "make a partition bootable",
4391    "\
4392 This sets the bootable flag on partition numbered C<partnum> on
4393 device C<device>.  Note that partitions are numbered from 1.
4394
4395 The bootable flag is used by some operating systems (notably
4396 Windows) to determine which partition to boot from.  It is by
4397 no means universally recognized.");
4398
4399   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4400    [InitEmpty, Always, TestRun (
4401       [["part_disk"; "/dev/sda"; "gpt"];
4402        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4403    "set partition name",
4404    "\
4405 This sets the partition name on partition numbered C<partnum> on
4406 device C<device>.  Note that partitions are numbered from 1.
4407
4408 The partition name can only be set on certain types of partition
4409 table.  This works on C<gpt> but not on C<mbr> partitions.");
4410
4411   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4412    [], (* XXX Add a regression test for this. *)
4413    "list partitions on a device",
4414    "\
4415 This command parses the partition table on C<device> and
4416 returns the list of partitions found.
4417
4418 The fields in the returned structure are:
4419
4420 =over 4
4421
4422 =item B<part_num>
4423
4424 Partition number, counting from 1.
4425
4426 =item B<part_start>
4427
4428 Start of the partition I<in bytes>.  To get sectors you have to
4429 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4430
4431 =item B<part_end>
4432
4433 End of the partition in bytes.
4434
4435 =item B<part_size>
4436
4437 Size of the partition in bytes.
4438
4439 =back");
4440
4441   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4442    [InitEmpty, Always, TestOutput (
4443       [["part_disk"; "/dev/sda"; "gpt"];
4444        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4445    "get the partition table type",
4446    "\
4447 This command examines the partition table on C<device> and
4448 returns the partition table type (format) being used.
4449
4450 Common return values include: C<msdos> (a DOS/Windows style MBR
4451 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4452 values are possible, although unusual.  See C<guestfs_part_init>
4453 for a full list.");
4454
4455   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4456    [InitBasicFS, Always, TestOutputBuffer (
4457       [["fill"; "0x63"; "10"; "/test"];
4458        ["read_file"; "/test"]], "cccccccccc")],
4459    "fill a file with octets",
4460    "\
4461 This command creates a new file called C<path>.  The initial
4462 content of the file is C<len> octets of C<c>, where C<c>
4463 must be a number in the range C<[0..255]>.
4464
4465 To fill a file with zero bytes (sparsely), it is
4466 much more efficient to use C<guestfs_truncate_size>.
4467 To create a file with a pattern of repeating bytes
4468 use C<guestfs_fill_pattern>.");
4469
4470   ("available", (RErr, [StringList "groups"]), 216, [],
4471    [InitNone, Always, TestRun [["available"; ""]]],
4472    "test availability of some parts of the API",
4473    "\
4474 This command is used to check the availability of some
4475 groups of functionality in the appliance, which not all builds of
4476 the libguestfs appliance will be able to provide.
4477
4478 The libguestfs groups, and the functions that those
4479 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4480 You can also fetch this list at runtime by calling
4481 C<guestfs_available_all_groups>.
4482
4483 The argument C<groups> is a list of group names, eg:
4484 C<[\"inotify\", \"augeas\"]> would check for the availability of
4485 the Linux inotify functions and Augeas (configuration file
4486 editing) functions.
4487
4488 The command returns no error if I<all> requested groups are available.
4489
4490 It fails with an error if one or more of the requested
4491 groups is unavailable in the appliance.
4492
4493 If an unknown group name is included in the
4494 list of groups then an error is always returned.
4495
4496 I<Notes:>
4497
4498 =over 4
4499
4500 =item *
4501
4502 You must call C<guestfs_launch> before calling this function.
4503
4504 The reason is because we don't know what groups are
4505 supported by the appliance/daemon until it is running and can
4506 be queried.
4507
4508 =item *
4509
4510 If a group of functions is available, this does not necessarily
4511 mean that they will work.  You still have to check for errors
4512 when calling individual API functions even if they are
4513 available.
4514
4515 =item *
4516
4517 It is usually the job of distro packagers to build
4518 complete functionality into the libguestfs appliance.
4519 Upstream libguestfs, if built from source with all
4520 requirements satisfied, will support everything.
4521
4522 =item *
4523
4524 This call was added in version C<1.0.80>.  In previous
4525 versions of libguestfs all you could do would be to speculatively
4526 execute a command to find out if the daemon implemented it.
4527 See also C<guestfs_version>.
4528
4529 =back");
4530
4531   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4532    [InitBasicFS, Always, TestOutputBuffer (
4533       [["write"; "/src"; "hello, world"];
4534        ["dd"; "/src"; "/dest"];
4535        ["read_file"; "/dest"]], "hello, world")],
4536    "copy from source to destination using dd",
4537    "\
4538 This command copies from one source device or file C<src>
4539 to another destination device or file C<dest>.  Normally you
4540 would use this to copy to or from a device or partition, for
4541 example to duplicate a filesystem.
4542
4543 If the destination is a device, it must be as large or larger
4544 than the source file or device, otherwise the copy will fail.
4545 This command cannot do partial copies (see C<guestfs_copy_size>).");
4546
4547   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4548    [InitBasicFS, Always, TestOutputInt (
4549       [["write"; "/file"; "hello, world"];
4550        ["filesize"; "/file"]], 12)],
4551    "return the size of the file in bytes",
4552    "\
4553 This command returns the size of C<file> in bytes.
4554
4555 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4556 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4557 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4558
4559   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4560    [InitBasicFSonLVM, Always, TestOutputList (
4561       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4562        ["lvs"]], ["/dev/VG/LV2"])],
4563    "rename an LVM logical volume",
4564    "\
4565 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4566
4567   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4568    [InitBasicFSonLVM, Always, TestOutputList (
4569       [["umount"; "/"];
4570        ["vg_activate"; "false"; "VG"];
4571        ["vgrename"; "VG"; "VG2"];
4572        ["vg_activate"; "true"; "VG2"];
4573        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4574        ["vgs"]], ["VG2"])],
4575    "rename an LVM volume group",
4576    "\
4577 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4578
4579   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4580    [InitISOFS, Always, TestOutputBuffer (
4581       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4582    "list the contents of a single file in an initrd",
4583    "\
4584 This command unpacks the file C<filename> from the initrd file
4585 called C<initrdpath>.  The filename must be given I<without> the
4586 initial C</> character.
4587
4588 For example, in guestfish you could use the following command
4589 to examine the boot script (usually called C</init>)
4590 contained in a Linux initrd or initramfs image:
4591
4592  initrd-cat /boot/initrd-<version>.img init
4593
4594 See also C<guestfs_initrd_list>.");
4595
4596   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4597    [],
4598    "get the UUID of a physical volume",
4599    "\
4600 This command returns the UUID of the LVM PV C<device>.");
4601
4602   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4603    [],
4604    "get the UUID of a volume group",
4605    "\
4606 This command returns the UUID of the LVM VG named C<vgname>.");
4607
4608   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4609    [],
4610    "get the UUID of a logical volume",
4611    "\
4612 This command returns the UUID of the LVM LV C<device>.");
4613
4614   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4615    [],
4616    "get the PV UUIDs containing the volume group",
4617    "\
4618 Given a VG called C<vgname>, this returns the UUIDs of all
4619 the physical volumes that this volume group resides on.
4620
4621 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4622 calls to associate physical volumes and volume groups.
4623
4624 See also C<guestfs_vglvuuids>.");
4625
4626   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4627    [],
4628    "get the LV UUIDs of all LVs in the volume group",
4629    "\
4630 Given a VG called C<vgname>, this returns the UUIDs of all
4631 the logical volumes created in this volume group.
4632
4633 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4634 calls to associate logical volumes and volume groups.
4635
4636 See also C<guestfs_vgpvuuids>.");
4637
4638   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4639    [InitBasicFS, Always, TestOutputBuffer (
4640       [["write"; "/src"; "hello, world"];
4641        ["copy_size"; "/src"; "/dest"; "5"];
4642        ["read_file"; "/dest"]], "hello")],
4643    "copy size bytes from source to destination using dd",
4644    "\
4645 This command copies exactly C<size> bytes from one source device
4646 or file C<src> to another destination device or file C<dest>.
4647
4648 Note this will fail if the source is too short or if the destination
4649 is not large enough.");
4650
4651   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4652    [InitBasicFSonLVM, Always, TestRun (
4653       [["zero_device"; "/dev/VG/LV"]])],
4654    "write zeroes to an entire device",
4655    "\
4656 This command writes zeroes over the entire C<device>.  Compare
4657 with C<guestfs_zero> which just zeroes the first few blocks of
4658 a device.");
4659
4660   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4661    [InitBasicFS, Always, TestOutput (
4662       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4663        ["cat"; "/hello"]], "hello\n")],
4664    "unpack compressed tarball to directory",
4665    "\
4666 This command uploads and unpacks local file C<tarball> (an
4667 I<xz compressed> tar file) into C<directory>.");
4668
4669   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4670    [],
4671    "pack directory into compressed tarball",
4672    "\
4673 This command packs the contents of C<directory> and downloads
4674 it to local file C<tarball> (as an xz compressed tar archive).");
4675
4676   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4677    [],
4678    "resize an NTFS filesystem",
4679    "\
4680 This command resizes an NTFS filesystem, expanding or
4681 shrinking it to the size of the underlying device.
4682 See also L<ntfsresize(8)>.");
4683
4684   ("vgscan", (RErr, []), 232, [],
4685    [InitEmpty, Always, TestRun (
4686       [["vgscan"]])],
4687    "rescan for LVM physical volumes, volume groups and logical volumes",
4688    "\
4689 This rescans all block devices and rebuilds the list of LVM
4690 physical volumes, volume groups and logical volumes.");
4691
4692   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4693    [InitEmpty, Always, TestRun (
4694       [["part_init"; "/dev/sda"; "mbr"];
4695        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4696        ["part_del"; "/dev/sda"; "1"]])],
4697    "delete a partition",
4698    "\
4699 This command deletes the partition numbered C<partnum> on C<device>.
4700
4701 Note that in the case of MBR partitioning, deleting an
4702 extended partition also deletes any logical partitions
4703 it contains.");
4704
4705   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4706    [InitEmpty, Always, TestOutputTrue (
4707       [["part_init"; "/dev/sda"; "mbr"];
4708        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4709        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4710        ["part_get_bootable"; "/dev/sda"; "1"]])],
4711    "return true if a partition is bootable",
4712    "\
4713 This command returns true if the partition C<partnum> on
4714 C<device> has the bootable flag set.
4715
4716 See also C<guestfs_part_set_bootable>.");
4717
4718   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4719    [InitEmpty, Always, TestOutputInt (
4720       [["part_init"; "/dev/sda"; "mbr"];
4721        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4722        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4723        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4724    "get the MBR type byte (ID byte) from a partition",
4725    "\
4726 Returns the MBR type byte (also known as the ID byte) from
4727 the numbered partition C<partnum>.
4728
4729 Note that only MBR (old DOS-style) partitions have type bytes.
4730 You will get undefined results for other partition table
4731 types (see C<guestfs_part_get_parttype>).");
4732
4733   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4734    [], (* tested by part_get_mbr_id *)
4735    "set the MBR type byte (ID byte) of a partition",
4736    "\
4737 Sets the MBR type byte (also known as the ID byte) of
4738 the numbered partition C<partnum> to C<idbyte>.  Note
4739 that the type bytes quoted in most documentation are
4740 in fact hexadecimal numbers, but usually documented
4741 without any leading \"0x\" which might be confusing.
4742
4743 Note that only MBR (old DOS-style) partitions have type bytes.
4744 You will get undefined results for other partition table
4745 types (see C<guestfs_part_get_parttype>).");
4746
4747   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4748    [InitISOFS, Always, TestOutput (
4749       [["checksum_device"; "md5"; "/dev/sdd"]],
4750       (Digest.to_hex (Digest.file "images/test.iso")))],
4751    "compute MD5, SHAx or CRC checksum of the contents of a device",
4752    "\
4753 This call computes the MD5, SHAx or CRC checksum of the
4754 contents of the device named C<device>.  For the types of
4755 checksums supported see the C<guestfs_checksum> command.");
4756
4757   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4758    [InitNone, Always, TestRun (
4759       [["part_disk"; "/dev/sda"; "mbr"];
4760        ["pvcreate"; "/dev/sda1"];
4761        ["vgcreate"; "VG"; "/dev/sda1"];
4762        ["lvcreate"; "LV"; "VG"; "10"];
4763        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4764    "expand an LV to fill free space",
4765    "\
4766 This expands an existing logical volume C<lv> so that it fills
4767 C<pc>% of the remaining free space in the volume group.  Commonly
4768 you would call this with pc = 100 which expands the logical volume
4769 as much as possible, using all remaining free space in the volume
4770 group.");
4771
4772   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4773    [], (* XXX Augeas code needs tests. *)
4774    "clear Augeas path",
4775    "\
4776 Set the value associated with C<path> to C<NULL>.  This
4777 is the same as the L<augtool(1)> C<clear> command.");
4778
4779   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4780    [InitEmpty, Always, TestOutputInt (
4781       [["get_umask"]], 0o22)],
4782    "get the current umask",
4783    "\
4784 Return the current umask.  By default the umask is C<022>
4785 unless it has been set by calling C<guestfs_umask>.");
4786
4787   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4788    [],
4789    "upload a file to the appliance (internal use only)",
4790    "\
4791 The C<guestfs_debug_upload> command uploads a file to
4792 the libguestfs appliance.
4793
4794 There is no comprehensive help for this command.  You have
4795 to look at the file C<daemon/debug.c> in the libguestfs source
4796 to find out what it is for.");
4797
4798   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4799    [InitBasicFS, Always, TestOutput (
4800       [["base64_in"; "../images/hello.b64"; "/hello"];
4801        ["cat"; "/hello"]], "hello\n")],
4802    "upload base64-encoded data to file",
4803    "\
4804 This command uploads base64-encoded data from C<base64file>
4805 to C<filename>.");
4806
4807   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4808    [],
4809    "download file and encode as base64",
4810    "\
4811 This command downloads the contents of C<filename>, writing
4812 it out to local file C<base64file> encoded as base64.");
4813
4814   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4815    [],
4816    "compute MD5, SHAx or CRC checksum of files in a directory",
4817    "\
4818 This command computes the checksums of all regular files in
4819 C<directory> and then emits a list of those checksums to
4820 the local output file C<sumsfile>.
4821
4822 This can be used for verifying the integrity of a virtual
4823 machine.  However to be properly secure you should pay
4824 attention to the output of the checksum command (it uses
4825 the ones from GNU coreutils).  In particular when the
4826 filename is not printable, coreutils uses a special
4827 backslash syntax.  For more information, see the GNU
4828 coreutils info file.");
4829
4830   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4831    [InitBasicFS, Always, TestOutputBuffer (
4832       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4833        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4834    "fill a file with a repeating pattern of bytes",
4835    "\
4836 This function is like C<guestfs_fill> except that it creates
4837 a new file of length C<len> containing the repeating pattern
4838 of bytes in C<pattern>.  The pattern is truncated if necessary
4839 to ensure the length of the file is exactly C<len> bytes.");
4840
4841   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4842    [InitBasicFS, Always, TestOutput (
4843       [["write"; "/new"; "new file contents"];
4844        ["cat"; "/new"]], "new file contents");
4845     InitBasicFS, Always, TestOutput (
4846       [["write"; "/new"; "\nnew file contents\n"];
4847        ["cat"; "/new"]], "\nnew file contents\n");
4848     InitBasicFS, Always, TestOutput (
4849       [["write"; "/new"; "\n\n"];
4850        ["cat"; "/new"]], "\n\n");
4851     InitBasicFS, Always, TestOutput (
4852       [["write"; "/new"; ""];
4853        ["cat"; "/new"]], "");
4854     InitBasicFS, Always, TestOutput (
4855       [["write"; "/new"; "\n\n\n"];
4856        ["cat"; "/new"]], "\n\n\n");
4857     InitBasicFS, Always, TestOutput (
4858       [["write"; "/new"; "\n"];
4859        ["cat"; "/new"]], "\n")],
4860    "create a new file",
4861    "\
4862 This call creates a file called C<path>.  The content of the
4863 file is the string C<content> (which can contain any 8 bit data).");
4864
4865   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4866    [InitBasicFS, Always, TestOutput (
4867       [["write"; "/new"; "new file contents"];
4868        ["pwrite"; "/new"; "data"; "4"];
4869        ["cat"; "/new"]], "new data contents");
4870     InitBasicFS, Always, TestOutput (
4871       [["write"; "/new"; "new file contents"];
4872        ["pwrite"; "/new"; "is extended"; "9"];
4873        ["cat"; "/new"]], "new file is extended");
4874     InitBasicFS, Always, TestOutput (
4875       [["write"; "/new"; "new file contents"];
4876        ["pwrite"; "/new"; ""; "4"];
4877        ["cat"; "/new"]], "new file contents")],
4878    "write to part of a file",
4879    "\
4880 This command writes to part of a file.  It writes the data
4881 buffer C<content> to the file C<path> starting at offset C<offset>.
4882
4883 This command implements the L<pwrite(2)> system call, and like
4884 that system call it may not write the full data requested.  The
4885 return value is the number of bytes that were actually written
4886 to the file.  This could even be 0, although short writes are
4887 unlikely for regular files in ordinary circumstances.
4888
4889 See also C<guestfs_pread>.");
4890
4891   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4892    [],
4893    "resize an ext2, ext3 or ext4 filesystem (with size)",
4894    "\
4895 This command is the same as C<guestfs_resize2fs> except that it
4896 allows you to specify the new size (in bytes) explicitly.");
4897
4898   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4899    [],
4900    "resize an LVM physical volume (with size)",
4901    "\
4902 This command is the same as C<guestfs_pvresize> except that it
4903 allows you to specify the new size (in bytes) explicitly.");
4904
4905   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4906    [],
4907    "resize an NTFS filesystem (with size)",
4908    "\
4909 This command is the same as C<guestfs_ntfsresize> except that it
4910 allows you to specify the new size (in bytes) explicitly.");
4911
4912   ("available_all_groups", (RStringList "groups", []), 251, [],
4913    [InitNone, Always, TestRun [["available_all_groups"]]],
4914    "return a list of all optional groups",
4915    "\
4916 This command returns a list of all optional groups that this
4917 daemon knows about.  Note this returns both supported and unsupported
4918 groups.  To find out which ones the daemon can actually support
4919 you have to call C<guestfs_available> on each member of the
4920 returned list.
4921
4922 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4923
4924   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4925    [InitBasicFS, Always, TestOutputStruct (
4926       [["fallocate64"; "/a"; "1000000"];
4927        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4928    "preallocate a file in the guest filesystem",
4929    "\
4930 This command preallocates a file (containing zero bytes) named
4931 C<path> of size C<len> bytes.  If the file exists already, it
4932 is overwritten.
4933
4934 Note that this call allocates disk blocks for the file.
4935 To create a sparse file use C<guestfs_truncate_size> instead.
4936
4937 The deprecated call C<guestfs_fallocate> does the same,
4938 but owing to an oversight it only allowed 30 bit lengths
4939 to be specified, effectively limiting the maximum size
4940 of files created through that call to 1GB.
4941
4942 Do not confuse this with the guestfish-specific
4943 C<alloc> and C<sparse> commands which create
4944 a file in the host and attach it as a device.");
4945
4946   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4947    [InitBasicFS, Always, TestOutput (
4948        [["set_e2label"; "/dev/sda1"; "LTEST"];
4949         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4950    "get the filesystem label",
4951    "\
4952 This returns the filesystem label of the filesystem on
4953 C<device>.
4954
4955 If the filesystem is unlabeled, this returns the empty string.
4956
4957 To find a filesystem from the label, use C<guestfs_findfs_label>.");
4958
4959   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4960    (let uuid = uuidgen () in
4961     [InitBasicFS, Always, TestOutput (
4962        [["set_e2uuid"; "/dev/sda1"; uuid];
4963         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4964    "get the filesystem UUID",
4965    "\
4966 This returns the filesystem UUID of the filesystem on
4967 C<device>.
4968
4969 If the filesystem does not have a UUID, this returns the empty string.
4970
4971 To find a filesystem from the UUID, use C<guestfs_findfs_uuid>.");
4972
4973   ("lvm_set_filter", (RErr, [DeviceList "devices"]), 255, [Optional "lvm2"],
4974    (* Can't be tested with the current framework because
4975     * the VG is being used by the mounted filesystem, so
4976     * the vgchange -an command we do first will fail.
4977     *)
4978     [],
4979    "set LVM device filter",
4980    "\
4981 This sets the LVM device filter so that LVM will only be
4982 able to \"see\" the block devices in the list C<devices>,
4983 and will ignore all other attached block devices.
4984
4985 Where disk image(s) contain duplicate PVs or VGs, this
4986 command is useful to get LVM to ignore the duplicates, otherwise
4987 LVM can get confused.  Note also there are two types
4988 of duplication possible: either cloned PVs/VGs which have
4989 identical UUIDs; or VGs that are not cloned but just happen
4990 to have the same name.  In normal operation you cannot
4991 create this situation, but you can do it outside LVM, eg.
4992 by cloning disk images or by bit twiddling inside the LVM
4993 metadata.
4994
4995 This command also clears the LVM cache and performs a volume
4996 group scan.
4997
4998 You can filter whole block devices or individual partitions.
4999
5000 You cannot use this if any VG is currently in use (eg.
5001 contains a mounted filesystem), even if you are not
5002 filtering out that VG.");
5003
5004   ("lvm_clear_filter", (RErr, []), 256, [],
5005    [], (* see note on lvm_set_filter *)
5006    "clear LVM device filter",
5007    "\
5008 This undoes the effect of C<guestfs_lvm_set_filter>.  LVM
5009 will be able to see every block device.
5010
5011 This command also clears the LVM cache and performs a volume
5012 group scan.");
5013
5014   ("luks_open", (RErr, [Device "device"; Key "key"; String "mapname"]), 257, [Optional "luks"],
5015    [],
5016    "open a LUKS-encrypted block device",
5017    "\
5018 This command opens a block device which has been encrypted
5019 according to the Linux Unified Key Setup (LUKS) standard.
5020
5021 C<device> is the encrypted block device or partition.
5022
5023 The caller must supply one of the keys associated with the
5024 LUKS block device, in the C<key> parameter.
5025
5026 This creates a new block device called C</dev/mapper/mapname>.
5027 Reads and writes to this block device are decrypted from and
5028 encrypted to the underlying C<device> respectively.
5029
5030 If this block device contains LVM volume groups, then
5031 calling C<guestfs_vgscan> followed by C<guestfs_vg_activate_all>
5032 will make them visible.");
5033
5034   ("luks_open_ro", (RErr, [Device "device"; Key "key"; String "mapname"]), 258, [Optional "luks"],
5035    [],
5036    "open a LUKS-encrypted block device read-only",
5037    "\
5038 This is the same as C<guestfs_luks_open> except that a read-only
5039 mapping is created.");
5040
5041   ("luks_close", (RErr, [Device "device"]), 259, [Optional "luks"],
5042    [],
5043    "close a LUKS device",
5044    "\
5045 This closes a LUKS device that was created earlier by
5046 C<guestfs_luks_open> or C<guestfs_luks_open_ro>.  The
5047 C<device> parameter must be the name of the LUKS mapping
5048 device (ie. C</dev/mapper/mapname>) and I<not> the name
5049 of the underlying block device.");
5050
5051   ("luks_format", (RErr, [Device "device"; Key "key"; Int "keyslot"]), 260, [Optional "luks"; DangerWillRobinson],
5052    [],
5053    "format a block device as a LUKS encrypted device",
5054    "\
5055 This command erases existing data on C<device> and formats
5056 the device as a LUKS encrypted device.  C<key> is the
5057 initial key, which is added to key slot C<slot>.  (LUKS
5058 supports 8 key slots, numbered 0-7).");
5059
5060   ("luks_format_cipher", (RErr, [Device "device"; Key "key"; Int "keyslot"; String "cipher"]), 261, [Optional "luks"; DangerWillRobinson],
5061    [],
5062    "format a block device as a LUKS encrypted device",
5063    "\
5064 This command is the same as C<guestfs_luks_format> but
5065 it also allows you to set the C<cipher> used.");
5066
5067   ("luks_add_key", (RErr, [Device "device"; Key "key"; Key "newkey"; Int "keyslot"]), 262, [Optional "luks"],
5068    [],
5069    "add a key on a LUKS encrypted device",
5070    "\
5071 This command adds a new key on LUKS device C<device>.
5072 C<key> is any existing key, and is used to access the device.
5073 C<newkey> is the new key to add.  C<keyslot> is the key slot
5074 that will be replaced.
5075
5076 Note that if C<keyslot> already contains a key, then this
5077 command will fail.  You have to use C<guestfs_luks_kill_slot>
5078 first to remove that key.");
5079
5080   ("luks_kill_slot", (RErr, [Device "device"; Key "key"; Int "keyslot"]), 263, [Optional "luks"],
5081    [],
5082    "remove a key from a LUKS encrypted device",
5083    "\
5084 This command deletes the key in key slot C<keyslot> from the
5085 encrypted LUKS device C<device>.  C<key> must be one of the
5086 I<other> keys.");
5087
5088   ("is_lv", (RBool "lvflag", [Device "device"]), 264, [Optional "lvm2"],
5089    [InitBasicFSonLVM, IfAvailable "lvm2", TestOutputTrue (
5090       [["is_lv"; "/dev/VG/LV"]]);
5091     InitBasicFSonLVM, IfAvailable "lvm2", TestOutputFalse (
5092       [["is_lv"; "/dev/sda1"]])],
5093    "test if device is a logical volume",
5094    "\
5095 This command tests whether C<device> is a logical volume, and
5096 returns true iff this is the case.");
5097
5098   ("findfs_uuid", (RString "device", [String "uuid"]), 265, [],
5099    [],
5100    "find a filesystem by UUID",
5101    "\
5102 This command searches the filesystems and returns the one
5103 which has the given UUID.  An error is returned if no such
5104 filesystem can be found.
5105
5106 To find the UUID of a filesystem, use C<guestfs_vfs_uuid>.");
5107
5108   ("findfs_label", (RString "device", [String "label"]), 266, [],
5109    [],
5110    "find a filesystem by label",
5111    "\
5112 This command searches the filesystems and returns the one
5113 which has the given label.  An error is returned if no such
5114 filesystem can be found.
5115
5116 To find the label of a filesystem, use C<guestfs_vfs_label>.");
5117
5118 ]
5119
5120 let all_functions = non_daemon_functions @ daemon_functions
5121
5122 (* In some places we want the functions to be displayed sorted
5123  * alphabetically, so this is useful:
5124  *)
5125 let all_functions_sorted =
5126   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
5127                compare n1 n2) all_functions
5128
5129 (* This is used to generate the src/MAX_PROC_NR file which
5130  * contains the maximum procedure number, a surrogate for the
5131  * ABI version number.  See src/Makefile.am for the details.
5132  *)
5133 let max_proc_nr =
5134   let proc_nrs = List.map (
5135     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
5136   ) daemon_functions in
5137   List.fold_left max 0 proc_nrs
5138
5139 (* Field types for structures. *)
5140 type field =
5141   | FChar                       (* C 'char' (really, a 7 bit byte). *)
5142   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
5143   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
5144   | FUInt32
5145   | FInt32
5146   | FUInt64
5147   | FInt64
5148   | FBytes                      (* Any int measure that counts bytes. *)
5149   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
5150   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
5151
5152 (* Because we generate extra parsing code for LVM command line tools,
5153  * we have to pull out the LVM columns separately here.
5154  *)
5155 let lvm_pv_cols = [
5156   "pv_name", FString;
5157   "pv_uuid", FUUID;
5158   "pv_fmt", FString;
5159   "pv_size", FBytes;
5160   "dev_size", FBytes;
5161   "pv_free", FBytes;
5162   "pv_used", FBytes;
5163   "pv_attr", FString (* XXX *);
5164   "pv_pe_count", FInt64;
5165   "pv_pe_alloc_count", FInt64;
5166   "pv_tags", FString;
5167   "pe_start", FBytes;
5168   "pv_mda_count", FInt64;
5169   "pv_mda_free", FBytes;
5170   (* Not in Fedora 10:
5171      "pv_mda_size", FBytes;
5172   *)
5173 ]
5174 let lvm_vg_cols = [
5175   "vg_name", FString;
5176   "vg_uuid", FUUID;
5177   "vg_fmt", FString;
5178   "vg_attr", FString (* XXX *);
5179   "vg_size", FBytes;
5180   "vg_free", FBytes;
5181   "vg_sysid", FString;
5182   "vg_extent_size", FBytes;
5183   "vg_extent_count", FInt64;
5184   "vg_free_count", FInt64;
5185   "max_lv", FInt64;
5186   "max_pv", FInt64;
5187   "pv_count", FInt64;
5188   "lv_count", FInt64;
5189   "snap_count", FInt64;
5190   "vg_seqno", FInt64;
5191   "vg_tags", FString;
5192   "vg_mda_count", FInt64;
5193   "vg_mda_free", FBytes;
5194   (* Not in Fedora 10:
5195      "vg_mda_size", FBytes;
5196   *)
5197 ]
5198 let lvm_lv_cols = [
5199   "lv_name", FString;
5200   "lv_uuid", FUUID;
5201   "lv_attr", FString (* XXX *);
5202   "lv_major", FInt64;
5203   "lv_minor", FInt64;
5204   "lv_kernel_major", FInt64;
5205   "lv_kernel_minor", FInt64;
5206   "lv_size", FBytes;
5207   "seg_count", FInt64;
5208   "origin", FString;
5209   "snap_percent", FOptPercent;
5210   "copy_percent", FOptPercent;
5211   "move_pv", FString;
5212   "lv_tags", FString;
5213   "mirror_log", FString;
5214   "modules", FString;
5215 ]
5216
5217 (* Names and fields in all structures (in RStruct and RStructList)
5218  * that we support.
5219  *)
5220 let structs = [
5221   (* The old RIntBool return type, only ever used for aug_defnode.  Do
5222    * not use this struct in any new code.
5223    *)
5224   "int_bool", [
5225     "i", FInt32;                (* for historical compatibility *)
5226     "b", FInt32;                (* for historical compatibility *)
5227   ];
5228
5229   (* LVM PVs, VGs, LVs. *)
5230   "lvm_pv", lvm_pv_cols;
5231   "lvm_vg", lvm_vg_cols;
5232   "lvm_lv", lvm_lv_cols;
5233
5234   (* Column names and types from stat structures.
5235    * NB. Can't use things like 'st_atime' because glibc header files
5236    * define some of these as macros.  Ugh.
5237    *)
5238   "stat", [
5239     "dev", FInt64;
5240     "ino", FInt64;
5241     "mode", FInt64;
5242     "nlink", FInt64;
5243     "uid", FInt64;
5244     "gid", FInt64;
5245     "rdev", FInt64;
5246     "size", FInt64;
5247     "blksize", FInt64;
5248     "blocks", FInt64;
5249     "atime", FInt64;
5250     "mtime", FInt64;
5251     "ctime", FInt64;
5252   ];
5253   "statvfs", [
5254     "bsize", FInt64;
5255     "frsize", FInt64;
5256     "blocks", FInt64;
5257     "bfree", FInt64;
5258     "bavail", FInt64;
5259     "files", FInt64;
5260     "ffree", FInt64;
5261     "favail", FInt64;
5262     "fsid", FInt64;
5263     "flag", FInt64;
5264     "namemax", FInt64;
5265   ];
5266
5267   (* Column names in dirent structure. *)
5268   "dirent", [
5269     "ino", FInt64;
5270     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
5271     "ftyp", FChar;
5272     "name", FString;
5273   ];
5274
5275   (* Version numbers. *)
5276   "version", [
5277     "major", FInt64;
5278     "minor", FInt64;
5279     "release", FInt64;
5280     "extra", FString;
5281   ];
5282
5283   (* Extended attribute. *)
5284   "xattr", [
5285     "attrname", FString;
5286     "attrval", FBuffer;
5287   ];
5288
5289   (* Inotify events. *)
5290   "inotify_event", [
5291     "in_wd", FInt64;
5292     "in_mask", FUInt32;
5293     "in_cookie", FUInt32;
5294     "in_name", FString;
5295   ];
5296
5297   (* Partition table entry. *)
5298   "partition", [
5299     "part_num", FInt32;
5300     "part_start", FBytes;
5301     "part_end", FBytes;
5302     "part_size", FBytes;
5303   ];
5304 ] (* end of structs *)
5305
5306 (* Ugh, Java has to be different ..
5307  * These names are also used by the Haskell bindings.
5308  *)
5309 let java_structs = [
5310   "int_bool", "IntBool";
5311   "lvm_pv", "PV";
5312   "lvm_vg", "VG";
5313   "lvm_lv", "LV";
5314   "stat", "Stat";
5315   "statvfs", "StatVFS";
5316   "dirent", "Dirent";
5317   "version", "Version";
5318   "xattr", "XAttr";
5319   "inotify_event", "INotifyEvent";
5320   "partition", "Partition";
5321 ]
5322
5323 (* What structs are actually returned. *)
5324 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5325
5326 (* Returns a list of RStruct/RStructList structs that are returned
5327  * by any function.  Each element of returned list is a pair:
5328  *
5329  * (structname, RStructOnly)
5330  *    == there exists function which returns RStruct (_, structname)
5331  * (structname, RStructListOnly)
5332  *    == there exists function which returns RStructList (_, structname)
5333  * (structname, RStructAndList)
5334  *    == there are functions returning both RStruct (_, structname)
5335  *                                      and RStructList (_, structname)
5336  *)
5337 let rstructs_used_by functions =
5338   (* ||| is a "logical OR" for rstructs_used_t *)
5339   let (|||) a b =
5340     match a, b with
5341     | RStructAndList, _
5342     | _, RStructAndList -> RStructAndList
5343     | RStructOnly, RStructListOnly
5344     | RStructListOnly, RStructOnly -> RStructAndList
5345     | RStructOnly, RStructOnly -> RStructOnly
5346     | RStructListOnly, RStructListOnly -> RStructListOnly
5347   in
5348
5349   let h = Hashtbl.create 13 in
5350
5351   (* if elem->oldv exists, update entry using ||| operator,
5352    * else just add elem->newv to the hash
5353    *)
5354   let update elem newv =
5355     try  let oldv = Hashtbl.find h elem in
5356          Hashtbl.replace h elem (newv ||| oldv)
5357     with Not_found -> Hashtbl.add h elem newv
5358   in
5359
5360   List.iter (
5361     fun (_, style, _, _, _, _, _) ->
5362       match fst style with
5363       | RStruct (_, structname) -> update structname RStructOnly
5364       | RStructList (_, structname) -> update structname RStructListOnly
5365       | _ -> ()
5366   ) functions;
5367
5368   (* return key->values as a list of (key,value) *)
5369   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5370
5371 (* Used for testing language bindings. *)
5372 type callt =
5373   | CallString of string
5374   | CallOptString of string option
5375   | CallStringList of string list
5376   | CallInt of int
5377   | CallInt64 of int64
5378   | CallBool of bool
5379   | CallBuffer of string
5380
5381 (* Used to memoize the result of pod2text. *)
5382 let pod2text_memo_filename = "src/.pod2text.data"
5383 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5384   try
5385     let chan = open_in pod2text_memo_filename in
5386     let v = input_value chan in
5387     close_in chan;
5388     v
5389   with
5390     _ -> Hashtbl.create 13
5391 let pod2text_memo_updated () =
5392   let chan = open_out pod2text_memo_filename in
5393   output_value chan pod2text_memo;
5394   close_out chan
5395
5396 (* Useful functions.
5397  * Note we don't want to use any external OCaml libraries which
5398  * makes this a bit harder than it should be.
5399  *)
5400 module StringMap = Map.Make (String)
5401
5402 let failwithf fs = ksprintf failwith fs
5403
5404 let unique = let i = ref 0 in fun () -> incr i; !i
5405
5406 let replace_char s c1 c2 =
5407   let s2 = String.copy s in
5408   let r = ref false in
5409   for i = 0 to String.length s2 - 1 do
5410     if String.unsafe_get s2 i = c1 then (
5411       String.unsafe_set s2 i c2;
5412       r := true
5413     )
5414   done;
5415   if not !r then s else s2
5416
5417 let isspace c =
5418   c = ' '
5419   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5420
5421 let triml ?(test = isspace) str =
5422   let i = ref 0 in
5423   let n = ref (String.length str) in
5424   while !n > 0 && test str.[!i]; do
5425     decr n;
5426     incr i
5427   done;
5428   if !i = 0 then str
5429   else String.sub str !i !n
5430
5431 let trimr ?(test = isspace) str =
5432   let n = ref (String.length str) in
5433   while !n > 0 && test str.[!n-1]; do
5434     decr n
5435   done;
5436   if !n = String.length str then str
5437   else String.sub str 0 !n
5438
5439 let trim ?(test = isspace) str =
5440   trimr ~test (triml ~test str)
5441
5442 let rec find s sub =
5443   let len = String.length s in
5444   let sublen = String.length sub in
5445   let rec loop i =
5446     if i <= len-sublen then (
5447       let rec loop2 j =
5448         if j < sublen then (
5449           if s.[i+j] = sub.[j] then loop2 (j+1)
5450           else -1
5451         ) else
5452           i (* found *)
5453       in
5454       let r = loop2 0 in
5455       if r = -1 then loop (i+1) else r
5456     ) else
5457       -1 (* not found *)
5458   in
5459   loop 0
5460
5461 let rec replace_str s s1 s2 =
5462   let len = String.length s in
5463   let sublen = String.length s1 in
5464   let i = find s s1 in
5465   if i = -1 then s
5466   else (
5467     let s' = String.sub s 0 i in
5468     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5469     s' ^ s2 ^ replace_str s'' s1 s2
5470   )
5471
5472 let rec string_split sep str =
5473   let len = String.length str in
5474   let seplen = String.length sep in
5475   let i = find str sep in
5476   if i = -1 then [str]
5477   else (
5478     let s' = String.sub str 0 i in
5479     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5480     s' :: string_split sep s''
5481   )
5482
5483 let files_equal n1 n2 =
5484   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5485   match Sys.command cmd with
5486   | 0 -> true
5487   | 1 -> false
5488   | i -> failwithf "%s: failed with error code %d" cmd i
5489
5490 let rec filter_map f = function
5491   | [] -> []
5492   | x :: xs ->
5493       match f x with
5494       | Some y -> y :: filter_map f xs
5495       | None -> filter_map f xs
5496
5497 let rec find_map f = function
5498   | [] -> raise Not_found
5499   | x :: xs ->
5500       match f x with
5501       | Some y -> y
5502       | None -> find_map f xs
5503
5504 let iteri f xs =
5505   let rec loop i = function
5506     | [] -> ()
5507     | x :: xs -> f i x; loop (i+1) xs
5508   in
5509   loop 0 xs
5510
5511 let mapi f xs =
5512   let rec loop i = function
5513     | [] -> []
5514     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5515   in
5516   loop 0 xs
5517
5518 let count_chars c str =
5519   let count = ref 0 in
5520   for i = 0 to String.length str - 1 do
5521     if c = String.unsafe_get str i then incr count
5522   done;
5523   !count
5524
5525 let explode str =
5526   let r = ref [] in
5527   for i = 0 to String.length str - 1 do
5528     let c = String.unsafe_get str i in
5529     r := c :: !r;
5530   done;
5531   List.rev !r
5532
5533 let map_chars f str =
5534   List.map f (explode str)
5535
5536 let name_of_argt = function
5537   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5538   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5539   | FileIn n | FileOut n | BufferIn n | Key n -> n
5540
5541 let java_name_of_struct typ =
5542   try List.assoc typ java_structs
5543   with Not_found ->
5544     failwithf
5545       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5546
5547 let cols_of_struct typ =
5548   try List.assoc typ structs
5549   with Not_found ->
5550     failwithf "cols_of_struct: unknown struct %s" typ
5551
5552 let seq_of_test = function
5553   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5554   | TestOutputListOfDevices (s, _)
5555   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5556   | TestOutputTrue s | TestOutputFalse s
5557   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5558   | TestOutputStruct (s, _)
5559   | TestLastFail s -> s
5560
5561 (* Handling for function flags. *)
5562 let protocol_limit_warning =
5563   "Because of the message protocol, there is a transfer limit
5564 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5565
5566 let danger_will_robinson =
5567   "B<This command is dangerous.  Without careful use you
5568 can easily destroy all your data>."
5569
5570 let deprecation_notice flags =
5571   try
5572     let alt =
5573       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5574     let txt =
5575       sprintf "This function is deprecated.
5576 In new code, use the C<%s> call instead.
5577
5578 Deprecated functions will not be removed from the API, but the
5579 fact that they are deprecated indicates that there are problems
5580 with correct use of these functions." alt in
5581     Some txt
5582   with
5583     Not_found -> None
5584
5585 (* Create list of optional groups. *)
5586 let optgroups =
5587   let h = Hashtbl.create 13 in
5588   List.iter (
5589     fun (name, _, _, flags, _, _, _) ->
5590       List.iter (
5591         function
5592         | Optional group ->
5593             let names = try Hashtbl.find h group with Not_found -> [] in
5594             Hashtbl.replace h group (name :: names)
5595         | _ -> ()
5596       ) flags
5597   ) daemon_functions;
5598   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5599   let groups =
5600     List.map (
5601       fun group -> group, List.sort compare (Hashtbl.find h group)
5602     ) groups in
5603   List.sort (fun x y -> compare (fst x) (fst y)) groups
5604
5605 (* Check function names etc. for consistency. *)
5606 let check_functions () =
5607   let contains_uppercase str =
5608     let len = String.length str in
5609     let rec loop i =
5610       if i >= len then false
5611       else (
5612         let c = str.[i] in
5613         if c >= 'A' && c <= 'Z' then true
5614         else loop (i+1)
5615       )
5616     in
5617     loop 0
5618   in
5619
5620   (* Check function names. *)
5621   List.iter (
5622     fun (name, _, _, _, _, _, _) ->
5623       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5624         failwithf "function name %s does not need 'guestfs' prefix" name;
5625       if name = "" then
5626         failwithf "function name is empty";
5627       if name.[0] < 'a' || name.[0] > 'z' then
5628         failwithf "function name %s must start with lowercase a-z" name;
5629       if String.contains name '-' then
5630         failwithf "function name %s should not contain '-', use '_' instead."
5631           name
5632   ) all_functions;
5633
5634   (* Check function parameter/return names. *)
5635   List.iter (
5636     fun (name, style, _, _, _, _, _) ->
5637       let check_arg_ret_name n =
5638         if contains_uppercase n then
5639           failwithf "%s param/ret %s should not contain uppercase chars"
5640             name n;
5641         if String.contains n '-' || String.contains n '_' then
5642           failwithf "%s param/ret %s should not contain '-' or '_'"
5643             name n;
5644         if n = "value" then
5645           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;
5646         if n = "int" || n = "char" || n = "short" || n = "long" then
5647           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5648         if n = "i" || n = "n" then
5649           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5650         if n = "argv" || n = "args" then
5651           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5652
5653         (* List Haskell, OCaml and C keywords here.
5654          * http://www.haskell.org/haskellwiki/Keywords
5655          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5656          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5657          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5658          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5659          * Omitting _-containing words, since they're handled above.
5660          * Omitting the OCaml reserved word, "val", is ok,
5661          * and saves us from renaming several parameters.
5662          *)
5663         let reserved = [
5664           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5665           "char"; "class"; "const"; "constraint"; "continue"; "data";
5666           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5667           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5668           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5669           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5670           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5671           "interface";
5672           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5673           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5674           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5675           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5676           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5677           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5678           "volatile"; "when"; "where"; "while";
5679           ] in
5680         if List.mem n reserved then
5681           failwithf "%s has param/ret using reserved word %s" name n;
5682       in
5683
5684       (match fst style with
5685        | RErr -> ()
5686        | RInt n | RInt64 n | RBool n
5687        | RConstString n | RConstOptString n | RString n
5688        | RStringList n | RStruct (n, _) | RStructList (n, _)
5689        | RHashtable n | RBufferOut n ->
5690            check_arg_ret_name n
5691       );
5692       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5693   ) all_functions;
5694
5695   (* Check short descriptions. *)
5696   List.iter (
5697     fun (name, _, _, _, _, shortdesc, _) ->
5698       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5699         failwithf "short description of %s should begin with lowercase." name;
5700       let c = shortdesc.[String.length shortdesc-1] in
5701       if c = '\n' || c = '.' then
5702         failwithf "short description of %s should not end with . or \\n." name
5703   ) all_functions;
5704
5705   (* Check long descriptions. *)
5706   List.iter (
5707     fun (name, _, _, _, _, _, longdesc) ->
5708       if longdesc.[String.length longdesc-1] = '\n' then
5709         failwithf "long description of %s should not end with \\n." name
5710   ) all_functions;
5711
5712   (* Check proc_nrs. *)
5713   List.iter (
5714     fun (name, _, proc_nr, _, _, _, _) ->
5715       if proc_nr <= 0 then
5716         failwithf "daemon function %s should have proc_nr > 0" name
5717   ) daemon_functions;
5718
5719   List.iter (
5720     fun (name, _, proc_nr, _, _, _, _) ->
5721       if proc_nr <> -1 then
5722         failwithf "non-daemon function %s should have proc_nr -1" name
5723   ) non_daemon_functions;
5724
5725   let proc_nrs =
5726     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5727       daemon_functions in
5728   let proc_nrs =
5729     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5730   let rec loop = function
5731     | [] -> ()
5732     | [_] -> ()
5733     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5734         loop rest
5735     | (name1,nr1) :: (name2,nr2) :: _ ->
5736         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5737           name1 name2 nr1 nr2
5738   in
5739   loop proc_nrs;
5740
5741   (* Check tests. *)
5742   List.iter (
5743     function
5744       (* Ignore functions that have no tests.  We generate a
5745        * warning when the user does 'make check' instead.
5746        *)
5747     | name, _, _, _, [], _, _ -> ()
5748     | name, _, _, _, tests, _, _ ->
5749         let funcs =
5750           List.map (
5751             fun (_, _, test) ->
5752               match seq_of_test test with
5753               | [] ->
5754                   failwithf "%s has a test containing an empty sequence" name
5755               | cmds -> List.map List.hd cmds
5756           ) tests in
5757         let funcs = List.flatten funcs in
5758
5759         let tested = List.mem name funcs in
5760
5761         if not tested then
5762           failwithf "function %s has tests but does not test itself" name
5763   ) all_functions
5764
5765 (* 'pr' prints to the current output file. *)
5766 let chan = ref Pervasives.stdout
5767 let lines = ref 0
5768 let pr fs =
5769   ksprintf
5770     (fun str ->
5771        let i = count_chars '\n' str in
5772        lines := !lines + i;
5773        output_string !chan str
5774     ) fs
5775
5776 let copyright_years =
5777   let this_year = 1900 + (localtime (time ())).tm_year in
5778   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5779
5780 (* Generate a header block in a number of standard styles. *)
5781 type comment_style =
5782     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5783 type license = GPLv2plus | LGPLv2plus
5784
5785 let generate_header ?(extra_inputs = []) comment license =
5786   let inputs = "src/generator.ml" :: extra_inputs in
5787   let c = match comment with
5788     | CStyle ->         pr "/* "; " *"
5789     | CPlusPlusStyle -> pr "// "; "//"
5790     | HashStyle ->      pr "# ";  "#"
5791     | OCamlStyle ->     pr "(* "; " *"
5792     | HaskellStyle ->   pr "{- "; "  " in
5793   pr "libguestfs generated file\n";
5794   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5795   List.iter (pr "%s   %s\n" c) inputs;
5796   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5797   pr "%s\n" c;
5798   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5799   pr "%s\n" c;
5800   (match license with
5801    | GPLv2plus ->
5802        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5803        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5804        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5805        pr "%s (at your option) any later version.\n" c;
5806        pr "%s\n" c;
5807        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5808        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5809        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5810        pr "%s GNU General Public License for more details.\n" c;
5811        pr "%s\n" c;
5812        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5813        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5814        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5815
5816    | LGPLv2plus ->
5817        pr "%s This library is free software; you can redistribute it and/or\n" c;
5818        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5819        pr "%s License as published by the Free Software Foundation; either\n" c;
5820        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5821        pr "%s\n" c;
5822        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5823        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5824        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5825        pr "%s Lesser General Public License for more details.\n" c;
5826        pr "%s\n" c;
5827        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5828        pr "%s License along with this library; if not, write to the Free Software\n" c;
5829        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5830   );
5831   (match comment with
5832    | CStyle -> pr " */\n"
5833    | CPlusPlusStyle
5834    | HashStyle -> ()
5835    | OCamlStyle -> pr " *)\n"
5836    | HaskellStyle -> pr "-}\n"
5837   );
5838   pr "\n"
5839
5840 (* Start of main code generation functions below this line. *)
5841
5842 (* Generate the pod documentation for the C API. *)
5843 let rec generate_actions_pod () =
5844   List.iter (
5845     fun (shortname, style, _, flags, _, _, longdesc) ->
5846       if not (List.mem NotInDocs flags) then (
5847         let name = "guestfs_" ^ shortname in
5848         pr "=head2 %s\n\n" name;
5849         pr " ";
5850         generate_prototype ~extern:false ~handle:"g" name style;
5851         pr "\n\n";
5852         pr "%s\n\n" longdesc;
5853         (match fst style with
5854          | RErr ->
5855              pr "This function returns 0 on success or -1 on error.\n\n"
5856          | RInt _ ->
5857              pr "On error this function returns -1.\n\n"
5858          | RInt64 _ ->
5859              pr "On error this function returns -1.\n\n"
5860          | RBool _ ->
5861              pr "This function returns a C truth value on success or -1 on error.\n\n"
5862          | RConstString _ ->
5863              pr "This function returns a string, or NULL on error.
5864 The string is owned by the guest handle and must I<not> be freed.\n\n"
5865          | RConstOptString _ ->
5866              pr "This function returns a string which may be NULL.
5867 There is no way to return an error from this function.
5868 The string is owned by the guest handle and must I<not> be freed.\n\n"
5869          | RString _ ->
5870              pr "This function returns a string, or NULL on error.
5871 I<The caller must free the returned string after use>.\n\n"
5872          | RStringList _ ->
5873              pr "This function returns a NULL-terminated array of strings
5874 (like L<environ(3)>), or NULL if there was an error.
5875 I<The caller must free the strings and the array after use>.\n\n"
5876          | RStruct (_, typ) ->
5877              pr "This function returns a C<struct guestfs_%s *>,
5878 or NULL if there was an error.
5879 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5880          | RStructList (_, typ) ->
5881              pr "This function returns a C<struct guestfs_%s_list *>
5882 (see E<lt>guestfs-structs.hE<gt>),
5883 or NULL if there was an error.
5884 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5885          | RHashtable _ ->
5886              pr "This function returns a NULL-terminated array of
5887 strings, or NULL if there was an error.
5888 The array of strings will always have length C<2n+1>, where
5889 C<n> keys and values alternate, followed by the trailing NULL entry.
5890 I<The caller must free the strings and the array after use>.\n\n"
5891          | RBufferOut _ ->
5892              pr "This function returns a buffer, or NULL on error.
5893 The size of the returned buffer is written to C<*size_r>.
5894 I<The caller must free the returned buffer after use>.\n\n"
5895         );
5896         if List.mem ProtocolLimitWarning flags then
5897           pr "%s\n\n" protocol_limit_warning;
5898         if List.mem DangerWillRobinson flags then
5899           pr "%s\n\n" danger_will_robinson;
5900         if List.exists (function Key _ -> true | _ -> false) (snd style) then
5901           pr "This function takes a key or passphrase parameter which
5902 could contain sensitive material.  Read the section
5903 L</KEYS AND PASSPHRASES> for more information.\n\n";
5904         match deprecation_notice flags with
5905         | None -> ()
5906         | Some txt -> pr "%s\n\n" txt
5907       )
5908   ) all_functions_sorted
5909
5910 and generate_structs_pod () =
5911   (* Structs documentation. *)
5912   List.iter (
5913     fun (typ, cols) ->
5914       pr "=head2 guestfs_%s\n" typ;
5915       pr "\n";
5916       pr " struct guestfs_%s {\n" typ;
5917       List.iter (
5918         function
5919         | name, FChar -> pr "   char %s;\n" name
5920         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5921         | name, FInt32 -> pr "   int32_t %s;\n" name
5922         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5923         | name, FInt64 -> pr "   int64_t %s;\n" name
5924         | name, FString -> pr "   char *%s;\n" name
5925         | name, FBuffer ->
5926             pr "   /* The next two fields describe a byte array. */\n";
5927             pr "   uint32_t %s_len;\n" name;
5928             pr "   char *%s;\n" name
5929         | name, FUUID ->
5930             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5931             pr "   char %s[32];\n" name
5932         | name, FOptPercent ->
5933             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5934             pr "   float %s;\n" name
5935       ) cols;
5936       pr " };\n";
5937       pr " \n";
5938       pr " struct guestfs_%s_list {\n" typ;
5939       pr "   uint32_t len; /* Number of elements in list. */\n";
5940       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5941       pr " };\n";
5942       pr " \n";
5943       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5944       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5945         typ typ;
5946       pr "\n"
5947   ) structs
5948
5949 and generate_availability_pod () =
5950   (* Availability documentation. *)
5951   pr "=over 4\n";
5952   pr "\n";
5953   List.iter (
5954     fun (group, functions) ->
5955       pr "=item B<%s>\n" group;
5956       pr "\n";
5957       pr "The following functions:\n";
5958       List.iter (pr "L</guestfs_%s>\n") functions;
5959       pr "\n"
5960   ) optgroups;
5961   pr "=back\n";
5962   pr "\n"
5963
5964 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5965  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5966  *
5967  * We have to use an underscore instead of a dash because otherwise
5968  * rpcgen generates incorrect code.
5969  *
5970  * This header is NOT exported to clients, but see also generate_structs_h.
5971  *)
5972 and generate_xdr () =
5973   generate_header CStyle LGPLv2plus;
5974
5975   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5976   pr "typedef string str<>;\n";
5977   pr "\n";
5978
5979   (* Internal structures. *)
5980   List.iter (
5981     function
5982     | typ, cols ->
5983         pr "struct guestfs_int_%s {\n" typ;
5984         List.iter (function
5985                    | name, FChar -> pr "  char %s;\n" name
5986                    | name, FString -> pr "  string %s<>;\n" name
5987                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5988                    | name, FUUID -> pr "  opaque %s[32];\n" name
5989                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5990                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5991                    | name, FOptPercent -> pr "  float %s;\n" name
5992                   ) cols;
5993         pr "};\n";
5994         pr "\n";
5995         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5996         pr "\n";
5997   ) structs;
5998
5999   List.iter (
6000     fun (shortname, style, _, _, _, _, _) ->
6001       let name = "guestfs_" ^ shortname in
6002
6003       (match snd style with
6004        | [] -> ()
6005        | args ->
6006            pr "struct %s_args {\n" name;
6007            List.iter (
6008              function
6009              | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
6010                  pr "  string %s<>;\n" n
6011              | OptString n -> pr "  str *%s;\n" n
6012              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
6013              | Bool n -> pr "  bool %s;\n" n
6014              | Int n -> pr "  int %s;\n" n
6015              | Int64 n -> pr "  hyper %s;\n" n
6016              | BufferIn n ->
6017                  pr "  opaque %s<>;\n" n
6018              | FileIn _ | FileOut _ -> ()
6019            ) args;
6020            pr "};\n\n"
6021       );
6022       (match fst style with
6023        | RErr -> ()
6024        | RInt n ->
6025            pr "struct %s_ret {\n" name;
6026            pr "  int %s;\n" n;
6027            pr "};\n\n"
6028        | RInt64 n ->
6029            pr "struct %s_ret {\n" name;
6030            pr "  hyper %s;\n" n;
6031            pr "};\n\n"
6032        | RBool n ->
6033            pr "struct %s_ret {\n" name;
6034            pr "  bool %s;\n" n;
6035            pr "};\n\n"
6036        | RConstString _ | RConstOptString _ ->
6037            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6038        | RString n ->
6039            pr "struct %s_ret {\n" name;
6040            pr "  string %s<>;\n" n;
6041            pr "};\n\n"
6042        | RStringList n ->
6043            pr "struct %s_ret {\n" name;
6044            pr "  str %s<>;\n" n;
6045            pr "};\n\n"
6046        | RStruct (n, typ) ->
6047            pr "struct %s_ret {\n" name;
6048            pr "  guestfs_int_%s %s;\n" typ n;
6049            pr "};\n\n"
6050        | RStructList (n, typ) ->
6051            pr "struct %s_ret {\n" name;
6052            pr "  guestfs_int_%s_list %s;\n" typ n;
6053            pr "};\n\n"
6054        | RHashtable n ->
6055            pr "struct %s_ret {\n" name;
6056            pr "  str %s<>;\n" n;
6057            pr "};\n\n"
6058        | RBufferOut n ->
6059            pr "struct %s_ret {\n" name;
6060            pr "  opaque %s<>;\n" n;
6061            pr "};\n\n"
6062       );
6063   ) daemon_functions;
6064
6065   (* Table of procedure numbers. *)
6066   pr "enum guestfs_procedure {\n";
6067   List.iter (
6068     fun (shortname, _, proc_nr, _, _, _, _) ->
6069       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
6070   ) daemon_functions;
6071   pr "  GUESTFS_PROC_NR_PROCS\n";
6072   pr "};\n";
6073   pr "\n";
6074
6075   (* Having to choose a maximum message size is annoying for several
6076    * reasons (it limits what we can do in the API), but it (a) makes
6077    * the protocol a lot simpler, and (b) provides a bound on the size
6078    * of the daemon which operates in limited memory space.
6079    *)
6080   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
6081   pr "\n";
6082
6083   (* Message header, etc. *)
6084   pr "\
6085 /* The communication protocol is now documented in the guestfs(3)
6086  * manpage.
6087  */
6088
6089 const GUESTFS_PROGRAM = 0x2000F5F5;
6090 const GUESTFS_PROTOCOL_VERSION = 1;
6091
6092 /* These constants must be larger than any possible message length. */
6093 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
6094 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
6095
6096 enum guestfs_message_direction {
6097   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
6098   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
6099 };
6100
6101 enum guestfs_message_status {
6102   GUESTFS_STATUS_OK = 0,
6103   GUESTFS_STATUS_ERROR = 1
6104 };
6105
6106 const GUESTFS_ERROR_LEN = 256;
6107
6108 struct guestfs_message_error {
6109   string error_message<GUESTFS_ERROR_LEN>;
6110 };
6111
6112 struct guestfs_message_header {
6113   unsigned prog;                     /* GUESTFS_PROGRAM */
6114   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
6115   guestfs_procedure proc;            /* GUESTFS_PROC_x */
6116   guestfs_message_direction direction;
6117   unsigned serial;                   /* message serial number */
6118   guestfs_message_status status;
6119 };
6120
6121 const GUESTFS_MAX_CHUNK_SIZE = 8192;
6122
6123 struct guestfs_chunk {
6124   int cancel;                        /* if non-zero, transfer is cancelled */
6125   /* data size is 0 bytes if the transfer has finished successfully */
6126   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
6127 };
6128 "
6129
6130 (* Generate the guestfs-structs.h file. *)
6131 and generate_structs_h () =
6132   generate_header CStyle LGPLv2plus;
6133
6134   (* This is a public exported header file containing various
6135    * structures.  The structures are carefully written to have
6136    * exactly the same in-memory format as the XDR structures that
6137    * we use on the wire to the daemon.  The reason for creating
6138    * copies of these structures here is just so we don't have to
6139    * export the whole of guestfs_protocol.h (which includes much
6140    * unrelated and XDR-dependent stuff that we don't want to be
6141    * public, or required by clients).
6142    *
6143    * To reiterate, we will pass these structures to and from the
6144    * client with a simple assignment or memcpy, so the format
6145    * must be identical to what rpcgen / the RFC defines.
6146    *)
6147
6148   (* Public structures. *)
6149   List.iter (
6150     fun (typ, cols) ->
6151       pr "struct guestfs_%s {\n" typ;
6152       List.iter (
6153         function
6154         | name, FChar -> pr "  char %s;\n" name
6155         | name, FString -> pr "  char *%s;\n" name
6156         | name, FBuffer ->
6157             pr "  uint32_t %s_len;\n" name;
6158             pr "  char *%s;\n" name
6159         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
6160         | name, FUInt32 -> pr "  uint32_t %s;\n" name
6161         | name, FInt32 -> pr "  int32_t %s;\n" name
6162         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
6163         | name, FInt64 -> pr "  int64_t %s;\n" name
6164         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
6165       ) cols;
6166       pr "};\n";
6167       pr "\n";
6168       pr "struct guestfs_%s_list {\n" typ;
6169       pr "  uint32_t len;\n";
6170       pr "  struct guestfs_%s *val;\n" typ;
6171       pr "};\n";
6172       pr "\n";
6173       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
6174       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
6175       pr "\n"
6176   ) structs
6177
6178 (* Generate the guestfs-actions.h file. *)
6179 and generate_actions_h () =
6180   generate_header CStyle LGPLv2plus;
6181   List.iter (
6182     fun (shortname, style, _, _, _, _, _) ->
6183       let name = "guestfs_" ^ shortname in
6184       generate_prototype ~single_line:true ~newline:true ~handle:"g"
6185         name style
6186   ) all_functions
6187
6188 (* Generate the guestfs-internal-actions.h file. *)
6189 and generate_internal_actions_h () =
6190   generate_header CStyle LGPLv2plus;
6191   List.iter (
6192     fun (shortname, style, _, _, _, _, _) ->
6193       let name = "guestfs__" ^ shortname in
6194       generate_prototype ~single_line:true ~newline:true ~handle:"g"
6195         name style
6196   ) non_daemon_functions
6197
6198 (* Generate the client-side dispatch stubs. *)
6199 and generate_client_actions () =
6200   generate_header CStyle LGPLv2plus;
6201
6202   pr "\
6203 #include <stdio.h>
6204 #include <stdlib.h>
6205 #include <stdint.h>
6206 #include <string.h>
6207 #include <inttypes.h>
6208
6209 #include \"guestfs.h\"
6210 #include \"guestfs-internal.h\"
6211 #include \"guestfs-internal-actions.h\"
6212 #include \"guestfs_protocol.h\"
6213
6214 /* Check the return message from a call for validity. */
6215 static int
6216 check_reply_header (guestfs_h *g,
6217                     const struct guestfs_message_header *hdr,
6218                     unsigned int proc_nr, unsigned int serial)
6219 {
6220   if (hdr->prog != GUESTFS_PROGRAM) {
6221     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
6222     return -1;
6223   }
6224   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
6225     error (g, \"wrong protocol version (%%d/%%d)\",
6226            hdr->vers, GUESTFS_PROTOCOL_VERSION);
6227     return -1;
6228   }
6229   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
6230     error (g, \"unexpected message direction (%%d/%%d)\",
6231            hdr->direction, GUESTFS_DIRECTION_REPLY);
6232     return -1;
6233   }
6234   if (hdr->proc != proc_nr) {
6235     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
6236     return -1;
6237   }
6238   if (hdr->serial != serial) {
6239     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
6240     return -1;
6241   }
6242
6243   return 0;
6244 }
6245
6246 /* Check we are in the right state to run a high-level action. */
6247 static int
6248 check_state (guestfs_h *g, const char *caller)
6249 {
6250   if (!guestfs__is_ready (g)) {
6251     if (guestfs__is_config (g) || guestfs__is_launching (g))
6252       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
6253         caller);
6254     else
6255       error (g, \"%%s called from the wrong state, %%d != READY\",
6256         caller, guestfs__get_state (g));
6257     return -1;
6258   }
6259   return 0;
6260 }
6261
6262 ";
6263
6264   let error_code_of = function
6265     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
6266     | RConstString _ | RConstOptString _
6267     | RString _ | RStringList _
6268     | RStruct _ | RStructList _
6269     | RHashtable _ | RBufferOut _ -> "NULL"
6270   in
6271
6272   (* Generate code to check String-like parameters are not passed in
6273    * as NULL (returning an error if they are).
6274    *)
6275   let check_null_strings shortname style =
6276     let pr_newline = ref false in
6277     List.iter (
6278       function
6279       (* parameters which should not be NULL *)
6280       | String n
6281       | Device n
6282       | Pathname n
6283       | Dev_or_Path n
6284       | FileIn n
6285       | FileOut n
6286       | BufferIn n
6287       | StringList n
6288       | DeviceList n
6289       | Key n ->
6290           pr "  if (%s == NULL) {\n" n;
6291           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6292           pr "           \"%s\", \"%s\");\n" shortname n;
6293           pr "    return %s;\n" (error_code_of (fst style));
6294           pr "  }\n";
6295           pr_newline := true
6296
6297       (* can be NULL *)
6298       | OptString _
6299
6300       (* not applicable *)
6301       | Bool _
6302       | Int _
6303       | Int64 _ -> ()
6304     ) (snd style);
6305
6306     if !pr_newline then pr "\n";
6307   in
6308
6309   (* Generate code to generate guestfish call traces. *)
6310   let trace_call shortname style =
6311     pr "  if (guestfs__get_trace (g)) {\n";
6312
6313     let needs_i =
6314       List.exists (function
6315                    | StringList _ | DeviceList _ -> true
6316                    | _ -> false) (snd style) in
6317     if needs_i then (
6318       pr "    size_t i;\n";
6319       pr "\n"
6320     );
6321
6322     pr "    fprintf (stderr, \"%s\");\n" shortname;
6323     List.iter (
6324       function
6325       | String n                        (* strings *)
6326       | Device n
6327       | Pathname n
6328       | Dev_or_Path n
6329       | FileIn n
6330       | FileOut n
6331       | BufferIn n
6332       | Key n ->
6333           (* guestfish doesn't support string escaping, so neither do we *)
6334           pr "    fprintf (stderr, \" \\\"%%s\\\"\", %s);\n" n
6335       | OptString n ->                  (* string option *)
6336           pr "    if (%s) fprintf (stderr, \" \\\"%%s\\\"\", %s);\n" n n;
6337           pr "    else fprintf (stderr, \" null\");\n"
6338       | StringList n
6339       | DeviceList n ->                 (* string list *)
6340           pr "    fputc (' ', stderr);\n";
6341           pr "    fputc ('\"', stderr);\n";
6342           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6343           pr "      if (i > 0) fputc (' ', stderr);\n";
6344           pr "      fputs (%s[i], stderr);\n" n;
6345           pr "    }\n";
6346           pr "    fputc ('\"', stderr);\n";
6347       | Bool n ->                       (* boolean *)
6348           pr "    fputs (%s ? \" true\" : \" false\", stderr);\n" n
6349       | Int n ->                        (* int *)
6350           pr "    fprintf (stderr, \" %%d\", %s);\n" n
6351       | Int64 n ->
6352           pr "    fprintf (stderr, \" %%\" PRIi64, %s);\n" n
6353     ) (snd style);
6354     pr "    fputc ('\\n', stderr);\n";
6355     pr "  }\n";
6356     pr "\n";
6357   in
6358
6359   (* For non-daemon functions, generate a wrapper around each function. *)
6360   List.iter (
6361     fun (shortname, style, _, _, _, _, _) ->
6362       let name = "guestfs_" ^ shortname in
6363
6364       generate_prototype ~extern:false ~semicolon:false ~newline:true
6365         ~handle:"g" name style;
6366       pr "{\n";
6367       check_null_strings shortname style;
6368       trace_call shortname style;
6369       pr "  return guestfs__%s " shortname;
6370       generate_c_call_args ~handle:"g" style;
6371       pr ";\n";
6372       pr "}\n";
6373       pr "\n"
6374   ) non_daemon_functions;
6375
6376   (* Client-side stubs for each function. *)
6377   List.iter (
6378     fun (shortname, style, _, _, _, _, _) ->
6379       let name = "guestfs_" ^ shortname in
6380       let error_code = error_code_of (fst style) in
6381
6382       (* Generate the action stub. *)
6383       generate_prototype ~extern:false ~semicolon:false ~newline:true
6384         ~handle:"g" name style;
6385
6386       pr "{\n";
6387
6388       (match snd style with
6389        | [] -> ()
6390        | _ -> pr "  struct %s_args args;\n" name
6391       );
6392
6393       pr "  guestfs_message_header hdr;\n";
6394       pr "  guestfs_message_error err;\n";
6395       let has_ret =
6396         match fst style with
6397         | RErr -> false
6398         | RConstString _ | RConstOptString _ ->
6399             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6400         | RInt _ | RInt64 _
6401         | RBool _ | RString _ | RStringList _
6402         | RStruct _ | RStructList _
6403         | RHashtable _ | RBufferOut _ ->
6404             pr "  struct %s_ret ret;\n" name;
6405             true in
6406
6407       pr "  int serial;\n";
6408       pr "  int r;\n";
6409       pr "\n";
6410       check_null_strings shortname style;
6411       trace_call shortname style;
6412       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6413         shortname error_code;
6414       pr "  guestfs___set_busy (g);\n";
6415       pr "\n";
6416
6417       (* Send the main header and arguments. *)
6418       (match snd style with
6419        | [] ->
6420            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6421              (String.uppercase shortname)
6422        | args ->
6423            List.iter (
6424              function
6425              | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
6426                  pr "  args.%s = (char *) %s;\n" n n
6427              | OptString n ->
6428                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6429              | StringList n | DeviceList n ->
6430                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6431                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6432              | Bool n ->
6433                  pr "  args.%s = %s;\n" n n
6434              | Int n ->
6435                  pr "  args.%s = %s;\n" n n
6436              | Int64 n ->
6437                  pr "  args.%s = %s;\n" n n
6438              | FileIn _ | FileOut _ -> ()
6439              | BufferIn n ->
6440                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6441                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6442                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6443                    shortname;
6444                  pr "    guestfs___end_busy (g);\n";
6445                  pr "    return %s;\n" error_code;
6446                  pr "  }\n";
6447                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6448                  pr "  args.%s.%s_len = %s_size;\n" n n n
6449            ) args;
6450            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6451              (String.uppercase shortname);
6452            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6453              name;
6454       );
6455       pr "  if (serial == -1) {\n";
6456       pr "    guestfs___end_busy (g);\n";
6457       pr "    return %s;\n" error_code;
6458       pr "  }\n";
6459       pr "\n";
6460
6461       (* Send any additional files (FileIn) requested. *)
6462       let need_read_reply_label = ref false in
6463       List.iter (
6464         function
6465         | FileIn n ->
6466             pr "  r = guestfs___send_file (g, %s);\n" n;
6467             pr "  if (r == -1) {\n";
6468             pr "    guestfs___end_busy (g);\n";
6469             pr "    return %s;\n" error_code;
6470             pr "  }\n";
6471             pr "  if (r == -2) /* daemon cancelled */\n";
6472             pr "    goto read_reply;\n";
6473             need_read_reply_label := true;
6474             pr "\n";
6475         | _ -> ()
6476       ) (snd style);
6477
6478       (* Wait for the reply from the remote end. *)
6479       if !need_read_reply_label then pr " read_reply:\n";
6480       pr "  memset (&hdr, 0, sizeof hdr);\n";
6481       pr "  memset (&err, 0, sizeof err);\n";
6482       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6483       pr "\n";
6484       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6485       if not has_ret then
6486         pr "NULL, NULL"
6487       else
6488         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6489       pr ");\n";
6490
6491       pr "  if (r == -1) {\n";
6492       pr "    guestfs___end_busy (g);\n";
6493       pr "    return %s;\n" error_code;
6494       pr "  }\n";
6495       pr "\n";
6496
6497       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6498         (String.uppercase shortname);
6499       pr "    guestfs___end_busy (g);\n";
6500       pr "    return %s;\n" error_code;
6501       pr "  }\n";
6502       pr "\n";
6503
6504       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6505       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6506       pr "    free (err.error_message);\n";
6507       pr "    guestfs___end_busy (g);\n";
6508       pr "    return %s;\n" error_code;
6509       pr "  }\n";
6510       pr "\n";
6511
6512       (* Expecting to receive further files (FileOut)? *)
6513       List.iter (
6514         function
6515         | FileOut n ->
6516             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6517             pr "    guestfs___end_busy (g);\n";
6518             pr "    return %s;\n" error_code;
6519             pr "  }\n";
6520             pr "\n";
6521         | _ -> ()
6522       ) (snd style);
6523
6524       pr "  guestfs___end_busy (g);\n";
6525
6526       (match fst style with
6527        | RErr -> pr "  return 0;\n"
6528        | RInt n | RInt64 n | RBool n ->
6529            pr "  return ret.%s;\n" n
6530        | RConstString _ | RConstOptString _ ->
6531            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6532        | RString n ->
6533            pr "  return ret.%s; /* caller will free */\n" n
6534        | RStringList n | RHashtable n ->
6535            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6536            pr "  ret.%s.%s_val =\n" n n;
6537            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6538            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6539              n n;
6540            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6541            pr "  return ret.%s.%s_val;\n" n n
6542        | RStruct (n, _) ->
6543            pr "  /* caller will free this */\n";
6544            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6545        | RStructList (n, _) ->
6546            pr "  /* caller will free this */\n";
6547            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6548        | RBufferOut n ->
6549            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6550            pr "   * _val might be NULL here.  To make the API saner for\n";
6551            pr "   * callers, we turn this case into a unique pointer (using\n";
6552            pr "   * malloc(1)).\n";
6553            pr "   */\n";
6554            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6555            pr "    *size_r = ret.%s.%s_len;\n" n n;
6556            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6557            pr "  } else {\n";
6558            pr "    free (ret.%s.%s_val);\n" n n;
6559            pr "    char *p = safe_malloc (g, 1);\n";
6560            pr "    *size_r = ret.%s.%s_len;\n" n n;
6561            pr "    return p;\n";
6562            pr "  }\n";
6563       );
6564
6565       pr "}\n\n"
6566   ) daemon_functions;
6567
6568   (* Functions to free structures. *)
6569   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6570   pr " * structure format is identical to the XDR format.  See note in\n";
6571   pr " * generator.ml.\n";
6572   pr " */\n";
6573   pr "\n";
6574
6575   List.iter (
6576     fun (typ, _) ->
6577       pr "void\n";
6578       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6579       pr "{\n";
6580       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6581       pr "  free (x);\n";
6582       pr "}\n";
6583       pr "\n";
6584
6585       pr "void\n";
6586       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6587       pr "{\n";
6588       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6589       pr "  free (x);\n";
6590       pr "}\n";
6591       pr "\n";
6592
6593   ) structs;
6594
6595 (* Generate daemon/actions.h. *)
6596 and generate_daemon_actions_h () =
6597   generate_header CStyle GPLv2plus;
6598
6599   pr "#include \"../src/guestfs_protocol.h\"\n";
6600   pr "\n";
6601
6602   List.iter (
6603     fun (name, style, _, _, _, _, _) ->
6604       generate_prototype
6605         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6606         name style;
6607   ) daemon_functions
6608
6609 (* Generate the linker script which controls the visibility of
6610  * symbols in the public ABI and ensures no other symbols get
6611  * exported accidentally.
6612  *)
6613 and generate_linker_script () =
6614   generate_header HashStyle GPLv2plus;
6615
6616   let globals = [
6617     "guestfs_create";
6618     "guestfs_close";
6619     "guestfs_get_error_handler";
6620     "guestfs_get_out_of_memory_handler";
6621     "guestfs_last_error";
6622     "guestfs_set_close_callback";
6623     "guestfs_set_error_handler";
6624     "guestfs_set_launch_done_callback";
6625     "guestfs_set_log_message_callback";
6626     "guestfs_set_out_of_memory_handler";
6627     "guestfs_set_subprocess_quit_callback";
6628
6629     (* Unofficial parts of the API: the bindings code use these
6630      * functions, so it is useful to export them.
6631      *)
6632     "guestfs_safe_calloc";
6633     "guestfs_safe_malloc";
6634     "guestfs_safe_strdup";
6635     "guestfs_safe_memdup";
6636   ] in
6637   let functions =
6638     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6639       all_functions in
6640   let structs =
6641     List.concat (
6642       List.map (fun (typ, _) ->
6643                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6644         structs
6645     ) in
6646   let globals = List.sort compare (globals @ functions @ structs) in
6647
6648   pr "{\n";
6649   pr "    global:\n";
6650   List.iter (pr "        %s;\n") globals;
6651   pr "\n";
6652
6653   pr "    local:\n";
6654   pr "        *;\n";
6655   pr "};\n"
6656
6657 (* Generate the server-side stubs. *)
6658 and generate_daemon_actions () =
6659   generate_header CStyle GPLv2plus;
6660
6661   pr "#include <config.h>\n";
6662   pr "\n";
6663   pr "#include <stdio.h>\n";
6664   pr "#include <stdlib.h>\n";
6665   pr "#include <string.h>\n";
6666   pr "#include <inttypes.h>\n";
6667   pr "#include <rpc/types.h>\n";
6668   pr "#include <rpc/xdr.h>\n";
6669   pr "\n";
6670   pr "#include \"daemon.h\"\n";
6671   pr "#include \"c-ctype.h\"\n";
6672   pr "#include \"../src/guestfs_protocol.h\"\n";
6673   pr "#include \"actions.h\"\n";
6674   pr "\n";
6675
6676   List.iter (
6677     fun (name, style, _, _, _, _, _) ->
6678       (* Generate server-side stubs. *)
6679       pr "static void %s_stub (XDR *xdr_in)\n" name;
6680       pr "{\n";
6681       let error_code =
6682         match fst style with
6683         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6684         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6685         | RBool _ -> pr "  int r;\n"; "-1"
6686         | RConstString _ | RConstOptString _ ->
6687             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6688         | RString _ -> pr "  char *r;\n"; "NULL"
6689         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6690         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6691         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6692         | RBufferOut _ ->
6693             pr "  size_t size = 1;\n";
6694             pr "  char *r;\n";
6695             "NULL" in
6696
6697       (match snd style with
6698        | [] -> ()
6699        | args ->
6700            pr "  struct guestfs_%s_args args;\n" name;
6701            List.iter (
6702              function
6703              | Device n | Dev_or_Path n
6704              | Pathname n
6705              | String n
6706              | Key n -> ()
6707              | OptString n -> pr "  char *%s;\n" n
6708              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6709              | Bool n -> pr "  int %s;\n" n
6710              | Int n -> pr "  int %s;\n" n
6711              | Int64 n -> pr "  int64_t %s;\n" n
6712              | FileIn _ | FileOut _ -> ()
6713              | BufferIn n ->
6714                  pr "  const char *%s;\n" n;
6715                  pr "  size_t %s_size;\n" n
6716            ) args
6717       );
6718       pr "\n";
6719
6720       let is_filein =
6721         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6722
6723       (match snd style with
6724        | [] -> ()
6725        | args ->
6726            pr "  memset (&args, 0, sizeof args);\n";
6727            pr "\n";
6728            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6729            if is_filein then
6730              pr "    if (cancel_receive () != -2)\n";
6731            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6732            pr "    goto done;\n";
6733            pr "  }\n";
6734            let pr_args n =
6735              pr "  char *%s = args.%s;\n" n n
6736            in
6737            let pr_list_handling_code n =
6738              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6739              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6740              pr "  if (%s == NULL) {\n" n;
6741              if is_filein then
6742                pr "    if (cancel_receive () != -2)\n";
6743              pr "      reply_with_perror (\"realloc\");\n";
6744              pr "    goto done;\n";
6745              pr "  }\n";
6746              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6747              pr "  args.%s.%s_val = %s;\n" n n n;
6748            in
6749            List.iter (
6750              function
6751              | Pathname n ->
6752                  pr_args n;
6753                  pr "  ABS_PATH (%s, %s, goto done);\n"
6754                    n (if is_filein then "cancel_receive ()" else "0");
6755              | Device n ->
6756                  pr_args n;
6757                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6758                    n (if is_filein then "cancel_receive ()" else "0");
6759              | Dev_or_Path n ->
6760                  pr_args n;
6761                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6762                    n (if is_filein then "cancel_receive ()" else "0");
6763              | String n | Key n -> pr_args n
6764              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6765              | StringList n ->
6766                  pr_list_handling_code n;
6767              | DeviceList n ->
6768                  pr_list_handling_code n;
6769                  pr "  /* Ensure that each is a device,\n";
6770                  pr "   * and perform device name translation.\n";
6771                  pr "   */\n";
6772                  pr "  {\n";
6773                  pr "    size_t i;\n";
6774                  pr "    for (i = 0; %s[i] != NULL; ++i)\n" n;
6775                  pr "      RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6776                    (if is_filein then "cancel_receive ()" else "0");
6777                  pr "  }\n";
6778              | Bool n -> pr "  %s = args.%s;\n" n n
6779              | Int n -> pr "  %s = args.%s;\n" n n
6780              | Int64 n -> pr "  %s = args.%s;\n" n n
6781              | FileIn _ | FileOut _ -> ()
6782              | BufferIn n ->
6783                  pr "  %s = args.%s.%s_val;\n" n n n;
6784                  pr "  %s_size = args.%s.%s_len;\n" n n n
6785            ) args;
6786            pr "\n"
6787       );
6788
6789       (* this is used at least for do_equal *)
6790       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6791         (* Emit NEED_ROOT just once, even when there are two or
6792            more Pathname args *)
6793         pr "  NEED_ROOT (%s, goto done);\n"
6794           (if is_filein then "cancel_receive ()" else "0");
6795       );
6796
6797       (* Don't want to call the impl with any FileIn or FileOut
6798        * parameters, since these go "outside" the RPC protocol.
6799        *)
6800       let args' =
6801         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6802           (snd style) in
6803       pr "  r = do_%s " name;
6804       generate_c_call_args (fst style, args');
6805       pr ";\n";
6806
6807       (match fst style with
6808        | RErr | RInt _ | RInt64 _ | RBool _
6809        | RConstString _ | RConstOptString _
6810        | RString _ | RStringList _ | RHashtable _
6811        | RStruct (_, _) | RStructList (_, _) ->
6812            pr "  if (r == %s)\n" error_code;
6813            pr "    /* do_%s has already called reply_with_error */\n" name;
6814            pr "    goto done;\n";
6815            pr "\n"
6816        | RBufferOut _ ->
6817            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6818            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6819            pr "   */\n";
6820            pr "  if (size == 1 && r == %s)\n" error_code;
6821            pr "    /* do_%s has already called reply_with_error */\n" name;
6822            pr "    goto done;\n";
6823            pr "\n"
6824       );
6825
6826       (* If there are any FileOut parameters, then the impl must
6827        * send its own reply.
6828        *)
6829       let no_reply =
6830         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6831       if no_reply then
6832         pr "  /* do_%s has already sent a reply */\n" name
6833       else (
6834         match fst style with
6835         | RErr -> pr "  reply (NULL, NULL);\n"
6836         | RInt n | RInt64 n | RBool n ->
6837             pr "  struct guestfs_%s_ret ret;\n" name;
6838             pr "  ret.%s = r;\n" n;
6839             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6840               name
6841         | RConstString _ | RConstOptString _ ->
6842             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6843         | RString n ->
6844             pr "  struct guestfs_%s_ret ret;\n" name;
6845             pr "  ret.%s = r;\n" n;
6846             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6847               name;
6848             pr "  free (r);\n"
6849         | RStringList n | RHashtable n ->
6850             pr "  struct guestfs_%s_ret ret;\n" name;
6851             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6852             pr "  ret.%s.%s_val = r;\n" n n;
6853             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6854               name;
6855             pr "  free_strings (r);\n"
6856         | RStruct (n, _) ->
6857             pr "  struct guestfs_%s_ret ret;\n" name;
6858             pr "  ret.%s = *r;\n" n;
6859             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6860               name;
6861             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6862               name
6863         | RStructList (n, _) ->
6864             pr "  struct guestfs_%s_ret ret;\n" name;
6865             pr "  ret.%s = *r;\n" n;
6866             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6867               name;
6868             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6869               name
6870         | RBufferOut n ->
6871             pr "  struct guestfs_%s_ret ret;\n" name;
6872             pr "  ret.%s.%s_val = r;\n" n n;
6873             pr "  ret.%s.%s_len = size;\n" n n;
6874             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6875               name;
6876             pr "  free (r);\n"
6877       );
6878
6879       (* Free the args. *)
6880       pr "done:\n";
6881       (match snd style with
6882        | [] -> ()
6883        | _ ->
6884            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6885              name
6886       );
6887       pr "  return;\n";
6888       pr "}\n\n";
6889   ) daemon_functions;
6890
6891   (* Dispatch function. *)
6892   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6893   pr "{\n";
6894   pr "  switch (proc_nr) {\n";
6895
6896   List.iter (
6897     fun (name, style, _, _, _, _, _) ->
6898       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6899       pr "      %s_stub (xdr_in);\n" name;
6900       pr "      break;\n"
6901   ) daemon_functions;
6902
6903   pr "    default:\n";
6904   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";
6905   pr "  }\n";
6906   pr "}\n";
6907   pr "\n";
6908
6909   (* LVM columns and tokenization functions. *)
6910   (* XXX This generates crap code.  We should rethink how we
6911    * do this parsing.
6912    *)
6913   List.iter (
6914     function
6915     | typ, cols ->
6916         pr "static const char *lvm_%s_cols = \"%s\";\n"
6917           typ (String.concat "," (List.map fst cols));
6918         pr "\n";
6919
6920         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6921         pr "{\n";
6922         pr "  char *tok, *p, *next;\n";
6923         pr "  size_t i, j;\n";
6924         pr "\n";
6925         (*
6926           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6927           pr "\n";
6928         *)
6929         pr "  if (!str) {\n";
6930         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6931         pr "    return -1;\n";
6932         pr "  }\n";
6933         pr "  if (!*str || c_isspace (*str)) {\n";
6934         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6935         pr "    return -1;\n";
6936         pr "  }\n";
6937         pr "  tok = str;\n";
6938         List.iter (
6939           fun (name, coltype) ->
6940             pr "  if (!tok) {\n";
6941             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6942             pr "    return -1;\n";
6943             pr "  }\n";
6944             pr "  p = strchrnul (tok, ',');\n";
6945             pr "  if (*p) next = p+1; else next = NULL;\n";
6946             pr "  *p = '\\0';\n";
6947             (match coltype with
6948              | FString ->
6949                  pr "  r->%s = strdup (tok);\n" name;
6950                  pr "  if (r->%s == NULL) {\n" name;
6951                  pr "    perror (\"strdup\");\n";
6952                  pr "    return -1;\n";
6953                  pr "  }\n"
6954              | FUUID ->
6955                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6956                  pr "    if (tok[j] == '\\0') {\n";
6957                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6958                  pr "      return -1;\n";
6959                  pr "    } else if (tok[j] != '-')\n";
6960                  pr "      r->%s[i++] = tok[j];\n" name;
6961                  pr "  }\n";
6962              | FBytes ->
6963                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6964                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6965                  pr "    return -1;\n";
6966                  pr "  }\n";
6967              | FInt64 ->
6968                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6969                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6970                  pr "    return -1;\n";
6971                  pr "  }\n";
6972              | FOptPercent ->
6973                  pr "  if (tok[0] == '\\0')\n";
6974                  pr "    r->%s = -1;\n" name;
6975                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6976                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6977                  pr "    return -1;\n";
6978                  pr "  }\n";
6979              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6980                  assert false (* can never be an LVM column *)
6981             );
6982             pr "  tok = next;\n";
6983         ) cols;
6984
6985         pr "  if (tok != NULL) {\n";
6986         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6987         pr "    return -1;\n";
6988         pr "  }\n";
6989         pr "  return 0;\n";
6990         pr "}\n";
6991         pr "\n";
6992
6993         pr "guestfs_int_lvm_%s_list *\n" typ;
6994         pr "parse_command_line_%ss (void)\n" typ;
6995         pr "{\n";
6996         pr "  char *out, *err;\n";
6997         pr "  char *p, *pend;\n";
6998         pr "  int r, i;\n";
6999         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
7000         pr "  void *newp;\n";
7001         pr "\n";
7002         pr "  ret = malloc (sizeof *ret);\n";
7003         pr "  if (!ret) {\n";
7004         pr "    reply_with_perror (\"malloc\");\n";
7005         pr "    return NULL;\n";
7006         pr "  }\n";
7007         pr "\n";
7008         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
7009         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
7010         pr "\n";
7011         pr "  r = command (&out, &err,\n";
7012         pr "           \"lvm\", \"%ss\",\n" typ;
7013         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
7014         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
7015         pr "  if (r == -1) {\n";
7016         pr "    reply_with_error (\"%%s\", err);\n";
7017         pr "    free (out);\n";
7018         pr "    free (err);\n";
7019         pr "    free (ret);\n";
7020         pr "    return NULL;\n";
7021         pr "  }\n";
7022         pr "\n";
7023         pr "  free (err);\n";
7024         pr "\n";
7025         pr "  /* Tokenize each line of the output. */\n";
7026         pr "  p = out;\n";
7027         pr "  i = 0;\n";
7028         pr "  while (p) {\n";
7029         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
7030         pr "    if (pend) {\n";
7031         pr "      *pend = '\\0';\n";
7032         pr "      pend++;\n";
7033         pr "    }\n";
7034         pr "\n";
7035         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
7036         pr "      p++;\n";
7037         pr "\n";
7038         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
7039         pr "      p = pend;\n";
7040         pr "      continue;\n";
7041         pr "    }\n";
7042         pr "\n";
7043         pr "    /* Allocate some space to store this next entry. */\n";
7044         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
7045         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
7046         pr "    if (newp == NULL) {\n";
7047         pr "      reply_with_perror (\"realloc\");\n";
7048         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
7049         pr "      free (ret);\n";
7050         pr "      free (out);\n";
7051         pr "      return NULL;\n";
7052         pr "    }\n";
7053         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
7054         pr "\n";
7055         pr "    /* Tokenize the next entry. */\n";
7056         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
7057         pr "    if (r == -1) {\n";
7058         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
7059         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
7060         pr "      free (ret);\n";
7061         pr "      free (out);\n";
7062         pr "      return NULL;\n";
7063         pr "    }\n";
7064         pr "\n";
7065         pr "    ++i;\n";
7066         pr "    p = pend;\n";
7067         pr "  }\n";
7068         pr "\n";
7069         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
7070         pr "\n";
7071         pr "  free (out);\n";
7072         pr "  return ret;\n";
7073         pr "}\n"
7074
7075   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
7076
7077 (* Generate a list of function names, for debugging in the daemon.. *)
7078 and generate_daemon_names () =
7079   generate_header CStyle GPLv2plus;
7080
7081   pr "#include <config.h>\n";
7082   pr "\n";
7083   pr "#include \"daemon.h\"\n";
7084   pr "\n";
7085
7086   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
7087   pr "const char *function_names[] = {\n";
7088   List.iter (
7089     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
7090   ) daemon_functions;
7091   pr "};\n";
7092
7093 (* Generate the optional groups for the daemon to implement
7094  * guestfs_available.
7095  *)
7096 and generate_daemon_optgroups_c () =
7097   generate_header CStyle GPLv2plus;
7098
7099   pr "#include <config.h>\n";
7100   pr "\n";
7101   pr "#include \"daemon.h\"\n";
7102   pr "#include \"optgroups.h\"\n";
7103   pr "\n";
7104
7105   pr "struct optgroup optgroups[] = {\n";
7106   List.iter (
7107     fun (group, _) ->
7108       pr "  { \"%s\", optgroup_%s_available },\n" group group
7109   ) optgroups;
7110   pr "  { NULL, NULL }\n";
7111   pr "};\n"
7112
7113 and generate_daemon_optgroups_h () =
7114   generate_header CStyle GPLv2plus;
7115
7116   List.iter (
7117     fun (group, _) ->
7118       pr "extern int optgroup_%s_available (void);\n" group
7119   ) optgroups
7120
7121 (* Generate the tests. *)
7122 and generate_tests () =
7123   generate_header CStyle GPLv2plus;
7124
7125   pr "\
7126 #include <stdio.h>
7127 #include <stdlib.h>
7128 #include <string.h>
7129 #include <unistd.h>
7130 #include <sys/types.h>
7131 #include <fcntl.h>
7132
7133 #include \"guestfs.h\"
7134 #include \"guestfs-internal.h\"
7135
7136 static guestfs_h *g;
7137 static int suppress_error = 0;
7138
7139 static void print_error (guestfs_h *g, void *data, const char *msg)
7140 {
7141   if (!suppress_error)
7142     fprintf (stderr, \"%%s\\n\", msg);
7143 }
7144
7145 /* FIXME: nearly identical code appears in fish.c */
7146 static void print_strings (char *const *argv)
7147 {
7148   size_t argc;
7149
7150   for (argc = 0; argv[argc] != NULL; ++argc)
7151     printf (\"\\t%%s\\n\", argv[argc]);
7152 }
7153
7154 /*
7155 static void print_table (char const *const *argv)
7156 {
7157   size_t i;
7158
7159   for (i = 0; argv[i] != NULL; i += 2)
7160     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
7161 }
7162 */
7163
7164 static int
7165 is_available (const char *group)
7166 {
7167   const char *groups[] = { group, NULL };
7168   int r;
7169
7170   suppress_error = 1;
7171   r = guestfs_available (g, (char **) groups);
7172   suppress_error = 0;
7173
7174   return r == 0;
7175 }
7176
7177 static void
7178 incr (guestfs_h *g, void *iv)
7179 {
7180   int *i = (int *) iv;
7181   (*i)++;
7182 }
7183
7184 ";
7185
7186   (* Generate a list of commands which are not tested anywhere. *)
7187   pr "static void no_test_warnings (void)\n";
7188   pr "{\n";
7189
7190   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
7191   List.iter (
7192     fun (_, _, _, _, tests, _, _) ->
7193       let tests = filter_map (
7194         function
7195         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
7196         | (_, Disabled, _) -> None
7197       ) tests in
7198       let seq = List.concat (List.map seq_of_test tests) in
7199       let cmds_tested = List.map List.hd seq in
7200       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
7201   ) all_functions;
7202
7203   List.iter (
7204     fun (name, _, _, _, _, _, _) ->
7205       if not (Hashtbl.mem hash name) then
7206         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
7207   ) all_functions;
7208
7209   pr "}\n";
7210   pr "\n";
7211
7212   (* Generate the actual tests.  Note that we generate the tests
7213    * in reverse order, deliberately, so that (in general) the
7214    * newest tests run first.  This makes it quicker and easier to
7215    * debug them.
7216    *)
7217   let test_names =
7218     List.map (
7219       fun (name, _, _, flags, tests, _, _) ->
7220         mapi (generate_one_test name flags) tests
7221     ) (List.rev all_functions) in
7222   let test_names = List.concat test_names in
7223   let nr_tests = List.length test_names in
7224
7225   pr "\
7226 int main (int argc, char *argv[])
7227 {
7228   char c = 0;
7229   unsigned long int n_failed = 0;
7230   const char *filename;
7231   int fd;
7232   int nr_tests, test_num = 0;
7233
7234   setbuf (stdout, NULL);
7235
7236   no_test_warnings ();
7237
7238   g = guestfs_create ();
7239   if (g == NULL) {
7240     printf (\"guestfs_create FAILED\\n\");
7241     exit (EXIT_FAILURE);
7242   }
7243
7244   guestfs_set_error_handler (g, print_error, NULL);
7245
7246   guestfs_set_path (g, \"../appliance\");
7247
7248   filename = \"test1.img\";
7249   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7250   if (fd == -1) {
7251     perror (filename);
7252     exit (EXIT_FAILURE);
7253   }
7254   if (lseek (fd, %d, SEEK_SET) == -1) {
7255     perror (\"lseek\");
7256     close (fd);
7257     unlink (filename);
7258     exit (EXIT_FAILURE);
7259   }
7260   if (write (fd, &c, 1) == -1) {
7261     perror (\"write\");
7262     close (fd);
7263     unlink (filename);
7264     exit (EXIT_FAILURE);
7265   }
7266   if (close (fd) == -1) {
7267     perror (filename);
7268     unlink (filename);
7269     exit (EXIT_FAILURE);
7270   }
7271   if (guestfs_add_drive (g, filename) == -1) {
7272     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7273     exit (EXIT_FAILURE);
7274   }
7275
7276   filename = \"test2.img\";
7277   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7278   if (fd == -1) {
7279     perror (filename);
7280     exit (EXIT_FAILURE);
7281   }
7282   if (lseek (fd, %d, SEEK_SET) == -1) {
7283     perror (\"lseek\");
7284     close (fd);
7285     unlink (filename);
7286     exit (EXIT_FAILURE);
7287   }
7288   if (write (fd, &c, 1) == -1) {
7289     perror (\"write\");
7290     close (fd);
7291     unlink (filename);
7292     exit (EXIT_FAILURE);
7293   }
7294   if (close (fd) == -1) {
7295     perror (filename);
7296     unlink (filename);
7297     exit (EXIT_FAILURE);
7298   }
7299   if (guestfs_add_drive (g, filename) == -1) {
7300     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7301     exit (EXIT_FAILURE);
7302   }
7303
7304   filename = \"test3.img\";
7305   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7306   if (fd == -1) {
7307     perror (filename);
7308     exit (EXIT_FAILURE);
7309   }
7310   if (lseek (fd, %d, SEEK_SET) == -1) {
7311     perror (\"lseek\");
7312     close (fd);
7313     unlink (filename);
7314     exit (EXIT_FAILURE);
7315   }
7316   if (write (fd, &c, 1) == -1) {
7317     perror (\"write\");
7318     close (fd);
7319     unlink (filename);
7320     exit (EXIT_FAILURE);
7321   }
7322   if (close (fd) == -1) {
7323     perror (filename);
7324     unlink (filename);
7325     exit (EXIT_FAILURE);
7326   }
7327   if (guestfs_add_drive (g, filename) == -1) {
7328     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7329     exit (EXIT_FAILURE);
7330   }
7331
7332   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7333     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7334     exit (EXIT_FAILURE);
7335   }
7336
7337   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7338   alarm (600);
7339
7340   if (guestfs_launch (g) == -1) {
7341     printf (\"guestfs_launch FAILED\\n\");
7342     exit (EXIT_FAILURE);
7343   }
7344
7345   /* Cancel previous alarm. */
7346   alarm (0);
7347
7348   nr_tests = %d;
7349
7350 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7351
7352   iteri (
7353     fun i test_name ->
7354       pr "  test_num++;\n";
7355       pr "  if (guestfs_get_verbose (g))\n";
7356       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7357       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7358       pr "  if (%s () == -1) {\n" test_name;
7359       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7360       pr "    n_failed++;\n";
7361       pr "  }\n";
7362   ) test_names;
7363   pr "\n";
7364
7365   pr "  /* Check close callback is called. */
7366   int close_sentinel = 1;
7367   guestfs_set_close_callback (g, incr, &close_sentinel);
7368
7369   guestfs_close (g);
7370
7371   if (close_sentinel != 2) {
7372     fprintf (stderr, \"close callback was not called\\n\");
7373     exit (EXIT_FAILURE);
7374   }
7375
7376   unlink (\"test1.img\");
7377   unlink (\"test2.img\");
7378   unlink (\"test3.img\");
7379
7380 ";
7381
7382   pr "  if (n_failed > 0) {\n";
7383   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7384   pr "    exit (EXIT_FAILURE);\n";
7385   pr "  }\n";
7386   pr "\n";
7387
7388   pr "  exit (EXIT_SUCCESS);\n";
7389   pr "}\n"
7390
7391 and generate_one_test name flags i (init, prereq, test) =
7392   let test_name = sprintf "test_%s_%d" name i in
7393
7394   pr "\
7395 static int %s_skip (void)
7396 {
7397   const char *str;
7398
7399   str = getenv (\"TEST_ONLY\");
7400   if (str)
7401     return strstr (str, \"%s\") == NULL;
7402   str = getenv (\"SKIP_%s\");
7403   if (str && STREQ (str, \"1\")) return 1;
7404   str = getenv (\"SKIP_TEST_%s\");
7405   if (str && STREQ (str, \"1\")) return 1;
7406   return 0;
7407 }
7408
7409 " test_name name (String.uppercase test_name) (String.uppercase name);
7410
7411   (match prereq with
7412    | Disabled | Always | IfAvailable _ -> ()
7413    | If code | Unless code ->
7414        pr "static int %s_prereq (void)\n" test_name;
7415        pr "{\n";
7416        pr "  %s\n" code;
7417        pr "}\n";
7418        pr "\n";
7419   );
7420
7421   pr "\
7422 static int %s (void)
7423 {
7424   if (%s_skip ()) {
7425     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7426     return 0;
7427   }
7428
7429 " test_name test_name test_name;
7430
7431   (* Optional functions should only be tested if the relevant
7432    * support is available in the daemon.
7433    *)
7434   List.iter (
7435     function
7436     | Optional group ->
7437         pr "  if (!is_available (\"%s\")) {\n" group;
7438         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7439         pr "    return 0;\n";
7440         pr "  }\n";
7441     | _ -> ()
7442   ) flags;
7443
7444   (match prereq with
7445    | Disabled ->
7446        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7447    | If _ ->
7448        pr "  if (! %s_prereq ()) {\n" test_name;
7449        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7450        pr "    return 0;\n";
7451        pr "  }\n";
7452        pr "\n";
7453        generate_one_test_body name i test_name init test;
7454    | Unless _ ->
7455        pr "  if (%s_prereq ()) {\n" test_name;
7456        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7457        pr "    return 0;\n";
7458        pr "  }\n";
7459        pr "\n";
7460        generate_one_test_body name i test_name init test;
7461    | IfAvailable group ->
7462        pr "  if (!is_available (\"%s\")) {\n" group;
7463        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7464        pr "    return 0;\n";
7465        pr "  }\n";
7466        pr "\n";
7467        generate_one_test_body name i test_name init test;
7468    | Always ->
7469        generate_one_test_body name i test_name init test
7470   );
7471
7472   pr "  return 0;\n";
7473   pr "}\n";
7474   pr "\n";
7475   test_name
7476
7477 and generate_one_test_body name i test_name init test =
7478   (match init with
7479    | InitNone (* XXX at some point, InitNone and InitEmpty became
7480                * folded together as the same thing.  Really we should
7481                * make InitNone do nothing at all, but the tests may
7482                * need to be checked to make sure this is OK.
7483                *)
7484    | InitEmpty ->
7485        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7486        List.iter (generate_test_command_call test_name)
7487          [["blockdev_setrw"; "/dev/sda"];
7488           ["umount_all"];
7489           ["lvm_remove_all"]]
7490    | InitPartition ->
7491        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7492        List.iter (generate_test_command_call test_name)
7493          [["blockdev_setrw"; "/dev/sda"];
7494           ["umount_all"];
7495           ["lvm_remove_all"];
7496           ["part_disk"; "/dev/sda"; "mbr"]]
7497    | InitBasicFS ->
7498        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7499        List.iter (generate_test_command_call test_name)
7500          [["blockdev_setrw"; "/dev/sda"];
7501           ["umount_all"];
7502           ["lvm_remove_all"];
7503           ["part_disk"; "/dev/sda"; "mbr"];
7504           ["mkfs"; "ext2"; "/dev/sda1"];
7505           ["mount_options"; ""; "/dev/sda1"; "/"]]
7506    | InitBasicFSonLVM ->
7507        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7508          test_name;
7509        List.iter (generate_test_command_call test_name)
7510          [["blockdev_setrw"; "/dev/sda"];
7511           ["umount_all"];
7512           ["lvm_remove_all"];
7513           ["part_disk"; "/dev/sda"; "mbr"];
7514           ["pvcreate"; "/dev/sda1"];
7515           ["vgcreate"; "VG"; "/dev/sda1"];
7516           ["lvcreate"; "LV"; "VG"; "8"];
7517           ["mkfs"; "ext2"; "/dev/VG/LV"];
7518           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7519    | InitISOFS ->
7520        pr "  /* InitISOFS for %s */\n" test_name;
7521        List.iter (generate_test_command_call test_name)
7522          [["blockdev_setrw"; "/dev/sda"];
7523           ["umount_all"];
7524           ["lvm_remove_all"];
7525           ["mount_ro"; "/dev/sdd"; "/"]]
7526   );
7527
7528   let get_seq_last = function
7529     | [] ->
7530         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7531           test_name
7532     | seq ->
7533         let seq = List.rev seq in
7534         List.rev (List.tl seq), List.hd seq
7535   in
7536
7537   match test with
7538   | TestRun seq ->
7539       pr "  /* TestRun for %s (%d) */\n" name i;
7540       List.iter (generate_test_command_call test_name) seq
7541   | TestOutput (seq, expected) ->
7542       pr "  /* TestOutput for %s (%d) */\n" name i;
7543       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7544       let seq, last = get_seq_last seq in
7545       let test () =
7546         pr "    if (STRNEQ (r, expected)) {\n";
7547         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7548         pr "      return -1;\n";
7549         pr "    }\n"
7550       in
7551       List.iter (generate_test_command_call test_name) seq;
7552       generate_test_command_call ~test test_name last
7553   | TestOutputList (seq, expected) ->
7554       pr "  /* TestOutputList for %s (%d) */\n" name i;
7555       let seq, last = get_seq_last seq in
7556       let test () =
7557         iteri (
7558           fun i str ->
7559             pr "    if (!r[%d]) {\n" i;
7560             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7561             pr "      print_strings (r);\n";
7562             pr "      return -1;\n";
7563             pr "    }\n";
7564             pr "    {\n";
7565             pr "      const char *expected = \"%s\";\n" (c_quote str);
7566             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7567             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7568             pr "        return -1;\n";
7569             pr "      }\n";
7570             pr "    }\n"
7571         ) expected;
7572         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7573         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7574           test_name;
7575         pr "      print_strings (r);\n";
7576         pr "      return -1;\n";
7577         pr "    }\n"
7578       in
7579       List.iter (generate_test_command_call test_name) seq;
7580       generate_test_command_call ~test test_name last
7581   | TestOutputListOfDevices (seq, expected) ->
7582       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7583       let seq, last = get_seq_last seq in
7584       let test () =
7585         iteri (
7586           fun i str ->
7587             pr "    if (!r[%d]) {\n" i;
7588             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7589             pr "      print_strings (r);\n";
7590             pr "      return -1;\n";
7591             pr "    }\n";
7592             pr "    {\n";
7593             pr "      const char *expected = \"%s\";\n" (c_quote str);
7594             pr "      r[%d][5] = 's';\n" i;
7595             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7596             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7597             pr "        return -1;\n";
7598             pr "      }\n";
7599             pr "    }\n"
7600         ) expected;
7601         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7602         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7603           test_name;
7604         pr "      print_strings (r);\n";
7605         pr "      return -1;\n";
7606         pr "    }\n"
7607       in
7608       List.iter (generate_test_command_call test_name) seq;
7609       generate_test_command_call ~test test_name last
7610   | TestOutputInt (seq, expected) ->
7611       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7612       let seq, last = get_seq_last seq in
7613       let test () =
7614         pr "    if (r != %d) {\n" expected;
7615         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7616           test_name expected;
7617         pr "               (int) r);\n";
7618         pr "      return -1;\n";
7619         pr "    }\n"
7620       in
7621       List.iter (generate_test_command_call test_name) seq;
7622       generate_test_command_call ~test test_name last
7623   | TestOutputIntOp (seq, op, expected) ->
7624       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7625       let seq, last = get_seq_last seq in
7626       let test () =
7627         pr "    if (! (r %s %d)) {\n" op expected;
7628         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7629           test_name op expected;
7630         pr "               (int) r);\n";
7631         pr "      return -1;\n";
7632         pr "    }\n"
7633       in
7634       List.iter (generate_test_command_call test_name) seq;
7635       generate_test_command_call ~test test_name last
7636   | TestOutputTrue seq ->
7637       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7638       let seq, last = get_seq_last seq in
7639       let test () =
7640         pr "    if (!r) {\n";
7641         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7642           test_name;
7643         pr "      return -1;\n";
7644         pr "    }\n"
7645       in
7646       List.iter (generate_test_command_call test_name) seq;
7647       generate_test_command_call ~test test_name last
7648   | TestOutputFalse seq ->
7649       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7650       let seq, last = get_seq_last seq in
7651       let test () =
7652         pr "    if (r) {\n";
7653         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7654           test_name;
7655         pr "      return -1;\n";
7656         pr "    }\n"
7657       in
7658       List.iter (generate_test_command_call test_name) seq;
7659       generate_test_command_call ~test test_name last
7660   | TestOutputLength (seq, expected) ->
7661       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7662       let seq, last = get_seq_last seq in
7663       let test () =
7664         pr "    int j;\n";
7665         pr "    for (j = 0; j < %d; ++j)\n" expected;
7666         pr "      if (r[j] == NULL) {\n";
7667         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7668           test_name;
7669         pr "        print_strings (r);\n";
7670         pr "        return -1;\n";
7671         pr "      }\n";
7672         pr "    if (r[j] != NULL) {\n";
7673         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7674           test_name;
7675         pr "      print_strings (r);\n";
7676         pr "      return -1;\n";
7677         pr "    }\n"
7678       in
7679       List.iter (generate_test_command_call test_name) seq;
7680       generate_test_command_call ~test test_name last
7681   | TestOutputBuffer (seq, expected) ->
7682       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7683       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7684       let seq, last = get_seq_last seq in
7685       let len = String.length expected in
7686       let test () =
7687         pr "    if (size != %d) {\n" len;
7688         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7689         pr "      return -1;\n";
7690         pr "    }\n";
7691         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7692         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7693         pr "      return -1;\n";
7694         pr "    }\n"
7695       in
7696       List.iter (generate_test_command_call test_name) seq;
7697       generate_test_command_call ~test test_name last
7698   | TestOutputStruct (seq, checks) ->
7699       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7700       let seq, last = get_seq_last seq in
7701       let test () =
7702         List.iter (
7703           function
7704           | CompareWithInt (field, expected) ->
7705               pr "    if (r->%s != %d) {\n" field expected;
7706               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7707                 test_name field expected;
7708               pr "               (int) r->%s);\n" field;
7709               pr "      return -1;\n";
7710               pr "    }\n"
7711           | CompareWithIntOp (field, op, expected) ->
7712               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7713               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7714                 test_name field op expected;
7715               pr "               (int) r->%s);\n" field;
7716               pr "      return -1;\n";
7717               pr "    }\n"
7718           | CompareWithString (field, expected) ->
7719               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7720               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7721                 test_name field expected;
7722               pr "               r->%s);\n" field;
7723               pr "      return -1;\n";
7724               pr "    }\n"
7725           | CompareFieldsIntEq (field1, field2) ->
7726               pr "    if (r->%s != r->%s) {\n" field1 field2;
7727               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7728                 test_name field1 field2;
7729               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7730               pr "      return -1;\n";
7731               pr "    }\n"
7732           | CompareFieldsStrEq (field1, field2) ->
7733               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7734               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7735                 test_name field1 field2;
7736               pr "               r->%s, r->%s);\n" field1 field2;
7737               pr "      return -1;\n";
7738               pr "    }\n"
7739         ) checks
7740       in
7741       List.iter (generate_test_command_call test_name) seq;
7742       generate_test_command_call ~test test_name last
7743   | TestLastFail seq ->
7744       pr "  /* TestLastFail for %s (%d) */\n" name i;
7745       let seq, last = get_seq_last seq in
7746       List.iter (generate_test_command_call test_name) seq;
7747       generate_test_command_call test_name ~expect_error:true last
7748
7749 (* Generate the code to run a command, leaving the result in 'r'.
7750  * If you expect to get an error then you should set expect_error:true.
7751  *)
7752 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7753   match cmd with
7754   | [] -> assert false
7755   | name :: args ->
7756       (* Look up the command to find out what args/ret it has. *)
7757       let style =
7758         try
7759           let _, style, _, _, _, _, _ =
7760             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7761           style
7762         with Not_found ->
7763           failwithf "%s: in test, command %s was not found" test_name name in
7764
7765       if List.length (snd style) <> List.length args then
7766         failwithf "%s: in test, wrong number of args given to %s"
7767           test_name name;
7768
7769       pr "  {\n";
7770
7771       List.iter (
7772         function
7773         | OptString n, "NULL" -> ()
7774         | Pathname n, arg
7775         | Device n, arg
7776         | Dev_or_Path n, arg
7777         | String n, arg
7778         | OptString n, arg
7779         | Key n, arg ->
7780             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7781         | BufferIn n, arg ->
7782             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7783             pr "    size_t %s_size = %d;\n" n (String.length arg)
7784         | Int _, _
7785         | Int64 _, _
7786         | Bool _, _
7787         | FileIn _, _ | FileOut _, _ -> ()
7788         | StringList n, "" | DeviceList n, "" ->
7789             pr "    const char *const %s[1] = { NULL };\n" n
7790         | StringList n, arg | DeviceList n, arg ->
7791             let strs = string_split " " arg in
7792             iteri (
7793               fun i str ->
7794                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7795             ) strs;
7796             pr "    const char *const %s[] = {\n" n;
7797             iteri (
7798               fun i _ -> pr "      %s_%d,\n" n i
7799             ) strs;
7800             pr "      NULL\n";
7801             pr "    };\n";
7802       ) (List.combine (snd style) args);
7803
7804       let error_code =
7805         match fst style with
7806         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7807         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7808         | RConstString _ | RConstOptString _ ->
7809             pr "    const char *r;\n"; "NULL"
7810         | RString _ -> pr "    char *r;\n"; "NULL"
7811         | RStringList _ | RHashtable _ ->
7812             pr "    char **r;\n";
7813             pr "    size_t i;\n";
7814             "NULL"
7815         | RStruct (_, typ) ->
7816             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7817         | RStructList (_, typ) ->
7818             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7819         | RBufferOut _ ->
7820             pr "    char *r;\n";
7821             pr "    size_t size;\n";
7822             "NULL" in
7823
7824       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7825       pr "    r = guestfs_%s (g" name;
7826
7827       (* Generate the parameters. *)
7828       List.iter (
7829         function
7830         | OptString _, "NULL" -> pr ", NULL"
7831         | Pathname n, _
7832         | Device n, _ | Dev_or_Path n, _
7833         | String n, _
7834         | OptString n, _
7835         | Key n, _ ->
7836             pr ", %s" n
7837         | BufferIn n, _ ->
7838             pr ", %s, %s_size" n n
7839         | FileIn _, arg | FileOut _, arg ->
7840             pr ", \"%s\"" (c_quote arg)
7841         | StringList n, _ | DeviceList n, _ ->
7842             pr ", (char **) %s" n
7843         | Int _, arg ->
7844             let i =
7845               try int_of_string arg
7846               with Failure "int_of_string" ->
7847                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7848             pr ", %d" i
7849         | Int64 _, arg ->
7850             let i =
7851               try Int64.of_string arg
7852               with Failure "int_of_string" ->
7853                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7854             pr ", %Ld" i
7855         | Bool _, arg ->
7856             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7857       ) (List.combine (snd style) args);
7858
7859       (match fst style with
7860        | RBufferOut _ -> pr ", &size"
7861        | _ -> ()
7862       );
7863
7864       pr ");\n";
7865
7866       if not expect_error then
7867         pr "    if (r == %s)\n" error_code
7868       else
7869         pr "    if (r != %s)\n" error_code;
7870       pr "      return -1;\n";
7871
7872       (* Insert the test code. *)
7873       (match test with
7874        | None -> ()
7875        | Some f -> f ()
7876       );
7877
7878       (match fst style with
7879        | RErr | RInt _ | RInt64 _ | RBool _
7880        | RConstString _ | RConstOptString _ -> ()
7881        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7882        | RStringList _ | RHashtable _ ->
7883            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7884            pr "      free (r[i]);\n";
7885            pr "    free (r);\n"
7886        | RStruct (_, typ) ->
7887            pr "    guestfs_free_%s (r);\n" typ
7888        | RStructList (_, typ) ->
7889            pr "    guestfs_free_%s_list (r);\n" typ
7890       );
7891
7892       pr "  }\n"
7893
7894 and c_quote str =
7895   let str = replace_str str "\r" "\\r" in
7896   let str = replace_str str "\n" "\\n" in
7897   let str = replace_str str "\t" "\\t" in
7898   let str = replace_str str "\000" "\\0" in
7899   str
7900
7901 (* Generate a lot of different functions for guestfish. *)
7902 and generate_fish_cmds () =
7903   generate_header CStyle GPLv2plus;
7904
7905   let all_functions =
7906     List.filter (
7907       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7908     ) all_functions in
7909   let all_functions_sorted =
7910     List.filter (
7911       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7912     ) all_functions_sorted in
7913
7914   pr "#include <config.h>\n";
7915   pr "\n";
7916   pr "#include <stdio.h>\n";
7917   pr "#include <stdlib.h>\n";
7918   pr "#include <string.h>\n";
7919   pr "#include <inttypes.h>\n";
7920   pr "\n";
7921   pr "#include <guestfs.h>\n";
7922   pr "#include \"c-ctype.h\"\n";
7923   pr "#include \"full-write.h\"\n";
7924   pr "#include \"xstrtol.h\"\n";
7925   pr "#include \"fish.h\"\n";
7926   pr "\n";
7927   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7928   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7929   pr "\n";
7930
7931   (* list_commands function, which implements guestfish -h *)
7932   pr "void list_commands (void)\n";
7933   pr "{\n";
7934   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7935   pr "  list_builtin_commands ();\n";
7936   List.iter (
7937     fun (name, _, _, flags, _, shortdesc, _) ->
7938       let name = replace_char name '_' '-' in
7939       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7940         name shortdesc
7941   ) all_functions_sorted;
7942   pr "  printf (\"    %%s\\n\",";
7943   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7944   pr "}\n";
7945   pr "\n";
7946
7947   (* display_command function, which implements guestfish -h cmd *)
7948   pr "int display_command (const char *cmd)\n";
7949   pr "{\n";
7950   List.iter (
7951     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7952       let name2 = replace_char name '_' '-' in
7953       let alias =
7954         try find_map (function FishAlias n -> Some n | _ -> None) flags
7955         with Not_found -> name in
7956       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7957       let synopsis =
7958         match snd style with
7959         | [] -> name2
7960         | args ->
7961             let args = List.filter (function Key _ -> false | _ -> true) args in
7962             sprintf "%s %s"
7963               name2 (String.concat " " (List.map name_of_argt args)) in
7964
7965       let warnings =
7966         if List.exists (function Key _ -> true | _ -> false) (snd style) then
7967           "\n\nThis command has one or more key or passphrase parameters.
7968 Guestfish will prompt for these separately."
7969         else "" in
7970
7971       let warnings =
7972         warnings ^
7973           if List.mem ProtocolLimitWarning flags then
7974             ("\n\n" ^ protocol_limit_warning)
7975           else "" in
7976
7977       (* For DangerWillRobinson commands, we should probably have
7978        * guestfish prompt before allowing you to use them (especially
7979        * in interactive mode). XXX
7980        *)
7981       let warnings =
7982         warnings ^
7983           if List.mem DangerWillRobinson flags then
7984             ("\n\n" ^ danger_will_robinson)
7985           else "" in
7986
7987       let warnings =
7988         warnings ^
7989           match deprecation_notice flags with
7990           | None -> ""
7991           | Some txt -> "\n\n" ^ txt in
7992
7993       let describe_alias =
7994         if name <> alias then
7995           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7996         else "" in
7997
7998       pr "  if (";
7999       pr "STRCASEEQ (cmd, \"%s\")" name;
8000       if name <> name2 then
8001         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8002       if name <> alias then
8003         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8004       pr ") {\n";
8005       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
8006         name2 shortdesc
8007         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
8008          "=head1 DESCRIPTION\n\n" ^
8009          longdesc ^ warnings ^ describe_alias);
8010       pr "    return 0;\n";
8011       pr "  }\n";
8012       pr "  else\n"
8013   ) all_functions;
8014   pr "    return display_builtin_command (cmd);\n";
8015   pr "}\n";
8016   pr "\n";
8017
8018   let emit_print_list_function typ =
8019     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
8020       typ typ typ;
8021     pr "{\n";
8022     pr "  unsigned int i;\n";
8023     pr "\n";
8024     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
8025     pr "    printf (\"[%%d] = {\\n\", i);\n";
8026     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
8027     pr "    printf (\"}\\n\");\n";
8028     pr "  }\n";
8029     pr "}\n";
8030     pr "\n";
8031   in
8032
8033   (* print_* functions *)
8034   List.iter (
8035     fun (typ, cols) ->
8036       let needs_i =
8037         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
8038
8039       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
8040       pr "{\n";
8041       if needs_i then (
8042         pr "  unsigned int i;\n";
8043         pr "\n"
8044       );
8045       List.iter (
8046         function
8047         | name, FString ->
8048             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
8049         | name, FUUID ->
8050             pr "  printf (\"%%s%s: \", indent);\n" name;
8051             pr "  for (i = 0; i < 32; ++i)\n";
8052             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
8053             pr "  printf (\"\\n\");\n"
8054         | name, FBuffer ->
8055             pr "  printf (\"%%s%s: \", indent);\n" name;
8056             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
8057             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
8058             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
8059             pr "    else\n";
8060             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
8061             pr "  printf (\"\\n\");\n"
8062         | name, (FUInt64|FBytes) ->
8063             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
8064               name typ name
8065         | name, FInt64 ->
8066             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
8067               name typ name
8068         | name, FUInt32 ->
8069             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
8070               name typ name
8071         | name, FInt32 ->
8072             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
8073               name typ name
8074         | name, FChar ->
8075             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
8076               name typ name
8077         | name, FOptPercent ->
8078             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
8079               typ name name typ name;
8080             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
8081       ) cols;
8082       pr "}\n";
8083       pr "\n";
8084   ) structs;
8085
8086   (* Emit a print_TYPE_list function definition only if that function is used. *)
8087   List.iter (
8088     function
8089     | typ, (RStructListOnly | RStructAndList) ->
8090         (* generate the function for typ *)
8091         emit_print_list_function typ
8092     | typ, _ -> () (* empty *)
8093   ) (rstructs_used_by all_functions);
8094
8095   (* Emit a print_TYPE function definition only if that function is used. *)
8096   List.iter (
8097     function
8098     | typ, (RStructOnly | RStructAndList) ->
8099         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
8100         pr "{\n";
8101         pr "  print_%s_indent (%s, \"\");\n" typ typ;
8102         pr "}\n";
8103         pr "\n";
8104     | typ, _ -> () (* empty *)
8105   ) (rstructs_used_by all_functions);
8106
8107   (* run_<action> actions *)
8108   List.iter (
8109     fun (name, style, _, flags, _, _, _) ->
8110       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
8111       pr "{\n";
8112       (match fst style with
8113        | RErr
8114        | RInt _
8115        | RBool _ -> pr "  int r;\n"
8116        | RInt64 _ -> pr "  int64_t r;\n"
8117        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
8118        | RString _ -> pr "  char *r;\n"
8119        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
8120        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
8121        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
8122        | RBufferOut _ ->
8123            pr "  char *r;\n";
8124            pr "  size_t size;\n";
8125       );
8126       List.iter (
8127         function
8128         | Device n
8129         | String n
8130         | OptString n -> pr "  const char *%s;\n" n
8131         | Pathname n
8132         | Dev_or_Path n
8133         | FileIn n
8134         | FileOut n
8135         | Key n -> pr "  char *%s;\n" n
8136         | BufferIn n ->
8137             pr "  const char *%s;\n" n;
8138             pr "  size_t %s_size;\n" n
8139         | StringList n | DeviceList n -> pr "  char **%s;\n" n
8140         | Bool n -> pr "  int %s;\n" n
8141         | Int n -> pr "  int %s;\n" n
8142         | Int64 n -> pr "  int64_t %s;\n" n
8143       ) (snd style);
8144
8145       (* Check and convert parameters. *)
8146       let argc_expected =
8147         let args_no_keys =
8148           List.filter (function Key _ -> false | _ -> true) (snd style) in
8149         List.length args_no_keys in
8150       pr "  if (argc != %d) {\n" argc_expected;
8151       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
8152         argc_expected;
8153       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
8154       pr "    return -1;\n";
8155       pr "  }\n";
8156
8157       let parse_integer fn fntyp rtyp range name =
8158         pr "  {\n";
8159         pr "    strtol_error xerr;\n";
8160         pr "    %s r;\n" fntyp;
8161         pr "\n";
8162         pr "    xerr = %s (argv[i++], NULL, 0, &r, xstrtol_suffixes);\n" fn;
8163         pr "    if (xerr != LONGINT_OK) {\n";
8164         pr "      fprintf (stderr,\n";
8165         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
8166         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
8167         pr "      return -1;\n";
8168         pr "    }\n";
8169         (match range with
8170          | None -> ()
8171          | Some (min, max, comment) ->
8172              pr "    /* %s */\n" comment;
8173              pr "    if (r < %s || r > %s) {\n" min max;
8174              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
8175                name;
8176              pr "      return -1;\n";
8177              pr "    }\n";
8178              pr "    /* The check above should ensure this assignment does not overflow. */\n";
8179         );
8180         pr "    %s = r;\n" name;
8181         pr "  }\n";
8182       in
8183
8184       if snd style <> [] then
8185         pr "  size_t i = 0;\n";
8186
8187       List.iter (
8188         function
8189         | Device name
8190         | String name ->
8191             pr "  %s = argv[i++];\n" name
8192         | Pathname name
8193         | Dev_or_Path name ->
8194             pr "  %s = resolve_win_path (argv[i++]);\n" name;
8195             pr "  if (%s == NULL) return -1;\n" name
8196         | OptString name ->
8197             pr "  %s = STRNEQ (argv[i], \"\") ? argv[i] : NULL;\n" name;
8198             pr "  i++;\n"
8199         | BufferIn name ->
8200             pr "  %s = argv[i];\n" name;
8201             pr "  %s_size = strlen (argv[i]);\n" name;
8202             pr "  i++;\n"
8203         | FileIn name ->
8204             pr "  %s = file_in (argv[i++]);\n" name;
8205             pr "  if (%s == NULL) return -1;\n" name
8206         | FileOut name ->
8207             pr "  %s = file_out (argv[i++]);\n" name;
8208             pr "  if (%s == NULL) return -1;\n" name
8209         | StringList name | DeviceList name ->
8210             pr "  %s = parse_string_list (argv[i++]);\n" name;
8211             pr "  if (%s == NULL) return -1;\n" name
8212         | Key name ->
8213             pr "  %s = read_key (\"%s\");\n" name name;
8214             pr "  if (%s == NULL) return -1;\n" name
8215         | Bool name ->
8216             pr "  %s = is_true (argv[i++]) ? 1 : 0;\n" name
8217         | Int name ->
8218             let range =
8219               let min = "(-(2LL<<30))"
8220               and max = "((2LL<<30)-1)"
8221               and comment =
8222                 "The Int type in the generator is a signed 31 bit int." in
8223               Some (min, max, comment) in
8224             parse_integer "xstrtoll" "long long" "int" range name
8225         | Int64 name ->
8226             parse_integer "xstrtoll" "long long" "int64_t" None name
8227       ) (snd style);
8228
8229       (* Call C API function. *)
8230       pr "  r = guestfs_%s " name;
8231       generate_c_call_args ~handle:"g" style;
8232       pr ";\n";
8233
8234       List.iter (
8235         function
8236         | Device _ | String _
8237         | OptString _ | Bool _
8238         | Int _ | Int64 _
8239         | BufferIn _ -> ()
8240         | Pathname name | Dev_or_Path name | FileOut name
8241         | Key name ->
8242             pr "  free (%s);\n" name
8243         | FileIn name ->
8244             pr "  free_file_in (%s);\n" name
8245         | StringList name | DeviceList name ->
8246             pr "  free_strings (%s);\n" name
8247       ) (snd style);
8248
8249       (* Any output flags? *)
8250       let fish_output =
8251         let flags = filter_map (
8252           function FishOutput flag -> Some flag | _ -> None
8253         ) flags in
8254         match flags with
8255         | [] -> None
8256         | [f] -> Some f
8257         | _ ->
8258             failwithf "%s: more than one FishOutput flag is not allowed" name in
8259
8260       (* Check return value for errors and display command results. *)
8261       (match fst style with
8262        | RErr -> pr "  return r;\n"
8263        | RInt _ ->
8264            pr "  if (r == -1) return -1;\n";
8265            (match fish_output with
8266             | None ->
8267                 pr "  printf (\"%%d\\n\", r);\n";
8268             | Some FishOutputOctal ->
8269                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
8270             | Some FishOutputHexadecimal ->
8271                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8272            pr "  return 0;\n"
8273        | RInt64 _ ->
8274            pr "  if (r == -1) return -1;\n";
8275            (match fish_output with
8276             | None ->
8277                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
8278             | Some FishOutputOctal ->
8279                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
8280             | Some FishOutputHexadecimal ->
8281                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8282            pr "  return 0;\n"
8283        | RBool _ ->
8284            pr "  if (r == -1) return -1;\n";
8285            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
8286            pr "  return 0;\n"
8287        | RConstString _ ->
8288            pr "  if (r == NULL) return -1;\n";
8289            pr "  printf (\"%%s\\n\", r);\n";
8290            pr "  return 0;\n"
8291        | RConstOptString _ ->
8292            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
8293            pr "  return 0;\n"
8294        | RString _ ->
8295            pr "  if (r == NULL) return -1;\n";
8296            pr "  printf (\"%%s\\n\", r);\n";
8297            pr "  free (r);\n";
8298            pr "  return 0;\n"
8299        | RStringList _ ->
8300            pr "  if (r == NULL) return -1;\n";
8301            pr "  print_strings (r);\n";
8302            pr "  free_strings (r);\n";
8303            pr "  return 0;\n"
8304        | RStruct (_, typ) ->
8305            pr "  if (r == NULL) return -1;\n";
8306            pr "  print_%s (r);\n" typ;
8307            pr "  guestfs_free_%s (r);\n" typ;
8308            pr "  return 0;\n"
8309        | RStructList (_, typ) ->
8310            pr "  if (r == NULL) return -1;\n";
8311            pr "  print_%s_list (r);\n" typ;
8312            pr "  guestfs_free_%s_list (r);\n" typ;
8313            pr "  return 0;\n"
8314        | RHashtable _ ->
8315            pr "  if (r == NULL) return -1;\n";
8316            pr "  print_table (r);\n";
8317            pr "  free_strings (r);\n";
8318            pr "  return 0;\n"
8319        | RBufferOut _ ->
8320            pr "  if (r == NULL) return -1;\n";
8321            pr "  if (full_write (1, r, size) != size) {\n";
8322            pr "    perror (\"write\");\n";
8323            pr "    free (r);\n";
8324            pr "    return -1;\n";
8325            pr "  }\n";
8326            pr "  free (r);\n";
8327            pr "  return 0;\n"
8328       );
8329       pr "}\n";
8330       pr "\n"
8331   ) all_functions;
8332
8333   (* run_action function *)
8334   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8335   pr "{\n";
8336   List.iter (
8337     fun (name, _, _, flags, _, _, _) ->
8338       let name2 = replace_char name '_' '-' in
8339       let alias =
8340         try find_map (function FishAlias n -> Some n | _ -> None) flags
8341         with Not_found -> name in
8342       pr "  if (";
8343       pr "STRCASEEQ (cmd, \"%s\")" name;
8344       if name <> name2 then
8345         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8346       if name <> alias then
8347         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8348       pr ")\n";
8349       pr "    return run_%s (cmd, argc, argv);\n" name;
8350       pr "  else\n";
8351   ) all_functions;
8352   pr "    {\n";
8353   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8354   pr "      if (command_num == 1)\n";
8355   pr "        extended_help_message ();\n";
8356   pr "      return -1;\n";
8357   pr "    }\n";
8358   pr "  return 0;\n";
8359   pr "}\n";
8360   pr "\n"
8361
8362 (* Readline completion for guestfish. *)
8363 and generate_fish_completion () =
8364   generate_header CStyle GPLv2plus;
8365
8366   let all_functions =
8367     List.filter (
8368       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8369     ) all_functions in
8370
8371   pr "\
8372 #include <config.h>
8373
8374 #include <stdio.h>
8375 #include <stdlib.h>
8376 #include <string.h>
8377
8378 #ifdef HAVE_LIBREADLINE
8379 #include <readline/readline.h>
8380 #endif
8381
8382 #include \"fish.h\"
8383
8384 #ifdef HAVE_LIBREADLINE
8385
8386 static const char *const commands[] = {
8387   BUILTIN_COMMANDS_FOR_COMPLETION,
8388 ";
8389
8390   (* Get the commands, including the aliases.  They don't need to be
8391    * sorted - the generator() function just does a dumb linear search.
8392    *)
8393   let commands =
8394     List.map (
8395       fun (name, _, _, flags, _, _, _) ->
8396         let name2 = replace_char name '_' '-' in
8397         let alias =
8398           try find_map (function FishAlias n -> Some n | _ -> None) flags
8399           with Not_found -> name in
8400
8401         if name <> alias then [name2; alias] else [name2]
8402     ) all_functions in
8403   let commands = List.flatten commands in
8404
8405   List.iter (pr "  \"%s\",\n") commands;
8406
8407   pr "  NULL
8408 };
8409
8410 static char *
8411 generator (const char *text, int state)
8412 {
8413   static size_t index, len;
8414   const char *name;
8415
8416   if (!state) {
8417     index = 0;
8418     len = strlen (text);
8419   }
8420
8421   rl_attempted_completion_over = 1;
8422
8423   while ((name = commands[index]) != NULL) {
8424     index++;
8425     if (STRCASEEQLEN (name, text, len))
8426       return strdup (name);
8427   }
8428
8429   return NULL;
8430 }
8431
8432 #endif /* HAVE_LIBREADLINE */
8433
8434 #ifdef HAVE_RL_COMPLETION_MATCHES
8435 #define RL_COMPLETION_MATCHES rl_completion_matches
8436 #else
8437 #ifdef HAVE_COMPLETION_MATCHES
8438 #define RL_COMPLETION_MATCHES completion_matches
8439 #endif
8440 #endif /* else just fail if we don't have either symbol */
8441
8442 char **
8443 do_completion (const char *text, int start, int end)
8444 {
8445   char **matches = NULL;
8446
8447 #ifdef HAVE_LIBREADLINE
8448   rl_completion_append_character = ' ';
8449
8450   if (start == 0)
8451     matches = RL_COMPLETION_MATCHES (text, generator);
8452   else if (complete_dest_paths)
8453     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8454 #endif
8455
8456   return matches;
8457 }
8458 ";
8459
8460 (* Generate the POD documentation for guestfish. *)
8461 and generate_fish_actions_pod () =
8462   let all_functions_sorted =
8463     List.filter (
8464       fun (_, _, _, flags, _, _, _) ->
8465         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8466     ) all_functions_sorted in
8467
8468   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8469
8470   List.iter (
8471     fun (name, style, _, flags, _, _, longdesc) ->
8472       let longdesc =
8473         Str.global_substitute rex (
8474           fun s ->
8475             let sub =
8476               try Str.matched_group 1 s
8477               with Not_found ->
8478                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8479             "C<" ^ replace_char sub '_' '-' ^ ">"
8480         ) longdesc in
8481       let name = replace_char name '_' '-' in
8482       let alias =
8483         try find_map (function FishAlias n -> Some n | _ -> None) flags
8484         with Not_found -> name in
8485
8486       pr "=head2 %s" name;
8487       if name <> alias then
8488         pr " | %s" alias;
8489       pr "\n";
8490       pr "\n";
8491       pr " %s" name;
8492       List.iter (
8493         function
8494         | Pathname n | Device n | Dev_or_Path n | String n ->
8495             pr " %s" n
8496         | OptString n -> pr " %s" n
8497         | StringList n | DeviceList n -> pr " '%s ...'" n
8498         | Bool _ -> pr " true|false"
8499         | Int n -> pr " %s" n
8500         | Int64 n -> pr " %s" n
8501         | FileIn n | FileOut n -> pr " (%s|-)" n
8502         | BufferIn n -> pr " %s" n
8503         | Key _ -> () (* keys are entered at a prompt *)
8504       ) (snd style);
8505       pr "\n";
8506       pr "\n";
8507       pr "%s\n\n" longdesc;
8508
8509       if List.exists (function FileIn _ | FileOut _ -> true
8510                       | _ -> false) (snd style) then
8511         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8512
8513       if List.exists (function Key _ -> true | _ -> false) (snd style) then
8514         pr "This command has one or more key or passphrase parameters.
8515 Guestfish will prompt for these separately.\n\n";
8516
8517       if List.mem ProtocolLimitWarning flags then
8518         pr "%s\n\n" protocol_limit_warning;
8519
8520       if List.mem DangerWillRobinson flags then
8521         pr "%s\n\n" danger_will_robinson;
8522
8523       match deprecation_notice flags with
8524       | None -> ()
8525       | Some txt -> pr "%s\n\n" txt
8526   ) all_functions_sorted
8527
8528 (* Generate a C function prototype. *)
8529 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8530     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8531     ?(prefix = "")
8532     ?handle name style =
8533   if extern then pr "extern ";
8534   if static then pr "static ";
8535   (match fst style with
8536    | RErr -> pr "int "
8537    | RInt _ -> pr "int "
8538    | RInt64 _ -> pr "int64_t "
8539    | RBool _ -> pr "int "
8540    | RConstString _ | RConstOptString _ -> pr "const char *"
8541    | RString _ | RBufferOut _ -> pr "char *"
8542    | RStringList _ | RHashtable _ -> pr "char **"
8543    | RStruct (_, typ) ->
8544        if not in_daemon then pr "struct guestfs_%s *" typ
8545        else pr "guestfs_int_%s *" typ
8546    | RStructList (_, typ) ->
8547        if not in_daemon then pr "struct guestfs_%s_list *" typ
8548        else pr "guestfs_int_%s_list *" typ
8549   );
8550   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8551   pr "%s%s (" prefix name;
8552   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8553     pr "void"
8554   else (
8555     let comma = ref false in
8556     (match handle with
8557      | None -> ()
8558      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8559     );
8560     let next () =
8561       if !comma then (
8562         if single_line then pr ", " else pr ",\n\t\t"
8563       );
8564       comma := true
8565     in
8566     List.iter (
8567       function
8568       | Pathname n
8569       | Device n | Dev_or_Path n
8570       | String n
8571       | OptString n
8572       | Key n ->
8573           next ();
8574           pr "const char *%s" n
8575       | StringList n | DeviceList n ->
8576           next ();
8577           pr "char *const *%s" n
8578       | Bool n -> next (); pr "int %s" n
8579       | Int n -> next (); pr "int %s" n
8580       | Int64 n -> next (); pr "int64_t %s" n
8581       | FileIn n
8582       | FileOut n ->
8583           if not in_daemon then (next (); pr "const char *%s" n)
8584       | BufferIn n ->
8585           next ();
8586           pr "const char *%s" n;
8587           next ();
8588           pr "size_t %s_size" n
8589     ) (snd style);
8590     if is_RBufferOut then (next (); pr "size_t *size_r");
8591   );
8592   pr ")";
8593   if semicolon then pr ";";
8594   if newline then pr "\n"
8595
8596 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8597 and generate_c_call_args ?handle ?(decl = false) style =
8598   pr "(";
8599   let comma = ref false in
8600   let next () =
8601     if !comma then pr ", ";
8602     comma := true
8603   in
8604   (match handle with
8605    | None -> ()
8606    | Some handle -> pr "%s" handle; comma := true
8607   );
8608   List.iter (
8609     function
8610     | BufferIn n ->
8611         next ();
8612         pr "%s, %s_size" n n
8613     | arg ->
8614         next ();
8615         pr "%s" (name_of_argt arg)
8616   ) (snd style);
8617   (* For RBufferOut calls, add implicit &size parameter. *)
8618   if not decl then (
8619     match fst style with
8620     | RBufferOut _ ->
8621         next ();
8622         pr "&size"
8623     | _ -> ()
8624   );
8625   pr ")"
8626
8627 (* Generate the OCaml bindings interface. *)
8628 and generate_ocaml_mli () =
8629   generate_header OCamlStyle LGPLv2plus;
8630
8631   pr "\
8632 (** For API documentation you should refer to the C API
8633     in the guestfs(3) manual page.  The OCaml API uses almost
8634     exactly the same calls. *)
8635
8636 type t
8637 (** A [guestfs_h] handle. *)
8638
8639 exception Error of string
8640 (** This exception is raised when there is an error. *)
8641
8642 exception Handle_closed of string
8643 (** This exception is raised if you use a {!Guestfs.t} handle
8644     after calling {!close} on it.  The string is the name of
8645     the function. *)
8646
8647 val create : unit -> t
8648 (** Create a {!Guestfs.t} handle. *)
8649
8650 val close : t -> unit
8651 (** Close the {!Guestfs.t} handle and free up all resources used
8652     by it immediately.
8653
8654     Handles are closed by the garbage collector when they become
8655     unreferenced, but callers can call this in order to provide
8656     predictable cleanup. *)
8657
8658 ";
8659   generate_ocaml_structure_decls ();
8660
8661   (* The actions. *)
8662   List.iter (
8663     fun (name, style, _, _, _, shortdesc, _) ->
8664       generate_ocaml_prototype name style;
8665       pr "(** %s *)\n" shortdesc;
8666       pr "\n"
8667   ) all_functions_sorted
8668
8669 (* Generate the OCaml bindings implementation. *)
8670 and generate_ocaml_ml () =
8671   generate_header OCamlStyle LGPLv2plus;
8672
8673   pr "\
8674 type t
8675
8676 exception Error of string
8677 exception Handle_closed of string
8678
8679 external create : unit -> t = \"ocaml_guestfs_create\"
8680 external close : t -> unit = \"ocaml_guestfs_close\"
8681
8682 (* Give the exceptions names, so they can be raised from the C code. *)
8683 let () =
8684   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8685   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8686
8687 ";
8688
8689   generate_ocaml_structure_decls ();
8690
8691   (* The actions. *)
8692   List.iter (
8693     fun (name, style, _, _, _, shortdesc, _) ->
8694       generate_ocaml_prototype ~is_external:true name style;
8695   ) all_functions_sorted
8696
8697 (* Generate the OCaml bindings C implementation. *)
8698 and generate_ocaml_c () =
8699   generate_header CStyle LGPLv2plus;
8700
8701   pr "\
8702 #include <stdio.h>
8703 #include <stdlib.h>
8704 #include <string.h>
8705
8706 #include <caml/config.h>
8707 #include <caml/alloc.h>
8708 #include <caml/callback.h>
8709 #include <caml/fail.h>
8710 #include <caml/memory.h>
8711 #include <caml/mlvalues.h>
8712 #include <caml/signals.h>
8713
8714 #include \"guestfs.h\"
8715
8716 #include \"guestfs_c.h\"
8717
8718 /* Copy a hashtable of string pairs into an assoc-list.  We return
8719  * the list in reverse order, but hashtables aren't supposed to be
8720  * ordered anyway.
8721  */
8722 static CAMLprim value
8723 copy_table (char * const * argv)
8724 {
8725   CAMLparam0 ();
8726   CAMLlocal5 (rv, pairv, kv, vv, cons);
8727   size_t i;
8728
8729   rv = Val_int (0);
8730   for (i = 0; argv[i] != NULL; i += 2) {
8731     kv = caml_copy_string (argv[i]);
8732     vv = caml_copy_string (argv[i+1]);
8733     pairv = caml_alloc (2, 0);
8734     Store_field (pairv, 0, kv);
8735     Store_field (pairv, 1, vv);
8736     cons = caml_alloc (2, 0);
8737     Store_field (cons, 1, rv);
8738     rv = cons;
8739     Store_field (cons, 0, pairv);
8740   }
8741
8742   CAMLreturn (rv);
8743 }
8744
8745 ";
8746
8747   (* Struct copy functions. *)
8748
8749   let emit_ocaml_copy_list_function typ =
8750     pr "static CAMLprim value\n";
8751     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8752     pr "{\n";
8753     pr "  CAMLparam0 ();\n";
8754     pr "  CAMLlocal2 (rv, v);\n";
8755     pr "  unsigned int i;\n";
8756     pr "\n";
8757     pr "  if (%ss->len == 0)\n" typ;
8758     pr "    CAMLreturn (Atom (0));\n";
8759     pr "  else {\n";
8760     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8761     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8762     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8763     pr "      caml_modify (&Field (rv, i), v);\n";
8764     pr "    }\n";
8765     pr "    CAMLreturn (rv);\n";
8766     pr "  }\n";
8767     pr "}\n";
8768     pr "\n";
8769   in
8770
8771   List.iter (
8772     fun (typ, cols) ->
8773       let has_optpercent_col =
8774         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8775
8776       pr "static CAMLprim value\n";
8777       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8778       pr "{\n";
8779       pr "  CAMLparam0 ();\n";
8780       if has_optpercent_col then
8781         pr "  CAMLlocal3 (rv, v, v2);\n"
8782       else
8783         pr "  CAMLlocal2 (rv, v);\n";
8784       pr "\n";
8785       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8786       iteri (
8787         fun i col ->
8788           (match col with
8789            | name, FString ->
8790                pr "  v = caml_copy_string (%s->%s);\n" typ name
8791            | name, FBuffer ->
8792                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8793                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8794                  typ name typ name
8795            | name, FUUID ->
8796                pr "  v = caml_alloc_string (32);\n";
8797                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8798            | name, (FBytes|FInt64|FUInt64) ->
8799                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8800            | name, (FInt32|FUInt32) ->
8801                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8802            | name, FOptPercent ->
8803                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8804                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8805                pr "    v = caml_alloc (1, 0);\n";
8806                pr "    Store_field (v, 0, v2);\n";
8807                pr "  } else /* None */\n";
8808                pr "    v = Val_int (0);\n";
8809            | name, FChar ->
8810                pr "  v = Val_int (%s->%s);\n" typ name
8811           );
8812           pr "  Store_field (rv, %d, v);\n" i
8813       ) cols;
8814       pr "  CAMLreturn (rv);\n";
8815       pr "}\n";
8816       pr "\n";
8817   ) structs;
8818
8819   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8820   List.iter (
8821     function
8822     | typ, (RStructListOnly | RStructAndList) ->
8823         (* generate the function for typ *)
8824         emit_ocaml_copy_list_function typ
8825     | typ, _ -> () (* empty *)
8826   ) (rstructs_used_by all_functions);
8827
8828   (* The wrappers. *)
8829   List.iter (
8830     fun (name, style, _, _, _, _, _) ->
8831       pr "/* Automatically generated wrapper for function\n";
8832       pr " * ";
8833       generate_ocaml_prototype name style;
8834       pr " */\n";
8835       pr "\n";
8836
8837       let params =
8838         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8839
8840       let needs_extra_vs =
8841         match fst style with RConstOptString _ -> true | _ -> false in
8842
8843       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8844       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8845       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8846       pr "\n";
8847
8848       pr "CAMLprim value\n";
8849       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8850       List.iter (pr ", value %s") (List.tl params);
8851       pr ")\n";
8852       pr "{\n";
8853
8854       (match params with
8855        | [p1; p2; p3; p4; p5] ->
8856            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8857        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8858            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8859            pr "  CAMLxparam%d (%s);\n"
8860              (List.length rest) (String.concat ", " rest)
8861        | ps ->
8862            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8863       );
8864       if not needs_extra_vs then
8865         pr "  CAMLlocal1 (rv);\n"
8866       else
8867         pr "  CAMLlocal3 (rv, v, v2);\n";
8868       pr "\n";
8869
8870       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8871       pr "  if (g == NULL)\n";
8872       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8873       pr "\n";
8874
8875       List.iter (
8876         function
8877         | Pathname n
8878         | Device n | Dev_or_Path n
8879         | String n
8880         | FileIn n
8881         | FileOut n
8882         | Key n ->
8883             (* Copy strings in case the GC moves them: RHBZ#604691 *)
8884             pr "  char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8885         | OptString n ->
8886             pr "  char *%s =\n" n;
8887             pr "    %sv != Val_int (0) ?" n;
8888             pr "      guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8889         | BufferIn n ->
8890             pr "  size_t %s_size = caml_string_length (%sv);\n" n n;
8891             pr "  char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8892         | StringList n | DeviceList n ->
8893             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8894         | Bool n ->
8895             pr "  int %s = Bool_val (%sv);\n" n n
8896         | Int n ->
8897             pr "  int %s = Int_val (%sv);\n" n n
8898         | Int64 n ->
8899             pr "  int64_t %s = Int64_val (%sv);\n" n n
8900       ) (snd style);
8901       let error_code =
8902         match fst style with
8903         | RErr -> pr "  int r;\n"; "-1"
8904         | RInt _ -> pr "  int r;\n"; "-1"
8905         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8906         | RBool _ -> pr "  int r;\n"; "-1"
8907         | RConstString _ | RConstOptString _ ->
8908             pr "  const char *r;\n"; "NULL"
8909         | RString _ -> pr "  char *r;\n"; "NULL"
8910         | RStringList _ ->
8911             pr "  size_t i;\n";
8912             pr "  char **r;\n";
8913             "NULL"
8914         | RStruct (_, typ) ->
8915             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8916         | RStructList (_, typ) ->
8917             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8918         | RHashtable _ ->
8919             pr "  size_t i;\n";
8920             pr "  char **r;\n";
8921             "NULL"
8922         | RBufferOut _ ->
8923             pr "  char *r;\n";
8924             pr "  size_t size;\n";
8925             "NULL" in
8926       pr "\n";
8927
8928       pr "  caml_enter_blocking_section ();\n";
8929       pr "  r = guestfs_%s " name;
8930       generate_c_call_args ~handle:"g" style;
8931       pr ";\n";
8932       pr "  caml_leave_blocking_section ();\n";
8933
8934       (* Free strings if we copied them above. *)
8935       List.iter (
8936         function
8937         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8938         | FileIn n | FileOut n | BufferIn n | Key n ->
8939             pr "  free (%s);\n" n
8940         | StringList n | DeviceList n ->
8941             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8942         | Bool _ | Int _ | Int64 _ -> ()
8943       ) (snd style);
8944
8945       pr "  if (r == %s)\n" error_code;
8946       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8947       pr "\n";
8948
8949       (match fst style with
8950        | RErr -> pr "  rv = Val_unit;\n"
8951        | RInt _ -> pr "  rv = Val_int (r);\n"
8952        | RInt64 _ ->
8953            pr "  rv = caml_copy_int64 (r);\n"
8954        | RBool _ -> pr "  rv = Val_bool (r);\n"
8955        | RConstString _ ->
8956            pr "  rv = caml_copy_string (r);\n"
8957        | RConstOptString _ ->
8958            pr "  if (r) { /* Some string */\n";
8959            pr "    v = caml_alloc (1, 0);\n";
8960            pr "    v2 = caml_copy_string (r);\n";
8961            pr "    Store_field (v, 0, v2);\n";
8962            pr "  } else /* None */\n";
8963            pr "    v = Val_int (0);\n";
8964        | RString _ ->
8965            pr "  rv = caml_copy_string (r);\n";
8966            pr "  free (r);\n"
8967        | RStringList _ ->
8968            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8969            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8970            pr "  free (r);\n"
8971        | RStruct (_, typ) ->
8972            pr "  rv = copy_%s (r);\n" typ;
8973            pr "  guestfs_free_%s (r);\n" typ;
8974        | RStructList (_, typ) ->
8975            pr "  rv = copy_%s_list (r);\n" typ;
8976            pr "  guestfs_free_%s_list (r);\n" typ;
8977        | RHashtable _ ->
8978            pr "  rv = copy_table (r);\n";
8979            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8980            pr "  free (r);\n";
8981        | RBufferOut _ ->
8982            pr "  rv = caml_alloc_string (size);\n";
8983            pr "  memcpy (String_val (rv), r, size);\n";
8984       );
8985
8986       pr "  CAMLreturn (rv);\n";
8987       pr "}\n";
8988       pr "\n";
8989
8990       if List.length params > 5 then (
8991         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8992         pr "CAMLprim value ";
8993         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8994         pr "CAMLprim value\n";
8995         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8996         pr "{\n";
8997         pr "  return ocaml_guestfs_%s (argv[0]" name;
8998         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8999         pr ");\n";
9000         pr "}\n";
9001         pr "\n"
9002       )
9003   ) all_functions_sorted
9004
9005 and generate_ocaml_structure_decls () =
9006   List.iter (
9007     fun (typ, cols) ->
9008       pr "type %s = {\n" typ;
9009       List.iter (
9010         function
9011         | name, FString -> pr "  %s : string;\n" name
9012         | name, FBuffer -> pr "  %s : string;\n" name
9013         | name, FUUID -> pr "  %s : string;\n" name
9014         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
9015         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
9016         | name, FChar -> pr "  %s : char;\n" name
9017         | name, FOptPercent -> pr "  %s : float option;\n" name
9018       ) cols;
9019       pr "}\n";
9020       pr "\n"
9021   ) structs
9022
9023 and generate_ocaml_prototype ?(is_external = false) name style =
9024   if is_external then pr "external " else pr "val ";
9025   pr "%s : t -> " name;
9026   List.iter (
9027     function
9028     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
9029     | BufferIn _ | Key _ -> pr "string -> "
9030     | OptString _ -> pr "string option -> "
9031     | StringList _ | DeviceList _ -> pr "string array -> "
9032     | Bool _ -> pr "bool -> "
9033     | Int _ -> pr "int -> "
9034     | Int64 _ -> pr "int64 -> "
9035   ) (snd style);
9036   (match fst style with
9037    | RErr -> pr "unit" (* all errors are turned into exceptions *)
9038    | RInt _ -> pr "int"
9039    | RInt64 _ -> pr "int64"
9040    | RBool _ -> pr "bool"
9041    | RConstString _ -> pr "string"
9042    | RConstOptString _ -> pr "string option"
9043    | RString _ | RBufferOut _ -> pr "string"
9044    | RStringList _ -> pr "string array"
9045    | RStruct (_, typ) -> pr "%s" typ
9046    | RStructList (_, typ) -> pr "%s array" typ
9047    | RHashtable _ -> pr "(string * string) list"
9048   );
9049   if is_external then (
9050     pr " = ";
9051     if List.length (snd style) + 1 > 5 then
9052       pr "\"ocaml_guestfs_%s_byte\" " name;
9053     pr "\"ocaml_guestfs_%s\"" name
9054   );
9055   pr "\n"
9056
9057 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
9058 and generate_perl_xs () =
9059   generate_header CStyle LGPLv2plus;
9060
9061   pr "\
9062 #include \"EXTERN.h\"
9063 #include \"perl.h\"
9064 #include \"XSUB.h\"
9065
9066 #include <guestfs.h>
9067
9068 #ifndef PRId64
9069 #define PRId64 \"lld\"
9070 #endif
9071
9072 static SV *
9073 my_newSVll(long long val) {
9074 #ifdef USE_64_BIT_ALL
9075   return newSViv(val);
9076 #else
9077   char buf[100];
9078   int len;
9079   len = snprintf(buf, 100, \"%%\" PRId64, val);
9080   return newSVpv(buf, len);
9081 #endif
9082 }
9083
9084 #ifndef PRIu64
9085 #define PRIu64 \"llu\"
9086 #endif
9087
9088 static SV *
9089 my_newSVull(unsigned long long val) {
9090 #ifdef USE_64_BIT_ALL
9091   return newSVuv(val);
9092 #else
9093   char buf[100];
9094   int len;
9095   len = snprintf(buf, 100, \"%%\" PRIu64, val);
9096   return newSVpv(buf, len);
9097 #endif
9098 }
9099
9100 /* http://www.perlmonks.org/?node_id=680842 */
9101 static char **
9102 XS_unpack_charPtrPtr (SV *arg) {
9103   char **ret;
9104   AV *av;
9105   I32 i;
9106
9107   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
9108     croak (\"array reference expected\");
9109
9110   av = (AV *)SvRV (arg);
9111   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
9112   if (!ret)
9113     croak (\"malloc failed\");
9114
9115   for (i = 0; i <= av_len (av); i++) {
9116     SV **elem = av_fetch (av, i, 0);
9117
9118     if (!elem || !*elem)
9119       croak (\"missing element in list\");
9120
9121     ret[i] = SvPV_nolen (*elem);
9122   }
9123
9124   ret[i] = NULL;
9125
9126   return ret;
9127 }
9128
9129 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
9130
9131 PROTOTYPES: ENABLE
9132
9133 guestfs_h *
9134 _create ()
9135    CODE:
9136       RETVAL = guestfs_create ();
9137       if (!RETVAL)
9138         croak (\"could not create guestfs handle\");
9139       guestfs_set_error_handler (RETVAL, NULL, NULL);
9140  OUTPUT:
9141       RETVAL
9142
9143 void
9144 DESTROY (sv)
9145       SV *sv;
9146  PPCODE:
9147       /* For the 'g' argument above we do the conversion explicitly and
9148        * don't rely on the typemap, because if the handle has been
9149        * explicitly closed we don't want the typemap conversion to
9150        * display an error.
9151        */
9152       HV *hv = (HV *) SvRV (sv);
9153       SV **svp = hv_fetch (hv, \"_g\", 2, 0);
9154       if (svp != NULL) {
9155         guestfs_h *g = (guestfs_h *) SvIV (*svp);
9156         assert (g != NULL);
9157         guestfs_close (g);
9158       }
9159
9160 void
9161 close (g)
9162       guestfs_h *g;
9163  PPCODE:
9164       guestfs_close (g);
9165       /* Avoid double-free in DESTROY method. */
9166       HV *hv = (HV *) SvRV (ST(0));
9167       (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
9168
9169 ";
9170
9171   List.iter (
9172     fun (name, style, _, _, _, _, _) ->
9173       (match fst style with
9174        | RErr -> pr "void\n"
9175        | RInt _ -> pr "SV *\n"
9176        | RInt64 _ -> pr "SV *\n"
9177        | RBool _ -> pr "SV *\n"
9178        | RConstString _ -> pr "SV *\n"
9179        | RConstOptString _ -> pr "SV *\n"
9180        | RString _ -> pr "SV *\n"
9181        | RBufferOut _ -> pr "SV *\n"
9182        | RStringList _
9183        | RStruct _ | RStructList _
9184        | RHashtable _ ->
9185            pr "void\n" (* all lists returned implictly on the stack *)
9186       );
9187       (* Call and arguments. *)
9188       pr "%s (g" name;
9189       List.iter (
9190         fun arg -> pr ", %s" (name_of_argt arg)
9191       ) (snd style);
9192       pr ")\n";
9193       pr "      guestfs_h *g;\n";
9194       iteri (
9195         fun i ->
9196           function
9197           | Pathname n | Device n | Dev_or_Path n | String n
9198           | FileIn n | FileOut n | Key n ->
9199               pr "      char *%s;\n" n
9200           | BufferIn n ->
9201               pr "      char *%s;\n" n;
9202               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
9203           | OptString n ->
9204               (* http://www.perlmonks.org/?node_id=554277
9205                * Note that the implicit handle argument means we have
9206                * to add 1 to the ST(x) operator.
9207                *)
9208               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
9209           | StringList n | DeviceList n -> pr "      char **%s;\n" n
9210           | Bool n -> pr "      int %s;\n" n
9211           | Int n -> pr "      int %s;\n" n
9212           | Int64 n -> pr "      int64_t %s;\n" n
9213       ) (snd style);
9214
9215       let do_cleanups () =
9216         List.iter (
9217           function
9218           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
9219           | Bool _ | Int _ | Int64 _
9220           | FileIn _ | FileOut _
9221           | BufferIn _ | Key _ -> ()
9222           | StringList n | DeviceList n -> pr "      free (%s);\n" n
9223         ) (snd style)
9224       in
9225
9226       (* Code. *)
9227       (match fst style with
9228        | RErr ->
9229            pr "PREINIT:\n";
9230            pr "      int r;\n";
9231            pr " PPCODE:\n";
9232            pr "      r = guestfs_%s " name;
9233            generate_c_call_args ~handle:"g" style;
9234            pr ";\n";
9235            do_cleanups ();
9236            pr "      if (r == -1)\n";
9237            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9238        | RInt n
9239        | RBool n ->
9240            pr "PREINIT:\n";
9241            pr "      int %s;\n" n;
9242            pr "   CODE:\n";
9243            pr "      %s = guestfs_%s " n name;
9244            generate_c_call_args ~handle:"g" style;
9245            pr ";\n";
9246            do_cleanups ();
9247            pr "      if (%s == -1)\n" n;
9248            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9249            pr "      RETVAL = newSViv (%s);\n" n;
9250            pr " OUTPUT:\n";
9251            pr "      RETVAL\n"
9252        | RInt64 n ->
9253            pr "PREINIT:\n";
9254            pr "      int64_t %s;\n" n;
9255            pr "   CODE:\n";
9256            pr "      %s = guestfs_%s " n name;
9257            generate_c_call_args ~handle:"g" style;
9258            pr ";\n";
9259            do_cleanups ();
9260            pr "      if (%s == -1)\n" n;
9261            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9262            pr "      RETVAL = my_newSVll (%s);\n" n;
9263            pr " OUTPUT:\n";
9264            pr "      RETVAL\n"
9265        | RConstString n ->
9266            pr "PREINIT:\n";
9267            pr "      const char *%s;\n" n;
9268            pr "   CODE:\n";
9269            pr "      %s = guestfs_%s " n name;
9270            generate_c_call_args ~handle:"g" style;
9271            pr ";\n";
9272            do_cleanups ();
9273            pr "      if (%s == NULL)\n" n;
9274            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9275            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9276            pr " OUTPUT:\n";
9277            pr "      RETVAL\n"
9278        | RConstOptString n ->
9279            pr "PREINIT:\n";
9280            pr "      const char *%s;\n" n;
9281            pr "   CODE:\n";
9282            pr "      %s = guestfs_%s " n name;
9283            generate_c_call_args ~handle:"g" style;
9284            pr ";\n";
9285            do_cleanups ();
9286            pr "      if (%s == NULL)\n" n;
9287            pr "        RETVAL = &PL_sv_undef;\n";
9288            pr "      else\n";
9289            pr "        RETVAL = newSVpv (%s, 0);\n" n;
9290            pr " OUTPUT:\n";
9291            pr "      RETVAL\n"
9292        | RString n ->
9293            pr "PREINIT:\n";
9294            pr "      char *%s;\n" n;
9295            pr "   CODE:\n";
9296            pr "      %s = guestfs_%s " n name;
9297            generate_c_call_args ~handle:"g" style;
9298            pr ";\n";
9299            do_cleanups ();
9300            pr "      if (%s == NULL)\n" n;
9301            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9302            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9303            pr "      free (%s);\n" n;
9304            pr " OUTPUT:\n";
9305            pr "      RETVAL\n"
9306        | RStringList n | RHashtable n ->
9307            pr "PREINIT:\n";
9308            pr "      char **%s;\n" n;
9309            pr "      size_t i, n;\n";
9310            pr " PPCODE:\n";
9311            pr "      %s = guestfs_%s " n name;
9312            generate_c_call_args ~handle:"g" style;
9313            pr ";\n";
9314            do_cleanups ();
9315            pr "      if (%s == NULL)\n" n;
9316            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9317            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9318            pr "      EXTEND (SP, n);\n";
9319            pr "      for (i = 0; i < n; ++i) {\n";
9320            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9321            pr "        free (%s[i]);\n" n;
9322            pr "      }\n";
9323            pr "      free (%s);\n" n;
9324        | RStruct (n, typ) ->
9325            let cols = cols_of_struct typ in
9326            generate_perl_struct_code typ cols name style n do_cleanups
9327        | RStructList (n, typ) ->
9328            let cols = cols_of_struct typ in
9329            generate_perl_struct_list_code typ cols name style n do_cleanups
9330        | RBufferOut n ->
9331            pr "PREINIT:\n";
9332            pr "      char *%s;\n" n;
9333            pr "      size_t size;\n";
9334            pr "   CODE:\n";
9335            pr "      %s = guestfs_%s " n name;
9336            generate_c_call_args ~handle:"g" style;
9337            pr ";\n";
9338            do_cleanups ();
9339            pr "      if (%s == NULL)\n" n;
9340            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9341            pr "      RETVAL = newSVpvn (%s, size);\n" n;
9342            pr "      free (%s);\n" n;
9343            pr " OUTPUT:\n";
9344            pr "      RETVAL\n"
9345       );
9346
9347       pr "\n"
9348   ) all_functions
9349
9350 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9351   pr "PREINIT:\n";
9352   pr "      struct guestfs_%s_list *%s;\n" typ n;
9353   pr "      size_t i;\n";
9354   pr "      HV *hv;\n";
9355   pr " PPCODE:\n";
9356   pr "      %s = guestfs_%s " n name;
9357   generate_c_call_args ~handle:"g" style;
9358   pr ";\n";
9359   do_cleanups ();
9360   pr "      if (%s == NULL)\n" n;
9361   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9362   pr "      EXTEND (SP, %s->len);\n" n;
9363   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
9364   pr "        hv = newHV ();\n";
9365   List.iter (
9366     function
9367     | name, FString ->
9368         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9369           name (String.length name) n name
9370     | name, FUUID ->
9371         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9372           name (String.length name) n name
9373     | name, FBuffer ->
9374         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9375           name (String.length name) n name n name
9376     | name, (FBytes|FUInt64) ->
9377         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9378           name (String.length name) n name
9379     | name, FInt64 ->
9380         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9381           name (String.length name) n name
9382     | name, (FInt32|FUInt32) ->
9383         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9384           name (String.length name) n name
9385     | name, FChar ->
9386         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9387           name (String.length name) n name
9388     | name, FOptPercent ->
9389         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9390           name (String.length name) n name
9391   ) cols;
9392   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9393   pr "      }\n";
9394   pr "      guestfs_free_%s_list (%s);\n" typ n
9395
9396 and generate_perl_struct_code typ cols name style n do_cleanups =
9397   pr "PREINIT:\n";
9398   pr "      struct guestfs_%s *%s;\n" typ n;
9399   pr " PPCODE:\n";
9400   pr "      %s = guestfs_%s " n name;
9401   generate_c_call_args ~handle:"g" style;
9402   pr ";\n";
9403   do_cleanups ();
9404   pr "      if (%s == NULL)\n" n;
9405   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9406   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9407   List.iter (
9408     fun ((name, _) as col) ->
9409       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9410
9411       match col with
9412       | name, FString ->
9413           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9414             n name
9415       | name, FBuffer ->
9416           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9417             n name n name
9418       | name, FUUID ->
9419           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9420             n name
9421       | name, (FBytes|FUInt64) ->
9422           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9423             n name
9424       | name, FInt64 ->
9425           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9426             n name
9427       | name, (FInt32|FUInt32) ->
9428           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9429             n name
9430       | name, FChar ->
9431           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9432             n name
9433       | name, FOptPercent ->
9434           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9435             n name
9436   ) cols;
9437   pr "      free (%s);\n" n
9438
9439 (* Generate Sys/Guestfs.pm. *)
9440 and generate_perl_pm () =
9441   generate_header HashStyle LGPLv2plus;
9442
9443   pr "\
9444 =pod
9445
9446 =head1 NAME
9447
9448 Sys::Guestfs - Perl bindings for libguestfs
9449
9450 =head1 SYNOPSIS
9451
9452  use Sys::Guestfs;
9453
9454  my $h = Sys::Guestfs->new ();
9455  $h->add_drive ('guest.img');
9456  $h->launch ();
9457  $h->mount ('/dev/sda1', '/');
9458  $h->touch ('/hello');
9459  $h->sync ();
9460
9461 =head1 DESCRIPTION
9462
9463 The C<Sys::Guestfs> module provides a Perl XS binding to the
9464 libguestfs API for examining and modifying virtual machine
9465 disk images.
9466
9467 Amongst the things this is good for: making batch configuration
9468 changes to guests, getting disk used/free statistics (see also:
9469 virt-df), migrating between virtualization systems (see also:
9470 virt-p2v), performing partial backups, performing partial guest
9471 clones, cloning guests and changing registry/UUID/hostname info, and
9472 much else besides.
9473
9474 Libguestfs uses Linux kernel and qemu code, and can access any type of
9475 guest filesystem that Linux and qemu can, including but not limited
9476 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9477 schemes, qcow, qcow2, vmdk.
9478
9479 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9480 LVs, what filesystem is in each LV, etc.).  It can also run commands
9481 in the context of the guest.  Also you can access filesystems over
9482 FUSE.
9483
9484 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9485 functions for using libguestfs from Perl, including integration
9486 with libvirt.
9487
9488 =head1 ERRORS
9489
9490 All errors turn into calls to C<croak> (see L<Carp(3)>).
9491
9492 =head1 METHODS
9493
9494 =over 4
9495
9496 =cut
9497
9498 package Sys::Guestfs;
9499
9500 use strict;
9501 use warnings;
9502
9503 # This version number changes whenever a new function
9504 # is added to the libguestfs API.  It is not directly
9505 # related to the libguestfs version number.
9506 use vars qw($VERSION);
9507 $VERSION = '0.%d';
9508
9509 require XSLoader;
9510 XSLoader::load ('Sys::Guestfs');
9511
9512 =item $h = Sys::Guestfs->new ();
9513
9514 Create a new guestfs handle.
9515
9516 =cut
9517
9518 sub new {
9519   my $proto = shift;
9520   my $class = ref ($proto) || $proto;
9521
9522   my $g = Sys::Guestfs::_create ();
9523   my $self = { _g => $g };
9524   bless $self, $class;
9525   return $self;
9526 }
9527
9528 =item $h->close ();
9529
9530 Explicitly close the guestfs handle.
9531
9532 B<Note:> You should not usually call this function.  The handle will
9533 be closed implicitly when its reference count goes to zero (eg.
9534 when it goes out of scope or the program ends).  This call is
9535 only required in some exceptional cases, such as where the program
9536 may contain cached references to the handle 'somewhere' and you
9537 really have to have the close happen right away.  After calling
9538 C<close> the program must not call any method (including C<close>)
9539 on the handle (but the implicit call to C<DESTROY> that happens
9540 when the final reference is cleaned up is OK).
9541
9542 =cut
9543
9544 " max_proc_nr;
9545
9546   (* Actions.  We only need to print documentation for these as
9547    * they are pulled in from the XS code automatically.
9548    *)
9549   List.iter (
9550     fun (name, style, _, flags, _, _, longdesc) ->
9551       if not (List.mem NotInDocs flags) then (
9552         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9553         pr "=item ";
9554         generate_perl_prototype name style;
9555         pr "\n\n";
9556         pr "%s\n\n" longdesc;
9557         if List.mem ProtocolLimitWarning flags then
9558           pr "%s\n\n" protocol_limit_warning;
9559         if List.mem DangerWillRobinson flags then
9560           pr "%s\n\n" danger_will_robinson;
9561         match deprecation_notice flags with
9562         | None -> ()
9563         | Some txt -> pr "%s\n\n" txt
9564       )
9565   ) all_functions_sorted;
9566
9567   (* End of file. *)
9568   pr "\
9569 =cut
9570
9571 1;
9572
9573 =back
9574
9575 =head1 COPYRIGHT
9576
9577 Copyright (C) %s Red Hat Inc.
9578
9579 =head1 LICENSE
9580
9581 Please see the file COPYING.LIB for the full license.
9582
9583 =head1 SEE ALSO
9584
9585 L<guestfs(3)>,
9586 L<guestfish(1)>,
9587 L<http://libguestfs.org>,
9588 L<Sys::Guestfs::Lib(3)>.
9589
9590 =cut
9591 " copyright_years
9592
9593 and generate_perl_prototype name style =
9594   (match fst style with
9595    | RErr -> ()
9596    | RBool n
9597    | RInt n
9598    | RInt64 n
9599    | RConstString n
9600    | RConstOptString n
9601    | RString n
9602    | RBufferOut n -> pr "$%s = " n
9603    | RStruct (n,_)
9604    | RHashtable n -> pr "%%%s = " n
9605    | RStringList n
9606    | RStructList (n,_) -> pr "@%s = " n
9607   );
9608   pr "$h->%s (" name;
9609   let comma = ref false in
9610   List.iter (
9611     fun arg ->
9612       if !comma then pr ", ";
9613       comma := true;
9614       match arg with
9615       | Pathname n | Device n | Dev_or_Path n | String n
9616       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9617       | BufferIn n | Key n ->
9618           pr "$%s" n
9619       | StringList n | DeviceList n ->
9620           pr "\\@%s" n
9621   ) (snd style);
9622   pr ");"
9623
9624 (* Generate Python C module. *)
9625 and generate_python_c () =
9626   generate_header CStyle LGPLv2plus;
9627
9628   pr "\
9629 #define PY_SSIZE_T_CLEAN 1
9630 #include <Python.h>
9631
9632 #if PY_VERSION_HEX < 0x02050000
9633 typedef int Py_ssize_t;
9634 #define PY_SSIZE_T_MAX INT_MAX
9635 #define PY_SSIZE_T_MIN INT_MIN
9636 #endif
9637
9638 #include <stdio.h>
9639 #include <stdlib.h>
9640 #include <assert.h>
9641
9642 #include \"guestfs.h\"
9643
9644 #ifndef HAVE_PYCAPSULE_NEW
9645 typedef struct {
9646   PyObject_HEAD
9647   guestfs_h *g;
9648 } Pyguestfs_Object;
9649 #endif
9650
9651 static guestfs_h *
9652 get_handle (PyObject *obj)
9653 {
9654   assert (obj);
9655   assert (obj != Py_None);
9656 #ifndef HAVE_PYCAPSULE_NEW
9657   return ((Pyguestfs_Object *) obj)->g;
9658 #else
9659   return (guestfs_h*) PyCapsule_GetPointer(obj, \"guestfs_h\");
9660 #endif
9661 }
9662
9663 static PyObject *
9664 put_handle (guestfs_h *g)
9665 {
9666   assert (g);
9667 #ifndef HAVE_PYCAPSULE_NEW
9668   return
9669     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9670 #else
9671   return PyCapsule_New ((void *) g, \"guestfs_h\", NULL);
9672 #endif
9673 }
9674
9675 /* This list should be freed (but not the strings) after use. */
9676 static char **
9677 get_string_list (PyObject *obj)
9678 {
9679   size_t i, len;
9680   char **r;
9681
9682   assert (obj);
9683
9684   if (!PyList_Check (obj)) {
9685     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9686     return NULL;
9687   }
9688
9689   Py_ssize_t slen = PyList_Size (obj);
9690   if (slen == -1) {
9691     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9692     return NULL;
9693   }
9694   len = (size_t) slen;
9695   r = malloc (sizeof (char *) * (len+1));
9696   if (r == NULL) {
9697     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9698     return NULL;
9699   }
9700
9701   for (i = 0; i < len; ++i)
9702     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9703   r[len] = NULL;
9704
9705   return r;
9706 }
9707
9708 static PyObject *
9709 put_string_list (char * const * const argv)
9710 {
9711   PyObject *list;
9712   int argc, i;
9713
9714   for (argc = 0; argv[argc] != NULL; ++argc)
9715     ;
9716
9717   list = PyList_New (argc);
9718   for (i = 0; i < argc; ++i)
9719     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9720
9721   return list;
9722 }
9723
9724 static PyObject *
9725 put_table (char * const * const argv)
9726 {
9727   PyObject *list, *item;
9728   int argc, i;
9729
9730   for (argc = 0; argv[argc] != NULL; ++argc)
9731     ;
9732
9733   list = PyList_New (argc >> 1);
9734   for (i = 0; i < argc; i += 2) {
9735     item = PyTuple_New (2);
9736     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9737     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9738     PyList_SetItem (list, i >> 1, item);
9739   }
9740
9741   return list;
9742 }
9743
9744 static void
9745 free_strings (char **argv)
9746 {
9747   int argc;
9748
9749   for (argc = 0; argv[argc] != NULL; ++argc)
9750     free (argv[argc]);
9751   free (argv);
9752 }
9753
9754 static PyObject *
9755 py_guestfs_create (PyObject *self, PyObject *args)
9756 {
9757   guestfs_h *g;
9758
9759   g = guestfs_create ();
9760   if (g == NULL) {
9761     PyErr_SetString (PyExc_RuntimeError,
9762                      \"guestfs.create: failed to allocate handle\");
9763     return NULL;
9764   }
9765   guestfs_set_error_handler (g, NULL, NULL);
9766   /* This can return NULL, but in that case put_handle will have
9767    * set the Python error string.
9768    */
9769   return put_handle (g);
9770 }
9771
9772 static PyObject *
9773 py_guestfs_close (PyObject *self, PyObject *args)
9774 {
9775   PyObject *py_g;
9776   guestfs_h *g;
9777
9778   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9779     return NULL;
9780   g = get_handle (py_g);
9781
9782   guestfs_close (g);
9783
9784   Py_INCREF (Py_None);
9785   return Py_None;
9786 }
9787
9788 ";
9789
9790   let emit_put_list_function typ =
9791     pr "static PyObject *\n";
9792     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9793     pr "{\n";
9794     pr "  PyObject *list;\n";
9795     pr "  size_t i;\n";
9796     pr "\n";
9797     pr "  list = PyList_New (%ss->len);\n" typ;
9798     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9799     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9800     pr "  return list;\n";
9801     pr "};\n";
9802     pr "\n"
9803   in
9804
9805   (* Structures, turned into Python dictionaries. *)
9806   List.iter (
9807     fun (typ, cols) ->
9808       pr "static PyObject *\n";
9809       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9810       pr "{\n";
9811       pr "  PyObject *dict;\n";
9812       pr "\n";
9813       pr "  dict = PyDict_New ();\n";
9814       List.iter (
9815         function
9816         | name, FString ->
9817             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9818             pr "                        PyString_FromString (%s->%s));\n"
9819               typ name
9820         | name, FBuffer ->
9821             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9822             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9823               typ name typ name
9824         | name, FUUID ->
9825             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9826             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9827               typ name
9828         | name, (FBytes|FUInt64) ->
9829             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9830             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9831               typ name
9832         | name, FInt64 ->
9833             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9834             pr "                        PyLong_FromLongLong (%s->%s));\n"
9835               typ name
9836         | name, FUInt32 ->
9837             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9838             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9839               typ name
9840         | name, FInt32 ->
9841             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9842             pr "                        PyLong_FromLong (%s->%s));\n"
9843               typ name
9844         | name, FOptPercent ->
9845             pr "  if (%s->%s >= 0)\n" typ name;
9846             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9847             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9848               typ name;
9849             pr "  else {\n";
9850             pr "    Py_INCREF (Py_None);\n";
9851             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9852             pr "  }\n"
9853         | name, FChar ->
9854             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9855             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9856       ) cols;
9857       pr "  return dict;\n";
9858       pr "};\n";
9859       pr "\n";
9860
9861   ) structs;
9862
9863   (* Emit a put_TYPE_list function definition only if that function is used. *)
9864   List.iter (
9865     function
9866     | typ, (RStructListOnly | RStructAndList) ->
9867         (* generate the function for typ *)
9868         emit_put_list_function typ
9869     | typ, _ -> () (* empty *)
9870   ) (rstructs_used_by all_functions);
9871
9872   (* Python wrapper functions. *)
9873   List.iter (
9874     fun (name, style, _, _, _, _, _) ->
9875       pr "static PyObject *\n";
9876       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9877       pr "{\n";
9878
9879       pr "  PyObject *py_g;\n";
9880       pr "  guestfs_h *g;\n";
9881       pr "  PyObject *py_r;\n";
9882
9883       let error_code =
9884         match fst style with
9885         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9886         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9887         | RConstString _ | RConstOptString _ ->
9888             pr "  const char *r;\n"; "NULL"
9889         | RString _ -> pr "  char *r;\n"; "NULL"
9890         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9891         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9892         | RStructList (_, typ) ->
9893             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9894         | RBufferOut _ ->
9895             pr "  char *r;\n";
9896             pr "  size_t size;\n";
9897             "NULL" in
9898
9899       List.iter (
9900         function
9901         | Pathname n | Device n | Dev_or_Path n | String n | Key n
9902         | FileIn n | FileOut n ->
9903             pr "  const char *%s;\n" n
9904         | OptString n -> pr "  const char *%s;\n" n
9905         | BufferIn n ->
9906             pr "  const char *%s;\n" n;
9907             pr "  Py_ssize_t %s_size;\n" n
9908         | StringList n | DeviceList n ->
9909             pr "  PyObject *py_%s;\n" n;
9910             pr "  char **%s;\n" n
9911         | Bool n -> pr "  int %s;\n" n
9912         | Int n -> pr "  int %s;\n" n
9913         | Int64 n -> pr "  long long %s;\n" n
9914       ) (snd style);
9915
9916       pr "\n";
9917
9918       (* Convert the parameters. *)
9919       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9920       List.iter (
9921         function
9922         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9923         | FileIn _ | FileOut _ -> pr "s"
9924         | OptString _ -> pr "z"
9925         | StringList _ | DeviceList _ -> pr "O"
9926         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9927         | Int _ -> pr "i"
9928         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9929                              * emulate C's int/long/long long in Python?
9930                              *)
9931         | BufferIn _ -> pr "s#"
9932       ) (snd style);
9933       pr ":guestfs_%s\",\n" name;
9934       pr "                         &py_g";
9935       List.iter (
9936         function
9937         | Pathname n | Device n | Dev_or_Path n | String n | Key n
9938         | FileIn n | FileOut n -> pr ", &%s" n
9939         | OptString n -> pr ", &%s" n
9940         | StringList n | DeviceList n -> pr ", &py_%s" n
9941         | Bool n -> pr ", &%s" n
9942         | Int n -> pr ", &%s" n
9943         | Int64 n -> pr ", &%s" n
9944         | BufferIn n -> pr ", &%s, &%s_size" n n
9945       ) (snd style);
9946
9947       pr "))\n";
9948       pr "    return NULL;\n";
9949
9950       pr "  g = get_handle (py_g);\n";
9951       List.iter (
9952         function
9953         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9954         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9955         | BufferIn _ -> ()
9956         | StringList n | DeviceList n ->
9957             pr "  %s = get_string_list (py_%s);\n" n n;
9958             pr "  if (!%s) return NULL;\n" n
9959       ) (snd style);
9960
9961       pr "\n";
9962
9963       pr "  r = guestfs_%s " name;
9964       generate_c_call_args ~handle:"g" style;
9965       pr ";\n";
9966
9967       List.iter (
9968         function
9969         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9970         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9971         | BufferIn _ -> ()
9972         | StringList n | DeviceList n ->
9973             pr "  free (%s);\n" n
9974       ) (snd style);
9975
9976       pr "  if (r == %s) {\n" error_code;
9977       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9978       pr "    return NULL;\n";
9979       pr "  }\n";
9980       pr "\n";
9981
9982       (match fst style with
9983        | RErr ->
9984            pr "  Py_INCREF (Py_None);\n";
9985            pr "  py_r = Py_None;\n"
9986        | RInt _
9987        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9988        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9989        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9990        | RConstOptString _ ->
9991            pr "  if (r)\n";
9992            pr "    py_r = PyString_FromString (r);\n";
9993            pr "  else {\n";
9994            pr "    Py_INCREF (Py_None);\n";
9995            pr "    py_r = Py_None;\n";
9996            pr "  }\n"
9997        | RString _ ->
9998            pr "  py_r = PyString_FromString (r);\n";
9999            pr "  free (r);\n"
10000        | RStringList _ ->
10001            pr "  py_r = put_string_list (r);\n";
10002            pr "  free_strings (r);\n"
10003        | RStruct (_, typ) ->
10004            pr "  py_r = put_%s (r);\n" typ;
10005            pr "  guestfs_free_%s (r);\n" typ
10006        | RStructList (_, typ) ->
10007            pr "  py_r = put_%s_list (r);\n" typ;
10008            pr "  guestfs_free_%s_list (r);\n" typ
10009        | RHashtable n ->
10010            pr "  py_r = put_table (r);\n";
10011            pr "  free_strings (r);\n"
10012        | RBufferOut _ ->
10013            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
10014            pr "  free (r);\n"
10015       );
10016
10017       pr "  return py_r;\n";
10018       pr "}\n";
10019       pr "\n"
10020   ) all_functions;
10021
10022   (* Table of functions. *)
10023   pr "static PyMethodDef methods[] = {\n";
10024   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
10025   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
10026   List.iter (
10027     fun (name, _, _, _, _, _, _) ->
10028       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
10029         name name
10030   ) all_functions;
10031   pr "  { NULL, NULL, 0, NULL }\n";
10032   pr "};\n";
10033   pr "\n";
10034
10035   (* Init function. *)
10036   pr "\
10037 void
10038 initlibguestfsmod (void)
10039 {
10040   static int initialized = 0;
10041
10042   if (initialized) return;
10043   Py_InitModule ((char *) \"libguestfsmod\", methods);
10044   initialized = 1;
10045 }
10046 "
10047
10048 (* Generate Python module. *)
10049 and generate_python_py () =
10050   generate_header HashStyle LGPLv2plus;
10051
10052   pr "\
10053 u\"\"\"Python bindings for libguestfs
10054
10055 import guestfs
10056 g = guestfs.GuestFS ()
10057 g.add_drive (\"guest.img\")
10058 g.launch ()
10059 parts = g.list_partitions ()
10060
10061 The guestfs module provides a Python binding to the libguestfs API
10062 for examining and modifying virtual machine disk images.
10063
10064 Amongst the things this is good for: making batch configuration
10065 changes to guests, getting disk used/free statistics (see also:
10066 virt-df), migrating between virtualization systems (see also:
10067 virt-p2v), performing partial backups, performing partial guest
10068 clones, cloning guests and changing registry/UUID/hostname info, and
10069 much else besides.
10070
10071 Libguestfs uses Linux kernel and qemu code, and can access any type of
10072 guest filesystem that Linux and qemu can, including but not limited
10073 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
10074 schemes, qcow, qcow2, vmdk.
10075
10076 Libguestfs provides ways to enumerate guest storage (eg. partitions,
10077 LVs, what filesystem is in each LV, etc.).  It can also run commands
10078 in the context of the guest.  Also you can access filesystems over
10079 FUSE.
10080
10081 Errors which happen while using the API are turned into Python
10082 RuntimeError exceptions.
10083
10084 To create a guestfs handle you usually have to perform the following
10085 sequence of calls:
10086
10087 # Create the handle, call add_drive at least once, and possibly
10088 # several times if the guest has multiple block devices:
10089 g = guestfs.GuestFS ()
10090 g.add_drive (\"guest.img\")
10091
10092 # Launch the qemu subprocess and wait for it to become ready:
10093 g.launch ()
10094
10095 # Now you can issue commands, for example:
10096 logvols = g.lvs ()
10097
10098 \"\"\"
10099
10100 import libguestfsmod
10101
10102 class GuestFS:
10103     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
10104
10105     def __init__ (self):
10106         \"\"\"Create a new libguestfs handle.\"\"\"
10107         self._o = libguestfsmod.create ()
10108
10109     def __del__ (self):
10110         libguestfsmod.close (self._o)
10111
10112 ";
10113
10114   List.iter (
10115     fun (name, style, _, flags, _, _, longdesc) ->
10116       pr "    def %s " name;
10117       generate_py_call_args ~handle:"self" (snd style);
10118       pr ":\n";
10119
10120       if not (List.mem NotInDocs flags) then (
10121         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10122         let doc =
10123           match fst style with
10124           | RErr | RInt _ | RInt64 _ | RBool _
10125           | RConstOptString _ | RConstString _
10126           | RString _ | RBufferOut _ -> doc
10127           | RStringList _ ->
10128               doc ^ "\n\nThis function returns a list of strings."
10129           | RStruct (_, typ) ->
10130               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
10131           | RStructList (_, typ) ->
10132               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
10133           | RHashtable _ ->
10134               doc ^ "\n\nThis function returns a dictionary." in
10135         let doc =
10136           if List.mem ProtocolLimitWarning flags then
10137             doc ^ "\n\n" ^ protocol_limit_warning
10138           else doc in
10139         let doc =
10140           if List.mem DangerWillRobinson flags then
10141             doc ^ "\n\n" ^ danger_will_robinson
10142           else doc in
10143         let doc =
10144           match deprecation_notice flags with
10145           | None -> doc
10146           | Some txt -> doc ^ "\n\n" ^ txt in
10147         let doc = pod2text ~width:60 name doc in
10148         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
10149         let doc = String.concat "\n        " doc in
10150         pr "        u\"\"\"%s\"\"\"\n" doc;
10151       );
10152       pr "        return libguestfsmod.%s " name;
10153       generate_py_call_args ~handle:"self._o" (snd style);
10154       pr "\n";
10155       pr "\n";
10156   ) all_functions
10157
10158 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
10159 and generate_py_call_args ~handle args =
10160   pr "(%s" handle;
10161   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10162   pr ")"
10163
10164 (* Useful if you need the longdesc POD text as plain text.  Returns a
10165  * list of lines.
10166  *
10167  * Because this is very slow (the slowest part of autogeneration),
10168  * we memoize the results.
10169  *)
10170 and pod2text ~width name longdesc =
10171   let key = width, name, longdesc in
10172   try Hashtbl.find pod2text_memo key
10173   with Not_found ->
10174     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
10175     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
10176     close_out chan;
10177     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
10178     let chan = open_process_in cmd in
10179     let lines = ref [] in
10180     let rec loop i =
10181       let line = input_line chan in
10182       if i = 1 then             (* discard the first line of output *)
10183         loop (i+1)
10184       else (
10185         let line = triml line in
10186         lines := line :: !lines;
10187         loop (i+1)
10188       ) in
10189     let lines = try loop 1 with End_of_file -> List.rev !lines in
10190     unlink filename;
10191     (match close_process_in chan with
10192      | WEXITED 0 -> ()
10193      | WEXITED i ->
10194          failwithf "pod2text: process exited with non-zero status (%d)" i
10195      | WSIGNALED i | WSTOPPED i ->
10196          failwithf "pod2text: process signalled or stopped by signal %d" i
10197     );
10198     Hashtbl.add pod2text_memo key lines;
10199     pod2text_memo_updated ();
10200     lines
10201
10202 (* Generate ruby bindings. *)
10203 and generate_ruby_c () =
10204   generate_header CStyle LGPLv2plus;
10205
10206   pr "\
10207 #include <stdio.h>
10208 #include <stdlib.h>
10209
10210 #include <ruby.h>
10211
10212 #include \"guestfs.h\"
10213
10214 #include \"extconf.h\"
10215
10216 /* For Ruby < 1.9 */
10217 #ifndef RARRAY_LEN
10218 #define RARRAY_LEN(r) (RARRAY((r))->len)
10219 #endif
10220
10221 static VALUE m_guestfs;                 /* guestfs module */
10222 static VALUE c_guestfs;                 /* guestfs_h handle */
10223 static VALUE e_Error;                   /* used for all errors */
10224
10225 static void ruby_guestfs_free (void *p)
10226 {
10227   if (!p) return;
10228   guestfs_close ((guestfs_h *) p);
10229 }
10230
10231 static VALUE ruby_guestfs_create (VALUE m)
10232 {
10233   guestfs_h *g;
10234
10235   g = guestfs_create ();
10236   if (!g)
10237     rb_raise (e_Error, \"failed to create guestfs handle\");
10238
10239   /* Don't print error messages to stderr by default. */
10240   guestfs_set_error_handler (g, NULL, NULL);
10241
10242   /* Wrap it, and make sure the close function is called when the
10243    * handle goes away.
10244    */
10245   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
10246 }
10247
10248 static VALUE ruby_guestfs_close (VALUE gv)
10249 {
10250   guestfs_h *g;
10251   Data_Get_Struct (gv, guestfs_h, g);
10252
10253   ruby_guestfs_free (g);
10254   DATA_PTR (gv) = NULL;
10255
10256   return Qnil;
10257 }
10258
10259 ";
10260
10261   List.iter (
10262     fun (name, style, _, _, _, _, _) ->
10263       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
10264       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
10265       pr ")\n";
10266       pr "{\n";
10267       pr "  guestfs_h *g;\n";
10268       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
10269       pr "  if (!g)\n";
10270       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
10271         name;
10272       pr "\n";
10273
10274       List.iter (
10275         function
10276         | Pathname n | Device n | Dev_or_Path n | String n | Key n
10277         | FileIn n | FileOut n ->
10278             pr "  Check_Type (%sv, T_STRING);\n" n;
10279             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
10280             pr "  if (!%s)\n" n;
10281             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10282             pr "              \"%s\", \"%s\");\n" n name
10283         | BufferIn n ->
10284             pr "  Check_Type (%sv, T_STRING);\n" n;
10285             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
10286             pr "  if (!%s)\n" n;
10287             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10288             pr "              \"%s\", \"%s\");\n" n name;
10289             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
10290         | OptString n ->
10291             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
10292         | StringList n | DeviceList n ->
10293             pr "  char **%s;\n" n;
10294             pr "  Check_Type (%sv, T_ARRAY);\n" n;
10295             pr "  {\n";
10296             pr "    size_t i, len;\n";
10297             pr "    len = RARRAY_LEN (%sv);\n" n;
10298             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
10299               n;
10300             pr "    for (i = 0; i < len; ++i) {\n";
10301             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
10302             pr "      %s[i] = StringValueCStr (v);\n" n;
10303             pr "    }\n";
10304             pr "    %s[len] = NULL;\n" n;
10305             pr "  }\n";
10306         | Bool n ->
10307             pr "  int %s = RTEST (%sv);\n" n n
10308         | Int n ->
10309             pr "  int %s = NUM2INT (%sv);\n" n n
10310         | Int64 n ->
10311             pr "  long long %s = NUM2LL (%sv);\n" n n
10312       ) (snd style);
10313       pr "\n";
10314
10315       let error_code =
10316         match fst style with
10317         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
10318         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
10319         | RConstString _ | RConstOptString _ ->
10320             pr "  const char *r;\n"; "NULL"
10321         | RString _ -> pr "  char *r;\n"; "NULL"
10322         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
10323         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
10324         | RStructList (_, typ) ->
10325             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
10326         | RBufferOut _ ->
10327             pr "  char *r;\n";
10328             pr "  size_t size;\n";
10329             "NULL" in
10330       pr "\n";
10331
10332       pr "  r = guestfs_%s " name;
10333       generate_c_call_args ~handle:"g" style;
10334       pr ";\n";
10335
10336       List.iter (
10337         function
10338         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
10339         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10340         | BufferIn _ -> ()
10341         | StringList n | DeviceList n ->
10342             pr "  free (%s);\n" n
10343       ) (snd style);
10344
10345       pr "  if (r == %s)\n" error_code;
10346       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10347       pr "\n";
10348
10349       (match fst style with
10350        | RErr ->
10351            pr "  return Qnil;\n"
10352        | RInt _ | RBool _ ->
10353            pr "  return INT2NUM (r);\n"
10354        | RInt64 _ ->
10355            pr "  return ULL2NUM (r);\n"
10356        | RConstString _ ->
10357            pr "  return rb_str_new2 (r);\n";
10358        | RConstOptString _ ->
10359            pr "  if (r)\n";
10360            pr "    return rb_str_new2 (r);\n";
10361            pr "  else\n";
10362            pr "    return Qnil;\n";
10363        | RString _ ->
10364            pr "  VALUE rv = rb_str_new2 (r);\n";
10365            pr "  free (r);\n";
10366            pr "  return rv;\n";
10367        | RStringList _ ->
10368            pr "  size_t i, len = 0;\n";
10369            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
10370            pr "  VALUE rv = rb_ary_new2 (len);\n";
10371            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
10372            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10373            pr "    free (r[i]);\n";
10374            pr "  }\n";
10375            pr "  free (r);\n";
10376            pr "  return rv;\n"
10377        | RStruct (_, typ) ->
10378            let cols = cols_of_struct typ in
10379            generate_ruby_struct_code typ cols
10380        | RStructList (_, typ) ->
10381            let cols = cols_of_struct typ in
10382            generate_ruby_struct_list_code typ cols
10383        | RHashtable _ ->
10384            pr "  VALUE rv = rb_hash_new ();\n";
10385            pr "  size_t i;\n";
10386            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
10387            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10388            pr "    free (r[i]);\n";
10389            pr "    free (r[i+1]);\n";
10390            pr "  }\n";
10391            pr "  free (r);\n";
10392            pr "  return rv;\n"
10393        | RBufferOut _ ->
10394            pr "  VALUE rv = rb_str_new (r, size);\n";
10395            pr "  free (r);\n";
10396            pr "  return rv;\n";
10397       );
10398
10399       pr "}\n";
10400       pr "\n"
10401   ) all_functions;
10402
10403   pr "\
10404 /* Initialize the module. */
10405 void Init__guestfs ()
10406 {
10407   m_guestfs = rb_define_module (\"Guestfs\");
10408   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10409   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10410
10411   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10412   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10413
10414 ";
10415   (* Define the rest of the methods. *)
10416   List.iter (
10417     fun (name, style, _, _, _, _, _) ->
10418       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10419       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10420   ) all_functions;
10421
10422   pr "}\n"
10423
10424 (* Ruby code to return a struct. *)
10425 and generate_ruby_struct_code typ cols =
10426   pr "  VALUE rv = rb_hash_new ();\n";
10427   List.iter (
10428     function
10429     | name, FString ->
10430         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10431     | name, FBuffer ->
10432         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10433     | name, FUUID ->
10434         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10435     | name, (FBytes|FUInt64) ->
10436         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10437     | name, FInt64 ->
10438         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10439     | name, FUInt32 ->
10440         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10441     | name, FInt32 ->
10442         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10443     | name, FOptPercent ->
10444         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10445     | name, FChar -> (* XXX wrong? *)
10446         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10447   ) cols;
10448   pr "  guestfs_free_%s (r);\n" typ;
10449   pr "  return rv;\n"
10450
10451 (* Ruby code to return a struct list. *)
10452 and generate_ruby_struct_list_code typ cols =
10453   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10454   pr "  size_t i;\n";
10455   pr "  for (i = 0; i < r->len; ++i) {\n";
10456   pr "    VALUE hv = rb_hash_new ();\n";
10457   List.iter (
10458     function
10459     | name, FString ->
10460         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10461     | name, FBuffer ->
10462         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
10463     | name, FUUID ->
10464         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10465     | name, (FBytes|FUInt64) ->
10466         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10467     | name, FInt64 ->
10468         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10469     | name, FUInt32 ->
10470         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10471     | name, FInt32 ->
10472         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10473     | name, FOptPercent ->
10474         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10475     | name, FChar -> (* XXX wrong? *)
10476         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10477   ) cols;
10478   pr "    rb_ary_push (rv, hv);\n";
10479   pr "  }\n";
10480   pr "  guestfs_free_%s_list (r);\n" typ;
10481   pr "  return rv;\n"
10482
10483 (* Generate Java bindings GuestFS.java file. *)
10484 and generate_java_java () =
10485   generate_header CStyle LGPLv2plus;
10486
10487   pr "\
10488 package com.redhat.et.libguestfs;
10489
10490 import java.util.HashMap;
10491 import com.redhat.et.libguestfs.LibGuestFSException;
10492 import com.redhat.et.libguestfs.PV;
10493 import com.redhat.et.libguestfs.VG;
10494 import com.redhat.et.libguestfs.LV;
10495 import com.redhat.et.libguestfs.Stat;
10496 import com.redhat.et.libguestfs.StatVFS;
10497 import com.redhat.et.libguestfs.IntBool;
10498 import com.redhat.et.libguestfs.Dirent;
10499
10500 /**
10501  * The GuestFS object is a libguestfs handle.
10502  *
10503  * @author rjones
10504  */
10505 public class GuestFS {
10506   // Load the native code.
10507   static {
10508     System.loadLibrary (\"guestfs_jni\");
10509   }
10510
10511   /**
10512    * The native guestfs_h pointer.
10513    */
10514   long g;
10515
10516   /**
10517    * Create a libguestfs handle.
10518    *
10519    * @throws LibGuestFSException
10520    */
10521   public GuestFS () throws LibGuestFSException
10522   {
10523     g = _create ();
10524   }
10525   private native long _create () throws LibGuestFSException;
10526
10527   /**
10528    * Close a libguestfs handle.
10529    *
10530    * You can also leave handles to be collected by the garbage
10531    * collector, but this method ensures that the resources used
10532    * by the handle are freed up immediately.  If you call any
10533    * other methods after closing the handle, you will get an
10534    * exception.
10535    *
10536    * @throws LibGuestFSException
10537    */
10538   public void close () throws LibGuestFSException
10539   {
10540     if (g != 0)
10541       _close (g);
10542     g = 0;
10543   }
10544   private native void _close (long g) throws LibGuestFSException;
10545
10546   public void finalize () throws LibGuestFSException
10547   {
10548     close ();
10549   }
10550
10551 ";
10552
10553   List.iter (
10554     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10555       if not (List.mem NotInDocs flags); then (
10556         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10557         let doc =
10558           if List.mem ProtocolLimitWarning flags then
10559             doc ^ "\n\n" ^ protocol_limit_warning
10560           else doc in
10561         let doc =
10562           if List.mem DangerWillRobinson flags then
10563             doc ^ "\n\n" ^ danger_will_robinson
10564           else doc in
10565         let doc =
10566           match deprecation_notice flags with
10567           | None -> doc
10568           | Some txt -> doc ^ "\n\n" ^ txt in
10569         let doc = pod2text ~width:60 name doc in
10570         let doc = List.map (            (* RHBZ#501883 *)
10571           function
10572           | "" -> "<p>"
10573           | nonempty -> nonempty
10574         ) doc in
10575         let doc = String.concat "\n   * " doc in
10576
10577         pr "  /**\n";
10578         pr "   * %s\n" shortdesc;
10579         pr "   * <p>\n";
10580         pr "   * %s\n" doc;
10581         pr "   * @throws LibGuestFSException\n";
10582         pr "   */\n";
10583         pr "  ";
10584       );
10585       generate_java_prototype ~public:true ~semicolon:false name style;
10586       pr "\n";
10587       pr "  {\n";
10588       pr "    if (g == 0)\n";
10589       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10590         name;
10591       pr "    ";
10592       if fst style <> RErr then pr "return ";
10593       pr "_%s " name;
10594       generate_java_call_args ~handle:"g" (snd style);
10595       pr ";\n";
10596       pr "  }\n";
10597       pr "  ";
10598       generate_java_prototype ~privat:true ~native:true name style;
10599       pr "\n";
10600       pr "\n";
10601   ) all_functions;
10602
10603   pr "}\n"
10604
10605 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10606 and generate_java_call_args ~handle args =
10607   pr "(%s" handle;
10608   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10609   pr ")"
10610
10611 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10612     ?(semicolon=true) name style =
10613   if privat then pr "private ";
10614   if public then pr "public ";
10615   if native then pr "native ";
10616
10617   (* return type *)
10618   (match fst style with
10619    | RErr -> pr "void ";
10620    | RInt _ -> pr "int ";
10621    | RInt64 _ -> pr "long ";
10622    | RBool _ -> pr "boolean ";
10623    | RConstString _ | RConstOptString _ | RString _
10624    | RBufferOut _ -> pr "String ";
10625    | RStringList _ -> pr "String[] ";
10626    | RStruct (_, typ) ->
10627        let name = java_name_of_struct typ in
10628        pr "%s " name;
10629    | RStructList (_, typ) ->
10630        let name = java_name_of_struct typ in
10631        pr "%s[] " name;
10632    | RHashtable _ -> pr "HashMap<String,String> ";
10633   );
10634
10635   if native then pr "_%s " name else pr "%s " name;
10636   pr "(";
10637   let needs_comma = ref false in
10638   if native then (
10639     pr "long g";
10640     needs_comma := true
10641   );
10642
10643   (* args *)
10644   List.iter (
10645     fun arg ->
10646       if !needs_comma then pr ", ";
10647       needs_comma := true;
10648
10649       match arg with
10650       | Pathname n
10651       | Device n | Dev_or_Path n
10652       | String n
10653       | OptString n
10654       | FileIn n
10655       | FileOut n
10656       | Key n ->
10657           pr "String %s" n
10658       | BufferIn n ->
10659           pr "byte[] %s" n
10660       | StringList n | DeviceList n ->
10661           pr "String[] %s" n
10662       | Bool n ->
10663           pr "boolean %s" n
10664       | Int n ->
10665           pr "int %s" n
10666       | Int64 n ->
10667           pr "long %s" n
10668   ) (snd style);
10669
10670   pr ")\n";
10671   pr "    throws LibGuestFSException";
10672   if semicolon then pr ";"
10673
10674 and generate_java_struct jtyp cols () =
10675   generate_header CStyle LGPLv2plus;
10676
10677   pr "\
10678 package com.redhat.et.libguestfs;
10679
10680 /**
10681  * Libguestfs %s structure.
10682  *
10683  * @author rjones
10684  * @see GuestFS
10685  */
10686 public class %s {
10687 " jtyp jtyp;
10688
10689   List.iter (
10690     function
10691     | name, FString
10692     | name, FUUID
10693     | name, FBuffer -> pr "  public String %s;\n" name
10694     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10695     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10696     | name, FChar -> pr "  public char %s;\n" name
10697     | name, FOptPercent ->
10698         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10699         pr "  public float %s;\n" name
10700   ) cols;
10701
10702   pr "}\n"
10703
10704 and generate_java_c () =
10705   generate_header CStyle LGPLv2plus;
10706
10707   pr "\
10708 #include <stdio.h>
10709 #include <stdlib.h>
10710 #include <string.h>
10711
10712 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10713 #include \"guestfs.h\"
10714
10715 /* Note that this function returns.  The exception is not thrown
10716  * until after the wrapper function returns.
10717  */
10718 static void
10719 throw_exception (JNIEnv *env, const char *msg)
10720 {
10721   jclass cl;
10722   cl = (*env)->FindClass (env,
10723                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10724   (*env)->ThrowNew (env, cl, msg);
10725 }
10726
10727 JNIEXPORT jlong JNICALL
10728 Java_com_redhat_et_libguestfs_GuestFS__1create
10729   (JNIEnv *env, jobject obj)
10730 {
10731   guestfs_h *g;
10732
10733   g = guestfs_create ();
10734   if (g == NULL) {
10735     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10736     return 0;
10737   }
10738   guestfs_set_error_handler (g, NULL, NULL);
10739   return (jlong) (long) g;
10740 }
10741
10742 JNIEXPORT void JNICALL
10743 Java_com_redhat_et_libguestfs_GuestFS__1close
10744   (JNIEnv *env, jobject obj, jlong jg)
10745 {
10746   guestfs_h *g = (guestfs_h *) (long) jg;
10747   guestfs_close (g);
10748 }
10749
10750 ";
10751
10752   List.iter (
10753     fun (name, style, _, _, _, _, _) ->
10754       pr "JNIEXPORT ";
10755       (match fst style with
10756        | RErr -> pr "void ";
10757        | RInt _ -> pr "jint ";
10758        | RInt64 _ -> pr "jlong ";
10759        | RBool _ -> pr "jboolean ";
10760        | RConstString _ | RConstOptString _ | RString _
10761        | RBufferOut _ -> pr "jstring ";
10762        | RStruct _ | RHashtable _ ->
10763            pr "jobject ";
10764        | RStringList _ | RStructList _ ->
10765            pr "jobjectArray ";
10766       );
10767       pr "JNICALL\n";
10768       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10769       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10770       pr "\n";
10771       pr "  (JNIEnv *env, jobject obj, jlong jg";
10772       List.iter (
10773         function
10774         | Pathname n
10775         | Device n | Dev_or_Path n
10776         | String n
10777         | OptString n
10778         | FileIn n
10779         | FileOut n
10780         | Key n ->
10781             pr ", jstring j%s" n
10782         | BufferIn n ->
10783             pr ", jbyteArray j%s" n
10784         | StringList n | DeviceList n ->
10785             pr ", jobjectArray j%s" n
10786         | Bool n ->
10787             pr ", jboolean j%s" n
10788         | Int n ->
10789             pr ", jint j%s" n
10790         | Int64 n ->
10791             pr ", jlong j%s" n
10792       ) (snd style);
10793       pr ")\n";
10794       pr "{\n";
10795       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10796       let error_code, no_ret =
10797         match fst style with
10798         | RErr -> pr "  int r;\n"; "-1", ""
10799         | RBool _
10800         | RInt _ -> pr "  int r;\n"; "-1", "0"
10801         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10802         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10803         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10804         | RString _ ->
10805             pr "  jstring jr;\n";
10806             pr "  char *r;\n"; "NULL", "NULL"
10807         | RStringList _ ->
10808             pr "  jobjectArray jr;\n";
10809             pr "  int r_len;\n";
10810             pr "  jclass cl;\n";
10811             pr "  jstring jstr;\n";
10812             pr "  char **r;\n"; "NULL", "NULL"
10813         | RStruct (_, typ) ->
10814             pr "  jobject jr;\n";
10815             pr "  jclass cl;\n";
10816             pr "  jfieldID fl;\n";
10817             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10818         | RStructList (_, typ) ->
10819             pr "  jobjectArray jr;\n";
10820             pr "  jclass cl;\n";
10821             pr "  jfieldID fl;\n";
10822             pr "  jobject jfl;\n";
10823             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10824         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10825         | RBufferOut _ ->
10826             pr "  jstring jr;\n";
10827             pr "  char *r;\n";
10828             pr "  size_t size;\n";
10829             "NULL", "NULL" in
10830       List.iter (
10831         function
10832         | Pathname n
10833         | Device n | Dev_or_Path n
10834         | String n
10835         | OptString n
10836         | FileIn n
10837         | FileOut n
10838         | Key n ->
10839             pr "  const char *%s;\n" n
10840         | BufferIn n ->
10841             pr "  jbyte *%s;\n" n;
10842             pr "  size_t %s_size;\n" n
10843         | StringList n | DeviceList n ->
10844             pr "  int %s_len;\n" n;
10845             pr "  const char **%s;\n" n
10846         | Bool n
10847         | Int n ->
10848             pr "  int %s;\n" n
10849         | Int64 n ->
10850             pr "  int64_t %s;\n" n
10851       ) (snd style);
10852
10853       let needs_i =
10854         (match fst style with
10855          | RStringList _ | RStructList _ -> true
10856          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10857          | RConstOptString _
10858          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10859           List.exists (function
10860                        | StringList _ -> true
10861                        | DeviceList _ -> true
10862                        | _ -> false) (snd style) in
10863       if needs_i then
10864         pr "  size_t i;\n";
10865
10866       pr "\n";
10867
10868       (* Get the parameters. *)
10869       List.iter (
10870         function
10871         | Pathname n
10872         | Device n | Dev_or_Path n
10873         | String n
10874         | FileIn n
10875         | FileOut n
10876         | Key n ->
10877             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10878         | OptString n ->
10879             (* This is completely undocumented, but Java null becomes
10880              * a NULL parameter.
10881              *)
10882             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10883         | BufferIn n ->
10884             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10885             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10886         | StringList n | DeviceList n ->
10887             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10888             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10889             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10890             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10891               n;
10892             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10893             pr "  }\n";
10894             pr "  %s[%s_len] = NULL;\n" n n;
10895         | Bool n
10896         | Int n
10897         | Int64 n ->
10898             pr "  %s = j%s;\n" n n
10899       ) (snd style);
10900
10901       (* Make the call. *)
10902       pr "  r = guestfs_%s " name;
10903       generate_c_call_args ~handle:"g" style;
10904       pr ";\n";
10905
10906       (* Release the parameters. *)
10907       List.iter (
10908         function
10909         | Pathname n
10910         | Device n | Dev_or_Path n
10911         | String n
10912         | FileIn n
10913         | FileOut n
10914         | Key n ->
10915             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10916         | OptString n ->
10917             pr "  if (j%s)\n" n;
10918             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10919         | BufferIn n ->
10920             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10921         | StringList n | DeviceList n ->
10922             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10923             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10924               n;
10925             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10926             pr "  }\n";
10927             pr "  free (%s);\n" n
10928         | Bool n
10929         | Int n
10930         | Int64 n -> ()
10931       ) (snd style);
10932
10933       (* Check for errors. *)
10934       pr "  if (r == %s) {\n" error_code;
10935       pr "    throw_exception (env, guestfs_last_error (g));\n";
10936       pr "    return %s;\n" no_ret;
10937       pr "  }\n";
10938
10939       (* Return value. *)
10940       (match fst style with
10941        | RErr -> ()
10942        | RInt _ -> pr "  return (jint) r;\n"
10943        | RBool _ -> pr "  return (jboolean) r;\n"
10944        | RInt64 _ -> pr "  return (jlong) r;\n"
10945        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10946        | RConstOptString _ ->
10947            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10948        | RString _ ->
10949            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10950            pr "  free (r);\n";
10951            pr "  return jr;\n"
10952        | RStringList _ ->
10953            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10954            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10955            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10956            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10957            pr "  for (i = 0; i < r_len; ++i) {\n";
10958            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10959            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10960            pr "    free (r[i]);\n";
10961            pr "  }\n";
10962            pr "  free (r);\n";
10963            pr "  return jr;\n"
10964        | RStruct (_, typ) ->
10965            let jtyp = java_name_of_struct typ in
10966            let cols = cols_of_struct typ in
10967            generate_java_struct_return typ jtyp cols
10968        | RStructList (_, typ) ->
10969            let jtyp = java_name_of_struct typ in
10970            let cols = cols_of_struct typ in
10971            generate_java_struct_list_return typ jtyp cols
10972        | RHashtable _ ->
10973            (* XXX *)
10974            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10975            pr "  return NULL;\n"
10976        | RBufferOut _ ->
10977            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10978            pr "  free (r);\n";
10979            pr "  return jr;\n"
10980       );
10981
10982       pr "}\n";
10983       pr "\n"
10984   ) all_functions
10985
10986 and generate_java_struct_return typ jtyp cols =
10987   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10988   pr "  jr = (*env)->AllocObject (env, cl);\n";
10989   List.iter (
10990     function
10991     | name, FString ->
10992         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10993         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10994     | name, FUUID ->
10995         pr "  {\n";
10996         pr "    char s[33];\n";
10997         pr "    memcpy (s, r->%s, 32);\n" name;
10998         pr "    s[32] = 0;\n";
10999         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
11000         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
11001         pr "  }\n";
11002     | name, FBuffer ->
11003         pr "  {\n";
11004         pr "    int len = r->%s_len;\n" name;
11005         pr "    char s[len+1];\n";
11006         pr "    memcpy (s, r->%s, len);\n" name;
11007         pr "    s[len] = 0;\n";
11008         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
11009         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
11010         pr "  }\n";
11011     | name, (FBytes|FUInt64|FInt64) ->
11012         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
11013         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
11014     | name, (FUInt32|FInt32) ->
11015         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
11016         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
11017     | name, FOptPercent ->
11018         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
11019         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
11020     | name, FChar ->
11021         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
11022         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
11023   ) cols;
11024   pr "  free (r);\n";
11025   pr "  return jr;\n"
11026
11027 and generate_java_struct_list_return typ jtyp cols =
11028   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
11029   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
11030   pr "  for (i = 0; i < r->len; ++i) {\n";
11031   pr "    jfl = (*env)->AllocObject (env, cl);\n";
11032   List.iter (
11033     function
11034     | name, FString ->
11035         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
11036         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
11037     | name, FUUID ->
11038         pr "    {\n";
11039         pr "      char s[33];\n";
11040         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
11041         pr "      s[32] = 0;\n";
11042         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
11043         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
11044         pr "    }\n";
11045     | name, FBuffer ->
11046         pr "    {\n";
11047         pr "      int len = r->val[i].%s_len;\n" name;
11048         pr "      char s[len+1];\n";
11049         pr "      memcpy (s, r->val[i].%s, len);\n" name;
11050         pr "      s[len] = 0;\n";
11051         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
11052         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
11053         pr "    }\n";
11054     | name, (FBytes|FUInt64|FInt64) ->
11055         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
11056         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
11057     | name, (FUInt32|FInt32) ->
11058         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
11059         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
11060     | name, FOptPercent ->
11061         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
11062         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
11063     | name, FChar ->
11064         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
11065         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
11066   ) cols;
11067   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
11068   pr "  }\n";
11069   pr "  guestfs_free_%s_list (r);\n" typ;
11070   pr "  return jr;\n"
11071
11072 and generate_java_makefile_inc () =
11073   generate_header HashStyle GPLv2plus;
11074
11075   pr "java_built_sources = \\\n";
11076   List.iter (
11077     fun (typ, jtyp) ->
11078         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
11079   ) java_structs;
11080   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
11081
11082 and generate_haskell_hs () =
11083   generate_header HaskellStyle LGPLv2plus;
11084
11085   (* XXX We only know how to generate partial FFI for Haskell
11086    * at the moment.  Please help out!
11087    *)
11088   let can_generate style =
11089     match style with
11090     | RErr, _
11091     | RInt _, _
11092     | RInt64 _, _ -> true
11093     | RBool _, _
11094     | RConstString _, _
11095     | RConstOptString _, _
11096     | RString _, _
11097     | RStringList _, _
11098     | RStruct _, _
11099     | RStructList _, _
11100     | RHashtable _, _
11101     | RBufferOut _, _ -> false in
11102
11103   pr "\
11104 {-# INCLUDE <guestfs.h> #-}
11105 {-# LANGUAGE ForeignFunctionInterface #-}
11106
11107 module Guestfs (
11108   create";
11109
11110   (* List out the names of the actions we want to export. *)
11111   List.iter (
11112     fun (name, style, _, _, _, _, _) ->
11113       if can_generate style then pr ",\n  %s" name
11114   ) all_functions;
11115
11116   pr "
11117   ) where
11118
11119 -- Unfortunately some symbols duplicate ones already present
11120 -- in Prelude.  We don't know which, so we hard-code a list
11121 -- here.
11122 import Prelude hiding (truncate)
11123
11124 import Foreign
11125 import Foreign.C
11126 import Foreign.C.Types
11127 import IO
11128 import Control.Exception
11129 import Data.Typeable
11130
11131 data GuestfsS = GuestfsS            -- represents the opaque C struct
11132 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
11133 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
11134
11135 -- XXX define properly later XXX
11136 data PV = PV
11137 data VG = VG
11138 data LV = LV
11139 data IntBool = IntBool
11140 data Stat = Stat
11141 data StatVFS = StatVFS
11142 data Hashtable = Hashtable
11143
11144 foreign import ccall unsafe \"guestfs_create\" c_create
11145   :: IO GuestfsP
11146 foreign import ccall unsafe \"&guestfs_close\" c_close
11147   :: FunPtr (GuestfsP -> IO ())
11148 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
11149   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
11150
11151 create :: IO GuestfsH
11152 create = do
11153   p <- c_create
11154   c_set_error_handler p nullPtr nullPtr
11155   h <- newForeignPtr c_close p
11156   return h
11157
11158 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
11159   :: GuestfsP -> IO CString
11160
11161 -- last_error :: GuestfsH -> IO (Maybe String)
11162 -- last_error h = do
11163 --   str <- withForeignPtr h (\\p -> c_last_error p)
11164 --   maybePeek peekCString str
11165
11166 last_error :: GuestfsH -> IO (String)
11167 last_error h = do
11168   str <- withForeignPtr h (\\p -> c_last_error p)
11169   if (str == nullPtr)
11170     then return \"no error\"
11171     else peekCString str
11172
11173 ";
11174
11175   (* Generate wrappers for each foreign function. *)
11176   List.iter (
11177     fun (name, style, _, _, _, _, _) ->
11178       if can_generate style then (
11179         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
11180         pr "  :: ";
11181         generate_haskell_prototype ~handle:"GuestfsP" style;
11182         pr "\n";
11183         pr "\n";
11184         pr "%s :: " name;
11185         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
11186         pr "\n";
11187         pr "%s %s = do\n" name
11188           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
11189         pr "  r <- ";
11190         (* Convert pointer arguments using with* functions. *)
11191         List.iter (
11192           function
11193           | FileIn n
11194           | FileOut n
11195           | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
11196               pr "withCString %s $ \\%s -> " n n
11197           | BufferIn n ->
11198               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
11199           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
11200           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
11201           | Bool _ | Int _ | Int64 _ -> ()
11202         ) (snd style);
11203         (* Convert integer arguments. *)
11204         let args =
11205           List.map (
11206             function
11207             | Bool n -> sprintf "(fromBool %s)" n
11208             | Int n -> sprintf "(fromIntegral %s)" n
11209             | Int64 n -> sprintf "(fromIntegral %s)" n
11210             | FileIn n | FileOut n
11211             | Pathname n | Device n | Dev_or_Path n
11212             | String n | OptString n
11213             | StringList n | DeviceList n
11214             | Key n -> n
11215             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
11216           ) (snd style) in
11217         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
11218           (String.concat " " ("p" :: args));
11219         (match fst style with
11220          | RErr | RInt _ | RInt64 _ | RBool _ ->
11221              pr "  if (r == -1)\n";
11222              pr "    then do\n";
11223              pr "      err <- last_error h\n";
11224              pr "      fail err\n";
11225          | RConstString _ | RConstOptString _ | RString _
11226          | RStringList _ | RStruct _
11227          | RStructList _ | RHashtable _ | RBufferOut _ ->
11228              pr "  if (r == nullPtr)\n";
11229              pr "    then do\n";
11230              pr "      err <- last_error h\n";
11231              pr "      fail err\n";
11232         );
11233         (match fst style with
11234          | RErr ->
11235              pr "    else return ()\n"
11236          | RInt _ ->
11237              pr "    else return (fromIntegral r)\n"
11238          | RInt64 _ ->
11239              pr "    else return (fromIntegral r)\n"
11240          | RBool _ ->
11241              pr "    else return (toBool r)\n"
11242          | RConstString _
11243          | RConstOptString _
11244          | RString _
11245          | RStringList _
11246          | RStruct _
11247          | RStructList _
11248          | RHashtable _
11249          | RBufferOut _ ->
11250              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
11251         );
11252         pr "\n";
11253       )
11254   ) all_functions
11255
11256 and generate_haskell_prototype ~handle ?(hs = false) style =
11257   pr "%s -> " handle;
11258   let string = if hs then "String" else "CString" in
11259   let int = if hs then "Int" else "CInt" in
11260   let bool = if hs then "Bool" else "CInt" in
11261   let int64 = if hs then "Integer" else "Int64" in
11262   List.iter (
11263     fun arg ->
11264       (match arg with
11265        | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _ ->
11266            pr "%s" string
11267        | BufferIn _ ->
11268            if hs then pr "String"
11269            else pr "CString -> CInt"
11270        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
11271        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
11272        | Bool _ -> pr "%s" bool
11273        | Int _ -> pr "%s" int
11274        | Int64 _ -> pr "%s" int
11275        | FileIn _ -> pr "%s" string
11276        | FileOut _ -> pr "%s" string
11277       );
11278       pr " -> ";
11279   ) (snd style);
11280   pr "IO (";
11281   (match fst style with
11282    | RErr -> if not hs then pr "CInt"
11283    | RInt _ -> pr "%s" int
11284    | RInt64 _ -> pr "%s" int64
11285    | RBool _ -> pr "%s" bool
11286    | RConstString _ -> pr "%s" string
11287    | RConstOptString _ -> pr "Maybe %s" string
11288    | RString _ -> pr "%s" string
11289    | RStringList _ -> pr "[%s]" string
11290    | RStruct (_, typ) ->
11291        let name = java_name_of_struct typ in
11292        pr "%s" name
11293    | RStructList (_, typ) ->
11294        let name = java_name_of_struct typ in
11295        pr "[%s]" name
11296    | RHashtable _ -> pr "Hashtable"
11297    | RBufferOut _ -> pr "%s" string
11298   );
11299   pr ")"
11300
11301 and generate_csharp () =
11302   generate_header CPlusPlusStyle LGPLv2plus;
11303
11304   (* XXX Make this configurable by the C# assembly users. *)
11305   let library = "libguestfs.so.0" in
11306
11307   pr "\
11308 // These C# bindings are highly experimental at present.
11309 //
11310 // Firstly they only work on Linux (ie. Mono).  In order to get them
11311 // to work on Windows (ie. .Net) you would need to port the library
11312 // itself to Windows first.
11313 //
11314 // The second issue is that some calls are known to be incorrect and
11315 // can cause Mono to segfault.  Particularly: calls which pass or
11316 // return string[], or return any structure value.  This is because
11317 // we haven't worked out the correct way to do this from C#.
11318 //
11319 // The third issue is that when compiling you get a lot of warnings.
11320 // We are not sure whether the warnings are important or not.
11321 //
11322 // Fourthly we do not routinely build or test these bindings as part
11323 // of the make && make check cycle, which means that regressions might
11324 // go unnoticed.
11325 //
11326 // Suggestions and patches are welcome.
11327
11328 // To compile:
11329 //
11330 // gmcs Libguestfs.cs
11331 // mono Libguestfs.exe
11332 //
11333 // (You'll probably want to add a Test class / static main function
11334 // otherwise this won't do anything useful).
11335
11336 using System;
11337 using System.IO;
11338 using System.Runtime.InteropServices;
11339 using System.Runtime.Serialization;
11340 using System.Collections;
11341
11342 namespace Guestfs
11343 {
11344   class Error : System.ApplicationException
11345   {
11346     public Error (string message) : base (message) {}
11347     protected Error (SerializationInfo info, StreamingContext context) {}
11348   }
11349
11350   class Guestfs
11351   {
11352     IntPtr _handle;
11353
11354     [DllImport (\"%s\")]
11355     static extern IntPtr guestfs_create ();
11356
11357     public Guestfs ()
11358     {
11359       _handle = guestfs_create ();
11360       if (_handle == IntPtr.Zero)
11361         throw new Error (\"could not create guestfs handle\");
11362     }
11363
11364     [DllImport (\"%s\")]
11365     static extern void guestfs_close (IntPtr h);
11366
11367     ~Guestfs ()
11368     {
11369       guestfs_close (_handle);
11370     }
11371
11372     [DllImport (\"%s\")]
11373     static extern string guestfs_last_error (IntPtr h);
11374
11375 " library library library;
11376
11377   (* Generate C# structure bindings.  We prefix struct names with
11378    * underscore because C# cannot have conflicting struct names and
11379    * method names (eg. "class stat" and "stat").
11380    *)
11381   List.iter (
11382     fun (typ, cols) ->
11383       pr "    [StructLayout (LayoutKind.Sequential)]\n";
11384       pr "    public class _%s {\n" typ;
11385       List.iter (
11386         function
11387         | name, FChar -> pr "      char %s;\n" name
11388         | name, FString -> pr "      string %s;\n" name
11389         | name, FBuffer ->
11390             pr "      uint %s_len;\n" name;
11391             pr "      string %s;\n" name
11392         | name, FUUID ->
11393             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11394             pr "      string %s;\n" name
11395         | name, FUInt32 -> pr "      uint %s;\n" name
11396         | name, FInt32 -> pr "      int %s;\n" name
11397         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
11398         | name, FInt64 -> pr "      long %s;\n" name
11399         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
11400       ) cols;
11401       pr "    }\n";
11402       pr "\n"
11403   ) structs;
11404
11405   (* Generate C# function bindings. *)
11406   List.iter (
11407     fun (name, style, _, _, _, shortdesc, _) ->
11408       let rec csharp_return_type () =
11409         match fst style with
11410         | RErr -> "void"
11411         | RBool n -> "bool"
11412         | RInt n -> "int"
11413         | RInt64 n -> "long"
11414         | RConstString n
11415         | RConstOptString n
11416         | RString n
11417         | RBufferOut n -> "string"
11418         | RStruct (_,n) -> "_" ^ n
11419         | RHashtable n -> "Hashtable"
11420         | RStringList n -> "string[]"
11421         | RStructList (_,n) -> sprintf "_%s[]" n
11422
11423       and c_return_type () =
11424         match fst style with
11425         | RErr
11426         | RBool _
11427         | RInt _ -> "int"
11428         | RInt64 _ -> "long"
11429         | RConstString _
11430         | RConstOptString _
11431         | RString _
11432         | RBufferOut _ -> "string"
11433         | RStruct (_,n) -> "_" ^ n
11434         | RHashtable _
11435         | RStringList _ -> "string[]"
11436         | RStructList (_,n) -> sprintf "_%s[]" n
11437
11438       and c_error_comparison () =
11439         match fst style with
11440         | RErr
11441         | RBool _
11442         | RInt _
11443         | RInt64 _ -> "== -1"
11444         | RConstString _
11445         | RConstOptString _
11446         | RString _
11447         | RBufferOut _
11448         | RStruct (_,_)
11449         | RHashtable _
11450         | RStringList _
11451         | RStructList (_,_) -> "== null"
11452
11453       and generate_extern_prototype () =
11454         pr "    static extern %s guestfs_%s (IntPtr h"
11455           (c_return_type ()) name;
11456         List.iter (
11457           function
11458           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11459           | FileIn n | FileOut n
11460           | Key n
11461           | BufferIn n ->
11462               pr ", [In] string %s" n
11463           | StringList n | DeviceList n ->
11464               pr ", [In] string[] %s" n
11465           | Bool n ->
11466               pr ", bool %s" n
11467           | Int n ->
11468               pr ", int %s" n
11469           | Int64 n ->
11470               pr ", long %s" n
11471         ) (snd style);
11472         pr ");\n"
11473
11474       and generate_public_prototype () =
11475         pr "    public %s %s (" (csharp_return_type ()) name;
11476         let comma = ref false in
11477         let next () =
11478           if !comma then pr ", ";
11479           comma := true
11480         in
11481         List.iter (
11482           function
11483           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11484           | FileIn n | FileOut n
11485           | Key n
11486           | BufferIn n ->
11487               next (); pr "string %s" n
11488           | StringList n | DeviceList n ->
11489               next (); pr "string[] %s" n
11490           | Bool n ->
11491               next (); pr "bool %s" n
11492           | Int n ->
11493               next (); pr "int %s" n
11494           | Int64 n ->
11495               next (); pr "long %s" n
11496         ) (snd style);
11497         pr ")\n"
11498
11499       and generate_call () =
11500         pr "guestfs_%s (_handle" name;
11501         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11502         pr ");\n";
11503       in
11504
11505       pr "    [DllImport (\"%s\")]\n" library;
11506       generate_extern_prototype ();
11507       pr "\n";
11508       pr "    /// <summary>\n";
11509       pr "    /// %s\n" shortdesc;
11510       pr "    /// </summary>\n";
11511       generate_public_prototype ();
11512       pr "    {\n";
11513       pr "      %s r;\n" (c_return_type ());
11514       pr "      r = ";
11515       generate_call ();
11516       pr "      if (r %s)\n" (c_error_comparison ());
11517       pr "        throw new Error (guestfs_last_error (_handle));\n";
11518       (match fst style with
11519        | RErr -> ()
11520        | RBool _ ->
11521            pr "      return r != 0 ? true : false;\n"
11522        | RHashtable _ ->
11523            pr "      Hashtable rr = new Hashtable ();\n";
11524            pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
11525            pr "        rr.Add (r[i], r[i+1]);\n";
11526            pr "      return rr;\n"
11527        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11528        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11529        | RStructList _ ->
11530            pr "      return r;\n"
11531       );
11532       pr "    }\n";
11533       pr "\n";
11534   ) all_functions_sorted;
11535
11536   pr "  }
11537 }
11538 "
11539
11540 and generate_bindtests () =
11541   generate_header CStyle LGPLv2plus;
11542
11543   pr "\
11544 #include <stdio.h>
11545 #include <stdlib.h>
11546 #include <inttypes.h>
11547 #include <string.h>
11548
11549 #include \"guestfs.h\"
11550 #include \"guestfs-internal.h\"
11551 #include \"guestfs-internal-actions.h\"
11552 #include \"guestfs_protocol.h\"
11553
11554 #define error guestfs_error
11555 #define safe_calloc guestfs_safe_calloc
11556 #define safe_malloc guestfs_safe_malloc
11557
11558 static void
11559 print_strings (char *const *argv)
11560 {
11561   size_t argc;
11562
11563   printf (\"[\");
11564   for (argc = 0; argv[argc] != NULL; ++argc) {
11565     if (argc > 0) printf (\", \");
11566     printf (\"\\\"%%s\\\"\", argv[argc]);
11567   }
11568   printf (\"]\\n\");
11569 }
11570
11571 /* The test0 function prints its parameters to stdout. */
11572 ";
11573
11574   let test0, tests =
11575     match test_functions with
11576     | [] -> assert false
11577     | test0 :: tests -> test0, tests in
11578
11579   let () =
11580     let (name, style, _, _, _, _, _) = test0 in
11581     generate_prototype ~extern:false ~semicolon:false ~newline:true
11582       ~handle:"g" ~prefix:"guestfs__" name style;
11583     pr "{\n";
11584     List.iter (
11585       function
11586       | Pathname n
11587       | Device n | Dev_or_Path n
11588       | String n
11589       | FileIn n
11590       | FileOut n
11591       | Key n -> pr "  printf (\"%%s\\n\", %s);\n" n
11592       | BufferIn n ->
11593           pr "  {\n";
11594           pr "    size_t i;\n";
11595           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11596           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11597           pr "    printf (\"\\n\");\n";
11598           pr "  }\n";
11599       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11600       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11601       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11602       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11603       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11604     ) (snd style);
11605     pr "  /* Java changes stdout line buffering so we need this: */\n";
11606     pr "  fflush (stdout);\n";
11607     pr "  return 0;\n";
11608     pr "}\n";
11609     pr "\n" in
11610
11611   List.iter (
11612     fun (name, style, _, _, _, _, _) ->
11613       if String.sub name (String.length name - 3) 3 <> "err" then (
11614         pr "/* Test normal return. */\n";
11615         generate_prototype ~extern:false ~semicolon:false ~newline:true
11616           ~handle:"g" ~prefix:"guestfs__" name style;
11617         pr "{\n";
11618         (match fst style with
11619          | RErr ->
11620              pr "  return 0;\n"
11621          | RInt _ ->
11622              pr "  int r;\n";
11623              pr "  sscanf (val, \"%%d\", &r);\n";
11624              pr "  return r;\n"
11625          | RInt64 _ ->
11626              pr "  int64_t r;\n";
11627              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11628              pr "  return r;\n"
11629          | RBool _ ->
11630              pr "  return STREQ (val, \"true\");\n"
11631          | RConstString _
11632          | RConstOptString _ ->
11633              (* Can't return the input string here.  Return a static
11634               * string so we ensure we get a segfault if the caller
11635               * tries to free it.
11636               *)
11637              pr "  return \"static string\";\n"
11638          | RString _ ->
11639              pr "  return strdup (val);\n"
11640          | RStringList _ ->
11641              pr "  char **strs;\n";
11642              pr "  int n, i;\n";
11643              pr "  sscanf (val, \"%%d\", &n);\n";
11644              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11645              pr "  for (i = 0; i < n; ++i) {\n";
11646              pr "    strs[i] = safe_malloc (g, 16);\n";
11647              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11648              pr "  }\n";
11649              pr "  strs[n] = NULL;\n";
11650              pr "  return strs;\n"
11651          | RStruct (_, typ) ->
11652              pr "  struct guestfs_%s *r;\n" typ;
11653              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11654              pr "  return r;\n"
11655          | RStructList (_, typ) ->
11656              pr "  struct guestfs_%s_list *r;\n" typ;
11657              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11658              pr "  sscanf (val, \"%%d\", &r->len);\n";
11659              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11660              pr "  return r;\n"
11661          | RHashtable _ ->
11662              pr "  char **strs;\n";
11663              pr "  int n, i;\n";
11664              pr "  sscanf (val, \"%%d\", &n);\n";
11665              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11666              pr "  for (i = 0; i < n; ++i) {\n";
11667              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11668              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11669              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11670              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11671              pr "  }\n";
11672              pr "  strs[n*2] = NULL;\n";
11673              pr "  return strs;\n"
11674          | RBufferOut _ ->
11675              pr "  return strdup (val);\n"
11676         );
11677         pr "}\n";
11678         pr "\n"
11679       ) else (
11680         pr "/* Test error return. */\n";
11681         generate_prototype ~extern:false ~semicolon:false ~newline:true
11682           ~handle:"g" ~prefix:"guestfs__" name style;
11683         pr "{\n";
11684         pr "  error (g, \"error\");\n";
11685         (match fst style with
11686          | RErr | RInt _ | RInt64 _ | RBool _ ->
11687              pr "  return -1;\n"
11688          | RConstString _ | RConstOptString _
11689          | RString _ | RStringList _ | RStruct _
11690          | RStructList _
11691          | RHashtable _
11692          | RBufferOut _ ->
11693              pr "  return NULL;\n"
11694         );
11695         pr "}\n";
11696         pr "\n"
11697       )
11698   ) tests
11699
11700 and generate_ocaml_bindtests () =
11701   generate_header OCamlStyle GPLv2plus;
11702
11703   pr "\
11704 let () =
11705   let g = Guestfs.create () in
11706 ";
11707
11708   let mkargs args =
11709     String.concat " " (
11710       List.map (
11711         function
11712         | CallString s -> "\"" ^ s ^ "\""
11713         | CallOptString None -> "None"
11714         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11715         | CallStringList xs ->
11716             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11717         | CallInt i when i >= 0 -> string_of_int i
11718         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11719         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11720         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11721         | CallBool b -> string_of_bool b
11722         | CallBuffer s -> sprintf "%S" s
11723       ) args
11724     )
11725   in
11726
11727   generate_lang_bindtests (
11728     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11729   );
11730
11731   pr "print_endline \"EOF\"\n"
11732
11733 and generate_perl_bindtests () =
11734   pr "#!/usr/bin/perl -w\n";
11735   generate_header HashStyle GPLv2plus;
11736
11737   pr "\
11738 use strict;
11739
11740 use Sys::Guestfs;
11741
11742 my $g = Sys::Guestfs->new ();
11743 ";
11744
11745   let mkargs args =
11746     String.concat ", " (
11747       List.map (
11748         function
11749         | CallString s -> "\"" ^ s ^ "\""
11750         | CallOptString None -> "undef"
11751         | CallOptString (Some s) -> sprintf "\"%s\"" s
11752         | CallStringList xs ->
11753             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11754         | CallInt i -> string_of_int i
11755         | CallInt64 i -> Int64.to_string i
11756         | CallBool b -> if b then "1" else "0"
11757         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11758       ) args
11759     )
11760   in
11761
11762   generate_lang_bindtests (
11763     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11764   );
11765
11766   pr "print \"EOF\\n\"\n"
11767
11768 and generate_python_bindtests () =
11769   generate_header HashStyle GPLv2plus;
11770
11771   pr "\
11772 import guestfs
11773
11774 g = guestfs.GuestFS ()
11775 ";
11776
11777   let mkargs args =
11778     String.concat ", " (
11779       List.map (
11780         function
11781         | CallString s -> "\"" ^ s ^ "\""
11782         | CallOptString None -> "None"
11783         | CallOptString (Some s) -> sprintf "\"%s\"" s
11784         | CallStringList xs ->
11785             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11786         | CallInt i -> string_of_int i
11787         | CallInt64 i -> Int64.to_string i
11788         | CallBool b -> if b then "1" else "0"
11789         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11790       ) args
11791     )
11792   in
11793
11794   generate_lang_bindtests (
11795     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11796   );
11797
11798   pr "print \"EOF\"\n"
11799
11800 and generate_ruby_bindtests () =
11801   generate_header HashStyle GPLv2plus;
11802
11803   pr "\
11804 require 'guestfs'
11805
11806 g = Guestfs::create()
11807 ";
11808
11809   let mkargs args =
11810     String.concat ", " (
11811       List.map (
11812         function
11813         | CallString s -> "\"" ^ s ^ "\""
11814         | CallOptString None -> "nil"
11815         | CallOptString (Some s) -> sprintf "\"%s\"" s
11816         | CallStringList xs ->
11817             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11818         | CallInt i -> string_of_int i
11819         | CallInt64 i -> Int64.to_string i
11820         | CallBool b -> string_of_bool b
11821         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11822       ) args
11823     )
11824   in
11825
11826   generate_lang_bindtests (
11827     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11828   );
11829
11830   pr "print \"EOF\\n\"\n"
11831
11832 and generate_java_bindtests () =
11833   generate_header CStyle GPLv2plus;
11834
11835   pr "\
11836 import com.redhat.et.libguestfs.*;
11837
11838 public class Bindtests {
11839     public static void main (String[] argv)
11840     {
11841         try {
11842             GuestFS g = new GuestFS ();
11843 ";
11844
11845   let mkargs args =
11846     String.concat ", " (
11847       List.map (
11848         function
11849         | CallString s -> "\"" ^ s ^ "\""
11850         | CallOptString None -> "null"
11851         | CallOptString (Some s) -> sprintf "\"%s\"" s
11852         | CallStringList xs ->
11853             "new String[]{" ^
11854               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11855         | CallInt i -> string_of_int i
11856         | CallInt64 i -> Int64.to_string i
11857         | CallBool b -> string_of_bool b
11858         | CallBuffer s ->
11859             "new byte[] { " ^ String.concat "," (
11860               map_chars (fun c -> string_of_int (Char.code c)) s
11861             ) ^ " }"
11862       ) args
11863     )
11864   in
11865
11866   generate_lang_bindtests (
11867     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11868   );
11869
11870   pr "
11871             System.out.println (\"EOF\");
11872         }
11873         catch (Exception exn) {
11874             System.err.println (exn);
11875             System.exit (1);
11876         }
11877     }
11878 }
11879 "
11880
11881 and generate_haskell_bindtests () =
11882   generate_header HaskellStyle GPLv2plus;
11883
11884   pr "\
11885 module Bindtests where
11886 import qualified Guestfs
11887
11888 main = do
11889   g <- Guestfs.create
11890 ";
11891
11892   let mkargs args =
11893     String.concat " " (
11894       List.map (
11895         function
11896         | CallString s -> "\"" ^ s ^ "\""
11897         | CallOptString None -> "Nothing"
11898         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11899         | CallStringList xs ->
11900             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11901         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11902         | CallInt i -> string_of_int i
11903         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11904         | CallInt64 i -> Int64.to_string i
11905         | CallBool true -> "True"
11906         | CallBool false -> "False"
11907         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11908       ) args
11909     )
11910   in
11911
11912   generate_lang_bindtests (
11913     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11914   );
11915
11916   pr "  putStrLn \"EOF\"\n"
11917
11918 (* Language-independent bindings tests - we do it this way to
11919  * ensure there is parity in testing bindings across all languages.
11920  *)
11921 and generate_lang_bindtests call =
11922   call "test0" [CallString "abc"; CallOptString (Some "def");
11923                 CallStringList []; CallBool false;
11924                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11925                 CallBuffer "abc\000abc"];
11926   call "test0" [CallString "abc"; CallOptString None;
11927                 CallStringList []; CallBool false;
11928                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11929                 CallBuffer "abc\000abc"];
11930   call "test0" [CallString ""; CallOptString (Some "def");
11931                 CallStringList []; CallBool false;
11932                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11933                 CallBuffer "abc\000abc"];
11934   call "test0" [CallString ""; CallOptString (Some "");
11935                 CallStringList []; CallBool false;
11936                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11937                 CallBuffer "abc\000abc"];
11938   call "test0" [CallString "abc"; CallOptString (Some "def");
11939                 CallStringList ["1"]; CallBool false;
11940                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11941                 CallBuffer "abc\000abc"];
11942   call "test0" [CallString "abc"; CallOptString (Some "def");
11943                 CallStringList ["1"; "2"]; CallBool false;
11944                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11945                 CallBuffer "abc\000abc"];
11946   call "test0" [CallString "abc"; CallOptString (Some "def");
11947                 CallStringList ["1"]; CallBool true;
11948                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11949                 CallBuffer "abc\000abc"];
11950   call "test0" [CallString "abc"; CallOptString (Some "def");
11951                 CallStringList ["1"]; CallBool false;
11952                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11953                 CallBuffer "abc\000abc"];
11954   call "test0" [CallString "abc"; CallOptString (Some "def");
11955                 CallStringList ["1"]; CallBool false;
11956                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11957                 CallBuffer "abc\000abc"];
11958   call "test0" [CallString "abc"; CallOptString (Some "def");
11959                 CallStringList ["1"]; CallBool false;
11960                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11961                 CallBuffer "abc\000abc"];
11962   call "test0" [CallString "abc"; CallOptString (Some "def");
11963                 CallStringList ["1"]; CallBool false;
11964                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11965                 CallBuffer "abc\000abc"];
11966   call "test0" [CallString "abc"; CallOptString (Some "def");
11967                 CallStringList ["1"]; CallBool false;
11968                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11969                 CallBuffer "abc\000abc"];
11970   call "test0" [CallString "abc"; CallOptString (Some "def");
11971                 CallStringList ["1"]; CallBool false;
11972                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11973                 CallBuffer "abc\000abc"]
11974
11975 (* XXX Add here tests of the return and error functions. *)
11976
11977 (* Code to generator bindings for virt-inspector.  Currently only
11978  * implemented for OCaml code (for virt-p2v 2.0).
11979  *)
11980 let rng_input = "inspector/virt-inspector.rng"
11981
11982 (* Read the input file and parse it into internal structures.  This is
11983  * by no means a complete RELAX NG parser, but is just enough to be
11984  * able to parse the specific input file.
11985  *)
11986 type rng =
11987   | Element of string * rng list        (* <element name=name/> *)
11988   | Attribute of string * rng list        (* <attribute name=name/> *)
11989   | Interleave of rng list                (* <interleave/> *)
11990   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11991   | OneOrMore of rng                        (* <oneOrMore/> *)
11992   | Optional of rng                        (* <optional/> *)
11993   | Choice of string list                (* <choice><value/>*</choice> *)
11994   | Value of string                        (* <value>str</value> *)
11995   | Text                                (* <text/> *)
11996
11997 let rec string_of_rng = function
11998   | Element (name, xs) ->
11999       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
12000   | Attribute (name, xs) ->
12001       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
12002   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
12003   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
12004   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
12005   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
12006   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
12007   | Value value -> "Value \"" ^ value ^ "\""
12008   | Text -> "Text"
12009
12010 and string_of_rng_list xs =
12011   String.concat ", " (List.map string_of_rng xs)
12012
12013 let rec parse_rng ?defines context = function
12014   | [] -> []
12015   | Xml.Element ("element", ["name", name], children) :: rest ->
12016       Element (name, parse_rng ?defines context children)
12017       :: parse_rng ?defines context rest
12018   | Xml.Element ("attribute", ["name", name], children) :: rest ->
12019       Attribute (name, parse_rng ?defines context children)
12020       :: parse_rng ?defines context rest
12021   | Xml.Element ("interleave", [], children) :: rest ->
12022       Interleave (parse_rng ?defines context children)
12023       :: parse_rng ?defines context rest
12024   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
12025       let rng = parse_rng ?defines context [child] in
12026       (match rng with
12027        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
12028        | _ ->
12029            failwithf "%s: <zeroOrMore> contains more than one child element"
12030              context
12031       )
12032   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
12033       let rng = parse_rng ?defines context [child] in
12034       (match rng with
12035        | [child] -> OneOrMore child :: parse_rng ?defines context rest
12036        | _ ->
12037            failwithf "%s: <oneOrMore> contains more than one child element"
12038              context
12039       )
12040   | Xml.Element ("optional", [], [child]) :: rest ->
12041       let rng = parse_rng ?defines context [child] in
12042       (match rng with
12043        | [child] -> Optional child :: parse_rng ?defines context rest
12044        | _ ->
12045            failwithf "%s: <optional> contains more than one child element"
12046              context
12047       )
12048   | Xml.Element ("choice", [], children) :: rest ->
12049       let values = List.map (
12050         function Xml.Element ("value", [], [Xml.PCData value]) -> value
12051         | _ ->
12052             failwithf "%s: can't handle anything except <value> in <choice>"
12053               context
12054       ) children in
12055       Choice values
12056       :: parse_rng ?defines context rest
12057   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
12058       Value value :: parse_rng ?defines context rest
12059   | Xml.Element ("text", [], []) :: rest ->
12060       Text :: parse_rng ?defines context rest
12061   | Xml.Element ("ref", ["name", name], []) :: rest ->
12062       (* Look up the reference.  Because of limitations in this parser,
12063        * we can't handle arbitrarily nested <ref> yet.  You can only
12064        * use <ref> from inside <start>.
12065        *)
12066       (match defines with
12067        | None ->
12068            failwithf "%s: contains <ref>, but no refs are defined yet" context
12069        | Some map ->
12070            let rng = StringMap.find name map in
12071            rng @ parse_rng ?defines context rest
12072       )
12073   | x :: _ ->
12074       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
12075
12076 let grammar =
12077   let xml = Xml.parse_file rng_input in
12078   match xml with
12079   | Xml.Element ("grammar", _,
12080                  Xml.Element ("start", _, gram) :: defines) ->
12081       (* The <define/> elements are referenced in the <start> section,
12082        * so build a map of those first.
12083        *)
12084       let defines = List.fold_left (
12085         fun map ->
12086           function Xml.Element ("define", ["name", name], defn) ->
12087             StringMap.add name defn map
12088           | _ ->
12089               failwithf "%s: expected <define name=name/>" rng_input
12090       ) StringMap.empty defines in
12091       let defines = StringMap.mapi parse_rng defines in
12092
12093       (* Parse the <start> clause, passing the defines. *)
12094       parse_rng ~defines "<start>" gram
12095   | _ ->
12096       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
12097         rng_input
12098
12099 let name_of_field = function
12100   | Element (name, _) | Attribute (name, _)
12101   | ZeroOrMore (Element (name, _))
12102   | OneOrMore (Element (name, _))
12103   | Optional (Element (name, _)) -> name
12104   | Optional (Attribute (name, _)) -> name
12105   | Text -> (* an unnamed field in an element *)
12106       "data"
12107   | rng ->
12108       failwithf "name_of_field failed at: %s" (string_of_rng rng)
12109
12110 (* At the moment this function only generates OCaml types.  However we
12111  * should parameterize it later so it can generate types/structs in a
12112  * variety of languages.
12113  *)
12114 let generate_types xs =
12115   (* A simple type is one that can be printed out directly, eg.
12116    * "string option".  A complex type is one which has a name and has
12117    * to be defined via another toplevel definition, eg. a struct.
12118    *
12119    * generate_type generates code for either simple or complex types.
12120    * In the simple case, it returns the string ("string option").  In
12121    * the complex case, it returns the name ("mountpoint").  In the
12122    * complex case it has to print out the definition before returning,
12123    * so it should only be called when we are at the beginning of a
12124    * new line (BOL context).
12125    *)
12126   let rec generate_type = function
12127     | Text ->                                (* string *)
12128         "string", true
12129     | Choice values ->                        (* [`val1|`val2|...] *)
12130         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
12131     | ZeroOrMore rng ->                        (* <rng> list *)
12132         let t, is_simple = generate_type rng in
12133         t ^ " list (* 0 or more *)", is_simple
12134     | OneOrMore rng ->                        (* <rng> list *)
12135         let t, is_simple = generate_type rng in
12136         t ^ " list (* 1 or more *)", is_simple
12137                                         (* virt-inspector hack: bool *)
12138     | Optional (Attribute (name, [Value "1"])) ->
12139         "bool", true
12140     | Optional rng ->                        (* <rng> list *)
12141         let t, is_simple = generate_type rng in
12142         t ^ " option", is_simple
12143                                         (* type name = { fields ... } *)
12144     | Element (name, fields) when is_attrs_interleave fields ->
12145         generate_type_struct name (get_attrs_interleave fields)
12146     | Element (name, [field])                (* type name = field *)
12147     | Attribute (name, [field]) ->
12148         let t, is_simple = generate_type field in
12149         if is_simple then (t, true)
12150         else (
12151           pr "type %s = %s\n" name t;
12152           name, false
12153         )
12154     | Element (name, fields) ->              (* type name = { fields ... } *)
12155         generate_type_struct name fields
12156     | rng ->
12157         failwithf "generate_type failed at: %s" (string_of_rng rng)
12158
12159   and is_attrs_interleave = function
12160     | [Interleave _] -> true
12161     | Attribute _ :: fields -> is_attrs_interleave fields
12162     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
12163     | _ -> false
12164
12165   and get_attrs_interleave = function
12166     | [Interleave fields] -> fields
12167     | ((Attribute _) as field) :: fields
12168     | ((Optional (Attribute _)) as field) :: fields ->
12169         field :: get_attrs_interleave fields
12170     | _ -> assert false
12171
12172   and generate_types xs =
12173     List.iter (fun x -> ignore (generate_type x)) xs
12174
12175   and generate_type_struct name fields =
12176     (* Calculate the types of the fields first.  We have to do this
12177      * before printing anything so we are still in BOL context.
12178      *)
12179     let types = List.map fst (List.map generate_type fields) in
12180
12181     (* Special case of a struct containing just a string and another
12182      * field.  Turn it into an assoc list.
12183      *)
12184     match types with
12185     | ["string"; other] ->
12186         let fname1, fname2 =
12187           match fields with
12188           | [f1; f2] -> name_of_field f1, name_of_field f2
12189           | _ -> assert false in
12190         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
12191         name, false
12192
12193     | types ->
12194         pr "type %s = {\n" name;
12195         List.iter (
12196           fun (field, ftype) ->
12197             let fname = name_of_field field in
12198             pr "  %s_%s : %s;\n" name fname ftype
12199         ) (List.combine fields types);
12200         pr "}\n";
12201         (* Return the name of this type, and
12202          * false because it's not a simple type.
12203          *)
12204         name, false
12205   in
12206
12207   generate_types xs
12208
12209 let generate_parsers xs =
12210   (* As for generate_type above, generate_parser makes a parser for
12211    * some type, and returns the name of the parser it has generated.
12212    * Because it (may) need to print something, it should always be
12213    * called in BOL context.
12214    *)
12215   let rec generate_parser = function
12216     | Text ->                                (* string *)
12217         "string_child_or_empty"
12218     | Choice values ->                        (* [`val1|`val2|...] *)
12219         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
12220           (String.concat "|"
12221              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
12222     | ZeroOrMore rng ->                        (* <rng> list *)
12223         let pa = generate_parser rng in
12224         sprintf "(fun x -> List.map %s (Xml.children x))" pa
12225     | OneOrMore rng ->                        (* <rng> list *)
12226         let pa = generate_parser rng in
12227         sprintf "(fun x -> List.map %s (Xml.children x))" pa
12228                                         (* virt-inspector hack: bool *)
12229     | Optional (Attribute (name, [Value "1"])) ->
12230         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
12231     | Optional rng ->                        (* <rng> list *)
12232         let pa = generate_parser rng in
12233         sprintf "(function None -> None | Some x -> Some (%s x))" pa
12234                                         (* type name = { fields ... } *)
12235     | Element (name, fields) when is_attrs_interleave fields ->
12236         generate_parser_struct name (get_attrs_interleave fields)
12237     | Element (name, [field]) ->        (* type name = field *)
12238         let pa = generate_parser field in
12239         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12240         pr "let %s =\n" parser_name;
12241         pr "  %s\n" pa;
12242         pr "let parse_%s = %s\n" name parser_name;
12243         parser_name
12244     | Attribute (name, [field]) ->
12245         let pa = generate_parser field in
12246         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12247         pr "let %s =\n" parser_name;
12248         pr "  %s\n" pa;
12249         pr "let parse_%s = %s\n" name parser_name;
12250         parser_name
12251     | Element (name, fields) ->              (* type name = { fields ... } *)
12252         generate_parser_struct name ([], fields)
12253     | rng ->
12254         failwithf "generate_parser failed at: %s" (string_of_rng rng)
12255
12256   and is_attrs_interleave = function
12257     | [Interleave _] -> true
12258     | Attribute _ :: fields -> is_attrs_interleave fields
12259     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
12260     | _ -> false
12261
12262   and get_attrs_interleave = function
12263     | [Interleave fields] -> [], fields
12264     | ((Attribute _) as field) :: fields
12265     | ((Optional (Attribute _)) as field) :: fields ->
12266         let attrs, interleaves = get_attrs_interleave fields in
12267         (field :: attrs), interleaves
12268     | _ -> assert false
12269
12270   and generate_parsers xs =
12271     List.iter (fun x -> ignore (generate_parser x)) xs
12272
12273   and generate_parser_struct name (attrs, interleaves) =
12274     (* Generate parsers for the fields first.  We have to do this
12275      * before printing anything so we are still in BOL context.
12276      *)
12277     let fields = attrs @ interleaves in
12278     let pas = List.map generate_parser fields in
12279
12280     (* Generate an intermediate tuple from all the fields first.
12281      * If the type is just a string + another field, then we will
12282      * return this directly, otherwise it is turned into a record.
12283      *
12284      * RELAX NG note: This code treats <interleave> and plain lists of
12285      * fields the same.  In other words, it doesn't bother enforcing
12286      * any ordering of fields in the XML.
12287      *)
12288     pr "let parse_%s x =\n" name;
12289     pr "  let t = (\n    ";
12290     let comma = ref false in
12291     List.iter (
12292       fun x ->
12293         if !comma then pr ",\n    ";
12294         comma := true;
12295         match x with
12296         | Optional (Attribute (fname, [field])), pa ->
12297             pr "%s x" pa
12298         | Optional (Element (fname, [field])), pa ->
12299             pr "%s (optional_child %S x)" pa fname
12300         | Attribute (fname, [Text]), _ ->
12301             pr "attribute %S x" fname
12302         | (ZeroOrMore _ | OneOrMore _), pa ->
12303             pr "%s x" pa
12304         | Text, pa ->
12305             pr "%s x" pa
12306         | (field, pa) ->
12307             let fname = name_of_field field in
12308             pr "%s (child %S x)" pa fname
12309     ) (List.combine fields pas);
12310     pr "\n  ) in\n";
12311
12312     (match fields with
12313      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
12314          pr "  t\n"
12315
12316      | _ ->
12317          pr "  (Obj.magic t : %s)\n" name
12318 (*
12319          List.iter (
12320            function
12321            | (Optional (Attribute (fname, [field])), pa) ->
12322                pr "  %s_%s =\n" name fname;
12323                pr "    %s x;\n" pa
12324            | (Optional (Element (fname, [field])), pa) ->
12325                pr "  %s_%s =\n" name fname;
12326                pr "    (let x = optional_child %S x in\n" fname;
12327                pr "     %s x);\n" pa
12328            | (field, pa) ->
12329                let fname = name_of_field field in
12330                pr "  %s_%s =\n" name fname;
12331                pr "    (let x = child %S x in\n" fname;
12332                pr "     %s x);\n" pa
12333          ) (List.combine fields pas);
12334          pr "}\n"
12335 *)
12336     );
12337     sprintf "parse_%s" name
12338   in
12339
12340   generate_parsers xs
12341
12342 (* Generate ocaml/guestfs_inspector.mli. *)
12343 let generate_ocaml_inspector_mli () =
12344   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12345
12346   pr "\
12347 (** This is an OCaml language binding to the external [virt-inspector]
12348     program.
12349
12350     For more information, please read the man page [virt-inspector(1)].
12351 *)
12352
12353 ";
12354
12355   generate_types grammar;
12356   pr "(** The nested information returned from the {!inspect} function. *)\n";
12357   pr "\n";
12358
12359   pr "\
12360 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12361 (** To inspect a libvirt domain called [name], pass a singleton
12362     list: [inspect [name]].  When using libvirt only, you may
12363     optionally pass a libvirt URI using [inspect ~connect:uri ...].
12364
12365     To inspect a disk image or images, pass a list of the filenames
12366     of the disk images: [inspect filenames]
12367
12368     This function inspects the given guest or disk images and
12369     returns a list of operating system(s) found and a large amount
12370     of information about them.  In the vast majority of cases,
12371     a virtual machine only contains a single operating system.
12372
12373     If the optional [~xml] parameter is given, then this function
12374     skips running the external virt-inspector program and just
12375     parses the given XML directly (which is expected to be XML
12376     produced from a previous run of virt-inspector).  The list of
12377     names and connect URI are ignored in this case.
12378
12379     This function can throw a wide variety of exceptions, for example
12380     if the external virt-inspector program cannot be found, or if
12381     it doesn't generate valid XML.
12382 *)
12383 "
12384
12385 (* Generate ocaml/guestfs_inspector.ml. *)
12386 let generate_ocaml_inspector_ml () =
12387   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12388
12389   pr "open Unix\n";
12390   pr "\n";
12391
12392   generate_types grammar;
12393   pr "\n";
12394
12395   pr "\
12396 (* Misc functions which are used by the parser code below. *)
12397 let first_child = function
12398   | Xml.Element (_, _, c::_) -> c
12399   | Xml.Element (name, _, []) ->
12400       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12401   | Xml.PCData str ->
12402       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12403
12404 let string_child_or_empty = function
12405   | Xml.Element (_, _, [Xml.PCData s]) -> s
12406   | Xml.Element (_, _, []) -> \"\"
12407   | Xml.Element (x, _, _) ->
12408       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12409                 x ^ \" instead\")
12410   | Xml.PCData str ->
12411       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12412
12413 let optional_child name xml =
12414   let children = Xml.children xml in
12415   try
12416     Some (List.find (function
12417                      | Xml.Element (n, _, _) when n = name -> true
12418                      | _ -> false) children)
12419   with
12420     Not_found -> None
12421
12422 let child name xml =
12423   match optional_child name xml with
12424   | Some c -> c
12425   | None ->
12426       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12427
12428 let attribute name xml =
12429   try Xml.attrib xml name
12430   with Xml.No_attribute _ ->
12431     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12432
12433 ";
12434
12435   generate_parsers grammar;
12436   pr "\n";
12437
12438   pr "\
12439 (* Run external virt-inspector, then use parser to parse the XML. *)
12440 let inspect ?connect ?xml names =
12441   let xml =
12442     match xml with
12443     | None ->
12444         if names = [] then invalid_arg \"inspect: no names given\";
12445         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12446           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12447           names in
12448         let cmd = List.map Filename.quote cmd in
12449         let cmd = String.concat \" \" cmd in
12450         let chan = open_process_in cmd in
12451         let xml = Xml.parse_in chan in
12452         (match close_process_in chan with
12453          | WEXITED 0 -> ()
12454          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12455          | WSIGNALED i | WSTOPPED i ->
12456              failwith (\"external virt-inspector command died or stopped on sig \" ^
12457                        string_of_int i)
12458         );
12459         xml
12460     | Some doc ->
12461         Xml.parse_string doc in
12462   parse_operatingsystems xml
12463 "
12464
12465 and generate_max_proc_nr () =
12466   pr "%d\n" max_proc_nr
12467
12468 let output_to filename k =
12469   let filename_new = filename ^ ".new" in
12470   chan := open_out filename_new;
12471   k ();
12472   close_out !chan;
12473   chan := Pervasives.stdout;
12474
12475   (* Is the new file different from the current file? *)
12476   if Sys.file_exists filename && files_equal filename filename_new then
12477     unlink filename_new                 (* same, so skip it *)
12478   else (
12479     (* different, overwrite old one *)
12480     (try chmod filename 0o644 with Unix_error _ -> ());
12481     rename filename_new filename;
12482     chmod filename 0o444;
12483     printf "written %s\n%!" filename;
12484   )
12485
12486 let perror msg = function
12487   | Unix_error (err, _, _) ->
12488       eprintf "%s: %s\n" msg (error_message err)
12489   | exn ->
12490       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12491
12492 (* Main program. *)
12493 let () =
12494   let lock_fd =
12495     try openfile "HACKING" [O_RDWR] 0
12496     with
12497     | Unix_error (ENOENT, _, _) ->
12498         eprintf "\
12499 You are probably running this from the wrong directory.
12500 Run it from the top source directory using the command
12501   src/generator.ml
12502 ";
12503         exit 1
12504     | exn ->
12505         perror "open: HACKING" exn;
12506         exit 1 in
12507
12508   (* Acquire a lock so parallel builds won't try to run the generator
12509    * twice at the same time.  Subsequent builds will wait for the first
12510    * one to finish.  Note the lock is released implicitly when the
12511    * program exits.
12512    *)
12513   (try lockf lock_fd F_LOCK 1
12514    with exn ->
12515      perror "lock: HACKING" exn;
12516      exit 1);
12517
12518   check_functions ();
12519
12520   output_to "src/guestfs_protocol.x" generate_xdr;
12521   output_to "src/guestfs-structs.h" generate_structs_h;
12522   output_to "src/guestfs-actions.h" generate_actions_h;
12523   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12524   output_to "src/actions.c" generate_client_actions;
12525   output_to "src/bindtests.c" generate_bindtests;
12526   output_to "src/guestfs-structs.pod" generate_structs_pod;
12527   output_to "src/guestfs-actions.pod" generate_actions_pod;
12528   output_to "src/guestfs-availability.pod" generate_availability_pod;
12529   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12530   output_to "src/libguestfs.syms" generate_linker_script;
12531   output_to "daemon/actions.h" generate_daemon_actions_h;
12532   output_to "daemon/stubs.c" generate_daemon_actions;
12533   output_to "daemon/names.c" generate_daemon_names;
12534   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12535   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12536   output_to "capitests/tests.c" generate_tests;
12537   output_to "fish/cmds.c" generate_fish_cmds;
12538   output_to "fish/completion.c" generate_fish_completion;
12539   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12540   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12541   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12542   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12543   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12544   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12545   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12546   output_to "perl/Guestfs.xs" generate_perl_xs;
12547   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12548   output_to "perl/bindtests.pl" generate_perl_bindtests;
12549   output_to "python/guestfs-py.c" generate_python_c;
12550   output_to "python/guestfs.py" generate_python_py;
12551   output_to "python/bindtests.py" generate_python_bindtests;
12552   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12553   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12554   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12555
12556   List.iter (
12557     fun (typ, jtyp) ->
12558       let cols = cols_of_struct typ in
12559       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12560       output_to filename (generate_java_struct jtyp cols);
12561   ) java_structs;
12562
12563   output_to "java/Makefile.inc" generate_java_makefile_inc;
12564   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12565   output_to "java/Bindtests.java" generate_java_bindtests;
12566   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12567   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12568   output_to "csharp/Libguestfs.cs" generate_csharp;
12569
12570   (* Always generate this file last, and unconditionally.  It's used
12571    * by the Makefile to know when we must re-run the generator.
12572    *)
12573   let chan = open_out "src/stamp-generator" in
12574   fprintf chan "1\n";
12575   close_out chan;
12576
12577   printf "generated %d lines of code\n" !lines