77c76424bda91d983e842135bec467cf80eb7e78
[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   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4958    (let uuid = uuidgen () in
4959     [InitBasicFS, Always, TestOutput (
4960        [["set_e2uuid"; "/dev/sda1"; uuid];
4961         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4962    "get the filesystem UUID",
4963    "\
4964 This returns the filesystem UUID of the filesystem on
4965 C<device>.
4966
4967 If the filesystem does not have a UUID, this returns the empty string.");
4968
4969   ("lvm_set_filter", (RErr, [DeviceList "devices"]), 255, [Optional "lvm2"],
4970    (* Can't be tested with the current framework because
4971     * the VG is being used by the mounted filesystem, so
4972     * the vgchange -an command we do first will fail.
4973     *)
4974     [],
4975    "set LVM device filter",
4976    "\
4977 This sets the LVM device filter so that LVM will only be
4978 able to \"see\" the block devices in the list C<devices>,
4979 and will ignore all other attached block devices.
4980
4981 Where disk image(s) contain duplicate PVs or VGs, this
4982 command is useful to get LVM to ignore the duplicates, otherwise
4983 LVM can get confused.  Note also there are two types
4984 of duplication possible: either cloned PVs/VGs which have
4985 identical UUIDs; or VGs that are not cloned but just happen
4986 to have the same name.  In normal operation you cannot
4987 create this situation, but you can do it outside LVM, eg.
4988 by cloning disk images or by bit twiddling inside the LVM
4989 metadata.
4990
4991 This command also clears the LVM cache and performs a volume
4992 group scan.
4993
4994 You can filter whole block devices or individual partitions.
4995
4996 You cannot use this if any VG is currently in use (eg.
4997 contains a mounted filesystem), even if you are not
4998 filtering out that VG.");
4999
5000   ("lvm_clear_filter", (RErr, []), 256, [],
5001    [], (* see note on lvm_set_filter *)
5002    "clear LVM device filter",
5003    "\
5004 This undoes the effect of C<guestfs_lvm_set_filter>.  LVM
5005 will be able to see every block device.
5006
5007 This command also clears the LVM cache and performs a volume
5008 group scan.");
5009
5010   ("luks_open", (RErr, [Device "device"; Key "key"; String "mapname"]), 257, [Optional "luks"],
5011    [],
5012    "open a LUKS-encrypted block device",
5013    "\
5014 This command opens a block device which has been encrypted
5015 according to the Linux Unified Key Setup (LUKS) standard.
5016
5017 C<device> is the encrypted block device or partition.
5018
5019 The caller must supply one of the keys associated with the
5020 LUKS block device, in the C<key> parameter.
5021
5022 This creates a new block device called C</dev/mapper/mapname>.
5023 Reads and writes to this block device are decrypted from and
5024 encrypted to the underlying C<device> respectively.
5025
5026 If this block device contains LVM volume groups, then
5027 calling C<guestfs_vgscan> followed by C<guestfs_vg_activate_all>
5028 will make them visible.");
5029
5030   ("luks_open_ro", (RErr, [Device "device"; Key "key"; String "mapname"]), 258, [Optional "luks"],
5031    [],
5032    "open a LUKS-encrypted block device read-only",
5033    "\
5034 This is the same as C<guestfs_luks_open> except that a read-only
5035 mapping is created.");
5036
5037   ("luks_close", (RErr, [Device "device"]), 259, [Optional "luks"],
5038    [],
5039    "close a LUKS device",
5040    "\
5041 This closes a LUKS device that was created earlier by
5042 C<guestfs_luks_open> or C<guestfs_luks_open_ro>.  The
5043 C<device> parameter must be the name of the LUKS mapping
5044 device (ie. C</dev/mapper/mapname>) and I<not> the name
5045 of the underlying block device.");
5046
5047   ("luks_format", (RErr, [Device "device"; Key "key"; Int "keyslot"]), 260, [Optional "luks"; DangerWillRobinson],
5048    [],
5049    "format a block device as a LUKS encrypted device",
5050    "\
5051 This command erases existing data on C<device> and formats
5052 the device as a LUKS encrypted device.  C<key> is the
5053 initial key, which is added to key slot C<slot>.  (LUKS
5054 supports 8 key slots, numbered 0-7).");
5055
5056   ("luks_format_cipher", (RErr, [Device "device"; Key "key"; Int "keyslot"; String "cipher"]), 261, [Optional "luks"; DangerWillRobinson],
5057    [],
5058    "format a block device as a LUKS encrypted device",
5059    "\
5060 This command is the same as C<guestfs_luks_format> but
5061 it also allows you to set the C<cipher> used.");
5062
5063   ("luks_add_key", (RErr, [Device "device"; Key "key"; Key "newkey"; Int "keyslot"]), 262, [Optional "luks"],
5064    [],
5065    "add a key on a LUKS encrypted device",
5066    "\
5067 This command adds a new key on LUKS device C<device>.
5068 C<key> is any existing key, and is used to access the device.
5069 C<newkey> is the new key to add.  C<keyslot> is the key slot
5070 that will be replaced.
5071
5072 Note that if C<keyslot> already contains a key, then this
5073 command will fail.  You have to use C<guestfs_luks_kill_slot>
5074 first to remove that key.");
5075
5076   ("luks_kill_slot", (RErr, [Device "device"; Key "key"; Int "keyslot"]), 263, [Optional "luks"],
5077    [],
5078    "remove a key from a LUKS encrypted device",
5079    "\
5080 This command deletes the key in key slot C<keyslot> from the
5081 encrypted LUKS device C<device>.  C<key> must be one of the
5082 I<other> keys.");
5083
5084   ("is_lv", (RBool "lvflag", [Device "device"]), 264, [Optional "lvm2"],
5085    [InitBasicFSonLVM, IfAvailable "lvm2", TestOutputTrue (
5086       [["is_lv"; "/dev/VG/LV"]]);
5087     InitBasicFSonLVM, IfAvailable "lvm2", TestOutputFalse (
5088       [["is_lv"; "/dev/sda1"]])],
5089    "test if device is a logical volume",
5090    "\
5091 This command tests whether C<device> is a logical volume, and
5092 returns true iff this is the case.");
5093
5094 ]
5095
5096 let all_functions = non_daemon_functions @ daemon_functions
5097
5098 (* In some places we want the functions to be displayed sorted
5099  * alphabetically, so this is useful:
5100  *)
5101 let all_functions_sorted =
5102   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
5103                compare n1 n2) all_functions
5104
5105 (* This is used to generate the src/MAX_PROC_NR file which
5106  * contains the maximum procedure number, a surrogate for the
5107  * ABI version number.  See src/Makefile.am for the details.
5108  *)
5109 let max_proc_nr =
5110   let proc_nrs = List.map (
5111     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
5112   ) daemon_functions in
5113   List.fold_left max 0 proc_nrs
5114
5115 (* Field types for structures. *)
5116 type field =
5117   | FChar                       (* C 'char' (really, a 7 bit byte). *)
5118   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
5119   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
5120   | FUInt32
5121   | FInt32
5122   | FUInt64
5123   | FInt64
5124   | FBytes                      (* Any int measure that counts bytes. *)
5125   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
5126   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
5127
5128 (* Because we generate extra parsing code for LVM command line tools,
5129  * we have to pull out the LVM columns separately here.
5130  *)
5131 let lvm_pv_cols = [
5132   "pv_name", FString;
5133   "pv_uuid", FUUID;
5134   "pv_fmt", FString;
5135   "pv_size", FBytes;
5136   "dev_size", FBytes;
5137   "pv_free", FBytes;
5138   "pv_used", FBytes;
5139   "pv_attr", FString (* XXX *);
5140   "pv_pe_count", FInt64;
5141   "pv_pe_alloc_count", FInt64;
5142   "pv_tags", FString;
5143   "pe_start", FBytes;
5144   "pv_mda_count", FInt64;
5145   "pv_mda_free", FBytes;
5146   (* Not in Fedora 10:
5147      "pv_mda_size", FBytes;
5148   *)
5149 ]
5150 let lvm_vg_cols = [
5151   "vg_name", FString;
5152   "vg_uuid", FUUID;
5153   "vg_fmt", FString;
5154   "vg_attr", FString (* XXX *);
5155   "vg_size", FBytes;
5156   "vg_free", FBytes;
5157   "vg_sysid", FString;
5158   "vg_extent_size", FBytes;
5159   "vg_extent_count", FInt64;
5160   "vg_free_count", FInt64;
5161   "max_lv", FInt64;
5162   "max_pv", FInt64;
5163   "pv_count", FInt64;
5164   "lv_count", FInt64;
5165   "snap_count", FInt64;
5166   "vg_seqno", FInt64;
5167   "vg_tags", FString;
5168   "vg_mda_count", FInt64;
5169   "vg_mda_free", FBytes;
5170   (* Not in Fedora 10:
5171      "vg_mda_size", FBytes;
5172   *)
5173 ]
5174 let lvm_lv_cols = [
5175   "lv_name", FString;
5176   "lv_uuid", FUUID;
5177   "lv_attr", FString (* XXX *);
5178   "lv_major", FInt64;
5179   "lv_minor", FInt64;
5180   "lv_kernel_major", FInt64;
5181   "lv_kernel_minor", FInt64;
5182   "lv_size", FBytes;
5183   "seg_count", FInt64;
5184   "origin", FString;
5185   "snap_percent", FOptPercent;
5186   "copy_percent", FOptPercent;
5187   "move_pv", FString;
5188   "lv_tags", FString;
5189   "mirror_log", FString;
5190   "modules", FString;
5191 ]
5192
5193 (* Names and fields in all structures (in RStruct and RStructList)
5194  * that we support.
5195  *)
5196 let structs = [
5197   (* The old RIntBool return type, only ever used for aug_defnode.  Do
5198    * not use this struct in any new code.
5199    *)
5200   "int_bool", [
5201     "i", FInt32;                (* for historical compatibility *)
5202     "b", FInt32;                (* for historical compatibility *)
5203   ];
5204
5205   (* LVM PVs, VGs, LVs. *)
5206   "lvm_pv", lvm_pv_cols;
5207   "lvm_vg", lvm_vg_cols;
5208   "lvm_lv", lvm_lv_cols;
5209
5210   (* Column names and types from stat structures.
5211    * NB. Can't use things like 'st_atime' because glibc header files
5212    * define some of these as macros.  Ugh.
5213    *)
5214   "stat", [
5215     "dev", FInt64;
5216     "ino", FInt64;
5217     "mode", FInt64;
5218     "nlink", FInt64;
5219     "uid", FInt64;
5220     "gid", FInt64;
5221     "rdev", FInt64;
5222     "size", FInt64;
5223     "blksize", FInt64;
5224     "blocks", FInt64;
5225     "atime", FInt64;
5226     "mtime", FInt64;
5227     "ctime", FInt64;
5228   ];
5229   "statvfs", [
5230     "bsize", FInt64;
5231     "frsize", FInt64;
5232     "blocks", FInt64;
5233     "bfree", FInt64;
5234     "bavail", FInt64;
5235     "files", FInt64;
5236     "ffree", FInt64;
5237     "favail", FInt64;
5238     "fsid", FInt64;
5239     "flag", FInt64;
5240     "namemax", FInt64;
5241   ];
5242
5243   (* Column names in dirent structure. *)
5244   "dirent", [
5245     "ino", FInt64;
5246     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
5247     "ftyp", FChar;
5248     "name", FString;
5249   ];
5250
5251   (* Version numbers. *)
5252   "version", [
5253     "major", FInt64;
5254     "minor", FInt64;
5255     "release", FInt64;
5256     "extra", FString;
5257   ];
5258
5259   (* Extended attribute. *)
5260   "xattr", [
5261     "attrname", FString;
5262     "attrval", FBuffer;
5263   ];
5264
5265   (* Inotify events. *)
5266   "inotify_event", [
5267     "in_wd", FInt64;
5268     "in_mask", FUInt32;
5269     "in_cookie", FUInt32;
5270     "in_name", FString;
5271   ];
5272
5273   (* Partition table entry. *)
5274   "partition", [
5275     "part_num", FInt32;
5276     "part_start", FBytes;
5277     "part_end", FBytes;
5278     "part_size", FBytes;
5279   ];
5280 ] (* end of structs *)
5281
5282 (* Ugh, Java has to be different ..
5283  * These names are also used by the Haskell bindings.
5284  *)
5285 let java_structs = [
5286   "int_bool", "IntBool";
5287   "lvm_pv", "PV";
5288   "lvm_vg", "VG";
5289   "lvm_lv", "LV";
5290   "stat", "Stat";
5291   "statvfs", "StatVFS";
5292   "dirent", "Dirent";
5293   "version", "Version";
5294   "xattr", "XAttr";
5295   "inotify_event", "INotifyEvent";
5296   "partition", "Partition";
5297 ]
5298
5299 (* What structs are actually returned. *)
5300 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5301
5302 (* Returns a list of RStruct/RStructList structs that are returned
5303  * by any function.  Each element of returned list is a pair:
5304  *
5305  * (structname, RStructOnly)
5306  *    == there exists function which returns RStruct (_, structname)
5307  * (structname, RStructListOnly)
5308  *    == there exists function which returns RStructList (_, structname)
5309  * (structname, RStructAndList)
5310  *    == there are functions returning both RStruct (_, structname)
5311  *                                      and RStructList (_, structname)
5312  *)
5313 let rstructs_used_by functions =
5314   (* ||| is a "logical OR" for rstructs_used_t *)
5315   let (|||) a b =
5316     match a, b with
5317     | RStructAndList, _
5318     | _, RStructAndList -> RStructAndList
5319     | RStructOnly, RStructListOnly
5320     | RStructListOnly, RStructOnly -> RStructAndList
5321     | RStructOnly, RStructOnly -> RStructOnly
5322     | RStructListOnly, RStructListOnly -> RStructListOnly
5323   in
5324
5325   let h = Hashtbl.create 13 in
5326
5327   (* if elem->oldv exists, update entry using ||| operator,
5328    * else just add elem->newv to the hash
5329    *)
5330   let update elem newv =
5331     try  let oldv = Hashtbl.find h elem in
5332          Hashtbl.replace h elem (newv ||| oldv)
5333     with Not_found -> Hashtbl.add h elem newv
5334   in
5335
5336   List.iter (
5337     fun (_, style, _, _, _, _, _) ->
5338       match fst style with
5339       | RStruct (_, structname) -> update structname RStructOnly
5340       | RStructList (_, structname) -> update structname RStructListOnly
5341       | _ -> ()
5342   ) functions;
5343
5344   (* return key->values as a list of (key,value) *)
5345   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5346
5347 (* Used for testing language bindings. *)
5348 type callt =
5349   | CallString of string
5350   | CallOptString of string option
5351   | CallStringList of string list
5352   | CallInt of int
5353   | CallInt64 of int64
5354   | CallBool of bool
5355   | CallBuffer of string
5356
5357 (* Used to memoize the result of pod2text. *)
5358 let pod2text_memo_filename = "src/.pod2text.data"
5359 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5360   try
5361     let chan = open_in pod2text_memo_filename in
5362     let v = input_value chan in
5363     close_in chan;
5364     v
5365   with
5366     _ -> Hashtbl.create 13
5367 let pod2text_memo_updated () =
5368   let chan = open_out pod2text_memo_filename in
5369   output_value chan pod2text_memo;
5370   close_out chan
5371
5372 (* Useful functions.
5373  * Note we don't want to use any external OCaml libraries which
5374  * makes this a bit harder than it should be.
5375  *)
5376 module StringMap = Map.Make (String)
5377
5378 let failwithf fs = ksprintf failwith fs
5379
5380 let unique = let i = ref 0 in fun () -> incr i; !i
5381
5382 let replace_char s c1 c2 =
5383   let s2 = String.copy s in
5384   let r = ref false in
5385   for i = 0 to String.length s2 - 1 do
5386     if String.unsafe_get s2 i = c1 then (
5387       String.unsafe_set s2 i c2;
5388       r := true
5389     )
5390   done;
5391   if not !r then s else s2
5392
5393 let isspace c =
5394   c = ' '
5395   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5396
5397 let triml ?(test = isspace) str =
5398   let i = ref 0 in
5399   let n = ref (String.length str) in
5400   while !n > 0 && test str.[!i]; do
5401     decr n;
5402     incr i
5403   done;
5404   if !i = 0 then str
5405   else String.sub str !i !n
5406
5407 let trimr ?(test = isspace) str =
5408   let n = ref (String.length str) in
5409   while !n > 0 && test str.[!n-1]; do
5410     decr n
5411   done;
5412   if !n = String.length str then str
5413   else String.sub str 0 !n
5414
5415 let trim ?(test = isspace) str =
5416   trimr ~test (triml ~test str)
5417
5418 let rec find s sub =
5419   let len = String.length s in
5420   let sublen = String.length sub in
5421   let rec loop i =
5422     if i <= len-sublen then (
5423       let rec loop2 j =
5424         if j < sublen then (
5425           if s.[i+j] = sub.[j] then loop2 (j+1)
5426           else -1
5427         ) else
5428           i (* found *)
5429       in
5430       let r = loop2 0 in
5431       if r = -1 then loop (i+1) else r
5432     ) else
5433       -1 (* not found *)
5434   in
5435   loop 0
5436
5437 let rec replace_str s s1 s2 =
5438   let len = String.length s in
5439   let sublen = String.length s1 in
5440   let i = find s s1 in
5441   if i = -1 then s
5442   else (
5443     let s' = String.sub s 0 i in
5444     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5445     s' ^ s2 ^ replace_str s'' s1 s2
5446   )
5447
5448 let rec string_split sep str =
5449   let len = String.length str in
5450   let seplen = String.length sep in
5451   let i = find str sep in
5452   if i = -1 then [str]
5453   else (
5454     let s' = String.sub str 0 i in
5455     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5456     s' :: string_split sep s''
5457   )
5458
5459 let files_equal n1 n2 =
5460   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5461   match Sys.command cmd with
5462   | 0 -> true
5463   | 1 -> false
5464   | i -> failwithf "%s: failed with error code %d" cmd i
5465
5466 let rec filter_map f = function
5467   | [] -> []
5468   | x :: xs ->
5469       match f x with
5470       | Some y -> y :: filter_map f xs
5471       | None -> filter_map f xs
5472
5473 let rec find_map f = function
5474   | [] -> raise Not_found
5475   | x :: xs ->
5476       match f x with
5477       | Some y -> y
5478       | None -> find_map f xs
5479
5480 let iteri f xs =
5481   let rec loop i = function
5482     | [] -> ()
5483     | x :: xs -> f i x; loop (i+1) xs
5484   in
5485   loop 0 xs
5486
5487 let mapi f xs =
5488   let rec loop i = function
5489     | [] -> []
5490     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5491   in
5492   loop 0 xs
5493
5494 let count_chars c str =
5495   let count = ref 0 in
5496   for i = 0 to String.length str - 1 do
5497     if c = String.unsafe_get str i then incr count
5498   done;
5499   !count
5500
5501 let explode str =
5502   let r = ref [] in
5503   for i = 0 to String.length str - 1 do
5504     let c = String.unsafe_get str i in
5505     r := c :: !r;
5506   done;
5507   List.rev !r
5508
5509 let map_chars f str =
5510   List.map f (explode str)
5511
5512 let name_of_argt = function
5513   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5514   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5515   | FileIn n | FileOut n | BufferIn n | Key n -> n
5516
5517 let java_name_of_struct typ =
5518   try List.assoc typ java_structs
5519   with Not_found ->
5520     failwithf
5521       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5522
5523 let cols_of_struct typ =
5524   try List.assoc typ structs
5525   with Not_found ->
5526     failwithf "cols_of_struct: unknown struct %s" typ
5527
5528 let seq_of_test = function
5529   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5530   | TestOutputListOfDevices (s, _)
5531   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5532   | TestOutputTrue s | TestOutputFalse s
5533   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5534   | TestOutputStruct (s, _)
5535   | TestLastFail s -> s
5536
5537 (* Handling for function flags. *)
5538 let protocol_limit_warning =
5539   "Because of the message protocol, there is a transfer limit
5540 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5541
5542 let danger_will_robinson =
5543   "B<This command is dangerous.  Without careful use you
5544 can easily destroy all your data>."
5545
5546 let deprecation_notice flags =
5547   try
5548     let alt =
5549       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5550     let txt =
5551       sprintf "This function is deprecated.
5552 In new code, use the C<%s> call instead.
5553
5554 Deprecated functions will not be removed from the API, but the
5555 fact that they are deprecated indicates that there are problems
5556 with correct use of these functions." alt in
5557     Some txt
5558   with
5559     Not_found -> None
5560
5561 (* Create list of optional groups. *)
5562 let optgroups =
5563   let h = Hashtbl.create 13 in
5564   List.iter (
5565     fun (name, _, _, flags, _, _, _) ->
5566       List.iter (
5567         function
5568         | Optional group ->
5569             let names = try Hashtbl.find h group with Not_found -> [] in
5570             Hashtbl.replace h group (name :: names)
5571         | _ -> ()
5572       ) flags
5573   ) daemon_functions;
5574   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5575   let groups =
5576     List.map (
5577       fun group -> group, List.sort compare (Hashtbl.find h group)
5578     ) groups in
5579   List.sort (fun x y -> compare (fst x) (fst y)) groups
5580
5581 (* Check function names etc. for consistency. *)
5582 let check_functions () =
5583   let contains_uppercase str =
5584     let len = String.length str in
5585     let rec loop i =
5586       if i >= len then false
5587       else (
5588         let c = str.[i] in
5589         if c >= 'A' && c <= 'Z' then true
5590         else loop (i+1)
5591       )
5592     in
5593     loop 0
5594   in
5595
5596   (* Check function names. *)
5597   List.iter (
5598     fun (name, _, _, _, _, _, _) ->
5599       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5600         failwithf "function name %s does not need 'guestfs' prefix" name;
5601       if name = "" then
5602         failwithf "function name is empty";
5603       if name.[0] < 'a' || name.[0] > 'z' then
5604         failwithf "function name %s must start with lowercase a-z" name;
5605       if String.contains name '-' then
5606         failwithf "function name %s should not contain '-', use '_' instead."
5607           name
5608   ) all_functions;
5609
5610   (* Check function parameter/return names. *)
5611   List.iter (
5612     fun (name, style, _, _, _, _, _) ->
5613       let check_arg_ret_name n =
5614         if contains_uppercase n then
5615           failwithf "%s param/ret %s should not contain uppercase chars"
5616             name n;
5617         if String.contains n '-' || String.contains n '_' then
5618           failwithf "%s param/ret %s should not contain '-' or '_'"
5619             name n;
5620         if n = "value" then
5621           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;
5622         if n = "int" || n = "char" || n = "short" || n = "long" then
5623           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5624         if n = "i" || n = "n" then
5625           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5626         if n = "argv" || n = "args" then
5627           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5628
5629         (* List Haskell, OCaml and C keywords here.
5630          * http://www.haskell.org/haskellwiki/Keywords
5631          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5632          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5633          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5634          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5635          * Omitting _-containing words, since they're handled above.
5636          * Omitting the OCaml reserved word, "val", is ok,
5637          * and saves us from renaming several parameters.
5638          *)
5639         let reserved = [
5640           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5641           "char"; "class"; "const"; "constraint"; "continue"; "data";
5642           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5643           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5644           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5645           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5646           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5647           "interface";
5648           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5649           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5650           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5651           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5652           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5653           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5654           "volatile"; "when"; "where"; "while";
5655           ] in
5656         if List.mem n reserved then
5657           failwithf "%s has param/ret using reserved word %s" name n;
5658       in
5659
5660       (match fst style with
5661        | RErr -> ()
5662        | RInt n | RInt64 n | RBool n
5663        | RConstString n | RConstOptString n | RString n
5664        | RStringList n | RStruct (n, _) | RStructList (n, _)
5665        | RHashtable n | RBufferOut n ->
5666            check_arg_ret_name n
5667       );
5668       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5669   ) all_functions;
5670
5671   (* Check short descriptions. *)
5672   List.iter (
5673     fun (name, _, _, _, _, shortdesc, _) ->
5674       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5675         failwithf "short description of %s should begin with lowercase." name;
5676       let c = shortdesc.[String.length shortdesc-1] in
5677       if c = '\n' || c = '.' then
5678         failwithf "short description of %s should not end with . or \\n." name
5679   ) all_functions;
5680
5681   (* Check long descriptions. *)
5682   List.iter (
5683     fun (name, _, _, _, _, _, longdesc) ->
5684       if longdesc.[String.length longdesc-1] = '\n' then
5685         failwithf "long description of %s should not end with \\n." name
5686   ) all_functions;
5687
5688   (* Check proc_nrs. *)
5689   List.iter (
5690     fun (name, _, proc_nr, _, _, _, _) ->
5691       if proc_nr <= 0 then
5692         failwithf "daemon function %s should have proc_nr > 0" name
5693   ) daemon_functions;
5694
5695   List.iter (
5696     fun (name, _, proc_nr, _, _, _, _) ->
5697       if proc_nr <> -1 then
5698         failwithf "non-daemon function %s should have proc_nr -1" name
5699   ) non_daemon_functions;
5700
5701   let proc_nrs =
5702     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5703       daemon_functions in
5704   let proc_nrs =
5705     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5706   let rec loop = function
5707     | [] -> ()
5708     | [_] -> ()
5709     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5710         loop rest
5711     | (name1,nr1) :: (name2,nr2) :: _ ->
5712         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5713           name1 name2 nr1 nr2
5714   in
5715   loop proc_nrs;
5716
5717   (* Check tests. *)
5718   List.iter (
5719     function
5720       (* Ignore functions that have no tests.  We generate a
5721        * warning when the user does 'make check' instead.
5722        *)
5723     | name, _, _, _, [], _, _ -> ()
5724     | name, _, _, _, tests, _, _ ->
5725         let funcs =
5726           List.map (
5727             fun (_, _, test) ->
5728               match seq_of_test test with
5729               | [] ->
5730                   failwithf "%s has a test containing an empty sequence" name
5731               | cmds -> List.map List.hd cmds
5732           ) tests in
5733         let funcs = List.flatten funcs in
5734
5735         let tested = List.mem name funcs in
5736
5737         if not tested then
5738           failwithf "function %s has tests but does not test itself" name
5739   ) all_functions
5740
5741 (* 'pr' prints to the current output file. *)
5742 let chan = ref Pervasives.stdout
5743 let lines = ref 0
5744 let pr fs =
5745   ksprintf
5746     (fun str ->
5747        let i = count_chars '\n' str in
5748        lines := !lines + i;
5749        output_string !chan str
5750     ) fs
5751
5752 let copyright_years =
5753   let this_year = 1900 + (localtime (time ())).tm_year in
5754   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5755
5756 (* Generate a header block in a number of standard styles. *)
5757 type comment_style =
5758     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5759 type license = GPLv2plus | LGPLv2plus
5760
5761 let generate_header ?(extra_inputs = []) comment license =
5762   let inputs = "src/generator.ml" :: extra_inputs in
5763   let c = match comment with
5764     | CStyle ->         pr "/* "; " *"
5765     | CPlusPlusStyle -> pr "// "; "//"
5766     | HashStyle ->      pr "# ";  "#"
5767     | OCamlStyle ->     pr "(* "; " *"
5768     | HaskellStyle ->   pr "{- "; "  " in
5769   pr "libguestfs generated file\n";
5770   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5771   List.iter (pr "%s   %s\n" c) inputs;
5772   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5773   pr "%s\n" c;
5774   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5775   pr "%s\n" c;
5776   (match license with
5777    | GPLv2plus ->
5778        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5779        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5780        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5781        pr "%s (at your option) any later version.\n" c;
5782        pr "%s\n" c;
5783        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5784        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5785        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5786        pr "%s GNU General Public License for more details.\n" c;
5787        pr "%s\n" c;
5788        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5789        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5790        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5791
5792    | LGPLv2plus ->
5793        pr "%s This library is free software; you can redistribute it and/or\n" c;
5794        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5795        pr "%s License as published by the Free Software Foundation; either\n" c;
5796        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5797        pr "%s\n" c;
5798        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5799        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5800        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5801        pr "%s Lesser General Public License for more details.\n" c;
5802        pr "%s\n" c;
5803        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5804        pr "%s License along with this library; if not, write to the Free Software\n" c;
5805        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5806   );
5807   (match comment with
5808    | CStyle -> pr " */\n"
5809    | CPlusPlusStyle
5810    | HashStyle -> ()
5811    | OCamlStyle -> pr " *)\n"
5812    | HaskellStyle -> pr "-}\n"
5813   );
5814   pr "\n"
5815
5816 (* Start of main code generation functions below this line. *)
5817
5818 (* Generate the pod documentation for the C API. *)
5819 let rec generate_actions_pod () =
5820   List.iter (
5821     fun (shortname, style, _, flags, _, _, longdesc) ->
5822       if not (List.mem NotInDocs flags) then (
5823         let name = "guestfs_" ^ shortname in
5824         pr "=head2 %s\n\n" name;
5825         pr " ";
5826         generate_prototype ~extern:false ~handle:"g" name style;
5827         pr "\n\n";
5828         pr "%s\n\n" longdesc;
5829         (match fst style with
5830          | RErr ->
5831              pr "This function returns 0 on success or -1 on error.\n\n"
5832          | RInt _ ->
5833              pr "On error this function returns -1.\n\n"
5834          | RInt64 _ ->
5835              pr "On error this function returns -1.\n\n"
5836          | RBool _ ->
5837              pr "This function returns a C truth value on success or -1 on error.\n\n"
5838          | RConstString _ ->
5839              pr "This function returns a string, or NULL on error.
5840 The string is owned by the guest handle and must I<not> be freed.\n\n"
5841          | RConstOptString _ ->
5842              pr "This function returns a string which may be NULL.
5843 There is no way to return an error from this function.
5844 The string is owned by the guest handle and must I<not> be freed.\n\n"
5845          | RString _ ->
5846              pr "This function returns a string, or NULL on error.
5847 I<The caller must free the returned string after use>.\n\n"
5848          | RStringList _ ->
5849              pr "This function returns a NULL-terminated array of strings
5850 (like L<environ(3)>), or NULL if there was an error.
5851 I<The caller must free the strings and the array after use>.\n\n"
5852          | RStruct (_, typ) ->
5853              pr "This function returns a C<struct guestfs_%s *>,
5854 or NULL if there was an error.
5855 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5856          | RStructList (_, typ) ->
5857              pr "This function returns a C<struct guestfs_%s_list *>
5858 (see E<lt>guestfs-structs.hE<gt>),
5859 or NULL if there was an error.
5860 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5861          | RHashtable _ ->
5862              pr "This function returns a NULL-terminated array of
5863 strings, or NULL if there was an error.
5864 The array of strings will always have length C<2n+1>, where
5865 C<n> keys and values alternate, followed by the trailing NULL entry.
5866 I<The caller must free the strings and the array after use>.\n\n"
5867          | RBufferOut _ ->
5868              pr "This function returns a buffer, or NULL on error.
5869 The size of the returned buffer is written to C<*size_r>.
5870 I<The caller must free the returned buffer after use>.\n\n"
5871         );
5872         if List.mem ProtocolLimitWarning flags then
5873           pr "%s\n\n" protocol_limit_warning;
5874         if List.mem DangerWillRobinson flags then
5875           pr "%s\n\n" danger_will_robinson;
5876         if List.exists (function Key _ -> true | _ -> false) (snd style) then
5877           pr "This function takes a key or passphrase parameter which
5878 could contain sensitive material.  Read the section
5879 L</KEYS AND PASSPHRASES> for more information.\n\n";
5880         match deprecation_notice flags with
5881         | None -> ()
5882         | Some txt -> pr "%s\n\n" txt
5883       )
5884   ) all_functions_sorted
5885
5886 and generate_structs_pod () =
5887   (* Structs documentation. *)
5888   List.iter (
5889     fun (typ, cols) ->
5890       pr "=head2 guestfs_%s\n" typ;
5891       pr "\n";
5892       pr " struct guestfs_%s {\n" typ;
5893       List.iter (
5894         function
5895         | name, FChar -> pr "   char %s;\n" name
5896         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5897         | name, FInt32 -> pr "   int32_t %s;\n" name
5898         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5899         | name, FInt64 -> pr "   int64_t %s;\n" name
5900         | name, FString -> pr "   char *%s;\n" name
5901         | name, FBuffer ->
5902             pr "   /* The next two fields describe a byte array. */\n";
5903             pr "   uint32_t %s_len;\n" name;
5904             pr "   char *%s;\n" name
5905         | name, FUUID ->
5906             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5907             pr "   char %s[32];\n" name
5908         | name, FOptPercent ->
5909             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5910             pr "   float %s;\n" name
5911       ) cols;
5912       pr " };\n";
5913       pr " \n";
5914       pr " struct guestfs_%s_list {\n" typ;
5915       pr "   uint32_t len; /* Number of elements in list. */\n";
5916       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5917       pr " };\n";
5918       pr " \n";
5919       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5920       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5921         typ typ;
5922       pr "\n"
5923   ) structs
5924
5925 and generate_availability_pod () =
5926   (* Availability documentation. *)
5927   pr "=over 4\n";
5928   pr "\n";
5929   List.iter (
5930     fun (group, functions) ->
5931       pr "=item B<%s>\n" group;
5932       pr "\n";
5933       pr "The following functions:\n";
5934       List.iter (pr "L</guestfs_%s>\n") functions;
5935       pr "\n"
5936   ) optgroups;
5937   pr "=back\n";
5938   pr "\n"
5939
5940 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5941  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5942  *
5943  * We have to use an underscore instead of a dash because otherwise
5944  * rpcgen generates incorrect code.
5945  *
5946  * This header is NOT exported to clients, but see also generate_structs_h.
5947  *)
5948 and generate_xdr () =
5949   generate_header CStyle LGPLv2plus;
5950
5951   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5952   pr "typedef string str<>;\n";
5953   pr "\n";
5954
5955   (* Internal structures. *)
5956   List.iter (
5957     function
5958     | typ, cols ->
5959         pr "struct guestfs_int_%s {\n" typ;
5960         List.iter (function
5961                    | name, FChar -> pr "  char %s;\n" name
5962                    | name, FString -> pr "  string %s<>;\n" name
5963                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5964                    | name, FUUID -> pr "  opaque %s[32];\n" name
5965                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5966                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5967                    | name, FOptPercent -> pr "  float %s;\n" name
5968                   ) cols;
5969         pr "};\n";
5970         pr "\n";
5971         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5972         pr "\n";
5973   ) structs;
5974
5975   List.iter (
5976     fun (shortname, style, _, _, _, _, _) ->
5977       let name = "guestfs_" ^ shortname in
5978
5979       (match snd style with
5980        | [] -> ()
5981        | args ->
5982            pr "struct %s_args {\n" name;
5983            List.iter (
5984              function
5985              | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
5986                  pr "  string %s<>;\n" n
5987              | OptString n -> pr "  str *%s;\n" n
5988              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5989              | Bool n -> pr "  bool %s;\n" n
5990              | Int n -> pr "  int %s;\n" n
5991              | Int64 n -> pr "  hyper %s;\n" n
5992              | BufferIn n ->
5993                  pr "  opaque %s<>;\n" n
5994              | FileIn _ | FileOut _ -> ()
5995            ) args;
5996            pr "};\n\n"
5997       );
5998       (match fst style with
5999        | RErr -> ()
6000        | RInt n ->
6001            pr "struct %s_ret {\n" name;
6002            pr "  int %s;\n" n;
6003            pr "};\n\n"
6004        | RInt64 n ->
6005            pr "struct %s_ret {\n" name;
6006            pr "  hyper %s;\n" n;
6007            pr "};\n\n"
6008        | RBool n ->
6009            pr "struct %s_ret {\n" name;
6010            pr "  bool %s;\n" n;
6011            pr "};\n\n"
6012        | RConstString _ | RConstOptString _ ->
6013            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6014        | RString n ->
6015            pr "struct %s_ret {\n" name;
6016            pr "  string %s<>;\n" n;
6017            pr "};\n\n"
6018        | RStringList n ->
6019            pr "struct %s_ret {\n" name;
6020            pr "  str %s<>;\n" n;
6021            pr "};\n\n"
6022        | RStruct (n, typ) ->
6023            pr "struct %s_ret {\n" name;
6024            pr "  guestfs_int_%s %s;\n" typ n;
6025            pr "};\n\n"
6026        | RStructList (n, typ) ->
6027            pr "struct %s_ret {\n" name;
6028            pr "  guestfs_int_%s_list %s;\n" typ n;
6029            pr "};\n\n"
6030        | RHashtable n ->
6031            pr "struct %s_ret {\n" name;
6032            pr "  str %s<>;\n" n;
6033            pr "};\n\n"
6034        | RBufferOut n ->
6035            pr "struct %s_ret {\n" name;
6036            pr "  opaque %s<>;\n" n;
6037            pr "};\n\n"
6038       );
6039   ) daemon_functions;
6040
6041   (* Table of procedure numbers. *)
6042   pr "enum guestfs_procedure {\n";
6043   List.iter (
6044     fun (shortname, _, proc_nr, _, _, _, _) ->
6045       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
6046   ) daemon_functions;
6047   pr "  GUESTFS_PROC_NR_PROCS\n";
6048   pr "};\n";
6049   pr "\n";
6050
6051   (* Having to choose a maximum message size is annoying for several
6052    * reasons (it limits what we can do in the API), but it (a) makes
6053    * the protocol a lot simpler, and (b) provides a bound on the size
6054    * of the daemon which operates in limited memory space.
6055    *)
6056   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
6057   pr "\n";
6058
6059   (* Message header, etc. *)
6060   pr "\
6061 /* The communication protocol is now documented in the guestfs(3)
6062  * manpage.
6063  */
6064
6065 const GUESTFS_PROGRAM = 0x2000F5F5;
6066 const GUESTFS_PROTOCOL_VERSION = 1;
6067
6068 /* These constants must be larger than any possible message length. */
6069 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
6070 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
6071
6072 enum guestfs_message_direction {
6073   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
6074   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
6075 };
6076
6077 enum guestfs_message_status {
6078   GUESTFS_STATUS_OK = 0,
6079   GUESTFS_STATUS_ERROR = 1
6080 };
6081
6082 const GUESTFS_ERROR_LEN = 256;
6083
6084 struct guestfs_message_error {
6085   string error_message<GUESTFS_ERROR_LEN>;
6086 };
6087
6088 struct guestfs_message_header {
6089   unsigned prog;                     /* GUESTFS_PROGRAM */
6090   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
6091   guestfs_procedure proc;            /* GUESTFS_PROC_x */
6092   guestfs_message_direction direction;
6093   unsigned serial;                   /* message serial number */
6094   guestfs_message_status status;
6095 };
6096
6097 const GUESTFS_MAX_CHUNK_SIZE = 8192;
6098
6099 struct guestfs_chunk {
6100   int cancel;                        /* if non-zero, transfer is cancelled */
6101   /* data size is 0 bytes if the transfer has finished successfully */
6102   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
6103 };
6104 "
6105
6106 (* Generate the guestfs-structs.h file. *)
6107 and generate_structs_h () =
6108   generate_header CStyle LGPLv2plus;
6109
6110   (* This is a public exported header file containing various
6111    * structures.  The structures are carefully written to have
6112    * exactly the same in-memory format as the XDR structures that
6113    * we use on the wire to the daemon.  The reason for creating
6114    * copies of these structures here is just so we don't have to
6115    * export the whole of guestfs_protocol.h (which includes much
6116    * unrelated and XDR-dependent stuff that we don't want to be
6117    * public, or required by clients).
6118    *
6119    * To reiterate, we will pass these structures to and from the
6120    * client with a simple assignment or memcpy, so the format
6121    * must be identical to what rpcgen / the RFC defines.
6122    *)
6123
6124   (* Public structures. *)
6125   List.iter (
6126     fun (typ, cols) ->
6127       pr "struct guestfs_%s {\n" typ;
6128       List.iter (
6129         function
6130         | name, FChar -> pr "  char %s;\n" name
6131         | name, FString -> pr "  char *%s;\n" name
6132         | name, FBuffer ->
6133             pr "  uint32_t %s_len;\n" name;
6134             pr "  char *%s;\n" name
6135         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
6136         | name, FUInt32 -> pr "  uint32_t %s;\n" name
6137         | name, FInt32 -> pr "  int32_t %s;\n" name
6138         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
6139         | name, FInt64 -> pr "  int64_t %s;\n" name
6140         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
6141       ) cols;
6142       pr "};\n";
6143       pr "\n";
6144       pr "struct guestfs_%s_list {\n" typ;
6145       pr "  uint32_t len;\n";
6146       pr "  struct guestfs_%s *val;\n" typ;
6147       pr "};\n";
6148       pr "\n";
6149       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
6150       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
6151       pr "\n"
6152   ) structs
6153
6154 (* Generate the guestfs-actions.h file. *)
6155 and generate_actions_h () =
6156   generate_header CStyle LGPLv2plus;
6157   List.iter (
6158     fun (shortname, style, _, _, _, _, _) ->
6159       let name = "guestfs_" ^ shortname in
6160       generate_prototype ~single_line:true ~newline:true ~handle:"g"
6161         name style
6162   ) all_functions
6163
6164 (* Generate the guestfs-internal-actions.h file. *)
6165 and generate_internal_actions_h () =
6166   generate_header CStyle LGPLv2plus;
6167   List.iter (
6168     fun (shortname, style, _, _, _, _, _) ->
6169       let name = "guestfs__" ^ shortname in
6170       generate_prototype ~single_line:true ~newline:true ~handle:"g"
6171         name style
6172   ) non_daemon_functions
6173
6174 (* Generate the client-side dispatch stubs. *)
6175 and generate_client_actions () =
6176   generate_header CStyle LGPLv2plus;
6177
6178   pr "\
6179 #include <stdio.h>
6180 #include <stdlib.h>
6181 #include <stdint.h>
6182 #include <string.h>
6183 #include <inttypes.h>
6184
6185 #include \"guestfs.h\"
6186 #include \"guestfs-internal.h\"
6187 #include \"guestfs-internal-actions.h\"
6188 #include \"guestfs_protocol.h\"
6189
6190 /* Check the return message from a call for validity. */
6191 static int
6192 check_reply_header (guestfs_h *g,
6193                     const struct guestfs_message_header *hdr,
6194                     unsigned int proc_nr, unsigned int serial)
6195 {
6196   if (hdr->prog != GUESTFS_PROGRAM) {
6197     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
6198     return -1;
6199   }
6200   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
6201     error (g, \"wrong protocol version (%%d/%%d)\",
6202            hdr->vers, GUESTFS_PROTOCOL_VERSION);
6203     return -1;
6204   }
6205   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
6206     error (g, \"unexpected message direction (%%d/%%d)\",
6207            hdr->direction, GUESTFS_DIRECTION_REPLY);
6208     return -1;
6209   }
6210   if (hdr->proc != proc_nr) {
6211     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
6212     return -1;
6213   }
6214   if (hdr->serial != serial) {
6215     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
6216     return -1;
6217   }
6218
6219   return 0;
6220 }
6221
6222 /* Check we are in the right state to run a high-level action. */
6223 static int
6224 check_state (guestfs_h *g, const char *caller)
6225 {
6226   if (!guestfs__is_ready (g)) {
6227     if (guestfs__is_config (g) || guestfs__is_launching (g))
6228       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
6229         caller);
6230     else
6231       error (g, \"%%s called from the wrong state, %%d != READY\",
6232         caller, guestfs__get_state (g));
6233     return -1;
6234   }
6235   return 0;
6236 }
6237
6238 ";
6239
6240   let error_code_of = function
6241     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
6242     | RConstString _ | RConstOptString _
6243     | RString _ | RStringList _
6244     | RStruct _ | RStructList _
6245     | RHashtable _ | RBufferOut _ -> "NULL"
6246   in
6247
6248   (* Generate code to check String-like parameters are not passed in
6249    * as NULL (returning an error if they are).
6250    *)
6251   let check_null_strings shortname style =
6252     let pr_newline = ref false in
6253     List.iter (
6254       function
6255       (* parameters which should not be NULL *)
6256       | String n
6257       | Device n
6258       | Pathname n
6259       | Dev_or_Path n
6260       | FileIn n
6261       | FileOut n
6262       | BufferIn n
6263       | StringList n
6264       | DeviceList n
6265       | Key n ->
6266           pr "  if (%s == NULL) {\n" n;
6267           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6268           pr "           \"%s\", \"%s\");\n" shortname n;
6269           pr "    return %s;\n" (error_code_of (fst style));
6270           pr "  }\n";
6271           pr_newline := true
6272
6273       (* can be NULL *)
6274       | OptString _
6275
6276       (* not applicable *)
6277       | Bool _
6278       | Int _
6279       | Int64 _ -> ()
6280     ) (snd style);
6281
6282     if !pr_newline then pr "\n";
6283   in
6284
6285   (* Generate code to generate guestfish call traces. *)
6286   let trace_call shortname style =
6287     pr "  if (guestfs__get_trace (g)) {\n";
6288
6289     let needs_i =
6290       List.exists (function
6291                    | StringList _ | DeviceList _ -> true
6292                    | _ -> false) (snd style) in
6293     if needs_i then (
6294       pr "    size_t i;\n";
6295       pr "\n"
6296     );
6297
6298     pr "    fprintf (stderr, \"%s\");\n" shortname;
6299     List.iter (
6300       function
6301       | String n                        (* strings *)
6302       | Device n
6303       | Pathname n
6304       | Dev_or_Path n
6305       | FileIn n
6306       | FileOut n
6307       | BufferIn n
6308       | Key n ->
6309           (* guestfish doesn't support string escaping, so neither do we *)
6310           pr "    fprintf (stderr, \" \\\"%%s\\\"\", %s);\n" n
6311       | OptString n ->                  (* string option *)
6312           pr "    if (%s) fprintf (stderr, \" \\\"%%s\\\"\", %s);\n" n n;
6313           pr "    else fprintf (stderr, \" null\");\n"
6314       | StringList n
6315       | DeviceList n ->                 (* string list *)
6316           pr "    fputc (' ', stderr);\n";
6317           pr "    fputc ('\"', stderr);\n";
6318           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6319           pr "      if (i > 0) fputc (' ', stderr);\n";
6320           pr "      fputs (%s[i], stderr);\n" n;
6321           pr "    }\n";
6322           pr "    fputc ('\"', stderr);\n";
6323       | Bool n ->                       (* boolean *)
6324           pr "    fputs (%s ? \" true\" : \" false\", stderr);\n" n
6325       | Int n ->                        (* int *)
6326           pr "    fprintf (stderr, \" %%d\", %s);\n" n
6327       | Int64 n ->
6328           pr "    fprintf (stderr, \" %%\" PRIi64, %s);\n" n
6329     ) (snd style);
6330     pr "    fputc ('\\n', stderr);\n";
6331     pr "  }\n";
6332     pr "\n";
6333   in
6334
6335   (* For non-daemon functions, generate a wrapper around each function. *)
6336   List.iter (
6337     fun (shortname, style, _, _, _, _, _) ->
6338       let name = "guestfs_" ^ shortname in
6339
6340       generate_prototype ~extern:false ~semicolon:false ~newline:true
6341         ~handle:"g" name style;
6342       pr "{\n";
6343       check_null_strings shortname style;
6344       trace_call shortname style;
6345       pr "  return guestfs__%s " shortname;
6346       generate_c_call_args ~handle:"g" style;
6347       pr ";\n";
6348       pr "}\n";
6349       pr "\n"
6350   ) non_daemon_functions;
6351
6352   (* Client-side stubs for each function. *)
6353   List.iter (
6354     fun (shortname, style, _, _, _, _, _) ->
6355       let name = "guestfs_" ^ shortname in
6356       let error_code = error_code_of (fst style) in
6357
6358       (* Generate the action stub. *)
6359       generate_prototype ~extern:false ~semicolon:false ~newline:true
6360         ~handle:"g" name style;
6361
6362       pr "{\n";
6363
6364       (match snd style with
6365        | [] -> ()
6366        | _ -> pr "  struct %s_args args;\n" name
6367       );
6368
6369       pr "  guestfs_message_header hdr;\n";
6370       pr "  guestfs_message_error err;\n";
6371       let has_ret =
6372         match fst style with
6373         | RErr -> false
6374         | RConstString _ | RConstOptString _ ->
6375             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6376         | RInt _ | RInt64 _
6377         | RBool _ | RString _ | RStringList _
6378         | RStruct _ | RStructList _
6379         | RHashtable _ | RBufferOut _ ->
6380             pr "  struct %s_ret ret;\n" name;
6381             true in
6382
6383       pr "  int serial;\n";
6384       pr "  int r;\n";
6385       pr "\n";
6386       check_null_strings shortname style;
6387       trace_call shortname style;
6388       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6389         shortname error_code;
6390       pr "  guestfs___set_busy (g);\n";
6391       pr "\n";
6392
6393       (* Send the main header and arguments. *)
6394       (match snd style with
6395        | [] ->
6396            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6397              (String.uppercase shortname)
6398        | args ->
6399            List.iter (
6400              function
6401              | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
6402                  pr "  args.%s = (char *) %s;\n" n n
6403              | OptString n ->
6404                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6405              | StringList n | DeviceList n ->
6406                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6407                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6408              | Bool n ->
6409                  pr "  args.%s = %s;\n" n n
6410              | Int n ->
6411                  pr "  args.%s = %s;\n" n n
6412              | Int64 n ->
6413                  pr "  args.%s = %s;\n" n n
6414              | FileIn _ | FileOut _ -> ()
6415              | BufferIn n ->
6416                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6417                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6418                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6419                    shortname;
6420                  pr "    guestfs___end_busy (g);\n";
6421                  pr "    return %s;\n" error_code;
6422                  pr "  }\n";
6423                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6424                  pr "  args.%s.%s_len = %s_size;\n" n n n
6425            ) args;
6426            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6427              (String.uppercase shortname);
6428            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6429              name;
6430       );
6431       pr "  if (serial == -1) {\n";
6432       pr "    guestfs___end_busy (g);\n";
6433       pr "    return %s;\n" error_code;
6434       pr "  }\n";
6435       pr "\n";
6436
6437       (* Send any additional files (FileIn) requested. *)
6438       let need_read_reply_label = ref false in
6439       List.iter (
6440         function
6441         | FileIn n ->
6442             pr "  r = guestfs___send_file (g, %s);\n" n;
6443             pr "  if (r == -1) {\n";
6444             pr "    guestfs___end_busy (g);\n";
6445             pr "    return %s;\n" error_code;
6446             pr "  }\n";
6447             pr "  if (r == -2) /* daemon cancelled */\n";
6448             pr "    goto read_reply;\n";
6449             need_read_reply_label := true;
6450             pr "\n";
6451         | _ -> ()
6452       ) (snd style);
6453
6454       (* Wait for the reply from the remote end. *)
6455       if !need_read_reply_label then pr " read_reply:\n";
6456       pr "  memset (&hdr, 0, sizeof hdr);\n";
6457       pr "  memset (&err, 0, sizeof err);\n";
6458       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6459       pr "\n";
6460       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6461       if not has_ret then
6462         pr "NULL, NULL"
6463       else
6464         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6465       pr ");\n";
6466
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 "\n";
6472
6473       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6474         (String.uppercase shortname);
6475       pr "    guestfs___end_busy (g);\n";
6476       pr "    return %s;\n" error_code;
6477       pr "  }\n";
6478       pr "\n";
6479
6480       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6481       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6482       pr "    free (err.error_message);\n";
6483       pr "    guestfs___end_busy (g);\n";
6484       pr "    return %s;\n" error_code;
6485       pr "  }\n";
6486       pr "\n";
6487
6488       (* Expecting to receive further files (FileOut)? *)
6489       List.iter (
6490         function
6491         | FileOut n ->
6492             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6493             pr "    guestfs___end_busy (g);\n";
6494             pr "    return %s;\n" error_code;
6495             pr "  }\n";
6496             pr "\n";
6497         | _ -> ()
6498       ) (snd style);
6499
6500       pr "  guestfs___end_busy (g);\n";
6501
6502       (match fst style with
6503        | RErr -> pr "  return 0;\n"
6504        | RInt n | RInt64 n | RBool n ->
6505            pr "  return ret.%s;\n" n
6506        | RConstString _ | RConstOptString _ ->
6507            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6508        | RString n ->
6509            pr "  return ret.%s; /* caller will free */\n" n
6510        | RStringList n | RHashtable n ->
6511            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6512            pr "  ret.%s.%s_val =\n" n n;
6513            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6514            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6515              n n;
6516            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6517            pr "  return ret.%s.%s_val;\n" n n
6518        | RStruct (n, _) ->
6519            pr "  /* caller will free this */\n";
6520            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6521        | RStructList (n, _) ->
6522            pr "  /* caller will free this */\n";
6523            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6524        | RBufferOut n ->
6525            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6526            pr "   * _val might be NULL here.  To make the API saner for\n";
6527            pr "   * callers, we turn this case into a unique pointer (using\n";
6528            pr "   * malloc(1)).\n";
6529            pr "   */\n";
6530            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6531            pr "    *size_r = ret.%s.%s_len;\n" n n;
6532            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6533            pr "  } else {\n";
6534            pr "    free (ret.%s.%s_val);\n" n n;
6535            pr "    char *p = safe_malloc (g, 1);\n";
6536            pr "    *size_r = ret.%s.%s_len;\n" n n;
6537            pr "    return p;\n";
6538            pr "  }\n";
6539       );
6540
6541       pr "}\n\n"
6542   ) daemon_functions;
6543
6544   (* Functions to free structures. *)
6545   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6546   pr " * structure format is identical to the XDR format.  See note in\n";
6547   pr " * generator.ml.\n";
6548   pr " */\n";
6549   pr "\n";
6550
6551   List.iter (
6552     fun (typ, _) ->
6553       pr "void\n";
6554       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6555       pr "{\n";
6556       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6557       pr "  free (x);\n";
6558       pr "}\n";
6559       pr "\n";
6560
6561       pr "void\n";
6562       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6563       pr "{\n";
6564       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6565       pr "  free (x);\n";
6566       pr "}\n";
6567       pr "\n";
6568
6569   ) structs;
6570
6571 (* Generate daemon/actions.h. *)
6572 and generate_daemon_actions_h () =
6573   generate_header CStyle GPLv2plus;
6574
6575   pr "#include \"../src/guestfs_protocol.h\"\n";
6576   pr "\n";
6577
6578   List.iter (
6579     fun (name, style, _, _, _, _, _) ->
6580       generate_prototype
6581         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6582         name style;
6583   ) daemon_functions
6584
6585 (* Generate the linker script which controls the visibility of
6586  * symbols in the public ABI and ensures no other symbols get
6587  * exported accidentally.
6588  *)
6589 and generate_linker_script () =
6590   generate_header HashStyle GPLv2plus;
6591
6592   let globals = [
6593     "guestfs_create";
6594     "guestfs_close";
6595     "guestfs_get_error_handler";
6596     "guestfs_get_out_of_memory_handler";
6597     "guestfs_last_error";
6598     "guestfs_set_close_callback";
6599     "guestfs_set_error_handler";
6600     "guestfs_set_launch_done_callback";
6601     "guestfs_set_log_message_callback";
6602     "guestfs_set_out_of_memory_handler";
6603     "guestfs_set_subprocess_quit_callback";
6604
6605     (* Unofficial parts of the API: the bindings code use these
6606      * functions, so it is useful to export them.
6607      *)
6608     "guestfs_safe_calloc";
6609     "guestfs_safe_malloc";
6610     "guestfs_safe_strdup";
6611     "guestfs_safe_memdup";
6612   ] in
6613   let functions =
6614     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6615       all_functions in
6616   let structs =
6617     List.concat (
6618       List.map (fun (typ, _) ->
6619                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6620         structs
6621     ) in
6622   let globals = List.sort compare (globals @ functions @ structs) in
6623
6624   pr "{\n";
6625   pr "    global:\n";
6626   List.iter (pr "        %s;\n") globals;
6627   pr "\n";
6628
6629   pr "    local:\n";
6630   pr "        *;\n";
6631   pr "};\n"
6632
6633 (* Generate the server-side stubs. *)
6634 and generate_daemon_actions () =
6635   generate_header CStyle GPLv2plus;
6636
6637   pr "#include <config.h>\n";
6638   pr "\n";
6639   pr "#include <stdio.h>\n";
6640   pr "#include <stdlib.h>\n";
6641   pr "#include <string.h>\n";
6642   pr "#include <inttypes.h>\n";
6643   pr "#include <rpc/types.h>\n";
6644   pr "#include <rpc/xdr.h>\n";
6645   pr "\n";
6646   pr "#include \"daemon.h\"\n";
6647   pr "#include \"c-ctype.h\"\n";
6648   pr "#include \"../src/guestfs_protocol.h\"\n";
6649   pr "#include \"actions.h\"\n";
6650   pr "\n";
6651
6652   List.iter (
6653     fun (name, style, _, _, _, _, _) ->
6654       (* Generate server-side stubs. *)
6655       pr "static void %s_stub (XDR *xdr_in)\n" name;
6656       pr "{\n";
6657       let error_code =
6658         match fst style with
6659         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6660         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6661         | RBool _ -> pr "  int r;\n"; "-1"
6662         | RConstString _ | RConstOptString _ ->
6663             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6664         | RString _ -> pr "  char *r;\n"; "NULL"
6665         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6666         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6667         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6668         | RBufferOut _ ->
6669             pr "  size_t size = 1;\n";
6670             pr "  char *r;\n";
6671             "NULL" in
6672
6673       (match snd style with
6674        | [] -> ()
6675        | args ->
6676            pr "  struct guestfs_%s_args args;\n" name;
6677            List.iter (
6678              function
6679              | Device n | Dev_or_Path n
6680              | Pathname n
6681              | String n
6682              | Key n -> ()
6683              | OptString n -> pr "  char *%s;\n" n
6684              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6685              | Bool n -> pr "  int %s;\n" n
6686              | Int n -> pr "  int %s;\n" n
6687              | Int64 n -> pr "  int64_t %s;\n" n
6688              | FileIn _ | FileOut _ -> ()
6689              | BufferIn n ->
6690                  pr "  const char *%s;\n" n;
6691                  pr "  size_t %s_size;\n" n
6692            ) args
6693       );
6694       pr "\n";
6695
6696       let is_filein =
6697         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6698
6699       (match snd style with
6700        | [] -> ()
6701        | args ->
6702            pr "  memset (&args, 0, sizeof args);\n";
6703            pr "\n";
6704            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6705            if is_filein then
6706              pr "    if (cancel_receive () != -2)\n";
6707            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6708            pr "    goto done;\n";
6709            pr "  }\n";
6710            let pr_args n =
6711              pr "  char *%s = args.%s;\n" n n
6712            in
6713            let pr_list_handling_code n =
6714              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6715              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6716              pr "  if (%s == NULL) {\n" n;
6717              if is_filein then
6718                pr "    if (cancel_receive () != -2)\n";
6719              pr "      reply_with_perror (\"realloc\");\n";
6720              pr "    goto done;\n";
6721              pr "  }\n";
6722              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6723              pr "  args.%s.%s_val = %s;\n" n n n;
6724            in
6725            List.iter (
6726              function
6727              | Pathname n ->
6728                  pr_args n;
6729                  pr "  ABS_PATH (%s, %s, goto done);\n"
6730                    n (if is_filein then "cancel_receive ()" else "0");
6731              | Device n ->
6732                  pr_args n;
6733                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6734                    n (if is_filein then "cancel_receive ()" else "0");
6735              | Dev_or_Path n ->
6736                  pr_args n;
6737                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6738                    n (if is_filein then "cancel_receive ()" else "0");
6739              | String n | Key n -> pr_args n
6740              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6741              | StringList n ->
6742                  pr_list_handling_code n;
6743              | DeviceList n ->
6744                  pr_list_handling_code n;
6745                  pr "  /* Ensure that each is a device,\n";
6746                  pr "   * and perform device name translation.\n";
6747                  pr "   */\n";
6748                  pr "  {\n";
6749                  pr "    size_t i;\n";
6750                  pr "    for (i = 0; %s[i] != NULL; ++i)\n" n;
6751                  pr "      RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6752                    (if is_filein then "cancel_receive ()" else "0");
6753                  pr "  }\n";
6754              | Bool n -> pr "  %s = args.%s;\n" n n
6755              | Int n -> pr "  %s = args.%s;\n" n n
6756              | Int64 n -> pr "  %s = args.%s;\n" n n
6757              | FileIn _ | FileOut _ -> ()
6758              | BufferIn n ->
6759                  pr "  %s = args.%s.%s_val;\n" n n n;
6760                  pr "  %s_size = args.%s.%s_len;\n" n n n
6761            ) args;
6762            pr "\n"
6763       );
6764
6765       (* this is used at least for do_equal *)
6766       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6767         (* Emit NEED_ROOT just once, even when there are two or
6768            more Pathname args *)
6769         pr "  NEED_ROOT (%s, goto done);\n"
6770           (if is_filein then "cancel_receive ()" else "0");
6771       );
6772
6773       (* Don't want to call the impl with any FileIn or FileOut
6774        * parameters, since these go "outside" the RPC protocol.
6775        *)
6776       let args' =
6777         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6778           (snd style) in
6779       pr "  r = do_%s " name;
6780       generate_c_call_args (fst style, args');
6781       pr ";\n";
6782
6783       (match fst style with
6784        | RErr | RInt _ | RInt64 _ | RBool _
6785        | RConstString _ | RConstOptString _
6786        | RString _ | RStringList _ | RHashtable _
6787        | RStruct (_, _) | RStructList (_, _) ->
6788            pr "  if (r == %s)\n" error_code;
6789            pr "    /* do_%s has already called reply_with_error */\n" name;
6790            pr "    goto done;\n";
6791            pr "\n"
6792        | RBufferOut _ ->
6793            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6794            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6795            pr "   */\n";
6796            pr "  if (size == 1 && r == %s)\n" error_code;
6797            pr "    /* do_%s has already called reply_with_error */\n" name;
6798            pr "    goto done;\n";
6799            pr "\n"
6800       );
6801
6802       (* If there are any FileOut parameters, then the impl must
6803        * send its own reply.
6804        *)
6805       let no_reply =
6806         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6807       if no_reply then
6808         pr "  /* do_%s has already sent a reply */\n" name
6809       else (
6810         match fst style with
6811         | RErr -> pr "  reply (NULL, NULL);\n"
6812         | RInt n | RInt64 n | RBool n ->
6813             pr "  struct guestfs_%s_ret ret;\n" name;
6814             pr "  ret.%s = r;\n" n;
6815             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6816               name
6817         | RConstString _ | RConstOptString _ ->
6818             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6819         | RString n ->
6820             pr "  struct guestfs_%s_ret ret;\n" name;
6821             pr "  ret.%s = r;\n" n;
6822             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6823               name;
6824             pr "  free (r);\n"
6825         | RStringList n | RHashtable n ->
6826             pr "  struct guestfs_%s_ret ret;\n" name;
6827             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6828             pr "  ret.%s.%s_val = r;\n" n n;
6829             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6830               name;
6831             pr "  free_strings (r);\n"
6832         | RStruct (n, _) ->
6833             pr "  struct guestfs_%s_ret ret;\n" name;
6834             pr "  ret.%s = *r;\n" n;
6835             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6836               name;
6837             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6838               name
6839         | RStructList (n, _) ->
6840             pr "  struct guestfs_%s_ret ret;\n" name;
6841             pr "  ret.%s = *r;\n" n;
6842             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6843               name;
6844             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6845               name
6846         | RBufferOut n ->
6847             pr "  struct guestfs_%s_ret ret;\n" name;
6848             pr "  ret.%s.%s_val = r;\n" n n;
6849             pr "  ret.%s.%s_len = size;\n" n n;
6850             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6851               name;
6852             pr "  free (r);\n"
6853       );
6854
6855       (* Free the args. *)
6856       pr "done:\n";
6857       (match snd style with
6858        | [] -> ()
6859        | _ ->
6860            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6861              name
6862       );
6863       pr "  return;\n";
6864       pr "}\n\n";
6865   ) daemon_functions;
6866
6867   (* Dispatch function. *)
6868   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6869   pr "{\n";
6870   pr "  switch (proc_nr) {\n";
6871
6872   List.iter (
6873     fun (name, style, _, _, _, _, _) ->
6874       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6875       pr "      %s_stub (xdr_in);\n" name;
6876       pr "      break;\n"
6877   ) daemon_functions;
6878
6879   pr "    default:\n";
6880   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";
6881   pr "  }\n";
6882   pr "}\n";
6883   pr "\n";
6884
6885   (* LVM columns and tokenization functions. *)
6886   (* XXX This generates crap code.  We should rethink how we
6887    * do this parsing.
6888    *)
6889   List.iter (
6890     function
6891     | typ, cols ->
6892         pr "static const char *lvm_%s_cols = \"%s\";\n"
6893           typ (String.concat "," (List.map fst cols));
6894         pr "\n";
6895
6896         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6897         pr "{\n";
6898         pr "  char *tok, *p, *next;\n";
6899         pr "  size_t i, j;\n";
6900         pr "\n";
6901         (*
6902           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6903           pr "\n";
6904         *)
6905         pr "  if (!str) {\n";
6906         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6907         pr "    return -1;\n";
6908         pr "  }\n";
6909         pr "  if (!*str || c_isspace (*str)) {\n";
6910         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6911         pr "    return -1;\n";
6912         pr "  }\n";
6913         pr "  tok = str;\n";
6914         List.iter (
6915           fun (name, coltype) ->
6916             pr "  if (!tok) {\n";
6917             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6918             pr "    return -1;\n";
6919             pr "  }\n";
6920             pr "  p = strchrnul (tok, ',');\n";
6921             pr "  if (*p) next = p+1; else next = NULL;\n";
6922             pr "  *p = '\\0';\n";
6923             (match coltype with
6924              | FString ->
6925                  pr "  r->%s = strdup (tok);\n" name;
6926                  pr "  if (r->%s == NULL) {\n" name;
6927                  pr "    perror (\"strdup\");\n";
6928                  pr "    return -1;\n";
6929                  pr "  }\n"
6930              | FUUID ->
6931                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6932                  pr "    if (tok[j] == '\\0') {\n";
6933                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6934                  pr "      return -1;\n";
6935                  pr "    } else if (tok[j] != '-')\n";
6936                  pr "      r->%s[i++] = tok[j];\n" name;
6937                  pr "  }\n";
6938              | FBytes ->
6939                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6940                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6941                  pr "    return -1;\n";
6942                  pr "  }\n";
6943              | FInt64 ->
6944                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6945                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6946                  pr "    return -1;\n";
6947                  pr "  }\n";
6948              | FOptPercent ->
6949                  pr "  if (tok[0] == '\\0')\n";
6950                  pr "    r->%s = -1;\n" name;
6951                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6952                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6953                  pr "    return -1;\n";
6954                  pr "  }\n";
6955              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6956                  assert false (* can never be an LVM column *)
6957             );
6958             pr "  tok = next;\n";
6959         ) cols;
6960
6961         pr "  if (tok != NULL) {\n";
6962         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6963         pr "    return -1;\n";
6964         pr "  }\n";
6965         pr "  return 0;\n";
6966         pr "}\n";
6967         pr "\n";
6968
6969         pr "guestfs_int_lvm_%s_list *\n" typ;
6970         pr "parse_command_line_%ss (void)\n" typ;
6971         pr "{\n";
6972         pr "  char *out, *err;\n";
6973         pr "  char *p, *pend;\n";
6974         pr "  int r, i;\n";
6975         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6976         pr "  void *newp;\n";
6977         pr "\n";
6978         pr "  ret = malloc (sizeof *ret);\n";
6979         pr "  if (!ret) {\n";
6980         pr "    reply_with_perror (\"malloc\");\n";
6981         pr "    return NULL;\n";
6982         pr "  }\n";
6983         pr "\n";
6984         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6985         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6986         pr "\n";
6987         pr "  r = command (&out, &err,\n";
6988         pr "           \"lvm\", \"%ss\",\n" typ;
6989         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6990         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6991         pr "  if (r == -1) {\n";
6992         pr "    reply_with_error (\"%%s\", err);\n";
6993         pr "    free (out);\n";
6994         pr "    free (err);\n";
6995         pr "    free (ret);\n";
6996         pr "    return NULL;\n";
6997         pr "  }\n";
6998         pr "\n";
6999         pr "  free (err);\n";
7000         pr "\n";
7001         pr "  /* Tokenize each line of the output. */\n";
7002         pr "  p = out;\n";
7003         pr "  i = 0;\n";
7004         pr "  while (p) {\n";
7005         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
7006         pr "    if (pend) {\n";
7007         pr "      *pend = '\\0';\n";
7008         pr "      pend++;\n";
7009         pr "    }\n";
7010         pr "\n";
7011         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
7012         pr "      p++;\n";
7013         pr "\n";
7014         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
7015         pr "      p = pend;\n";
7016         pr "      continue;\n";
7017         pr "    }\n";
7018         pr "\n";
7019         pr "    /* Allocate some space to store this next entry. */\n";
7020         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
7021         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
7022         pr "    if (newp == NULL) {\n";
7023         pr "      reply_with_perror (\"realloc\");\n";
7024         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
7025         pr "      free (ret);\n";
7026         pr "      free (out);\n";
7027         pr "      return NULL;\n";
7028         pr "    }\n";
7029         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
7030         pr "\n";
7031         pr "    /* Tokenize the next entry. */\n";
7032         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
7033         pr "    if (r == -1) {\n";
7034         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
7035         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
7036         pr "      free (ret);\n";
7037         pr "      free (out);\n";
7038         pr "      return NULL;\n";
7039         pr "    }\n";
7040         pr "\n";
7041         pr "    ++i;\n";
7042         pr "    p = pend;\n";
7043         pr "  }\n";
7044         pr "\n";
7045         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
7046         pr "\n";
7047         pr "  free (out);\n";
7048         pr "  return ret;\n";
7049         pr "}\n"
7050
7051   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
7052
7053 (* Generate a list of function names, for debugging in the daemon.. *)
7054 and generate_daemon_names () =
7055   generate_header CStyle GPLv2plus;
7056
7057   pr "#include <config.h>\n";
7058   pr "\n";
7059   pr "#include \"daemon.h\"\n";
7060   pr "\n";
7061
7062   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
7063   pr "const char *function_names[] = {\n";
7064   List.iter (
7065     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
7066   ) daemon_functions;
7067   pr "};\n";
7068
7069 (* Generate the optional groups for the daemon to implement
7070  * guestfs_available.
7071  *)
7072 and generate_daemon_optgroups_c () =
7073   generate_header CStyle GPLv2plus;
7074
7075   pr "#include <config.h>\n";
7076   pr "\n";
7077   pr "#include \"daemon.h\"\n";
7078   pr "#include \"optgroups.h\"\n";
7079   pr "\n";
7080
7081   pr "struct optgroup optgroups[] = {\n";
7082   List.iter (
7083     fun (group, _) ->
7084       pr "  { \"%s\", optgroup_%s_available },\n" group group
7085   ) optgroups;
7086   pr "  { NULL, NULL }\n";
7087   pr "};\n"
7088
7089 and generate_daemon_optgroups_h () =
7090   generate_header CStyle GPLv2plus;
7091
7092   List.iter (
7093     fun (group, _) ->
7094       pr "extern int optgroup_%s_available (void);\n" group
7095   ) optgroups
7096
7097 (* Generate the tests. *)
7098 and generate_tests () =
7099   generate_header CStyle GPLv2plus;
7100
7101   pr "\
7102 #include <stdio.h>
7103 #include <stdlib.h>
7104 #include <string.h>
7105 #include <unistd.h>
7106 #include <sys/types.h>
7107 #include <fcntl.h>
7108
7109 #include \"guestfs.h\"
7110 #include \"guestfs-internal.h\"
7111
7112 static guestfs_h *g;
7113 static int suppress_error = 0;
7114
7115 static void print_error (guestfs_h *g, void *data, const char *msg)
7116 {
7117   if (!suppress_error)
7118     fprintf (stderr, \"%%s\\n\", msg);
7119 }
7120
7121 /* FIXME: nearly identical code appears in fish.c */
7122 static void print_strings (char *const *argv)
7123 {
7124   size_t argc;
7125
7126   for (argc = 0; argv[argc] != NULL; ++argc)
7127     printf (\"\\t%%s\\n\", argv[argc]);
7128 }
7129
7130 /*
7131 static void print_table (char const *const *argv)
7132 {
7133   size_t i;
7134
7135   for (i = 0; argv[i] != NULL; i += 2)
7136     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
7137 }
7138 */
7139
7140 static int
7141 is_available (const char *group)
7142 {
7143   const char *groups[] = { group, NULL };
7144   int r;
7145
7146   suppress_error = 1;
7147   r = guestfs_available (g, (char **) groups);
7148   suppress_error = 0;
7149
7150   return r == 0;
7151 }
7152
7153 static void
7154 incr (guestfs_h *g, void *iv)
7155 {
7156   int *i = (int *) iv;
7157   (*i)++;
7158 }
7159
7160 ";
7161
7162   (* Generate a list of commands which are not tested anywhere. *)
7163   pr "static void no_test_warnings (void)\n";
7164   pr "{\n";
7165
7166   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
7167   List.iter (
7168     fun (_, _, _, _, tests, _, _) ->
7169       let tests = filter_map (
7170         function
7171         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
7172         | (_, Disabled, _) -> None
7173       ) tests in
7174       let seq = List.concat (List.map seq_of_test tests) in
7175       let cmds_tested = List.map List.hd seq in
7176       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
7177   ) all_functions;
7178
7179   List.iter (
7180     fun (name, _, _, _, _, _, _) ->
7181       if not (Hashtbl.mem hash name) then
7182         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
7183   ) all_functions;
7184
7185   pr "}\n";
7186   pr "\n";
7187
7188   (* Generate the actual tests.  Note that we generate the tests
7189    * in reverse order, deliberately, so that (in general) the
7190    * newest tests run first.  This makes it quicker and easier to
7191    * debug them.
7192    *)
7193   let test_names =
7194     List.map (
7195       fun (name, _, _, flags, tests, _, _) ->
7196         mapi (generate_one_test name flags) tests
7197     ) (List.rev all_functions) in
7198   let test_names = List.concat test_names in
7199   let nr_tests = List.length test_names in
7200
7201   pr "\
7202 int main (int argc, char *argv[])
7203 {
7204   char c = 0;
7205   unsigned long int n_failed = 0;
7206   const char *filename;
7207   int fd;
7208   int nr_tests, test_num = 0;
7209
7210   setbuf (stdout, NULL);
7211
7212   no_test_warnings ();
7213
7214   g = guestfs_create ();
7215   if (g == NULL) {
7216     printf (\"guestfs_create FAILED\\n\");
7217     exit (EXIT_FAILURE);
7218   }
7219
7220   guestfs_set_error_handler (g, print_error, NULL);
7221
7222   guestfs_set_path (g, \"../appliance\");
7223
7224   filename = \"test1.img\";
7225   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7226   if (fd == -1) {
7227     perror (filename);
7228     exit (EXIT_FAILURE);
7229   }
7230   if (lseek (fd, %d, SEEK_SET) == -1) {
7231     perror (\"lseek\");
7232     close (fd);
7233     unlink (filename);
7234     exit (EXIT_FAILURE);
7235   }
7236   if (write (fd, &c, 1) == -1) {
7237     perror (\"write\");
7238     close (fd);
7239     unlink (filename);
7240     exit (EXIT_FAILURE);
7241   }
7242   if (close (fd) == -1) {
7243     perror (filename);
7244     unlink (filename);
7245     exit (EXIT_FAILURE);
7246   }
7247   if (guestfs_add_drive (g, filename) == -1) {
7248     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7249     exit (EXIT_FAILURE);
7250   }
7251
7252   filename = \"test2.img\";
7253   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7254   if (fd == -1) {
7255     perror (filename);
7256     exit (EXIT_FAILURE);
7257   }
7258   if (lseek (fd, %d, SEEK_SET) == -1) {
7259     perror (\"lseek\");
7260     close (fd);
7261     unlink (filename);
7262     exit (EXIT_FAILURE);
7263   }
7264   if (write (fd, &c, 1) == -1) {
7265     perror (\"write\");
7266     close (fd);
7267     unlink (filename);
7268     exit (EXIT_FAILURE);
7269   }
7270   if (close (fd) == -1) {
7271     perror (filename);
7272     unlink (filename);
7273     exit (EXIT_FAILURE);
7274   }
7275   if (guestfs_add_drive (g, filename) == -1) {
7276     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7277     exit (EXIT_FAILURE);
7278   }
7279
7280   filename = \"test3.img\";
7281   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7282   if (fd == -1) {
7283     perror (filename);
7284     exit (EXIT_FAILURE);
7285   }
7286   if (lseek (fd, %d, SEEK_SET) == -1) {
7287     perror (\"lseek\");
7288     close (fd);
7289     unlink (filename);
7290     exit (EXIT_FAILURE);
7291   }
7292   if (write (fd, &c, 1) == -1) {
7293     perror (\"write\");
7294     close (fd);
7295     unlink (filename);
7296     exit (EXIT_FAILURE);
7297   }
7298   if (close (fd) == -1) {
7299     perror (filename);
7300     unlink (filename);
7301     exit (EXIT_FAILURE);
7302   }
7303   if (guestfs_add_drive (g, filename) == -1) {
7304     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7305     exit (EXIT_FAILURE);
7306   }
7307
7308   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7309     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7310     exit (EXIT_FAILURE);
7311   }
7312
7313   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7314   alarm (600);
7315
7316   if (guestfs_launch (g) == -1) {
7317     printf (\"guestfs_launch FAILED\\n\");
7318     exit (EXIT_FAILURE);
7319   }
7320
7321   /* Cancel previous alarm. */
7322   alarm (0);
7323
7324   nr_tests = %d;
7325
7326 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7327
7328   iteri (
7329     fun i test_name ->
7330       pr "  test_num++;\n";
7331       pr "  if (guestfs_get_verbose (g))\n";
7332       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7333       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7334       pr "  if (%s () == -1) {\n" test_name;
7335       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7336       pr "    n_failed++;\n";
7337       pr "  }\n";
7338   ) test_names;
7339   pr "\n";
7340
7341   pr "  /* Check close callback is called. */
7342   int close_sentinel = 1;
7343   guestfs_set_close_callback (g, incr, &close_sentinel);
7344
7345   guestfs_close (g);
7346
7347   if (close_sentinel != 2) {
7348     fprintf (stderr, \"close callback was not called\\n\");
7349     exit (EXIT_FAILURE);
7350   }
7351
7352   unlink (\"test1.img\");
7353   unlink (\"test2.img\");
7354   unlink (\"test3.img\");
7355
7356 ";
7357
7358   pr "  if (n_failed > 0) {\n";
7359   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7360   pr "    exit (EXIT_FAILURE);\n";
7361   pr "  }\n";
7362   pr "\n";
7363
7364   pr "  exit (EXIT_SUCCESS);\n";
7365   pr "}\n"
7366
7367 and generate_one_test name flags i (init, prereq, test) =
7368   let test_name = sprintf "test_%s_%d" name i in
7369
7370   pr "\
7371 static int %s_skip (void)
7372 {
7373   const char *str;
7374
7375   str = getenv (\"TEST_ONLY\");
7376   if (str)
7377     return strstr (str, \"%s\") == NULL;
7378   str = getenv (\"SKIP_%s\");
7379   if (str && STREQ (str, \"1\")) return 1;
7380   str = getenv (\"SKIP_TEST_%s\");
7381   if (str && STREQ (str, \"1\")) return 1;
7382   return 0;
7383 }
7384
7385 " test_name name (String.uppercase test_name) (String.uppercase name);
7386
7387   (match prereq with
7388    | Disabled | Always | IfAvailable _ -> ()
7389    | If code | Unless code ->
7390        pr "static int %s_prereq (void)\n" test_name;
7391        pr "{\n";
7392        pr "  %s\n" code;
7393        pr "}\n";
7394        pr "\n";
7395   );
7396
7397   pr "\
7398 static int %s (void)
7399 {
7400   if (%s_skip ()) {
7401     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7402     return 0;
7403   }
7404
7405 " test_name test_name test_name;
7406
7407   (* Optional functions should only be tested if the relevant
7408    * support is available in the daemon.
7409    *)
7410   List.iter (
7411     function
7412     | Optional group ->
7413         pr "  if (!is_available (\"%s\")) {\n" group;
7414         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7415         pr "    return 0;\n";
7416         pr "  }\n";
7417     | _ -> ()
7418   ) flags;
7419
7420   (match prereq with
7421    | Disabled ->
7422        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7423    | If _ ->
7424        pr "  if (! %s_prereq ()) {\n" test_name;
7425        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7426        pr "    return 0;\n";
7427        pr "  }\n";
7428        pr "\n";
7429        generate_one_test_body name i test_name init test;
7430    | Unless _ ->
7431        pr "  if (%s_prereq ()) {\n" test_name;
7432        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7433        pr "    return 0;\n";
7434        pr "  }\n";
7435        pr "\n";
7436        generate_one_test_body name i test_name init test;
7437    | IfAvailable group ->
7438        pr "  if (!is_available (\"%s\")) {\n" group;
7439        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7440        pr "    return 0;\n";
7441        pr "  }\n";
7442        pr "\n";
7443        generate_one_test_body name i test_name init test;
7444    | Always ->
7445        generate_one_test_body name i test_name init test
7446   );
7447
7448   pr "  return 0;\n";
7449   pr "}\n";
7450   pr "\n";
7451   test_name
7452
7453 and generate_one_test_body name i test_name init test =
7454   (match init with
7455    | InitNone (* XXX at some point, InitNone and InitEmpty became
7456                * folded together as the same thing.  Really we should
7457                * make InitNone do nothing at all, but the tests may
7458                * need to be checked to make sure this is OK.
7459                *)
7460    | InitEmpty ->
7461        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7462        List.iter (generate_test_command_call test_name)
7463          [["blockdev_setrw"; "/dev/sda"];
7464           ["umount_all"];
7465           ["lvm_remove_all"]]
7466    | InitPartition ->
7467        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7468        List.iter (generate_test_command_call test_name)
7469          [["blockdev_setrw"; "/dev/sda"];
7470           ["umount_all"];
7471           ["lvm_remove_all"];
7472           ["part_disk"; "/dev/sda"; "mbr"]]
7473    | InitBasicFS ->
7474        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7475        List.iter (generate_test_command_call test_name)
7476          [["blockdev_setrw"; "/dev/sda"];
7477           ["umount_all"];
7478           ["lvm_remove_all"];
7479           ["part_disk"; "/dev/sda"; "mbr"];
7480           ["mkfs"; "ext2"; "/dev/sda1"];
7481           ["mount_options"; ""; "/dev/sda1"; "/"]]
7482    | InitBasicFSonLVM ->
7483        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7484          test_name;
7485        List.iter (generate_test_command_call test_name)
7486          [["blockdev_setrw"; "/dev/sda"];
7487           ["umount_all"];
7488           ["lvm_remove_all"];
7489           ["part_disk"; "/dev/sda"; "mbr"];
7490           ["pvcreate"; "/dev/sda1"];
7491           ["vgcreate"; "VG"; "/dev/sda1"];
7492           ["lvcreate"; "LV"; "VG"; "8"];
7493           ["mkfs"; "ext2"; "/dev/VG/LV"];
7494           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7495    | InitISOFS ->
7496        pr "  /* InitISOFS for %s */\n" test_name;
7497        List.iter (generate_test_command_call test_name)
7498          [["blockdev_setrw"; "/dev/sda"];
7499           ["umount_all"];
7500           ["lvm_remove_all"];
7501           ["mount_ro"; "/dev/sdd"; "/"]]
7502   );
7503
7504   let get_seq_last = function
7505     | [] ->
7506         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7507           test_name
7508     | seq ->
7509         let seq = List.rev seq in
7510         List.rev (List.tl seq), List.hd seq
7511   in
7512
7513   match test with
7514   | TestRun seq ->
7515       pr "  /* TestRun for %s (%d) */\n" name i;
7516       List.iter (generate_test_command_call test_name) seq
7517   | TestOutput (seq, expected) ->
7518       pr "  /* TestOutput for %s (%d) */\n" name i;
7519       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7520       let seq, last = get_seq_last seq in
7521       let test () =
7522         pr "    if (STRNEQ (r, expected)) {\n";
7523         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7524         pr "      return -1;\n";
7525         pr "    }\n"
7526       in
7527       List.iter (generate_test_command_call test_name) seq;
7528       generate_test_command_call ~test test_name last
7529   | TestOutputList (seq, expected) ->
7530       pr "  /* TestOutputList for %s (%d) */\n" name i;
7531       let seq, last = get_seq_last seq in
7532       let test () =
7533         iteri (
7534           fun i str ->
7535             pr "    if (!r[%d]) {\n" i;
7536             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7537             pr "      print_strings (r);\n";
7538             pr "      return -1;\n";
7539             pr "    }\n";
7540             pr "    {\n";
7541             pr "      const char *expected = \"%s\";\n" (c_quote str);
7542             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7543             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7544             pr "        return -1;\n";
7545             pr "      }\n";
7546             pr "    }\n"
7547         ) expected;
7548         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7549         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7550           test_name;
7551         pr "      print_strings (r);\n";
7552         pr "      return -1;\n";
7553         pr "    }\n"
7554       in
7555       List.iter (generate_test_command_call test_name) seq;
7556       generate_test_command_call ~test test_name last
7557   | TestOutputListOfDevices (seq, expected) ->
7558       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7559       let seq, last = get_seq_last seq in
7560       let test () =
7561         iteri (
7562           fun i str ->
7563             pr "    if (!r[%d]) {\n" i;
7564             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7565             pr "      print_strings (r);\n";
7566             pr "      return -1;\n";
7567             pr "    }\n";
7568             pr "    {\n";
7569             pr "      const char *expected = \"%s\";\n" (c_quote str);
7570             pr "      r[%d][5] = 's';\n" i;
7571             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7572             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7573             pr "        return -1;\n";
7574             pr "      }\n";
7575             pr "    }\n"
7576         ) expected;
7577         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7578         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7579           test_name;
7580         pr "      print_strings (r);\n";
7581         pr "      return -1;\n";
7582         pr "    }\n"
7583       in
7584       List.iter (generate_test_command_call test_name) seq;
7585       generate_test_command_call ~test test_name last
7586   | TestOutputInt (seq, expected) ->
7587       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7588       let seq, last = get_seq_last seq in
7589       let test () =
7590         pr "    if (r != %d) {\n" expected;
7591         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7592           test_name expected;
7593         pr "               (int) r);\n";
7594         pr "      return -1;\n";
7595         pr "    }\n"
7596       in
7597       List.iter (generate_test_command_call test_name) seq;
7598       generate_test_command_call ~test test_name last
7599   | TestOutputIntOp (seq, op, expected) ->
7600       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7601       let seq, last = get_seq_last seq in
7602       let test () =
7603         pr "    if (! (r %s %d)) {\n" op expected;
7604         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7605           test_name op expected;
7606         pr "               (int) r);\n";
7607         pr "      return -1;\n";
7608         pr "    }\n"
7609       in
7610       List.iter (generate_test_command_call test_name) seq;
7611       generate_test_command_call ~test test_name last
7612   | TestOutputTrue seq ->
7613       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7614       let seq, last = get_seq_last seq in
7615       let test () =
7616         pr "    if (!r) {\n";
7617         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7618           test_name;
7619         pr "      return -1;\n";
7620         pr "    }\n"
7621       in
7622       List.iter (generate_test_command_call test_name) seq;
7623       generate_test_command_call ~test test_name last
7624   | TestOutputFalse seq ->
7625       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7626       let seq, last = get_seq_last seq in
7627       let test () =
7628         pr "    if (r) {\n";
7629         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7630           test_name;
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   | TestOutputLength (seq, expected) ->
7637       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7638       let seq, last = get_seq_last seq in
7639       let test () =
7640         pr "    int j;\n";
7641         pr "    for (j = 0; j < %d; ++j)\n" expected;
7642         pr "      if (r[j] == NULL) {\n";
7643         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7644           test_name;
7645         pr "        print_strings (r);\n";
7646         pr "        return -1;\n";
7647         pr "      }\n";
7648         pr "    if (r[j] != NULL) {\n";
7649         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7650           test_name;
7651         pr "      print_strings (r);\n";
7652         pr "      return -1;\n";
7653         pr "    }\n"
7654       in
7655       List.iter (generate_test_command_call test_name) seq;
7656       generate_test_command_call ~test test_name last
7657   | TestOutputBuffer (seq, expected) ->
7658       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7659       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7660       let seq, last = get_seq_last seq in
7661       let len = String.length expected in
7662       let test () =
7663         pr "    if (size != %d) {\n" len;
7664         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7665         pr "      return -1;\n";
7666         pr "    }\n";
7667         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7668         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7669         pr "      return -1;\n";
7670         pr "    }\n"
7671       in
7672       List.iter (generate_test_command_call test_name) seq;
7673       generate_test_command_call ~test test_name last
7674   | TestOutputStruct (seq, checks) ->
7675       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7676       let seq, last = get_seq_last seq in
7677       let test () =
7678         List.iter (
7679           function
7680           | CompareWithInt (field, expected) ->
7681               pr "    if (r->%s != %d) {\n" field expected;
7682               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7683                 test_name field expected;
7684               pr "               (int) r->%s);\n" field;
7685               pr "      return -1;\n";
7686               pr "    }\n"
7687           | CompareWithIntOp (field, op, expected) ->
7688               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7689               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7690                 test_name field op expected;
7691               pr "               (int) r->%s);\n" field;
7692               pr "      return -1;\n";
7693               pr "    }\n"
7694           | CompareWithString (field, expected) ->
7695               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7696               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7697                 test_name field expected;
7698               pr "               r->%s);\n" field;
7699               pr "      return -1;\n";
7700               pr "    }\n"
7701           | CompareFieldsIntEq (field1, field2) ->
7702               pr "    if (r->%s != r->%s) {\n" field1 field2;
7703               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7704                 test_name field1 field2;
7705               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7706               pr "      return -1;\n";
7707               pr "    }\n"
7708           | CompareFieldsStrEq (field1, field2) ->
7709               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7710               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7711                 test_name field1 field2;
7712               pr "               r->%s, r->%s);\n" field1 field2;
7713               pr "      return -1;\n";
7714               pr "    }\n"
7715         ) checks
7716       in
7717       List.iter (generate_test_command_call test_name) seq;
7718       generate_test_command_call ~test test_name last
7719   | TestLastFail seq ->
7720       pr "  /* TestLastFail for %s (%d) */\n" name i;
7721       let seq, last = get_seq_last seq in
7722       List.iter (generate_test_command_call test_name) seq;
7723       generate_test_command_call test_name ~expect_error:true last
7724
7725 (* Generate the code to run a command, leaving the result in 'r'.
7726  * If you expect to get an error then you should set expect_error:true.
7727  *)
7728 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7729   match cmd with
7730   | [] -> assert false
7731   | name :: args ->
7732       (* Look up the command to find out what args/ret it has. *)
7733       let style =
7734         try
7735           let _, style, _, _, _, _, _ =
7736             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7737           style
7738         with Not_found ->
7739           failwithf "%s: in test, command %s was not found" test_name name in
7740
7741       if List.length (snd style) <> List.length args then
7742         failwithf "%s: in test, wrong number of args given to %s"
7743           test_name name;
7744
7745       pr "  {\n";
7746
7747       List.iter (
7748         function
7749         | OptString n, "NULL" -> ()
7750         | Pathname n, arg
7751         | Device n, arg
7752         | Dev_or_Path n, arg
7753         | String n, arg
7754         | OptString n, arg
7755         | Key n, arg ->
7756             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7757         | BufferIn n, arg ->
7758             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7759             pr "    size_t %s_size = %d;\n" n (String.length arg)
7760         | Int _, _
7761         | Int64 _, _
7762         | Bool _, _
7763         | FileIn _, _ | FileOut _, _ -> ()
7764         | StringList n, "" | DeviceList n, "" ->
7765             pr "    const char *const %s[1] = { NULL };\n" n
7766         | StringList n, arg | DeviceList n, arg ->
7767             let strs = string_split " " arg in
7768             iteri (
7769               fun i str ->
7770                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7771             ) strs;
7772             pr "    const char *const %s[] = {\n" n;
7773             iteri (
7774               fun i _ -> pr "      %s_%d,\n" n i
7775             ) strs;
7776             pr "      NULL\n";
7777             pr "    };\n";
7778       ) (List.combine (snd style) args);
7779
7780       let error_code =
7781         match fst style with
7782         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7783         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7784         | RConstString _ | RConstOptString _ ->
7785             pr "    const char *r;\n"; "NULL"
7786         | RString _ -> pr "    char *r;\n"; "NULL"
7787         | RStringList _ | RHashtable _ ->
7788             pr "    char **r;\n";
7789             pr "    size_t i;\n";
7790             "NULL"
7791         | RStruct (_, typ) ->
7792             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7793         | RStructList (_, typ) ->
7794             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7795         | RBufferOut _ ->
7796             pr "    char *r;\n";
7797             pr "    size_t size;\n";
7798             "NULL" in
7799
7800       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7801       pr "    r = guestfs_%s (g" name;
7802
7803       (* Generate the parameters. *)
7804       List.iter (
7805         function
7806         | OptString _, "NULL" -> pr ", NULL"
7807         | Pathname n, _
7808         | Device n, _ | Dev_or_Path n, _
7809         | String n, _
7810         | OptString n, _
7811         | Key n, _ ->
7812             pr ", %s" n
7813         | BufferIn n, _ ->
7814             pr ", %s, %s_size" n n
7815         | FileIn _, arg | FileOut _, arg ->
7816             pr ", \"%s\"" (c_quote arg)
7817         | StringList n, _ | DeviceList n, _ ->
7818             pr ", (char **) %s" n
7819         | Int _, arg ->
7820             let i =
7821               try int_of_string arg
7822               with Failure "int_of_string" ->
7823                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7824             pr ", %d" i
7825         | Int64 _, arg ->
7826             let i =
7827               try Int64.of_string arg
7828               with Failure "int_of_string" ->
7829                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7830             pr ", %Ld" i
7831         | Bool _, arg ->
7832             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7833       ) (List.combine (snd style) args);
7834
7835       (match fst style with
7836        | RBufferOut _ -> pr ", &size"
7837        | _ -> ()
7838       );
7839
7840       pr ");\n";
7841
7842       if not expect_error then
7843         pr "    if (r == %s)\n" error_code
7844       else
7845         pr "    if (r != %s)\n" error_code;
7846       pr "      return -1;\n";
7847
7848       (* Insert the test code. *)
7849       (match test with
7850        | None -> ()
7851        | Some f -> f ()
7852       );
7853
7854       (match fst style with
7855        | RErr | RInt _ | RInt64 _ | RBool _
7856        | RConstString _ | RConstOptString _ -> ()
7857        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7858        | RStringList _ | RHashtable _ ->
7859            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7860            pr "      free (r[i]);\n";
7861            pr "    free (r);\n"
7862        | RStruct (_, typ) ->
7863            pr "    guestfs_free_%s (r);\n" typ
7864        | RStructList (_, typ) ->
7865            pr "    guestfs_free_%s_list (r);\n" typ
7866       );
7867
7868       pr "  }\n"
7869
7870 and c_quote str =
7871   let str = replace_str str "\r" "\\r" in
7872   let str = replace_str str "\n" "\\n" in
7873   let str = replace_str str "\t" "\\t" in
7874   let str = replace_str str "\000" "\\0" in
7875   str
7876
7877 (* Generate a lot of different functions for guestfish. *)
7878 and generate_fish_cmds () =
7879   generate_header CStyle GPLv2plus;
7880
7881   let all_functions =
7882     List.filter (
7883       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7884     ) all_functions in
7885   let all_functions_sorted =
7886     List.filter (
7887       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7888     ) all_functions_sorted in
7889
7890   pr "#include <config.h>\n";
7891   pr "\n";
7892   pr "#include <stdio.h>\n";
7893   pr "#include <stdlib.h>\n";
7894   pr "#include <string.h>\n";
7895   pr "#include <inttypes.h>\n";
7896   pr "\n";
7897   pr "#include <guestfs.h>\n";
7898   pr "#include \"c-ctype.h\"\n";
7899   pr "#include \"full-write.h\"\n";
7900   pr "#include \"xstrtol.h\"\n";
7901   pr "#include \"fish.h\"\n";
7902   pr "\n";
7903   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7904   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7905   pr "\n";
7906
7907   (* list_commands function, which implements guestfish -h *)
7908   pr "void list_commands (void)\n";
7909   pr "{\n";
7910   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7911   pr "  list_builtin_commands ();\n";
7912   List.iter (
7913     fun (name, _, _, flags, _, shortdesc, _) ->
7914       let name = replace_char name '_' '-' in
7915       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7916         name shortdesc
7917   ) all_functions_sorted;
7918   pr "  printf (\"    %%s\\n\",";
7919   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7920   pr "}\n";
7921   pr "\n";
7922
7923   (* display_command function, which implements guestfish -h cmd *)
7924   pr "int display_command (const char *cmd)\n";
7925   pr "{\n";
7926   List.iter (
7927     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7928       let name2 = replace_char name '_' '-' in
7929       let alias =
7930         try find_map (function FishAlias n -> Some n | _ -> None) flags
7931         with Not_found -> name in
7932       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7933       let synopsis =
7934         match snd style with
7935         | [] -> name2
7936         | args ->
7937             let args = List.filter (function Key _ -> false | _ -> true) args in
7938             sprintf "%s %s"
7939               name2 (String.concat " " (List.map name_of_argt args)) in
7940
7941       let warnings =
7942         if List.exists (function Key _ -> true | _ -> false) (snd style) then
7943           "\n\nThis command has one or more key or passphrase parameters.
7944 Guestfish will prompt for these separately."
7945         else "" in
7946
7947       let warnings =
7948         warnings ^
7949           if List.mem ProtocolLimitWarning flags then
7950             ("\n\n" ^ protocol_limit_warning)
7951           else "" in
7952
7953       (* For DangerWillRobinson commands, we should probably have
7954        * guestfish prompt before allowing you to use them (especially
7955        * in interactive mode). XXX
7956        *)
7957       let warnings =
7958         warnings ^
7959           if List.mem DangerWillRobinson flags then
7960             ("\n\n" ^ danger_will_robinson)
7961           else "" in
7962
7963       let warnings =
7964         warnings ^
7965           match deprecation_notice flags with
7966           | None -> ""
7967           | Some txt -> "\n\n" ^ txt in
7968
7969       let describe_alias =
7970         if name <> alias then
7971           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7972         else "" in
7973
7974       pr "  if (";
7975       pr "STRCASEEQ (cmd, \"%s\")" name;
7976       if name <> name2 then
7977         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7978       if name <> alias then
7979         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7980       pr ") {\n";
7981       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7982         name2 shortdesc
7983         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7984          "=head1 DESCRIPTION\n\n" ^
7985          longdesc ^ warnings ^ describe_alias);
7986       pr "    return 0;\n";
7987       pr "  }\n";
7988       pr "  else\n"
7989   ) all_functions;
7990   pr "    return display_builtin_command (cmd);\n";
7991   pr "}\n";
7992   pr "\n";
7993
7994   let emit_print_list_function typ =
7995     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7996       typ typ typ;
7997     pr "{\n";
7998     pr "  unsigned int i;\n";
7999     pr "\n";
8000     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
8001     pr "    printf (\"[%%d] = {\\n\", i);\n";
8002     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
8003     pr "    printf (\"}\\n\");\n";
8004     pr "  }\n";
8005     pr "}\n";
8006     pr "\n";
8007   in
8008
8009   (* print_* functions *)
8010   List.iter (
8011     fun (typ, cols) ->
8012       let needs_i =
8013         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
8014
8015       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
8016       pr "{\n";
8017       if needs_i then (
8018         pr "  unsigned int i;\n";
8019         pr "\n"
8020       );
8021       List.iter (
8022         function
8023         | name, FString ->
8024             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
8025         | name, FUUID ->
8026             pr "  printf (\"%%s%s: \", indent);\n" name;
8027             pr "  for (i = 0; i < 32; ++i)\n";
8028             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
8029             pr "  printf (\"\\n\");\n"
8030         | name, FBuffer ->
8031             pr "  printf (\"%%s%s: \", indent);\n" name;
8032             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
8033             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
8034             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
8035             pr "    else\n";
8036             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
8037             pr "  printf (\"\\n\");\n"
8038         | name, (FUInt64|FBytes) ->
8039             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
8040               name typ name
8041         | name, FInt64 ->
8042             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
8043               name typ name
8044         | name, FUInt32 ->
8045             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
8046               name typ name
8047         | name, FInt32 ->
8048             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
8049               name typ name
8050         | name, FChar ->
8051             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
8052               name typ name
8053         | name, FOptPercent ->
8054             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
8055               typ name name typ name;
8056             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
8057       ) cols;
8058       pr "}\n";
8059       pr "\n";
8060   ) structs;
8061
8062   (* Emit a print_TYPE_list function definition only if that function is used. *)
8063   List.iter (
8064     function
8065     | typ, (RStructListOnly | RStructAndList) ->
8066         (* generate the function for typ *)
8067         emit_print_list_function typ
8068     | typ, _ -> () (* empty *)
8069   ) (rstructs_used_by all_functions);
8070
8071   (* Emit a print_TYPE function definition only if that function is used. *)
8072   List.iter (
8073     function
8074     | typ, (RStructOnly | RStructAndList) ->
8075         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
8076         pr "{\n";
8077         pr "  print_%s_indent (%s, \"\");\n" typ typ;
8078         pr "}\n";
8079         pr "\n";
8080     | typ, _ -> () (* empty *)
8081   ) (rstructs_used_by all_functions);
8082
8083   (* run_<action> actions *)
8084   List.iter (
8085     fun (name, style, _, flags, _, _, _) ->
8086       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
8087       pr "{\n";
8088       (match fst style with
8089        | RErr
8090        | RInt _
8091        | RBool _ -> pr "  int r;\n"
8092        | RInt64 _ -> pr "  int64_t r;\n"
8093        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
8094        | RString _ -> pr "  char *r;\n"
8095        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
8096        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
8097        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
8098        | RBufferOut _ ->
8099            pr "  char *r;\n";
8100            pr "  size_t size;\n";
8101       );
8102       List.iter (
8103         function
8104         | Device n
8105         | String n
8106         | OptString n -> pr "  const char *%s;\n" n
8107         | Pathname n
8108         | Dev_or_Path n
8109         | FileIn n
8110         | FileOut n
8111         | Key n -> pr "  char *%s;\n" n
8112         | BufferIn n ->
8113             pr "  const char *%s;\n" n;
8114             pr "  size_t %s_size;\n" n
8115         | StringList n | DeviceList n -> pr "  char **%s;\n" n
8116         | Bool n -> pr "  int %s;\n" n
8117         | Int n -> pr "  int %s;\n" n
8118         | Int64 n -> pr "  int64_t %s;\n" n
8119       ) (snd style);
8120
8121       (* Check and convert parameters. *)
8122       let argc_expected =
8123         let args_no_keys =
8124           List.filter (function Key _ -> false | _ -> true) (snd style) in
8125         List.length args_no_keys in
8126       pr "  if (argc != %d) {\n" argc_expected;
8127       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
8128         argc_expected;
8129       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
8130       pr "    return -1;\n";
8131       pr "  }\n";
8132
8133       let parse_integer fn fntyp rtyp range name =
8134         pr "  {\n";
8135         pr "    strtol_error xerr;\n";
8136         pr "    %s r;\n" fntyp;
8137         pr "\n";
8138         pr "    xerr = %s (argv[i++], NULL, 0, &r, xstrtol_suffixes);\n" fn;
8139         pr "    if (xerr != LONGINT_OK) {\n";
8140         pr "      fprintf (stderr,\n";
8141         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
8142         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
8143         pr "      return -1;\n";
8144         pr "    }\n";
8145         (match range with
8146          | None -> ()
8147          | Some (min, max, comment) ->
8148              pr "    /* %s */\n" comment;
8149              pr "    if (r < %s || r > %s) {\n" min max;
8150              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
8151                name;
8152              pr "      return -1;\n";
8153              pr "    }\n";
8154              pr "    /* The check above should ensure this assignment does not overflow. */\n";
8155         );
8156         pr "    %s = r;\n" name;
8157         pr "  }\n";
8158       in
8159
8160       if snd style <> [] then
8161         pr "  size_t i = 0;\n";
8162
8163       List.iter (
8164         function
8165         | Device name
8166         | String name ->
8167             pr "  %s = argv[i++];\n" name
8168         | Pathname name
8169         | Dev_or_Path name ->
8170             pr "  %s = resolve_win_path (argv[i++]);\n" name;
8171             pr "  if (%s == NULL) return -1;\n" name
8172         | OptString name ->
8173             pr "  %s = STRNEQ (argv[i], \"\") ? argv[i] : NULL;\n" name;
8174             pr "  i++;\n"
8175         | BufferIn name ->
8176             pr "  %s = argv[i];\n" name;
8177             pr "  %s_size = strlen (argv[i]);\n" name;
8178             pr "  i++;\n"
8179         | FileIn name ->
8180             pr "  %s = file_in (argv[i++]);\n" name;
8181             pr "  if (%s == NULL) return -1;\n" name
8182         | FileOut name ->
8183             pr "  %s = file_out (argv[i++]);\n" name;
8184             pr "  if (%s == NULL) return -1;\n" name
8185         | StringList name | DeviceList name ->
8186             pr "  %s = parse_string_list (argv[i++]);\n" name;
8187             pr "  if (%s == NULL) return -1;\n" name
8188         | Key name ->
8189             pr "  %s = read_key (\"%s\");\n" name name;
8190             pr "  if (%s == NULL) return -1;\n" name
8191         | Bool name ->
8192             pr "  %s = is_true (argv[i++]) ? 1 : 0;\n" name
8193         | Int name ->
8194             let range =
8195               let min = "(-(2LL<<30))"
8196               and max = "((2LL<<30)-1)"
8197               and comment =
8198                 "The Int type in the generator is a signed 31 bit int." in
8199               Some (min, max, comment) in
8200             parse_integer "xstrtoll" "long long" "int" range name
8201         | Int64 name ->
8202             parse_integer "xstrtoll" "long long" "int64_t" None name
8203       ) (snd style);
8204
8205       (* Call C API function. *)
8206       pr "  r = guestfs_%s " name;
8207       generate_c_call_args ~handle:"g" style;
8208       pr ";\n";
8209
8210       List.iter (
8211         function
8212         | Device _ | String _
8213         | OptString _ | Bool _
8214         | Int _ | Int64 _
8215         | BufferIn _ -> ()
8216         | Pathname name | Dev_or_Path name | FileOut name
8217         | Key name ->
8218             pr "  free (%s);\n" name
8219         | FileIn name ->
8220             pr "  free_file_in (%s);\n" name
8221         | StringList name | DeviceList name ->
8222             pr "  free_strings (%s);\n" name
8223       ) (snd style);
8224
8225       (* Any output flags? *)
8226       let fish_output =
8227         let flags = filter_map (
8228           function FishOutput flag -> Some flag | _ -> None
8229         ) flags in
8230         match flags with
8231         | [] -> None
8232         | [f] -> Some f
8233         | _ ->
8234             failwithf "%s: more than one FishOutput flag is not allowed" name in
8235
8236       (* Check return value for errors and display command results. *)
8237       (match fst style with
8238        | RErr -> pr "  return r;\n"
8239        | RInt _ ->
8240            pr "  if (r == -1) return -1;\n";
8241            (match fish_output with
8242             | None ->
8243                 pr "  printf (\"%%d\\n\", r);\n";
8244             | Some FishOutputOctal ->
8245                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
8246             | Some FishOutputHexadecimal ->
8247                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8248            pr "  return 0;\n"
8249        | RInt64 _ ->
8250            pr "  if (r == -1) return -1;\n";
8251            (match fish_output with
8252             | None ->
8253                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
8254             | Some FishOutputOctal ->
8255                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
8256             | Some FishOutputHexadecimal ->
8257                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8258            pr "  return 0;\n"
8259        | RBool _ ->
8260            pr "  if (r == -1) return -1;\n";
8261            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
8262            pr "  return 0;\n"
8263        | RConstString _ ->
8264            pr "  if (r == NULL) return -1;\n";
8265            pr "  printf (\"%%s\\n\", r);\n";
8266            pr "  return 0;\n"
8267        | RConstOptString _ ->
8268            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
8269            pr "  return 0;\n"
8270        | RString _ ->
8271            pr "  if (r == NULL) return -1;\n";
8272            pr "  printf (\"%%s\\n\", r);\n";
8273            pr "  free (r);\n";
8274            pr "  return 0;\n"
8275        | RStringList _ ->
8276            pr "  if (r == NULL) return -1;\n";
8277            pr "  print_strings (r);\n";
8278            pr "  free_strings (r);\n";
8279            pr "  return 0;\n"
8280        | RStruct (_, typ) ->
8281            pr "  if (r == NULL) return -1;\n";
8282            pr "  print_%s (r);\n" typ;
8283            pr "  guestfs_free_%s (r);\n" typ;
8284            pr "  return 0;\n"
8285        | RStructList (_, typ) ->
8286            pr "  if (r == NULL) return -1;\n";
8287            pr "  print_%s_list (r);\n" typ;
8288            pr "  guestfs_free_%s_list (r);\n" typ;
8289            pr "  return 0;\n"
8290        | RHashtable _ ->
8291            pr "  if (r == NULL) return -1;\n";
8292            pr "  print_table (r);\n";
8293            pr "  free_strings (r);\n";
8294            pr "  return 0;\n"
8295        | RBufferOut _ ->
8296            pr "  if (r == NULL) return -1;\n";
8297            pr "  if (full_write (1, r, size) != size) {\n";
8298            pr "    perror (\"write\");\n";
8299            pr "    free (r);\n";
8300            pr "    return -1;\n";
8301            pr "  }\n";
8302            pr "  free (r);\n";
8303            pr "  return 0;\n"
8304       );
8305       pr "}\n";
8306       pr "\n"
8307   ) all_functions;
8308
8309   (* run_action function *)
8310   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8311   pr "{\n";
8312   List.iter (
8313     fun (name, _, _, flags, _, _, _) ->
8314       let name2 = replace_char name '_' '-' in
8315       let alias =
8316         try find_map (function FishAlias n -> Some n | _ -> None) flags
8317         with Not_found -> name in
8318       pr "  if (";
8319       pr "STRCASEEQ (cmd, \"%s\")" name;
8320       if name <> name2 then
8321         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8322       if name <> alias then
8323         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8324       pr ")\n";
8325       pr "    return run_%s (cmd, argc, argv);\n" name;
8326       pr "  else\n";
8327   ) all_functions;
8328   pr "    {\n";
8329   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8330   pr "      if (command_num == 1)\n";
8331   pr "        extended_help_message ();\n";
8332   pr "      return -1;\n";
8333   pr "    }\n";
8334   pr "  return 0;\n";
8335   pr "}\n";
8336   pr "\n"
8337
8338 (* Readline completion for guestfish. *)
8339 and generate_fish_completion () =
8340   generate_header CStyle GPLv2plus;
8341
8342   let all_functions =
8343     List.filter (
8344       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8345     ) all_functions in
8346
8347   pr "\
8348 #include <config.h>
8349
8350 #include <stdio.h>
8351 #include <stdlib.h>
8352 #include <string.h>
8353
8354 #ifdef HAVE_LIBREADLINE
8355 #include <readline/readline.h>
8356 #endif
8357
8358 #include \"fish.h\"
8359
8360 #ifdef HAVE_LIBREADLINE
8361
8362 static const char *const commands[] = {
8363   BUILTIN_COMMANDS_FOR_COMPLETION,
8364 ";
8365
8366   (* Get the commands, including the aliases.  They don't need to be
8367    * sorted - the generator() function just does a dumb linear search.
8368    *)
8369   let commands =
8370     List.map (
8371       fun (name, _, _, flags, _, _, _) ->
8372         let name2 = replace_char name '_' '-' in
8373         let alias =
8374           try find_map (function FishAlias n -> Some n | _ -> None) flags
8375           with Not_found -> name in
8376
8377         if name <> alias then [name2; alias] else [name2]
8378     ) all_functions in
8379   let commands = List.flatten commands in
8380
8381   List.iter (pr "  \"%s\",\n") commands;
8382
8383   pr "  NULL
8384 };
8385
8386 static char *
8387 generator (const char *text, int state)
8388 {
8389   static size_t index, len;
8390   const char *name;
8391
8392   if (!state) {
8393     index = 0;
8394     len = strlen (text);
8395   }
8396
8397   rl_attempted_completion_over = 1;
8398
8399   while ((name = commands[index]) != NULL) {
8400     index++;
8401     if (STRCASEEQLEN (name, text, len))
8402       return strdup (name);
8403   }
8404
8405   return NULL;
8406 }
8407
8408 #endif /* HAVE_LIBREADLINE */
8409
8410 #ifdef HAVE_RL_COMPLETION_MATCHES
8411 #define RL_COMPLETION_MATCHES rl_completion_matches
8412 #else
8413 #ifdef HAVE_COMPLETION_MATCHES
8414 #define RL_COMPLETION_MATCHES completion_matches
8415 #endif
8416 #endif /* else just fail if we don't have either symbol */
8417
8418 char **
8419 do_completion (const char *text, int start, int end)
8420 {
8421   char **matches = NULL;
8422
8423 #ifdef HAVE_LIBREADLINE
8424   rl_completion_append_character = ' ';
8425
8426   if (start == 0)
8427     matches = RL_COMPLETION_MATCHES (text, generator);
8428   else if (complete_dest_paths)
8429     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8430 #endif
8431
8432   return matches;
8433 }
8434 ";
8435
8436 (* Generate the POD documentation for guestfish. *)
8437 and generate_fish_actions_pod () =
8438   let all_functions_sorted =
8439     List.filter (
8440       fun (_, _, _, flags, _, _, _) ->
8441         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8442     ) all_functions_sorted in
8443
8444   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8445
8446   List.iter (
8447     fun (name, style, _, flags, _, _, longdesc) ->
8448       let longdesc =
8449         Str.global_substitute rex (
8450           fun s ->
8451             let sub =
8452               try Str.matched_group 1 s
8453               with Not_found ->
8454                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8455             "C<" ^ replace_char sub '_' '-' ^ ">"
8456         ) longdesc in
8457       let name = replace_char name '_' '-' in
8458       let alias =
8459         try find_map (function FishAlias n -> Some n | _ -> None) flags
8460         with Not_found -> name in
8461
8462       pr "=head2 %s" name;
8463       if name <> alias then
8464         pr " | %s" alias;
8465       pr "\n";
8466       pr "\n";
8467       pr " %s" name;
8468       List.iter (
8469         function
8470         | Pathname n | Device n | Dev_or_Path n | String n ->
8471             pr " %s" n
8472         | OptString n -> pr " %s" n
8473         | StringList n | DeviceList n -> pr " '%s ...'" n
8474         | Bool _ -> pr " true|false"
8475         | Int n -> pr " %s" n
8476         | Int64 n -> pr " %s" n
8477         | FileIn n | FileOut n -> pr " (%s|-)" n
8478         | BufferIn n -> pr " %s" n
8479         | Key _ -> () (* keys are entered at a prompt *)
8480       ) (snd style);
8481       pr "\n";
8482       pr "\n";
8483       pr "%s\n\n" longdesc;
8484
8485       if List.exists (function FileIn _ | FileOut _ -> true
8486                       | _ -> false) (snd style) then
8487         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8488
8489       if List.exists (function Key _ -> true | _ -> false) (snd style) then
8490         pr "This command has one or more key or passphrase parameters.
8491 Guestfish will prompt for these separately.\n\n";
8492
8493       if List.mem ProtocolLimitWarning flags then
8494         pr "%s\n\n" protocol_limit_warning;
8495
8496       if List.mem DangerWillRobinson flags then
8497         pr "%s\n\n" danger_will_robinson;
8498
8499       match deprecation_notice flags with
8500       | None -> ()
8501       | Some txt -> pr "%s\n\n" txt
8502   ) all_functions_sorted
8503
8504 (* Generate a C function prototype. *)
8505 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8506     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8507     ?(prefix = "")
8508     ?handle name style =
8509   if extern then pr "extern ";
8510   if static then pr "static ";
8511   (match fst style with
8512    | RErr -> pr "int "
8513    | RInt _ -> pr "int "
8514    | RInt64 _ -> pr "int64_t "
8515    | RBool _ -> pr "int "
8516    | RConstString _ | RConstOptString _ -> pr "const char *"
8517    | RString _ | RBufferOut _ -> pr "char *"
8518    | RStringList _ | RHashtable _ -> pr "char **"
8519    | RStruct (_, typ) ->
8520        if not in_daemon then pr "struct guestfs_%s *" typ
8521        else pr "guestfs_int_%s *" typ
8522    | RStructList (_, typ) ->
8523        if not in_daemon then pr "struct guestfs_%s_list *" typ
8524        else pr "guestfs_int_%s_list *" typ
8525   );
8526   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8527   pr "%s%s (" prefix name;
8528   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8529     pr "void"
8530   else (
8531     let comma = ref false in
8532     (match handle with
8533      | None -> ()
8534      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8535     );
8536     let next () =
8537       if !comma then (
8538         if single_line then pr ", " else pr ",\n\t\t"
8539       );
8540       comma := true
8541     in
8542     List.iter (
8543       function
8544       | Pathname n
8545       | Device n | Dev_or_Path n
8546       | String n
8547       | OptString n
8548       | Key n ->
8549           next ();
8550           pr "const char *%s" n
8551       | StringList n | DeviceList n ->
8552           next ();
8553           pr "char *const *%s" n
8554       | Bool n -> next (); pr "int %s" n
8555       | Int n -> next (); pr "int %s" n
8556       | Int64 n -> next (); pr "int64_t %s" n
8557       | FileIn n
8558       | FileOut n ->
8559           if not in_daemon then (next (); pr "const char *%s" n)
8560       | BufferIn n ->
8561           next ();
8562           pr "const char *%s" n;
8563           next ();
8564           pr "size_t %s_size" n
8565     ) (snd style);
8566     if is_RBufferOut then (next (); pr "size_t *size_r");
8567   );
8568   pr ")";
8569   if semicolon then pr ";";
8570   if newline then pr "\n"
8571
8572 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8573 and generate_c_call_args ?handle ?(decl = false) style =
8574   pr "(";
8575   let comma = ref false in
8576   let next () =
8577     if !comma then pr ", ";
8578     comma := true
8579   in
8580   (match handle with
8581    | None -> ()
8582    | Some handle -> pr "%s" handle; comma := true
8583   );
8584   List.iter (
8585     function
8586     | BufferIn n ->
8587         next ();
8588         pr "%s, %s_size" n n
8589     | arg ->
8590         next ();
8591         pr "%s" (name_of_argt arg)
8592   ) (snd style);
8593   (* For RBufferOut calls, add implicit &size parameter. *)
8594   if not decl then (
8595     match fst style with
8596     | RBufferOut _ ->
8597         next ();
8598         pr "&size"
8599     | _ -> ()
8600   );
8601   pr ")"
8602
8603 (* Generate the OCaml bindings interface. *)
8604 and generate_ocaml_mli () =
8605   generate_header OCamlStyle LGPLv2plus;
8606
8607   pr "\
8608 (** For API documentation you should refer to the C API
8609     in the guestfs(3) manual page.  The OCaml API uses almost
8610     exactly the same calls. *)
8611
8612 type t
8613 (** A [guestfs_h] handle. *)
8614
8615 exception Error of string
8616 (** This exception is raised when there is an error. *)
8617
8618 exception Handle_closed of string
8619 (** This exception is raised if you use a {!Guestfs.t} handle
8620     after calling {!close} on it.  The string is the name of
8621     the function. *)
8622
8623 val create : unit -> t
8624 (** Create a {!Guestfs.t} handle. *)
8625
8626 val close : t -> unit
8627 (** Close the {!Guestfs.t} handle and free up all resources used
8628     by it immediately.
8629
8630     Handles are closed by the garbage collector when they become
8631     unreferenced, but callers can call this in order to provide
8632     predictable cleanup. *)
8633
8634 ";
8635   generate_ocaml_structure_decls ();
8636
8637   (* The actions. *)
8638   List.iter (
8639     fun (name, style, _, _, _, shortdesc, _) ->
8640       generate_ocaml_prototype name style;
8641       pr "(** %s *)\n" shortdesc;
8642       pr "\n"
8643   ) all_functions_sorted
8644
8645 (* Generate the OCaml bindings implementation. *)
8646 and generate_ocaml_ml () =
8647   generate_header OCamlStyle LGPLv2plus;
8648
8649   pr "\
8650 type t
8651
8652 exception Error of string
8653 exception Handle_closed of string
8654
8655 external create : unit -> t = \"ocaml_guestfs_create\"
8656 external close : t -> unit = \"ocaml_guestfs_close\"
8657
8658 (* Give the exceptions names, so they can be raised from the C code. *)
8659 let () =
8660   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8661   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8662
8663 ";
8664
8665   generate_ocaml_structure_decls ();
8666
8667   (* The actions. *)
8668   List.iter (
8669     fun (name, style, _, _, _, shortdesc, _) ->
8670       generate_ocaml_prototype ~is_external:true name style;
8671   ) all_functions_sorted
8672
8673 (* Generate the OCaml bindings C implementation. *)
8674 and generate_ocaml_c () =
8675   generate_header CStyle LGPLv2plus;
8676
8677   pr "\
8678 #include <stdio.h>
8679 #include <stdlib.h>
8680 #include <string.h>
8681
8682 #include <caml/config.h>
8683 #include <caml/alloc.h>
8684 #include <caml/callback.h>
8685 #include <caml/fail.h>
8686 #include <caml/memory.h>
8687 #include <caml/mlvalues.h>
8688 #include <caml/signals.h>
8689
8690 #include \"guestfs.h\"
8691
8692 #include \"guestfs_c.h\"
8693
8694 /* Copy a hashtable of string pairs into an assoc-list.  We return
8695  * the list in reverse order, but hashtables aren't supposed to be
8696  * ordered anyway.
8697  */
8698 static CAMLprim value
8699 copy_table (char * const * argv)
8700 {
8701   CAMLparam0 ();
8702   CAMLlocal5 (rv, pairv, kv, vv, cons);
8703   size_t i;
8704
8705   rv = Val_int (0);
8706   for (i = 0; argv[i] != NULL; i += 2) {
8707     kv = caml_copy_string (argv[i]);
8708     vv = caml_copy_string (argv[i+1]);
8709     pairv = caml_alloc (2, 0);
8710     Store_field (pairv, 0, kv);
8711     Store_field (pairv, 1, vv);
8712     cons = caml_alloc (2, 0);
8713     Store_field (cons, 1, rv);
8714     rv = cons;
8715     Store_field (cons, 0, pairv);
8716   }
8717
8718   CAMLreturn (rv);
8719 }
8720
8721 ";
8722
8723   (* Struct copy functions. *)
8724
8725   let emit_ocaml_copy_list_function typ =
8726     pr "static CAMLprim value\n";
8727     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8728     pr "{\n";
8729     pr "  CAMLparam0 ();\n";
8730     pr "  CAMLlocal2 (rv, v);\n";
8731     pr "  unsigned int i;\n";
8732     pr "\n";
8733     pr "  if (%ss->len == 0)\n" typ;
8734     pr "    CAMLreturn (Atom (0));\n";
8735     pr "  else {\n";
8736     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8737     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8738     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8739     pr "      caml_modify (&Field (rv, i), v);\n";
8740     pr "    }\n";
8741     pr "    CAMLreturn (rv);\n";
8742     pr "  }\n";
8743     pr "}\n";
8744     pr "\n";
8745   in
8746
8747   List.iter (
8748     fun (typ, cols) ->
8749       let has_optpercent_col =
8750         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8751
8752       pr "static CAMLprim value\n";
8753       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8754       pr "{\n";
8755       pr "  CAMLparam0 ();\n";
8756       if has_optpercent_col then
8757         pr "  CAMLlocal3 (rv, v, v2);\n"
8758       else
8759         pr "  CAMLlocal2 (rv, v);\n";
8760       pr "\n";
8761       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8762       iteri (
8763         fun i col ->
8764           (match col with
8765            | name, FString ->
8766                pr "  v = caml_copy_string (%s->%s);\n" typ name
8767            | name, FBuffer ->
8768                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8769                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8770                  typ name typ name
8771            | name, FUUID ->
8772                pr "  v = caml_alloc_string (32);\n";
8773                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8774            | name, (FBytes|FInt64|FUInt64) ->
8775                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8776            | name, (FInt32|FUInt32) ->
8777                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8778            | name, FOptPercent ->
8779                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8780                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8781                pr "    v = caml_alloc (1, 0);\n";
8782                pr "    Store_field (v, 0, v2);\n";
8783                pr "  } else /* None */\n";
8784                pr "    v = Val_int (0);\n";
8785            | name, FChar ->
8786                pr "  v = Val_int (%s->%s);\n" typ name
8787           );
8788           pr "  Store_field (rv, %d, v);\n" i
8789       ) cols;
8790       pr "  CAMLreturn (rv);\n";
8791       pr "}\n";
8792       pr "\n";
8793   ) structs;
8794
8795   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8796   List.iter (
8797     function
8798     | typ, (RStructListOnly | RStructAndList) ->
8799         (* generate the function for typ *)
8800         emit_ocaml_copy_list_function typ
8801     | typ, _ -> () (* empty *)
8802   ) (rstructs_used_by all_functions);
8803
8804   (* The wrappers. *)
8805   List.iter (
8806     fun (name, style, _, _, _, _, _) ->
8807       pr "/* Automatically generated wrapper for function\n";
8808       pr " * ";
8809       generate_ocaml_prototype name style;
8810       pr " */\n";
8811       pr "\n";
8812
8813       let params =
8814         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8815
8816       let needs_extra_vs =
8817         match fst style with RConstOptString _ -> true | _ -> false in
8818
8819       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8820       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8821       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8822       pr "\n";
8823
8824       pr "CAMLprim value\n";
8825       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8826       List.iter (pr ", value %s") (List.tl params);
8827       pr ")\n";
8828       pr "{\n";
8829
8830       (match params with
8831        | [p1; p2; p3; p4; p5] ->
8832            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8833        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8834            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8835            pr "  CAMLxparam%d (%s);\n"
8836              (List.length rest) (String.concat ", " rest)
8837        | ps ->
8838            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8839       );
8840       if not needs_extra_vs then
8841         pr "  CAMLlocal1 (rv);\n"
8842       else
8843         pr "  CAMLlocal3 (rv, v, v2);\n";
8844       pr "\n";
8845
8846       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8847       pr "  if (g == NULL)\n";
8848       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8849       pr "\n";
8850
8851       List.iter (
8852         function
8853         | Pathname n
8854         | Device n | Dev_or_Path n
8855         | String n
8856         | FileIn n
8857         | FileOut n
8858         | Key n ->
8859             (* Copy strings in case the GC moves them: RHBZ#604691 *)
8860             pr "  char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8861         | OptString n ->
8862             pr "  char *%s =\n" n;
8863             pr "    %sv != Val_int (0) ?" n;
8864             pr "      guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8865         | BufferIn n ->
8866             pr "  size_t %s_size = caml_string_length (%sv);\n" n n;
8867             pr "  char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8868         | StringList n | DeviceList n ->
8869             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8870         | Bool n ->
8871             pr "  int %s = Bool_val (%sv);\n" n n
8872         | Int n ->
8873             pr "  int %s = Int_val (%sv);\n" n n
8874         | Int64 n ->
8875             pr "  int64_t %s = Int64_val (%sv);\n" n n
8876       ) (snd style);
8877       let error_code =
8878         match fst style with
8879         | RErr -> pr "  int r;\n"; "-1"
8880         | RInt _ -> pr "  int r;\n"; "-1"
8881         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8882         | RBool _ -> pr "  int r;\n"; "-1"
8883         | RConstString _ | RConstOptString _ ->
8884             pr "  const char *r;\n"; "NULL"
8885         | RString _ -> pr "  char *r;\n"; "NULL"
8886         | RStringList _ ->
8887             pr "  size_t i;\n";
8888             pr "  char **r;\n";
8889             "NULL"
8890         | RStruct (_, typ) ->
8891             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8892         | RStructList (_, typ) ->
8893             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8894         | RHashtable _ ->
8895             pr "  size_t i;\n";
8896             pr "  char **r;\n";
8897             "NULL"
8898         | RBufferOut _ ->
8899             pr "  char *r;\n";
8900             pr "  size_t size;\n";
8901             "NULL" in
8902       pr "\n";
8903
8904       pr "  caml_enter_blocking_section ();\n";
8905       pr "  r = guestfs_%s " name;
8906       generate_c_call_args ~handle:"g" style;
8907       pr ";\n";
8908       pr "  caml_leave_blocking_section ();\n";
8909
8910       (* Free strings if we copied them above. *)
8911       List.iter (
8912         function
8913         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8914         | FileIn n | FileOut n | BufferIn n | Key n ->
8915             pr "  free (%s);\n" n
8916         | StringList n | DeviceList n ->
8917             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8918         | Bool _ | Int _ | Int64 _ -> ()
8919       ) (snd style);
8920
8921       pr "  if (r == %s)\n" error_code;
8922       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8923       pr "\n";
8924
8925       (match fst style with
8926        | RErr -> pr "  rv = Val_unit;\n"
8927        | RInt _ -> pr "  rv = Val_int (r);\n"
8928        | RInt64 _ ->
8929            pr "  rv = caml_copy_int64 (r);\n"
8930        | RBool _ -> pr "  rv = Val_bool (r);\n"
8931        | RConstString _ ->
8932            pr "  rv = caml_copy_string (r);\n"
8933        | RConstOptString _ ->
8934            pr "  if (r) { /* Some string */\n";
8935            pr "    v = caml_alloc (1, 0);\n";
8936            pr "    v2 = caml_copy_string (r);\n";
8937            pr "    Store_field (v, 0, v2);\n";
8938            pr "  } else /* None */\n";
8939            pr "    v = Val_int (0);\n";
8940        | RString _ ->
8941            pr "  rv = caml_copy_string (r);\n";
8942            pr "  free (r);\n"
8943        | RStringList _ ->
8944            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8945            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8946            pr "  free (r);\n"
8947        | RStruct (_, typ) ->
8948            pr "  rv = copy_%s (r);\n" typ;
8949            pr "  guestfs_free_%s (r);\n" typ;
8950        | RStructList (_, typ) ->
8951            pr "  rv = copy_%s_list (r);\n" typ;
8952            pr "  guestfs_free_%s_list (r);\n" typ;
8953        | RHashtable _ ->
8954            pr "  rv = copy_table (r);\n";
8955            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8956            pr "  free (r);\n";
8957        | RBufferOut _ ->
8958            pr "  rv = caml_alloc_string (size);\n";
8959            pr "  memcpy (String_val (rv), r, size);\n";
8960       );
8961
8962       pr "  CAMLreturn (rv);\n";
8963       pr "}\n";
8964       pr "\n";
8965
8966       if List.length params > 5 then (
8967         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8968         pr "CAMLprim value ";
8969         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8970         pr "CAMLprim value\n";
8971         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8972         pr "{\n";
8973         pr "  return ocaml_guestfs_%s (argv[0]" name;
8974         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8975         pr ");\n";
8976         pr "}\n";
8977         pr "\n"
8978       )
8979   ) all_functions_sorted
8980
8981 and generate_ocaml_structure_decls () =
8982   List.iter (
8983     fun (typ, cols) ->
8984       pr "type %s = {\n" typ;
8985       List.iter (
8986         function
8987         | name, FString -> pr "  %s : string;\n" name
8988         | name, FBuffer -> pr "  %s : string;\n" name
8989         | name, FUUID -> pr "  %s : string;\n" name
8990         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8991         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8992         | name, FChar -> pr "  %s : char;\n" name
8993         | name, FOptPercent -> pr "  %s : float option;\n" name
8994       ) cols;
8995       pr "}\n";
8996       pr "\n"
8997   ) structs
8998
8999 and generate_ocaml_prototype ?(is_external = false) name style =
9000   if is_external then pr "external " else pr "val ";
9001   pr "%s : t -> " name;
9002   List.iter (
9003     function
9004     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
9005     | BufferIn _ | Key _ -> pr "string -> "
9006     | OptString _ -> pr "string option -> "
9007     | StringList _ | DeviceList _ -> pr "string array -> "
9008     | Bool _ -> pr "bool -> "
9009     | Int _ -> pr "int -> "
9010     | Int64 _ -> pr "int64 -> "
9011   ) (snd style);
9012   (match fst style with
9013    | RErr -> pr "unit" (* all errors are turned into exceptions *)
9014    | RInt _ -> pr "int"
9015    | RInt64 _ -> pr "int64"
9016    | RBool _ -> pr "bool"
9017    | RConstString _ -> pr "string"
9018    | RConstOptString _ -> pr "string option"
9019    | RString _ | RBufferOut _ -> pr "string"
9020    | RStringList _ -> pr "string array"
9021    | RStruct (_, typ) -> pr "%s" typ
9022    | RStructList (_, typ) -> pr "%s array" typ
9023    | RHashtable _ -> pr "(string * string) list"
9024   );
9025   if is_external then (
9026     pr " = ";
9027     if List.length (snd style) + 1 > 5 then
9028       pr "\"ocaml_guestfs_%s_byte\" " name;
9029     pr "\"ocaml_guestfs_%s\"" name
9030   );
9031   pr "\n"
9032
9033 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
9034 and generate_perl_xs () =
9035   generate_header CStyle LGPLv2plus;
9036
9037   pr "\
9038 #include \"EXTERN.h\"
9039 #include \"perl.h\"
9040 #include \"XSUB.h\"
9041
9042 #include <guestfs.h>
9043
9044 #ifndef PRId64
9045 #define PRId64 \"lld\"
9046 #endif
9047
9048 static SV *
9049 my_newSVll(long long val) {
9050 #ifdef USE_64_BIT_ALL
9051   return newSViv(val);
9052 #else
9053   char buf[100];
9054   int len;
9055   len = snprintf(buf, 100, \"%%\" PRId64, val);
9056   return newSVpv(buf, len);
9057 #endif
9058 }
9059
9060 #ifndef PRIu64
9061 #define PRIu64 \"llu\"
9062 #endif
9063
9064 static SV *
9065 my_newSVull(unsigned long long val) {
9066 #ifdef USE_64_BIT_ALL
9067   return newSVuv(val);
9068 #else
9069   char buf[100];
9070   int len;
9071   len = snprintf(buf, 100, \"%%\" PRIu64, val);
9072   return newSVpv(buf, len);
9073 #endif
9074 }
9075
9076 /* http://www.perlmonks.org/?node_id=680842 */
9077 static char **
9078 XS_unpack_charPtrPtr (SV *arg) {
9079   char **ret;
9080   AV *av;
9081   I32 i;
9082
9083   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
9084     croak (\"array reference expected\");
9085
9086   av = (AV *)SvRV (arg);
9087   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
9088   if (!ret)
9089     croak (\"malloc failed\");
9090
9091   for (i = 0; i <= av_len (av); i++) {
9092     SV **elem = av_fetch (av, i, 0);
9093
9094     if (!elem || !*elem)
9095       croak (\"missing element in list\");
9096
9097     ret[i] = SvPV_nolen (*elem);
9098   }
9099
9100   ret[i] = NULL;
9101
9102   return ret;
9103 }
9104
9105 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
9106
9107 PROTOTYPES: ENABLE
9108
9109 guestfs_h *
9110 _create ()
9111    CODE:
9112       RETVAL = guestfs_create ();
9113       if (!RETVAL)
9114         croak (\"could not create guestfs handle\");
9115       guestfs_set_error_handler (RETVAL, NULL, NULL);
9116  OUTPUT:
9117       RETVAL
9118
9119 void
9120 DESTROY (sv)
9121       SV *sv;
9122  PPCODE:
9123       /* For the 'g' argument above we do the conversion explicitly and
9124        * don't rely on the typemap, because if the handle has been
9125        * explicitly closed we don't want the typemap conversion to
9126        * display an error.
9127        */
9128       HV *hv = (HV *) SvRV (sv);
9129       SV **svp = hv_fetch (hv, \"_g\", 2, 0);
9130       if (svp != NULL) {
9131         guestfs_h *g = (guestfs_h *) SvIV (*svp);
9132         assert (g != NULL);
9133         guestfs_close (g);
9134       }
9135
9136 void
9137 close (g)
9138       guestfs_h *g;
9139  PPCODE:
9140       guestfs_close (g);
9141       /* Avoid double-free in DESTROY method. */
9142       HV *hv = (HV *) SvRV (ST(0));
9143       (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
9144
9145 ";
9146
9147   List.iter (
9148     fun (name, style, _, _, _, _, _) ->
9149       (match fst style with
9150        | RErr -> pr "void\n"
9151        | RInt _ -> pr "SV *\n"
9152        | RInt64 _ -> pr "SV *\n"
9153        | RBool _ -> pr "SV *\n"
9154        | RConstString _ -> pr "SV *\n"
9155        | RConstOptString _ -> pr "SV *\n"
9156        | RString _ -> pr "SV *\n"
9157        | RBufferOut _ -> pr "SV *\n"
9158        | RStringList _
9159        | RStruct _ | RStructList _
9160        | RHashtable _ ->
9161            pr "void\n" (* all lists returned implictly on the stack *)
9162       );
9163       (* Call and arguments. *)
9164       pr "%s (g" name;
9165       List.iter (
9166         fun arg -> pr ", %s" (name_of_argt arg)
9167       ) (snd style);
9168       pr ")\n";
9169       pr "      guestfs_h *g;\n";
9170       iteri (
9171         fun i ->
9172           function
9173           | Pathname n | Device n | Dev_or_Path n | String n
9174           | FileIn n | FileOut n | Key n ->
9175               pr "      char *%s;\n" n
9176           | BufferIn n ->
9177               pr "      char *%s;\n" n;
9178               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
9179           | OptString n ->
9180               (* http://www.perlmonks.org/?node_id=554277
9181                * Note that the implicit handle argument means we have
9182                * to add 1 to the ST(x) operator.
9183                *)
9184               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
9185           | StringList n | DeviceList n -> pr "      char **%s;\n" n
9186           | Bool n -> pr "      int %s;\n" n
9187           | Int n -> pr "      int %s;\n" n
9188           | Int64 n -> pr "      int64_t %s;\n" n
9189       ) (snd style);
9190
9191       let do_cleanups () =
9192         List.iter (
9193           function
9194           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
9195           | Bool _ | Int _ | Int64 _
9196           | FileIn _ | FileOut _
9197           | BufferIn _ | Key _ -> ()
9198           | StringList n | DeviceList n -> pr "      free (%s);\n" n
9199         ) (snd style)
9200       in
9201
9202       (* Code. *)
9203       (match fst style with
9204        | RErr ->
9205            pr "PREINIT:\n";
9206            pr "      int r;\n";
9207            pr " PPCODE:\n";
9208            pr "      r = guestfs_%s " name;
9209            generate_c_call_args ~handle:"g" style;
9210            pr ";\n";
9211            do_cleanups ();
9212            pr "      if (r == -1)\n";
9213            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9214        | RInt n
9215        | RBool n ->
9216            pr "PREINIT:\n";
9217            pr "      int %s;\n" n;
9218            pr "   CODE:\n";
9219            pr "      %s = guestfs_%s " n name;
9220            generate_c_call_args ~handle:"g" style;
9221            pr ";\n";
9222            do_cleanups ();
9223            pr "      if (%s == -1)\n" n;
9224            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9225            pr "      RETVAL = newSViv (%s);\n" n;
9226            pr " OUTPUT:\n";
9227            pr "      RETVAL\n"
9228        | RInt64 n ->
9229            pr "PREINIT:\n";
9230            pr "      int64_t %s;\n" n;
9231            pr "   CODE:\n";
9232            pr "      %s = guestfs_%s " n name;
9233            generate_c_call_args ~handle:"g" style;
9234            pr ";\n";
9235            do_cleanups ();
9236            pr "      if (%s == -1)\n" n;
9237            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9238            pr "      RETVAL = my_newSVll (%s);\n" n;
9239            pr " OUTPUT:\n";
9240            pr "      RETVAL\n"
9241        | RConstString n ->
9242            pr "PREINIT:\n";
9243            pr "      const char *%s;\n" n;
9244            pr "   CODE:\n";
9245            pr "      %s = guestfs_%s " n name;
9246            generate_c_call_args ~handle:"g" style;
9247            pr ";\n";
9248            do_cleanups ();
9249            pr "      if (%s == NULL)\n" n;
9250            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9251            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9252            pr " OUTPUT:\n";
9253            pr "      RETVAL\n"
9254        | RConstOptString n ->
9255            pr "PREINIT:\n";
9256            pr "      const char *%s;\n" n;
9257            pr "   CODE:\n";
9258            pr "      %s = guestfs_%s " n name;
9259            generate_c_call_args ~handle:"g" style;
9260            pr ";\n";
9261            do_cleanups ();
9262            pr "      if (%s == NULL)\n" n;
9263            pr "        RETVAL = &PL_sv_undef;\n";
9264            pr "      else\n";
9265            pr "        RETVAL = newSVpv (%s, 0);\n" n;
9266            pr " OUTPUT:\n";
9267            pr "      RETVAL\n"
9268        | RString n ->
9269            pr "PREINIT:\n";
9270            pr "      char *%s;\n" n;
9271            pr "   CODE:\n";
9272            pr "      %s = guestfs_%s " n name;
9273            generate_c_call_args ~handle:"g" style;
9274            pr ";\n";
9275            do_cleanups ();
9276            pr "      if (%s == NULL)\n" n;
9277            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9278            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9279            pr "      free (%s);\n" n;
9280            pr " OUTPUT:\n";
9281            pr "      RETVAL\n"
9282        | RStringList n | RHashtable n ->
9283            pr "PREINIT:\n";
9284            pr "      char **%s;\n" n;
9285            pr "      size_t i, n;\n";
9286            pr " PPCODE:\n";
9287            pr "      %s = guestfs_%s " n name;
9288            generate_c_call_args ~handle:"g" style;
9289            pr ";\n";
9290            do_cleanups ();
9291            pr "      if (%s == NULL)\n" n;
9292            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9293            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9294            pr "      EXTEND (SP, n);\n";
9295            pr "      for (i = 0; i < n; ++i) {\n";
9296            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9297            pr "        free (%s[i]);\n" n;
9298            pr "      }\n";
9299            pr "      free (%s);\n" n;
9300        | RStruct (n, typ) ->
9301            let cols = cols_of_struct typ in
9302            generate_perl_struct_code typ cols name style n do_cleanups
9303        | RStructList (n, typ) ->
9304            let cols = cols_of_struct typ in
9305            generate_perl_struct_list_code typ cols name style n do_cleanups
9306        | RBufferOut n ->
9307            pr "PREINIT:\n";
9308            pr "      char *%s;\n" n;
9309            pr "      size_t size;\n";
9310            pr "   CODE:\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 "      RETVAL = newSVpvn (%s, size);\n" n;
9318            pr "      free (%s);\n" n;
9319            pr " OUTPUT:\n";
9320            pr "      RETVAL\n"
9321       );
9322
9323       pr "\n"
9324   ) all_functions
9325
9326 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9327   pr "PREINIT:\n";
9328   pr "      struct guestfs_%s_list *%s;\n" typ n;
9329   pr "      size_t i;\n";
9330   pr "      HV *hv;\n";
9331   pr " PPCODE:\n";
9332   pr "      %s = guestfs_%s " n name;
9333   generate_c_call_args ~handle:"g" style;
9334   pr ";\n";
9335   do_cleanups ();
9336   pr "      if (%s == NULL)\n" n;
9337   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9338   pr "      EXTEND (SP, %s->len);\n" n;
9339   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
9340   pr "        hv = newHV ();\n";
9341   List.iter (
9342     function
9343     | name, FString ->
9344         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9345           name (String.length name) n name
9346     | name, FUUID ->
9347         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9348           name (String.length name) n name
9349     | name, FBuffer ->
9350         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9351           name (String.length name) n name n name
9352     | name, (FBytes|FUInt64) ->
9353         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9354           name (String.length name) n name
9355     | name, FInt64 ->
9356         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9357           name (String.length name) n name
9358     | name, (FInt32|FUInt32) ->
9359         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9360           name (String.length name) n name
9361     | name, FChar ->
9362         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9363           name (String.length name) n name
9364     | name, FOptPercent ->
9365         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9366           name (String.length name) n name
9367   ) cols;
9368   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9369   pr "      }\n";
9370   pr "      guestfs_free_%s_list (%s);\n" typ n
9371
9372 and generate_perl_struct_code typ cols name style n do_cleanups =
9373   pr "PREINIT:\n";
9374   pr "      struct guestfs_%s *%s;\n" typ n;
9375   pr " PPCODE:\n";
9376   pr "      %s = guestfs_%s " n name;
9377   generate_c_call_args ~handle:"g" style;
9378   pr ";\n";
9379   do_cleanups ();
9380   pr "      if (%s == NULL)\n" n;
9381   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9382   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9383   List.iter (
9384     fun ((name, _) as col) ->
9385       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9386
9387       match col with
9388       | name, FString ->
9389           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9390             n name
9391       | name, FBuffer ->
9392           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9393             n name n name
9394       | name, FUUID ->
9395           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9396             n name
9397       | name, (FBytes|FUInt64) ->
9398           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9399             n name
9400       | name, FInt64 ->
9401           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9402             n name
9403       | name, (FInt32|FUInt32) ->
9404           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9405             n name
9406       | name, FChar ->
9407           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9408             n name
9409       | name, FOptPercent ->
9410           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9411             n name
9412   ) cols;
9413   pr "      free (%s);\n" n
9414
9415 (* Generate Sys/Guestfs.pm. *)
9416 and generate_perl_pm () =
9417   generate_header HashStyle LGPLv2plus;
9418
9419   pr "\
9420 =pod
9421
9422 =head1 NAME
9423
9424 Sys::Guestfs - Perl bindings for libguestfs
9425
9426 =head1 SYNOPSIS
9427
9428  use Sys::Guestfs;
9429
9430  my $h = Sys::Guestfs->new ();
9431  $h->add_drive ('guest.img');
9432  $h->launch ();
9433  $h->mount ('/dev/sda1', '/');
9434  $h->touch ('/hello');
9435  $h->sync ();
9436
9437 =head1 DESCRIPTION
9438
9439 The C<Sys::Guestfs> module provides a Perl XS binding to the
9440 libguestfs API for examining and modifying virtual machine
9441 disk images.
9442
9443 Amongst the things this is good for: making batch configuration
9444 changes to guests, getting disk used/free statistics (see also:
9445 virt-df), migrating between virtualization systems (see also:
9446 virt-p2v), performing partial backups, performing partial guest
9447 clones, cloning guests and changing registry/UUID/hostname info, and
9448 much else besides.
9449
9450 Libguestfs uses Linux kernel and qemu code, and can access any type of
9451 guest filesystem that Linux and qemu can, including but not limited
9452 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9453 schemes, qcow, qcow2, vmdk.
9454
9455 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9456 LVs, what filesystem is in each LV, etc.).  It can also run commands
9457 in the context of the guest.  Also you can access filesystems over
9458 FUSE.
9459
9460 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9461 functions for using libguestfs from Perl, including integration
9462 with libvirt.
9463
9464 =head1 ERRORS
9465
9466 All errors turn into calls to C<croak> (see L<Carp(3)>).
9467
9468 =head1 METHODS
9469
9470 =over 4
9471
9472 =cut
9473
9474 package Sys::Guestfs;
9475
9476 use strict;
9477 use warnings;
9478
9479 # This version number changes whenever a new function
9480 # is added to the libguestfs API.  It is not directly
9481 # related to the libguestfs version number.
9482 use vars qw($VERSION);
9483 $VERSION = '0.%d';
9484
9485 require XSLoader;
9486 XSLoader::load ('Sys::Guestfs');
9487
9488 =item $h = Sys::Guestfs->new ();
9489
9490 Create a new guestfs handle.
9491
9492 =cut
9493
9494 sub new {
9495   my $proto = shift;
9496   my $class = ref ($proto) || $proto;
9497
9498   my $g = Sys::Guestfs::_create ();
9499   my $self = { _g => $g };
9500   bless $self, $class;
9501   return $self;
9502 }
9503
9504 =item $h->close ();
9505
9506 Explicitly close the guestfs handle.
9507
9508 B<Note:> You should not usually call this function.  The handle will
9509 be closed implicitly when its reference count goes to zero (eg.
9510 when it goes out of scope or the program ends).  This call is
9511 only required in some exceptional cases, such as where the program
9512 may contain cached references to the handle 'somewhere' and you
9513 really have to have the close happen right away.  After calling
9514 C<close> the program must not call any method (including C<close>)
9515 on the handle (but the implicit call to C<DESTROY> that happens
9516 when the final reference is cleaned up is OK).
9517
9518 =cut
9519
9520 " max_proc_nr;
9521
9522   (* Actions.  We only need to print documentation for these as
9523    * they are pulled in from the XS code automatically.
9524    *)
9525   List.iter (
9526     fun (name, style, _, flags, _, _, longdesc) ->
9527       if not (List.mem NotInDocs flags) then (
9528         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9529         pr "=item ";
9530         generate_perl_prototype name style;
9531         pr "\n\n";
9532         pr "%s\n\n" longdesc;
9533         if List.mem ProtocolLimitWarning flags then
9534           pr "%s\n\n" protocol_limit_warning;
9535         if List.mem DangerWillRobinson flags then
9536           pr "%s\n\n" danger_will_robinson;
9537         match deprecation_notice flags with
9538         | None -> ()
9539         | Some txt -> pr "%s\n\n" txt
9540       )
9541   ) all_functions_sorted;
9542
9543   (* End of file. *)
9544   pr "\
9545 =cut
9546
9547 1;
9548
9549 =back
9550
9551 =head1 COPYRIGHT
9552
9553 Copyright (C) %s Red Hat Inc.
9554
9555 =head1 LICENSE
9556
9557 Please see the file COPYING.LIB for the full license.
9558
9559 =head1 SEE ALSO
9560
9561 L<guestfs(3)>,
9562 L<guestfish(1)>,
9563 L<http://libguestfs.org>,
9564 L<Sys::Guestfs::Lib(3)>.
9565
9566 =cut
9567 " copyright_years
9568
9569 and generate_perl_prototype name style =
9570   (match fst style with
9571    | RErr -> ()
9572    | RBool n
9573    | RInt n
9574    | RInt64 n
9575    | RConstString n
9576    | RConstOptString n
9577    | RString n
9578    | RBufferOut n -> pr "$%s = " n
9579    | RStruct (n,_)
9580    | RHashtable n -> pr "%%%s = " n
9581    | RStringList n
9582    | RStructList (n,_) -> pr "@%s = " n
9583   );
9584   pr "$h->%s (" name;
9585   let comma = ref false in
9586   List.iter (
9587     fun arg ->
9588       if !comma then pr ", ";
9589       comma := true;
9590       match arg with
9591       | Pathname n | Device n | Dev_or_Path n | String n
9592       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9593       | BufferIn n | Key n ->
9594           pr "$%s" n
9595       | StringList n | DeviceList n ->
9596           pr "\\@%s" n
9597   ) (snd style);
9598   pr ");"
9599
9600 (* Generate Python C module. *)
9601 and generate_python_c () =
9602   generate_header CStyle LGPLv2plus;
9603
9604   pr "\
9605 #define PY_SSIZE_T_CLEAN 1
9606 #include <Python.h>
9607
9608 #if PY_VERSION_HEX < 0x02050000
9609 typedef int Py_ssize_t;
9610 #define PY_SSIZE_T_MAX INT_MAX
9611 #define PY_SSIZE_T_MIN INT_MIN
9612 #endif
9613
9614 #include <stdio.h>
9615 #include <stdlib.h>
9616 #include <assert.h>
9617
9618 #include \"guestfs.h\"
9619
9620 #ifndef HAVE_PYCAPSULE_NEW
9621 typedef struct {
9622   PyObject_HEAD
9623   guestfs_h *g;
9624 } Pyguestfs_Object;
9625 #endif
9626
9627 static guestfs_h *
9628 get_handle (PyObject *obj)
9629 {
9630   assert (obj);
9631   assert (obj != Py_None);
9632 #ifndef HAVE_PYCAPSULE_NEW
9633   return ((Pyguestfs_Object *) obj)->g;
9634 #else
9635   return (guestfs_h*) PyCapsule_GetPointer(obj, \"guestfs_h\");
9636 #endif
9637 }
9638
9639 static PyObject *
9640 put_handle (guestfs_h *g)
9641 {
9642   assert (g);
9643 #ifndef HAVE_PYCAPSULE_NEW
9644   return
9645     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9646 #else
9647   return PyCapsule_New ((void *) g, \"guestfs_h\", NULL);
9648 #endif
9649 }
9650
9651 /* This list should be freed (but not the strings) after use. */
9652 static char **
9653 get_string_list (PyObject *obj)
9654 {
9655   size_t i, len;
9656   char **r;
9657
9658   assert (obj);
9659
9660   if (!PyList_Check (obj)) {
9661     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9662     return NULL;
9663   }
9664
9665   Py_ssize_t slen = PyList_Size (obj);
9666   if (slen == -1) {
9667     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9668     return NULL;
9669   }
9670   len = (size_t) slen;
9671   r = malloc (sizeof (char *) * (len+1));
9672   if (r == NULL) {
9673     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9674     return NULL;
9675   }
9676
9677   for (i = 0; i < len; ++i)
9678     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9679   r[len] = NULL;
9680
9681   return r;
9682 }
9683
9684 static PyObject *
9685 put_string_list (char * const * const argv)
9686 {
9687   PyObject *list;
9688   int argc, i;
9689
9690   for (argc = 0; argv[argc] != NULL; ++argc)
9691     ;
9692
9693   list = PyList_New (argc);
9694   for (i = 0; i < argc; ++i)
9695     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9696
9697   return list;
9698 }
9699
9700 static PyObject *
9701 put_table (char * const * const argv)
9702 {
9703   PyObject *list, *item;
9704   int argc, i;
9705
9706   for (argc = 0; argv[argc] != NULL; ++argc)
9707     ;
9708
9709   list = PyList_New (argc >> 1);
9710   for (i = 0; i < argc; i += 2) {
9711     item = PyTuple_New (2);
9712     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9713     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9714     PyList_SetItem (list, i >> 1, item);
9715   }
9716
9717   return list;
9718 }
9719
9720 static void
9721 free_strings (char **argv)
9722 {
9723   int argc;
9724
9725   for (argc = 0; argv[argc] != NULL; ++argc)
9726     free (argv[argc]);
9727   free (argv);
9728 }
9729
9730 static PyObject *
9731 py_guestfs_create (PyObject *self, PyObject *args)
9732 {
9733   guestfs_h *g;
9734
9735   g = guestfs_create ();
9736   if (g == NULL) {
9737     PyErr_SetString (PyExc_RuntimeError,
9738                      \"guestfs.create: failed to allocate handle\");
9739     return NULL;
9740   }
9741   guestfs_set_error_handler (g, NULL, NULL);
9742   /* This can return NULL, but in that case put_handle will have
9743    * set the Python error string.
9744    */
9745   return put_handle (g);
9746 }
9747
9748 static PyObject *
9749 py_guestfs_close (PyObject *self, PyObject *args)
9750 {
9751   PyObject *py_g;
9752   guestfs_h *g;
9753
9754   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9755     return NULL;
9756   g = get_handle (py_g);
9757
9758   guestfs_close (g);
9759
9760   Py_INCREF (Py_None);
9761   return Py_None;
9762 }
9763
9764 ";
9765
9766   let emit_put_list_function typ =
9767     pr "static PyObject *\n";
9768     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9769     pr "{\n";
9770     pr "  PyObject *list;\n";
9771     pr "  size_t i;\n";
9772     pr "\n";
9773     pr "  list = PyList_New (%ss->len);\n" typ;
9774     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9775     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9776     pr "  return list;\n";
9777     pr "};\n";
9778     pr "\n"
9779   in
9780
9781   (* Structures, turned into Python dictionaries. *)
9782   List.iter (
9783     fun (typ, cols) ->
9784       pr "static PyObject *\n";
9785       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9786       pr "{\n";
9787       pr "  PyObject *dict;\n";
9788       pr "\n";
9789       pr "  dict = PyDict_New ();\n";
9790       List.iter (
9791         function
9792         | name, FString ->
9793             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9794             pr "                        PyString_FromString (%s->%s));\n"
9795               typ name
9796         | name, FBuffer ->
9797             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9798             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9799               typ name typ name
9800         | name, FUUID ->
9801             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9802             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9803               typ name
9804         | name, (FBytes|FUInt64) ->
9805             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9806             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9807               typ name
9808         | name, FInt64 ->
9809             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9810             pr "                        PyLong_FromLongLong (%s->%s));\n"
9811               typ name
9812         | name, FUInt32 ->
9813             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9814             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9815               typ name
9816         | name, FInt32 ->
9817             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9818             pr "                        PyLong_FromLong (%s->%s));\n"
9819               typ name
9820         | name, FOptPercent ->
9821             pr "  if (%s->%s >= 0)\n" typ name;
9822             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9823             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9824               typ name;
9825             pr "  else {\n";
9826             pr "    Py_INCREF (Py_None);\n";
9827             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9828             pr "  }\n"
9829         | name, FChar ->
9830             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9831             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9832       ) cols;
9833       pr "  return dict;\n";
9834       pr "};\n";
9835       pr "\n";
9836
9837   ) structs;
9838
9839   (* Emit a put_TYPE_list function definition only if that function is used. *)
9840   List.iter (
9841     function
9842     | typ, (RStructListOnly | RStructAndList) ->
9843         (* generate the function for typ *)
9844         emit_put_list_function typ
9845     | typ, _ -> () (* empty *)
9846   ) (rstructs_used_by all_functions);
9847
9848   (* Python wrapper functions. *)
9849   List.iter (
9850     fun (name, style, _, _, _, _, _) ->
9851       pr "static PyObject *\n";
9852       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9853       pr "{\n";
9854
9855       pr "  PyObject *py_g;\n";
9856       pr "  guestfs_h *g;\n";
9857       pr "  PyObject *py_r;\n";
9858
9859       let error_code =
9860         match fst style with
9861         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9862         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9863         | RConstString _ | RConstOptString _ ->
9864             pr "  const char *r;\n"; "NULL"
9865         | RString _ -> pr "  char *r;\n"; "NULL"
9866         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9867         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9868         | RStructList (_, typ) ->
9869             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9870         | RBufferOut _ ->
9871             pr "  char *r;\n";
9872             pr "  size_t size;\n";
9873             "NULL" in
9874
9875       List.iter (
9876         function
9877         | Pathname n | Device n | Dev_or_Path n | String n | Key n
9878         | FileIn n | FileOut n ->
9879             pr "  const char *%s;\n" n
9880         | OptString n -> pr "  const char *%s;\n" n
9881         | BufferIn n ->
9882             pr "  const char *%s;\n" n;
9883             pr "  Py_ssize_t %s_size;\n" n
9884         | StringList n | DeviceList n ->
9885             pr "  PyObject *py_%s;\n" n;
9886             pr "  char **%s;\n" n
9887         | Bool n -> pr "  int %s;\n" n
9888         | Int n -> pr "  int %s;\n" n
9889         | Int64 n -> pr "  long long %s;\n" n
9890       ) (snd style);
9891
9892       pr "\n";
9893
9894       (* Convert the parameters. *)
9895       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9896       List.iter (
9897         function
9898         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9899         | FileIn _ | FileOut _ -> pr "s"
9900         | OptString _ -> pr "z"
9901         | StringList _ | DeviceList _ -> pr "O"
9902         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9903         | Int _ -> pr "i"
9904         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9905                              * emulate C's int/long/long long in Python?
9906                              *)
9907         | BufferIn _ -> pr "s#"
9908       ) (snd style);
9909       pr ":guestfs_%s\",\n" name;
9910       pr "                         &py_g";
9911       List.iter (
9912         function
9913         | Pathname n | Device n | Dev_or_Path n | String n | Key n
9914         | FileIn n | FileOut n -> pr ", &%s" n
9915         | OptString n -> pr ", &%s" n
9916         | StringList n | DeviceList n -> pr ", &py_%s" n
9917         | Bool n -> pr ", &%s" n
9918         | Int n -> pr ", &%s" n
9919         | Int64 n -> pr ", &%s" n
9920         | BufferIn n -> pr ", &%s, &%s_size" n n
9921       ) (snd style);
9922
9923       pr "))\n";
9924       pr "    return NULL;\n";
9925
9926       pr "  g = get_handle (py_g);\n";
9927       List.iter (
9928         function
9929         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9930         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9931         | BufferIn _ -> ()
9932         | StringList n | DeviceList n ->
9933             pr "  %s = get_string_list (py_%s);\n" n n;
9934             pr "  if (!%s) return NULL;\n" n
9935       ) (snd style);
9936
9937       pr "\n";
9938
9939       pr "  r = guestfs_%s " name;
9940       generate_c_call_args ~handle:"g" style;
9941       pr ";\n";
9942
9943       List.iter (
9944         function
9945         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
9946         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9947         | BufferIn _ -> ()
9948         | StringList n | DeviceList n ->
9949             pr "  free (%s);\n" n
9950       ) (snd style);
9951
9952       pr "  if (r == %s) {\n" error_code;
9953       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9954       pr "    return NULL;\n";
9955       pr "  }\n";
9956       pr "\n";
9957
9958       (match fst style with
9959        | RErr ->
9960            pr "  Py_INCREF (Py_None);\n";
9961            pr "  py_r = Py_None;\n"
9962        | RInt _
9963        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9964        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9965        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9966        | RConstOptString _ ->
9967            pr "  if (r)\n";
9968            pr "    py_r = PyString_FromString (r);\n";
9969            pr "  else {\n";
9970            pr "    Py_INCREF (Py_None);\n";
9971            pr "    py_r = Py_None;\n";
9972            pr "  }\n"
9973        | RString _ ->
9974            pr "  py_r = PyString_FromString (r);\n";
9975            pr "  free (r);\n"
9976        | RStringList _ ->
9977            pr "  py_r = put_string_list (r);\n";
9978            pr "  free_strings (r);\n"
9979        | RStruct (_, typ) ->
9980            pr "  py_r = put_%s (r);\n" typ;
9981            pr "  guestfs_free_%s (r);\n" typ
9982        | RStructList (_, typ) ->
9983            pr "  py_r = put_%s_list (r);\n" typ;
9984            pr "  guestfs_free_%s_list (r);\n" typ
9985        | RHashtable n ->
9986            pr "  py_r = put_table (r);\n";
9987            pr "  free_strings (r);\n"
9988        | RBufferOut _ ->
9989            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9990            pr "  free (r);\n"
9991       );
9992
9993       pr "  return py_r;\n";
9994       pr "}\n";
9995       pr "\n"
9996   ) all_functions;
9997
9998   (* Table of functions. *)
9999   pr "static PyMethodDef methods[] = {\n";
10000   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
10001   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
10002   List.iter (
10003     fun (name, _, _, _, _, _, _) ->
10004       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
10005         name name
10006   ) all_functions;
10007   pr "  { NULL, NULL, 0, NULL }\n";
10008   pr "};\n";
10009   pr "\n";
10010
10011   (* Init function. *)
10012   pr "\
10013 void
10014 initlibguestfsmod (void)
10015 {
10016   static int initialized = 0;
10017
10018   if (initialized) return;
10019   Py_InitModule ((char *) \"libguestfsmod\", methods);
10020   initialized = 1;
10021 }
10022 "
10023
10024 (* Generate Python module. *)
10025 and generate_python_py () =
10026   generate_header HashStyle LGPLv2plus;
10027
10028   pr "\
10029 u\"\"\"Python bindings for libguestfs
10030
10031 import guestfs
10032 g = guestfs.GuestFS ()
10033 g.add_drive (\"guest.img\")
10034 g.launch ()
10035 parts = g.list_partitions ()
10036
10037 The guestfs module provides a Python binding to the libguestfs API
10038 for examining and modifying virtual machine disk images.
10039
10040 Amongst the things this is good for: making batch configuration
10041 changes to guests, getting disk used/free statistics (see also:
10042 virt-df), migrating between virtualization systems (see also:
10043 virt-p2v), performing partial backups, performing partial guest
10044 clones, cloning guests and changing registry/UUID/hostname info, and
10045 much else besides.
10046
10047 Libguestfs uses Linux kernel and qemu code, and can access any type of
10048 guest filesystem that Linux and qemu can, including but not limited
10049 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
10050 schemes, qcow, qcow2, vmdk.
10051
10052 Libguestfs provides ways to enumerate guest storage (eg. partitions,
10053 LVs, what filesystem is in each LV, etc.).  It can also run commands
10054 in the context of the guest.  Also you can access filesystems over
10055 FUSE.
10056
10057 Errors which happen while using the API are turned into Python
10058 RuntimeError exceptions.
10059
10060 To create a guestfs handle you usually have to perform the following
10061 sequence of calls:
10062
10063 # Create the handle, call add_drive at least once, and possibly
10064 # several times if the guest has multiple block devices:
10065 g = guestfs.GuestFS ()
10066 g.add_drive (\"guest.img\")
10067
10068 # Launch the qemu subprocess and wait for it to become ready:
10069 g.launch ()
10070
10071 # Now you can issue commands, for example:
10072 logvols = g.lvs ()
10073
10074 \"\"\"
10075
10076 import libguestfsmod
10077
10078 class GuestFS:
10079     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
10080
10081     def __init__ (self):
10082         \"\"\"Create a new libguestfs handle.\"\"\"
10083         self._o = libguestfsmod.create ()
10084
10085     def __del__ (self):
10086         libguestfsmod.close (self._o)
10087
10088 ";
10089
10090   List.iter (
10091     fun (name, style, _, flags, _, _, longdesc) ->
10092       pr "    def %s " name;
10093       generate_py_call_args ~handle:"self" (snd style);
10094       pr ":\n";
10095
10096       if not (List.mem NotInDocs flags) then (
10097         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10098         let doc =
10099           match fst style with
10100           | RErr | RInt _ | RInt64 _ | RBool _
10101           | RConstOptString _ | RConstString _
10102           | RString _ | RBufferOut _ -> doc
10103           | RStringList _ ->
10104               doc ^ "\n\nThis function returns a list of strings."
10105           | RStruct (_, typ) ->
10106               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
10107           | RStructList (_, typ) ->
10108               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
10109           | RHashtable _ ->
10110               doc ^ "\n\nThis function returns a dictionary." in
10111         let doc =
10112           if List.mem ProtocolLimitWarning flags then
10113             doc ^ "\n\n" ^ protocol_limit_warning
10114           else doc in
10115         let doc =
10116           if List.mem DangerWillRobinson flags then
10117             doc ^ "\n\n" ^ danger_will_robinson
10118           else doc in
10119         let doc =
10120           match deprecation_notice flags with
10121           | None -> doc
10122           | Some txt -> doc ^ "\n\n" ^ txt in
10123         let doc = pod2text ~width:60 name doc in
10124         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
10125         let doc = String.concat "\n        " doc in
10126         pr "        u\"\"\"%s\"\"\"\n" doc;
10127       );
10128       pr "        return libguestfsmod.%s " name;
10129       generate_py_call_args ~handle:"self._o" (snd style);
10130       pr "\n";
10131       pr "\n";
10132   ) all_functions
10133
10134 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
10135 and generate_py_call_args ~handle args =
10136   pr "(%s" handle;
10137   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10138   pr ")"
10139
10140 (* Useful if you need the longdesc POD text as plain text.  Returns a
10141  * list of lines.
10142  *
10143  * Because this is very slow (the slowest part of autogeneration),
10144  * we memoize the results.
10145  *)
10146 and pod2text ~width name longdesc =
10147   let key = width, name, longdesc in
10148   try Hashtbl.find pod2text_memo key
10149   with Not_found ->
10150     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
10151     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
10152     close_out chan;
10153     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
10154     let chan = open_process_in cmd in
10155     let lines = ref [] in
10156     let rec loop i =
10157       let line = input_line chan in
10158       if i = 1 then             (* discard the first line of output *)
10159         loop (i+1)
10160       else (
10161         let line = triml line in
10162         lines := line :: !lines;
10163         loop (i+1)
10164       ) in
10165     let lines = try loop 1 with End_of_file -> List.rev !lines in
10166     unlink filename;
10167     (match close_process_in chan with
10168      | WEXITED 0 -> ()
10169      | WEXITED i ->
10170          failwithf "pod2text: process exited with non-zero status (%d)" i
10171      | WSIGNALED i | WSTOPPED i ->
10172          failwithf "pod2text: process signalled or stopped by signal %d" i
10173     );
10174     Hashtbl.add pod2text_memo key lines;
10175     pod2text_memo_updated ();
10176     lines
10177
10178 (* Generate ruby bindings. *)
10179 and generate_ruby_c () =
10180   generate_header CStyle LGPLv2plus;
10181
10182   pr "\
10183 #include <stdio.h>
10184 #include <stdlib.h>
10185
10186 #include <ruby.h>
10187
10188 #include \"guestfs.h\"
10189
10190 #include \"extconf.h\"
10191
10192 /* For Ruby < 1.9 */
10193 #ifndef RARRAY_LEN
10194 #define RARRAY_LEN(r) (RARRAY((r))->len)
10195 #endif
10196
10197 static VALUE m_guestfs;                 /* guestfs module */
10198 static VALUE c_guestfs;                 /* guestfs_h handle */
10199 static VALUE e_Error;                   /* used for all errors */
10200
10201 static void ruby_guestfs_free (void *p)
10202 {
10203   if (!p) return;
10204   guestfs_close ((guestfs_h *) p);
10205 }
10206
10207 static VALUE ruby_guestfs_create (VALUE m)
10208 {
10209   guestfs_h *g;
10210
10211   g = guestfs_create ();
10212   if (!g)
10213     rb_raise (e_Error, \"failed to create guestfs handle\");
10214
10215   /* Don't print error messages to stderr by default. */
10216   guestfs_set_error_handler (g, NULL, NULL);
10217
10218   /* Wrap it, and make sure the close function is called when the
10219    * handle goes away.
10220    */
10221   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
10222 }
10223
10224 static VALUE ruby_guestfs_close (VALUE gv)
10225 {
10226   guestfs_h *g;
10227   Data_Get_Struct (gv, guestfs_h, g);
10228
10229   ruby_guestfs_free (g);
10230   DATA_PTR (gv) = NULL;
10231
10232   return Qnil;
10233 }
10234
10235 ";
10236
10237   List.iter (
10238     fun (name, style, _, _, _, _, _) ->
10239       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
10240       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
10241       pr ")\n";
10242       pr "{\n";
10243       pr "  guestfs_h *g;\n";
10244       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
10245       pr "  if (!g)\n";
10246       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
10247         name;
10248       pr "\n";
10249
10250       List.iter (
10251         function
10252         | Pathname n | Device n | Dev_or_Path n | String n | Key n
10253         | FileIn n | FileOut n ->
10254             pr "  Check_Type (%sv, T_STRING);\n" n;
10255             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
10256             pr "  if (!%s)\n" n;
10257             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10258             pr "              \"%s\", \"%s\");\n" n name
10259         | BufferIn n ->
10260             pr "  Check_Type (%sv, T_STRING);\n" n;
10261             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
10262             pr "  if (!%s)\n" n;
10263             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10264             pr "              \"%s\", \"%s\");\n" n name;
10265             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
10266         | OptString n ->
10267             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
10268         | StringList n | DeviceList n ->
10269             pr "  char **%s;\n" n;
10270             pr "  Check_Type (%sv, T_ARRAY);\n" n;
10271             pr "  {\n";
10272             pr "    size_t i, len;\n";
10273             pr "    len = RARRAY_LEN (%sv);\n" n;
10274             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
10275               n;
10276             pr "    for (i = 0; i < len; ++i) {\n";
10277             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
10278             pr "      %s[i] = StringValueCStr (v);\n" n;
10279             pr "    }\n";
10280             pr "    %s[len] = NULL;\n" n;
10281             pr "  }\n";
10282         | Bool n ->
10283             pr "  int %s = RTEST (%sv);\n" n n
10284         | Int n ->
10285             pr "  int %s = NUM2INT (%sv);\n" n n
10286         | Int64 n ->
10287             pr "  long long %s = NUM2LL (%sv);\n" n n
10288       ) (snd style);
10289       pr "\n";
10290
10291       let error_code =
10292         match fst style with
10293         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
10294         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
10295         | RConstString _ | RConstOptString _ ->
10296             pr "  const char *r;\n"; "NULL"
10297         | RString _ -> pr "  char *r;\n"; "NULL"
10298         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
10299         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
10300         | RStructList (_, typ) ->
10301             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
10302         | RBufferOut _ ->
10303             pr "  char *r;\n";
10304             pr "  size_t size;\n";
10305             "NULL" in
10306       pr "\n";
10307
10308       pr "  r = guestfs_%s " name;
10309       generate_c_call_args ~handle:"g" style;
10310       pr ";\n";
10311
10312       List.iter (
10313         function
10314         | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _
10315         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10316         | BufferIn _ -> ()
10317         | StringList n | DeviceList n ->
10318             pr "  free (%s);\n" n
10319       ) (snd style);
10320
10321       pr "  if (r == %s)\n" error_code;
10322       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10323       pr "\n";
10324
10325       (match fst style with
10326        | RErr ->
10327            pr "  return Qnil;\n"
10328        | RInt _ | RBool _ ->
10329            pr "  return INT2NUM (r);\n"
10330        | RInt64 _ ->
10331            pr "  return ULL2NUM (r);\n"
10332        | RConstString _ ->
10333            pr "  return rb_str_new2 (r);\n";
10334        | RConstOptString _ ->
10335            pr "  if (r)\n";
10336            pr "    return rb_str_new2 (r);\n";
10337            pr "  else\n";
10338            pr "    return Qnil;\n";
10339        | RString _ ->
10340            pr "  VALUE rv = rb_str_new2 (r);\n";
10341            pr "  free (r);\n";
10342            pr "  return rv;\n";
10343        | RStringList _ ->
10344            pr "  size_t i, len = 0;\n";
10345            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
10346            pr "  VALUE rv = rb_ary_new2 (len);\n";
10347            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
10348            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10349            pr "    free (r[i]);\n";
10350            pr "  }\n";
10351            pr "  free (r);\n";
10352            pr "  return rv;\n"
10353        | RStruct (_, typ) ->
10354            let cols = cols_of_struct typ in
10355            generate_ruby_struct_code typ cols
10356        | RStructList (_, typ) ->
10357            let cols = cols_of_struct typ in
10358            generate_ruby_struct_list_code typ cols
10359        | RHashtable _ ->
10360            pr "  VALUE rv = rb_hash_new ();\n";
10361            pr "  size_t i;\n";
10362            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
10363            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10364            pr "    free (r[i]);\n";
10365            pr "    free (r[i+1]);\n";
10366            pr "  }\n";
10367            pr "  free (r);\n";
10368            pr "  return rv;\n"
10369        | RBufferOut _ ->
10370            pr "  VALUE rv = rb_str_new (r, size);\n";
10371            pr "  free (r);\n";
10372            pr "  return rv;\n";
10373       );
10374
10375       pr "}\n";
10376       pr "\n"
10377   ) all_functions;
10378
10379   pr "\
10380 /* Initialize the module. */
10381 void Init__guestfs ()
10382 {
10383   m_guestfs = rb_define_module (\"Guestfs\");
10384   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10385   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10386
10387   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10388   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10389
10390 ";
10391   (* Define the rest of the methods. *)
10392   List.iter (
10393     fun (name, style, _, _, _, _, _) ->
10394       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10395       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10396   ) all_functions;
10397
10398   pr "}\n"
10399
10400 (* Ruby code to return a struct. *)
10401 and generate_ruby_struct_code typ cols =
10402   pr "  VALUE rv = rb_hash_new ();\n";
10403   List.iter (
10404     function
10405     | name, FString ->
10406         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10407     | name, FBuffer ->
10408         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10409     | name, FUUID ->
10410         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10411     | name, (FBytes|FUInt64) ->
10412         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10413     | name, FInt64 ->
10414         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10415     | name, FUInt32 ->
10416         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10417     | name, FInt32 ->
10418         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10419     | name, FOptPercent ->
10420         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10421     | name, FChar -> (* XXX wrong? *)
10422         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10423   ) cols;
10424   pr "  guestfs_free_%s (r);\n" typ;
10425   pr "  return rv;\n"
10426
10427 (* Ruby code to return a struct list. *)
10428 and generate_ruby_struct_list_code typ cols =
10429   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10430   pr "  size_t i;\n";
10431   pr "  for (i = 0; i < r->len; ++i) {\n";
10432   pr "    VALUE hv = rb_hash_new ();\n";
10433   List.iter (
10434     function
10435     | name, FString ->
10436         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10437     | name, FBuffer ->
10438         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
10439     | name, FUUID ->
10440         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10441     | name, (FBytes|FUInt64) ->
10442         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10443     | name, FInt64 ->
10444         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10445     | name, FUInt32 ->
10446         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10447     | name, FInt32 ->
10448         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10449     | name, FOptPercent ->
10450         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10451     | name, FChar -> (* XXX wrong? *)
10452         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10453   ) cols;
10454   pr "    rb_ary_push (rv, hv);\n";
10455   pr "  }\n";
10456   pr "  guestfs_free_%s_list (r);\n" typ;
10457   pr "  return rv;\n"
10458
10459 (* Generate Java bindings GuestFS.java file. *)
10460 and generate_java_java () =
10461   generate_header CStyle LGPLv2plus;
10462
10463   pr "\
10464 package com.redhat.et.libguestfs;
10465
10466 import java.util.HashMap;
10467 import com.redhat.et.libguestfs.LibGuestFSException;
10468 import com.redhat.et.libguestfs.PV;
10469 import com.redhat.et.libguestfs.VG;
10470 import com.redhat.et.libguestfs.LV;
10471 import com.redhat.et.libguestfs.Stat;
10472 import com.redhat.et.libguestfs.StatVFS;
10473 import com.redhat.et.libguestfs.IntBool;
10474 import com.redhat.et.libguestfs.Dirent;
10475
10476 /**
10477  * The GuestFS object is a libguestfs handle.
10478  *
10479  * @author rjones
10480  */
10481 public class GuestFS {
10482   // Load the native code.
10483   static {
10484     System.loadLibrary (\"guestfs_jni\");
10485   }
10486
10487   /**
10488    * The native guestfs_h pointer.
10489    */
10490   long g;
10491
10492   /**
10493    * Create a libguestfs handle.
10494    *
10495    * @throws LibGuestFSException
10496    */
10497   public GuestFS () throws LibGuestFSException
10498   {
10499     g = _create ();
10500   }
10501   private native long _create () throws LibGuestFSException;
10502
10503   /**
10504    * Close a libguestfs handle.
10505    *
10506    * You can also leave handles to be collected by the garbage
10507    * collector, but this method ensures that the resources used
10508    * by the handle are freed up immediately.  If you call any
10509    * other methods after closing the handle, you will get an
10510    * exception.
10511    *
10512    * @throws LibGuestFSException
10513    */
10514   public void close () throws LibGuestFSException
10515   {
10516     if (g != 0)
10517       _close (g);
10518     g = 0;
10519   }
10520   private native void _close (long g) throws LibGuestFSException;
10521
10522   public void finalize () throws LibGuestFSException
10523   {
10524     close ();
10525   }
10526
10527 ";
10528
10529   List.iter (
10530     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10531       if not (List.mem NotInDocs flags); then (
10532         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10533         let doc =
10534           if List.mem ProtocolLimitWarning flags then
10535             doc ^ "\n\n" ^ protocol_limit_warning
10536           else doc in
10537         let doc =
10538           if List.mem DangerWillRobinson flags then
10539             doc ^ "\n\n" ^ danger_will_robinson
10540           else doc in
10541         let doc =
10542           match deprecation_notice flags with
10543           | None -> doc
10544           | Some txt -> doc ^ "\n\n" ^ txt in
10545         let doc = pod2text ~width:60 name doc in
10546         let doc = List.map (            (* RHBZ#501883 *)
10547           function
10548           | "" -> "<p>"
10549           | nonempty -> nonempty
10550         ) doc in
10551         let doc = String.concat "\n   * " doc in
10552
10553         pr "  /**\n";
10554         pr "   * %s\n" shortdesc;
10555         pr "   * <p>\n";
10556         pr "   * %s\n" doc;
10557         pr "   * @throws LibGuestFSException\n";
10558         pr "   */\n";
10559         pr "  ";
10560       );
10561       generate_java_prototype ~public:true ~semicolon:false name style;
10562       pr "\n";
10563       pr "  {\n";
10564       pr "    if (g == 0)\n";
10565       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10566         name;
10567       pr "    ";
10568       if fst style <> RErr then pr "return ";
10569       pr "_%s " name;
10570       generate_java_call_args ~handle:"g" (snd style);
10571       pr ";\n";
10572       pr "  }\n";
10573       pr "  ";
10574       generate_java_prototype ~privat:true ~native:true name style;
10575       pr "\n";
10576       pr "\n";
10577   ) all_functions;
10578
10579   pr "}\n"
10580
10581 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10582 and generate_java_call_args ~handle args =
10583   pr "(%s" handle;
10584   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10585   pr ")"
10586
10587 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10588     ?(semicolon=true) name style =
10589   if privat then pr "private ";
10590   if public then pr "public ";
10591   if native then pr "native ";
10592
10593   (* return type *)
10594   (match fst style with
10595    | RErr -> pr "void ";
10596    | RInt _ -> pr "int ";
10597    | RInt64 _ -> pr "long ";
10598    | RBool _ -> pr "boolean ";
10599    | RConstString _ | RConstOptString _ | RString _
10600    | RBufferOut _ -> pr "String ";
10601    | RStringList _ -> pr "String[] ";
10602    | RStruct (_, typ) ->
10603        let name = java_name_of_struct typ in
10604        pr "%s " name;
10605    | RStructList (_, typ) ->
10606        let name = java_name_of_struct typ in
10607        pr "%s[] " name;
10608    | RHashtable _ -> pr "HashMap<String,String> ";
10609   );
10610
10611   if native then pr "_%s " name else pr "%s " name;
10612   pr "(";
10613   let needs_comma = ref false in
10614   if native then (
10615     pr "long g";
10616     needs_comma := true
10617   );
10618
10619   (* args *)
10620   List.iter (
10621     fun arg ->
10622       if !needs_comma then pr ", ";
10623       needs_comma := true;
10624
10625       match arg with
10626       | Pathname n
10627       | Device n | Dev_or_Path n
10628       | String n
10629       | OptString n
10630       | FileIn n
10631       | FileOut n
10632       | Key n ->
10633           pr "String %s" n
10634       | BufferIn n ->
10635           pr "byte[] %s" n
10636       | StringList n | DeviceList n ->
10637           pr "String[] %s" n
10638       | Bool n ->
10639           pr "boolean %s" n
10640       | Int n ->
10641           pr "int %s" n
10642       | Int64 n ->
10643           pr "long %s" n
10644   ) (snd style);
10645
10646   pr ")\n";
10647   pr "    throws LibGuestFSException";
10648   if semicolon then pr ";"
10649
10650 and generate_java_struct jtyp cols () =
10651   generate_header CStyle LGPLv2plus;
10652
10653   pr "\
10654 package com.redhat.et.libguestfs;
10655
10656 /**
10657  * Libguestfs %s structure.
10658  *
10659  * @author rjones
10660  * @see GuestFS
10661  */
10662 public class %s {
10663 " jtyp jtyp;
10664
10665   List.iter (
10666     function
10667     | name, FString
10668     | name, FUUID
10669     | name, FBuffer -> pr "  public String %s;\n" name
10670     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10671     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10672     | name, FChar -> pr "  public char %s;\n" name
10673     | name, FOptPercent ->
10674         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10675         pr "  public float %s;\n" name
10676   ) cols;
10677
10678   pr "}\n"
10679
10680 and generate_java_c () =
10681   generate_header CStyle LGPLv2plus;
10682
10683   pr "\
10684 #include <stdio.h>
10685 #include <stdlib.h>
10686 #include <string.h>
10687
10688 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10689 #include \"guestfs.h\"
10690
10691 /* Note that this function returns.  The exception is not thrown
10692  * until after the wrapper function returns.
10693  */
10694 static void
10695 throw_exception (JNIEnv *env, const char *msg)
10696 {
10697   jclass cl;
10698   cl = (*env)->FindClass (env,
10699                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10700   (*env)->ThrowNew (env, cl, msg);
10701 }
10702
10703 JNIEXPORT jlong JNICALL
10704 Java_com_redhat_et_libguestfs_GuestFS__1create
10705   (JNIEnv *env, jobject obj)
10706 {
10707   guestfs_h *g;
10708
10709   g = guestfs_create ();
10710   if (g == NULL) {
10711     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10712     return 0;
10713   }
10714   guestfs_set_error_handler (g, NULL, NULL);
10715   return (jlong) (long) g;
10716 }
10717
10718 JNIEXPORT void JNICALL
10719 Java_com_redhat_et_libguestfs_GuestFS__1close
10720   (JNIEnv *env, jobject obj, jlong jg)
10721 {
10722   guestfs_h *g = (guestfs_h *) (long) jg;
10723   guestfs_close (g);
10724 }
10725
10726 ";
10727
10728   List.iter (
10729     fun (name, style, _, _, _, _, _) ->
10730       pr "JNIEXPORT ";
10731       (match fst style with
10732        | RErr -> pr "void ";
10733        | RInt _ -> pr "jint ";
10734        | RInt64 _ -> pr "jlong ";
10735        | RBool _ -> pr "jboolean ";
10736        | RConstString _ | RConstOptString _ | RString _
10737        | RBufferOut _ -> pr "jstring ";
10738        | RStruct _ | RHashtable _ ->
10739            pr "jobject ";
10740        | RStringList _ | RStructList _ ->
10741            pr "jobjectArray ";
10742       );
10743       pr "JNICALL\n";
10744       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10745       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10746       pr "\n";
10747       pr "  (JNIEnv *env, jobject obj, jlong jg";
10748       List.iter (
10749         function
10750         | Pathname n
10751         | Device n | Dev_or_Path n
10752         | String n
10753         | OptString n
10754         | FileIn n
10755         | FileOut n
10756         | Key n ->
10757             pr ", jstring j%s" n
10758         | BufferIn n ->
10759             pr ", jbyteArray j%s" n
10760         | StringList n | DeviceList n ->
10761             pr ", jobjectArray j%s" n
10762         | Bool n ->
10763             pr ", jboolean j%s" n
10764         | Int n ->
10765             pr ", jint j%s" n
10766         | Int64 n ->
10767             pr ", jlong j%s" n
10768       ) (snd style);
10769       pr ")\n";
10770       pr "{\n";
10771       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10772       let error_code, no_ret =
10773         match fst style with
10774         | RErr -> pr "  int r;\n"; "-1", ""
10775         | RBool _
10776         | RInt _ -> pr "  int r;\n"; "-1", "0"
10777         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10778         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10779         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10780         | RString _ ->
10781             pr "  jstring jr;\n";
10782             pr "  char *r;\n"; "NULL", "NULL"
10783         | RStringList _ ->
10784             pr "  jobjectArray jr;\n";
10785             pr "  int r_len;\n";
10786             pr "  jclass cl;\n";
10787             pr "  jstring jstr;\n";
10788             pr "  char **r;\n"; "NULL", "NULL"
10789         | RStruct (_, typ) ->
10790             pr "  jobject jr;\n";
10791             pr "  jclass cl;\n";
10792             pr "  jfieldID fl;\n";
10793             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10794         | RStructList (_, typ) ->
10795             pr "  jobjectArray jr;\n";
10796             pr "  jclass cl;\n";
10797             pr "  jfieldID fl;\n";
10798             pr "  jobject jfl;\n";
10799             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10800         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10801         | RBufferOut _ ->
10802             pr "  jstring jr;\n";
10803             pr "  char *r;\n";
10804             pr "  size_t size;\n";
10805             "NULL", "NULL" in
10806       List.iter (
10807         function
10808         | Pathname n
10809         | Device n | Dev_or_Path n
10810         | String n
10811         | OptString n
10812         | FileIn n
10813         | FileOut n
10814         | Key n ->
10815             pr "  const char *%s;\n" n
10816         | BufferIn n ->
10817             pr "  jbyte *%s;\n" n;
10818             pr "  size_t %s_size;\n" n
10819         | StringList n | DeviceList n ->
10820             pr "  int %s_len;\n" n;
10821             pr "  const char **%s;\n" n
10822         | Bool n
10823         | Int n ->
10824             pr "  int %s;\n" n
10825         | Int64 n ->
10826             pr "  int64_t %s;\n" n
10827       ) (snd style);
10828
10829       let needs_i =
10830         (match fst style with
10831          | RStringList _ | RStructList _ -> true
10832          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10833          | RConstOptString _
10834          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10835           List.exists (function
10836                        | StringList _ -> true
10837                        | DeviceList _ -> true
10838                        | _ -> false) (snd style) in
10839       if needs_i then
10840         pr "  size_t i;\n";
10841
10842       pr "\n";
10843
10844       (* Get the parameters. *)
10845       List.iter (
10846         function
10847         | Pathname n
10848         | Device n | Dev_or_Path n
10849         | String n
10850         | FileIn n
10851         | FileOut n
10852         | Key n ->
10853             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10854         | OptString n ->
10855             (* This is completely undocumented, but Java null becomes
10856              * a NULL parameter.
10857              *)
10858             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10859         | BufferIn n ->
10860             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10861             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10862         | StringList n | DeviceList n ->
10863             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10864             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10865             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10866             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10867               n;
10868             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10869             pr "  }\n";
10870             pr "  %s[%s_len] = NULL;\n" n n;
10871         | Bool n
10872         | Int n
10873         | Int64 n ->
10874             pr "  %s = j%s;\n" n n
10875       ) (snd style);
10876
10877       (* Make the call. *)
10878       pr "  r = guestfs_%s " name;
10879       generate_c_call_args ~handle:"g" style;
10880       pr ";\n";
10881
10882       (* Release the parameters. *)
10883       List.iter (
10884         function
10885         | Pathname n
10886         | Device n | Dev_or_Path n
10887         | String n
10888         | FileIn n
10889         | FileOut n
10890         | Key n ->
10891             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10892         | OptString n ->
10893             pr "  if (j%s)\n" n;
10894             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10895         | BufferIn n ->
10896             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10897         | StringList n | DeviceList n ->
10898             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10899             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10900               n;
10901             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10902             pr "  }\n";
10903             pr "  free (%s);\n" n
10904         | Bool n
10905         | Int n
10906         | Int64 n -> ()
10907       ) (snd style);
10908
10909       (* Check for errors. *)
10910       pr "  if (r == %s) {\n" error_code;
10911       pr "    throw_exception (env, guestfs_last_error (g));\n";
10912       pr "    return %s;\n" no_ret;
10913       pr "  }\n";
10914
10915       (* Return value. *)
10916       (match fst style with
10917        | RErr -> ()
10918        | RInt _ -> pr "  return (jint) r;\n"
10919        | RBool _ -> pr "  return (jboolean) r;\n"
10920        | RInt64 _ -> pr "  return (jlong) r;\n"
10921        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10922        | RConstOptString _ ->
10923            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10924        | RString _ ->
10925            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10926            pr "  free (r);\n";
10927            pr "  return jr;\n"
10928        | RStringList _ ->
10929            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10930            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10931            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10932            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10933            pr "  for (i = 0; i < r_len; ++i) {\n";
10934            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10935            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10936            pr "    free (r[i]);\n";
10937            pr "  }\n";
10938            pr "  free (r);\n";
10939            pr "  return jr;\n"
10940        | RStruct (_, typ) ->
10941            let jtyp = java_name_of_struct typ in
10942            let cols = cols_of_struct typ in
10943            generate_java_struct_return typ jtyp cols
10944        | RStructList (_, typ) ->
10945            let jtyp = java_name_of_struct typ in
10946            let cols = cols_of_struct typ in
10947            generate_java_struct_list_return typ jtyp cols
10948        | RHashtable _ ->
10949            (* XXX *)
10950            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10951            pr "  return NULL;\n"
10952        | RBufferOut _ ->
10953            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10954            pr "  free (r);\n";
10955            pr "  return jr;\n"
10956       );
10957
10958       pr "}\n";
10959       pr "\n"
10960   ) all_functions
10961
10962 and generate_java_struct_return typ jtyp cols =
10963   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10964   pr "  jr = (*env)->AllocObject (env, cl);\n";
10965   List.iter (
10966     function
10967     | name, FString ->
10968         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10969         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10970     | name, FUUID ->
10971         pr "  {\n";
10972         pr "    char s[33];\n";
10973         pr "    memcpy (s, r->%s, 32);\n" name;
10974         pr "    s[32] = 0;\n";
10975         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10976         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10977         pr "  }\n";
10978     | name, FBuffer ->
10979         pr "  {\n";
10980         pr "    int len = r->%s_len;\n" name;
10981         pr "    char s[len+1];\n";
10982         pr "    memcpy (s, r->%s, len);\n" name;
10983         pr "    s[len] = 0;\n";
10984         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10985         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10986         pr "  }\n";
10987     | name, (FBytes|FUInt64|FInt64) ->
10988         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10989         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10990     | name, (FUInt32|FInt32) ->
10991         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10992         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10993     | name, FOptPercent ->
10994         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10995         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10996     | name, FChar ->
10997         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10998         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10999   ) cols;
11000   pr "  free (r);\n";
11001   pr "  return jr;\n"
11002
11003 and generate_java_struct_list_return typ jtyp cols =
11004   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
11005   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
11006   pr "  for (i = 0; i < r->len; ++i) {\n";
11007   pr "    jfl = (*env)->AllocObject (env, cl);\n";
11008   List.iter (
11009     function
11010     | name, FString ->
11011         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
11012         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
11013     | name, FUUID ->
11014         pr "    {\n";
11015         pr "      char s[33];\n";
11016         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
11017         pr "      s[32] = 0;\n";
11018         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
11019         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
11020         pr "    }\n";
11021     | name, FBuffer ->
11022         pr "    {\n";
11023         pr "      int len = r->val[i].%s_len;\n" name;
11024         pr "      char s[len+1];\n";
11025         pr "      memcpy (s, r->val[i].%s, len);\n" name;
11026         pr "      s[len] = 0;\n";
11027         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
11028         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
11029         pr "    }\n";
11030     | name, (FBytes|FUInt64|FInt64) ->
11031         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
11032         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
11033     | name, (FUInt32|FInt32) ->
11034         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
11035         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
11036     | name, FOptPercent ->
11037         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
11038         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
11039     | name, FChar ->
11040         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
11041         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
11042   ) cols;
11043   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
11044   pr "  }\n";
11045   pr "  guestfs_free_%s_list (r);\n" typ;
11046   pr "  return jr;\n"
11047
11048 and generate_java_makefile_inc () =
11049   generate_header HashStyle GPLv2plus;
11050
11051   pr "java_built_sources = \\\n";
11052   List.iter (
11053     fun (typ, jtyp) ->
11054         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
11055   ) java_structs;
11056   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
11057
11058 and generate_haskell_hs () =
11059   generate_header HaskellStyle LGPLv2plus;
11060
11061   (* XXX We only know how to generate partial FFI for Haskell
11062    * at the moment.  Please help out!
11063    *)
11064   let can_generate style =
11065     match style with
11066     | RErr, _
11067     | RInt _, _
11068     | RInt64 _, _ -> true
11069     | RBool _, _
11070     | RConstString _, _
11071     | RConstOptString _, _
11072     | RString _, _
11073     | RStringList _, _
11074     | RStruct _, _
11075     | RStructList _, _
11076     | RHashtable _, _
11077     | RBufferOut _, _ -> false in
11078
11079   pr "\
11080 {-# INCLUDE <guestfs.h> #-}
11081 {-# LANGUAGE ForeignFunctionInterface #-}
11082
11083 module Guestfs (
11084   create";
11085
11086   (* List out the names of the actions we want to export. *)
11087   List.iter (
11088     fun (name, style, _, _, _, _, _) ->
11089       if can_generate style then pr ",\n  %s" name
11090   ) all_functions;
11091
11092   pr "
11093   ) where
11094
11095 -- Unfortunately some symbols duplicate ones already present
11096 -- in Prelude.  We don't know which, so we hard-code a list
11097 -- here.
11098 import Prelude hiding (truncate)
11099
11100 import Foreign
11101 import Foreign.C
11102 import Foreign.C.Types
11103 import IO
11104 import Control.Exception
11105 import Data.Typeable
11106
11107 data GuestfsS = GuestfsS            -- represents the opaque C struct
11108 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
11109 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
11110
11111 -- XXX define properly later XXX
11112 data PV = PV
11113 data VG = VG
11114 data LV = LV
11115 data IntBool = IntBool
11116 data Stat = Stat
11117 data StatVFS = StatVFS
11118 data Hashtable = Hashtable
11119
11120 foreign import ccall unsafe \"guestfs_create\" c_create
11121   :: IO GuestfsP
11122 foreign import ccall unsafe \"&guestfs_close\" c_close
11123   :: FunPtr (GuestfsP -> IO ())
11124 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
11125   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
11126
11127 create :: IO GuestfsH
11128 create = do
11129   p <- c_create
11130   c_set_error_handler p nullPtr nullPtr
11131   h <- newForeignPtr c_close p
11132   return h
11133
11134 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
11135   :: GuestfsP -> IO CString
11136
11137 -- last_error :: GuestfsH -> IO (Maybe String)
11138 -- last_error h = do
11139 --   str <- withForeignPtr h (\\p -> c_last_error p)
11140 --   maybePeek peekCString str
11141
11142 last_error :: GuestfsH -> IO (String)
11143 last_error h = do
11144   str <- withForeignPtr h (\\p -> c_last_error p)
11145   if (str == nullPtr)
11146     then return \"no error\"
11147     else peekCString str
11148
11149 ";
11150
11151   (* Generate wrappers for each foreign function. *)
11152   List.iter (
11153     fun (name, style, _, _, _, _, _) ->
11154       if can_generate style then (
11155         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
11156         pr "  :: ";
11157         generate_haskell_prototype ~handle:"GuestfsP" style;
11158         pr "\n";
11159         pr "\n";
11160         pr "%s :: " name;
11161         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
11162         pr "\n";
11163         pr "%s %s = do\n" name
11164           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
11165         pr "  r <- ";
11166         (* Convert pointer arguments using with* functions. *)
11167         List.iter (
11168           function
11169           | FileIn n
11170           | FileOut n
11171           | Pathname n | Device n | Dev_or_Path n | String n | Key n ->
11172               pr "withCString %s $ \\%s -> " n n
11173           | BufferIn n ->
11174               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
11175           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
11176           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
11177           | Bool _ | Int _ | Int64 _ -> ()
11178         ) (snd style);
11179         (* Convert integer arguments. *)
11180         let args =
11181           List.map (
11182             function
11183             | Bool n -> sprintf "(fromBool %s)" n
11184             | Int n -> sprintf "(fromIntegral %s)" n
11185             | Int64 n -> sprintf "(fromIntegral %s)" n
11186             | FileIn n | FileOut n
11187             | Pathname n | Device n | Dev_or_Path n
11188             | String n | OptString n
11189             | StringList n | DeviceList n
11190             | Key n -> n
11191             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
11192           ) (snd style) in
11193         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
11194           (String.concat " " ("p" :: args));
11195         (match fst style with
11196          | RErr | RInt _ | RInt64 _ | RBool _ ->
11197              pr "  if (r == -1)\n";
11198              pr "    then do\n";
11199              pr "      err <- last_error h\n";
11200              pr "      fail err\n";
11201          | RConstString _ | RConstOptString _ | RString _
11202          | RStringList _ | RStruct _
11203          | RStructList _ | RHashtable _ | RBufferOut _ ->
11204              pr "  if (r == nullPtr)\n";
11205              pr "    then do\n";
11206              pr "      err <- last_error h\n";
11207              pr "      fail err\n";
11208         );
11209         (match fst style with
11210          | RErr ->
11211              pr "    else return ()\n"
11212          | RInt _ ->
11213              pr "    else return (fromIntegral r)\n"
11214          | RInt64 _ ->
11215              pr "    else return (fromIntegral r)\n"
11216          | RBool _ ->
11217              pr "    else return (toBool r)\n"
11218          | RConstString _
11219          | RConstOptString _
11220          | RString _
11221          | RStringList _
11222          | RStruct _
11223          | RStructList _
11224          | RHashtable _
11225          | RBufferOut _ ->
11226              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
11227         );
11228         pr "\n";
11229       )
11230   ) all_functions
11231
11232 and generate_haskell_prototype ~handle ?(hs = false) style =
11233   pr "%s -> " handle;
11234   let string = if hs then "String" else "CString" in
11235   let int = if hs then "Int" else "CInt" in
11236   let bool = if hs then "Bool" else "CInt" in
11237   let int64 = if hs then "Integer" else "Int64" in
11238   List.iter (
11239     fun arg ->
11240       (match arg with
11241        | Pathname _ | Device _ | Dev_or_Path _ | String _ | Key _ ->
11242            pr "%s" string
11243        | BufferIn _ ->
11244            if hs then pr "String"
11245            else pr "CString -> CInt"
11246        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
11247        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
11248        | Bool _ -> pr "%s" bool
11249        | Int _ -> pr "%s" int
11250        | Int64 _ -> pr "%s" int
11251        | FileIn _ -> pr "%s" string
11252        | FileOut _ -> pr "%s" string
11253       );
11254       pr " -> ";
11255   ) (snd style);
11256   pr "IO (";
11257   (match fst style with
11258    | RErr -> if not hs then pr "CInt"
11259    | RInt _ -> pr "%s" int
11260    | RInt64 _ -> pr "%s" int64
11261    | RBool _ -> pr "%s" bool
11262    | RConstString _ -> pr "%s" string
11263    | RConstOptString _ -> pr "Maybe %s" string
11264    | RString _ -> pr "%s" string
11265    | RStringList _ -> pr "[%s]" string
11266    | RStruct (_, typ) ->
11267        let name = java_name_of_struct typ in
11268        pr "%s" name
11269    | RStructList (_, typ) ->
11270        let name = java_name_of_struct typ in
11271        pr "[%s]" name
11272    | RHashtable _ -> pr "Hashtable"
11273    | RBufferOut _ -> pr "%s" string
11274   );
11275   pr ")"
11276
11277 and generate_csharp () =
11278   generate_header CPlusPlusStyle LGPLv2plus;
11279
11280   (* XXX Make this configurable by the C# assembly users. *)
11281   let library = "libguestfs.so.0" in
11282
11283   pr "\
11284 // These C# bindings are highly experimental at present.
11285 //
11286 // Firstly they only work on Linux (ie. Mono).  In order to get them
11287 // to work on Windows (ie. .Net) you would need to port the library
11288 // itself to Windows first.
11289 //
11290 // The second issue is that some calls are known to be incorrect and
11291 // can cause Mono to segfault.  Particularly: calls which pass or
11292 // return string[], or return any structure value.  This is because
11293 // we haven't worked out the correct way to do this from C#.
11294 //
11295 // The third issue is that when compiling you get a lot of warnings.
11296 // We are not sure whether the warnings are important or not.
11297 //
11298 // Fourthly we do not routinely build or test these bindings as part
11299 // of the make && make check cycle, which means that regressions might
11300 // go unnoticed.
11301 //
11302 // Suggestions and patches are welcome.
11303
11304 // To compile:
11305 //
11306 // gmcs Libguestfs.cs
11307 // mono Libguestfs.exe
11308 //
11309 // (You'll probably want to add a Test class / static main function
11310 // otherwise this won't do anything useful).
11311
11312 using System;
11313 using System.IO;
11314 using System.Runtime.InteropServices;
11315 using System.Runtime.Serialization;
11316 using System.Collections;
11317
11318 namespace Guestfs
11319 {
11320   class Error : System.ApplicationException
11321   {
11322     public Error (string message) : base (message) {}
11323     protected Error (SerializationInfo info, StreamingContext context) {}
11324   }
11325
11326   class Guestfs
11327   {
11328     IntPtr _handle;
11329
11330     [DllImport (\"%s\")]
11331     static extern IntPtr guestfs_create ();
11332
11333     public Guestfs ()
11334     {
11335       _handle = guestfs_create ();
11336       if (_handle == IntPtr.Zero)
11337         throw new Error (\"could not create guestfs handle\");
11338     }
11339
11340     [DllImport (\"%s\")]
11341     static extern void guestfs_close (IntPtr h);
11342
11343     ~Guestfs ()
11344     {
11345       guestfs_close (_handle);
11346     }
11347
11348     [DllImport (\"%s\")]
11349     static extern string guestfs_last_error (IntPtr h);
11350
11351 " library library library;
11352
11353   (* Generate C# structure bindings.  We prefix struct names with
11354    * underscore because C# cannot have conflicting struct names and
11355    * method names (eg. "class stat" and "stat").
11356    *)
11357   List.iter (
11358     fun (typ, cols) ->
11359       pr "    [StructLayout (LayoutKind.Sequential)]\n";
11360       pr "    public class _%s {\n" typ;
11361       List.iter (
11362         function
11363         | name, FChar -> pr "      char %s;\n" name
11364         | name, FString -> pr "      string %s;\n" name
11365         | name, FBuffer ->
11366             pr "      uint %s_len;\n" name;
11367             pr "      string %s;\n" name
11368         | name, FUUID ->
11369             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11370             pr "      string %s;\n" name
11371         | name, FUInt32 -> pr "      uint %s;\n" name
11372         | name, FInt32 -> pr "      int %s;\n" name
11373         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
11374         | name, FInt64 -> pr "      long %s;\n" name
11375         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
11376       ) cols;
11377       pr "    }\n";
11378       pr "\n"
11379   ) structs;
11380
11381   (* Generate C# function bindings. *)
11382   List.iter (
11383     fun (name, style, _, _, _, shortdesc, _) ->
11384       let rec csharp_return_type () =
11385         match fst style with
11386         | RErr -> "void"
11387         | RBool n -> "bool"
11388         | RInt n -> "int"
11389         | RInt64 n -> "long"
11390         | RConstString n
11391         | RConstOptString n
11392         | RString n
11393         | RBufferOut n -> "string"
11394         | RStruct (_,n) -> "_" ^ n
11395         | RHashtable n -> "Hashtable"
11396         | RStringList n -> "string[]"
11397         | RStructList (_,n) -> sprintf "_%s[]" n
11398
11399       and c_return_type () =
11400         match fst style with
11401         | RErr
11402         | RBool _
11403         | RInt _ -> "int"
11404         | RInt64 _ -> "long"
11405         | RConstString _
11406         | RConstOptString _
11407         | RString _
11408         | RBufferOut _ -> "string"
11409         | RStruct (_,n) -> "_" ^ n
11410         | RHashtable _
11411         | RStringList _ -> "string[]"
11412         | RStructList (_,n) -> sprintf "_%s[]" n
11413
11414       and c_error_comparison () =
11415         match fst style with
11416         | RErr
11417         | RBool _
11418         | RInt _
11419         | RInt64 _ -> "== -1"
11420         | RConstString _
11421         | RConstOptString _
11422         | RString _
11423         | RBufferOut _
11424         | RStruct (_,_)
11425         | RHashtable _
11426         | RStringList _
11427         | RStructList (_,_) -> "== null"
11428
11429       and generate_extern_prototype () =
11430         pr "    static extern %s guestfs_%s (IntPtr h"
11431           (c_return_type ()) name;
11432         List.iter (
11433           function
11434           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11435           | FileIn n | FileOut n
11436           | Key n
11437           | BufferIn n ->
11438               pr ", [In] string %s" n
11439           | StringList n | DeviceList n ->
11440               pr ", [In] string[] %s" n
11441           | Bool n ->
11442               pr ", bool %s" n
11443           | Int n ->
11444               pr ", int %s" n
11445           | Int64 n ->
11446               pr ", long %s" n
11447         ) (snd style);
11448         pr ");\n"
11449
11450       and generate_public_prototype () =
11451         pr "    public %s %s (" (csharp_return_type ()) name;
11452         let comma = ref false in
11453         let next () =
11454           if !comma then pr ", ";
11455           comma := true
11456         in
11457         List.iter (
11458           function
11459           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11460           | FileIn n | FileOut n
11461           | Key n
11462           | BufferIn n ->
11463               next (); pr "string %s" n
11464           | StringList n | DeviceList n ->
11465               next (); pr "string[] %s" n
11466           | Bool n ->
11467               next (); pr "bool %s" n
11468           | Int n ->
11469               next (); pr "int %s" n
11470           | Int64 n ->
11471               next (); pr "long %s" n
11472         ) (snd style);
11473         pr ")\n"
11474
11475       and generate_call () =
11476         pr "guestfs_%s (_handle" name;
11477         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11478         pr ");\n";
11479       in
11480
11481       pr "    [DllImport (\"%s\")]\n" library;
11482       generate_extern_prototype ();
11483       pr "\n";
11484       pr "    /// <summary>\n";
11485       pr "    /// %s\n" shortdesc;
11486       pr "    /// </summary>\n";
11487       generate_public_prototype ();
11488       pr "    {\n";
11489       pr "      %s r;\n" (c_return_type ());
11490       pr "      r = ";
11491       generate_call ();
11492       pr "      if (r %s)\n" (c_error_comparison ());
11493       pr "        throw new Error (guestfs_last_error (_handle));\n";
11494       (match fst style with
11495        | RErr -> ()
11496        | RBool _ ->
11497            pr "      return r != 0 ? true : false;\n"
11498        | RHashtable _ ->
11499            pr "      Hashtable rr = new Hashtable ();\n";
11500            pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
11501            pr "        rr.Add (r[i], r[i+1]);\n";
11502            pr "      return rr;\n"
11503        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11504        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11505        | RStructList _ ->
11506            pr "      return r;\n"
11507       );
11508       pr "    }\n";
11509       pr "\n";
11510   ) all_functions_sorted;
11511
11512   pr "  }
11513 }
11514 "
11515
11516 and generate_bindtests () =
11517   generate_header CStyle LGPLv2plus;
11518
11519   pr "\
11520 #include <stdio.h>
11521 #include <stdlib.h>
11522 #include <inttypes.h>
11523 #include <string.h>
11524
11525 #include \"guestfs.h\"
11526 #include \"guestfs-internal.h\"
11527 #include \"guestfs-internal-actions.h\"
11528 #include \"guestfs_protocol.h\"
11529
11530 #define error guestfs_error
11531 #define safe_calloc guestfs_safe_calloc
11532 #define safe_malloc guestfs_safe_malloc
11533
11534 static void
11535 print_strings (char *const *argv)
11536 {
11537   size_t argc;
11538
11539   printf (\"[\");
11540   for (argc = 0; argv[argc] != NULL; ++argc) {
11541     if (argc > 0) printf (\", \");
11542     printf (\"\\\"%%s\\\"\", argv[argc]);
11543   }
11544   printf (\"]\\n\");
11545 }
11546
11547 /* The test0 function prints its parameters to stdout. */
11548 ";
11549
11550   let test0, tests =
11551     match test_functions with
11552     | [] -> assert false
11553     | test0 :: tests -> test0, tests in
11554
11555   let () =
11556     let (name, style, _, _, _, _, _) = test0 in
11557     generate_prototype ~extern:false ~semicolon:false ~newline:true
11558       ~handle:"g" ~prefix:"guestfs__" name style;
11559     pr "{\n";
11560     List.iter (
11561       function
11562       | Pathname n
11563       | Device n | Dev_or_Path n
11564       | String n
11565       | FileIn n
11566       | FileOut n
11567       | Key n -> pr "  printf (\"%%s\\n\", %s);\n" n
11568       | BufferIn n ->
11569           pr "  {\n";
11570           pr "    size_t i;\n";
11571           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11572           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11573           pr "    printf (\"\\n\");\n";
11574           pr "  }\n";
11575       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11576       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11577       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11578       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11579       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11580     ) (snd style);
11581     pr "  /* Java changes stdout line buffering so we need this: */\n";
11582     pr "  fflush (stdout);\n";
11583     pr "  return 0;\n";
11584     pr "}\n";
11585     pr "\n" in
11586
11587   List.iter (
11588     fun (name, style, _, _, _, _, _) ->
11589       if String.sub name (String.length name - 3) 3 <> "err" then (
11590         pr "/* Test normal return. */\n";
11591         generate_prototype ~extern:false ~semicolon:false ~newline:true
11592           ~handle:"g" ~prefix:"guestfs__" name style;
11593         pr "{\n";
11594         (match fst style with
11595          | RErr ->
11596              pr "  return 0;\n"
11597          | RInt _ ->
11598              pr "  int r;\n";
11599              pr "  sscanf (val, \"%%d\", &r);\n";
11600              pr "  return r;\n"
11601          | RInt64 _ ->
11602              pr "  int64_t r;\n";
11603              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11604              pr "  return r;\n"
11605          | RBool _ ->
11606              pr "  return STREQ (val, \"true\");\n"
11607          | RConstString _
11608          | RConstOptString _ ->
11609              (* Can't return the input string here.  Return a static
11610               * string so we ensure we get a segfault if the caller
11611               * tries to free it.
11612               *)
11613              pr "  return \"static string\";\n"
11614          | RString _ ->
11615              pr "  return strdup (val);\n"
11616          | RStringList _ ->
11617              pr "  char **strs;\n";
11618              pr "  int n, i;\n";
11619              pr "  sscanf (val, \"%%d\", &n);\n";
11620              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11621              pr "  for (i = 0; i < n; ++i) {\n";
11622              pr "    strs[i] = safe_malloc (g, 16);\n";
11623              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11624              pr "  }\n";
11625              pr "  strs[n] = NULL;\n";
11626              pr "  return strs;\n"
11627          | RStruct (_, typ) ->
11628              pr "  struct guestfs_%s *r;\n" typ;
11629              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11630              pr "  return r;\n"
11631          | RStructList (_, typ) ->
11632              pr "  struct guestfs_%s_list *r;\n" typ;
11633              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11634              pr "  sscanf (val, \"%%d\", &r->len);\n";
11635              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11636              pr "  return r;\n"
11637          | RHashtable _ ->
11638              pr "  char **strs;\n";
11639              pr "  int n, i;\n";
11640              pr "  sscanf (val, \"%%d\", &n);\n";
11641              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11642              pr "  for (i = 0; i < n; ++i) {\n";
11643              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11644              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11645              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11646              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11647              pr "  }\n";
11648              pr "  strs[n*2] = NULL;\n";
11649              pr "  return strs;\n"
11650          | RBufferOut _ ->
11651              pr "  return strdup (val);\n"
11652         );
11653         pr "}\n";
11654         pr "\n"
11655       ) else (
11656         pr "/* Test error return. */\n";
11657         generate_prototype ~extern:false ~semicolon:false ~newline:true
11658           ~handle:"g" ~prefix:"guestfs__" name style;
11659         pr "{\n";
11660         pr "  error (g, \"error\");\n";
11661         (match fst style with
11662          | RErr | RInt _ | RInt64 _ | RBool _ ->
11663              pr "  return -1;\n"
11664          | RConstString _ | RConstOptString _
11665          | RString _ | RStringList _ | RStruct _
11666          | RStructList _
11667          | RHashtable _
11668          | RBufferOut _ ->
11669              pr "  return NULL;\n"
11670         );
11671         pr "}\n";
11672         pr "\n"
11673       )
11674   ) tests
11675
11676 and generate_ocaml_bindtests () =
11677   generate_header OCamlStyle GPLv2plus;
11678
11679   pr "\
11680 let () =
11681   let g = Guestfs.create () in
11682 ";
11683
11684   let mkargs args =
11685     String.concat " " (
11686       List.map (
11687         function
11688         | CallString s -> "\"" ^ s ^ "\""
11689         | CallOptString None -> "None"
11690         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11691         | CallStringList xs ->
11692             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11693         | CallInt i when i >= 0 -> string_of_int i
11694         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11695         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11696         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11697         | CallBool b -> string_of_bool b
11698         | CallBuffer s -> sprintf "%S" s
11699       ) args
11700     )
11701   in
11702
11703   generate_lang_bindtests (
11704     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11705   );
11706
11707   pr "print_endline \"EOF\"\n"
11708
11709 and generate_perl_bindtests () =
11710   pr "#!/usr/bin/perl -w\n";
11711   generate_header HashStyle GPLv2plus;
11712
11713   pr "\
11714 use strict;
11715
11716 use Sys::Guestfs;
11717
11718 my $g = Sys::Guestfs->new ();
11719 ";
11720
11721   let mkargs args =
11722     String.concat ", " (
11723       List.map (
11724         function
11725         | CallString s -> "\"" ^ s ^ "\""
11726         | CallOptString None -> "undef"
11727         | CallOptString (Some s) -> sprintf "\"%s\"" s
11728         | CallStringList xs ->
11729             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11730         | CallInt i -> string_of_int i
11731         | CallInt64 i -> Int64.to_string i
11732         | CallBool b -> if b then "1" else "0"
11733         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11734       ) args
11735     )
11736   in
11737
11738   generate_lang_bindtests (
11739     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11740   );
11741
11742   pr "print \"EOF\\n\"\n"
11743
11744 and generate_python_bindtests () =
11745   generate_header HashStyle GPLv2plus;
11746
11747   pr "\
11748 import guestfs
11749
11750 g = guestfs.GuestFS ()
11751 ";
11752
11753   let mkargs args =
11754     String.concat ", " (
11755       List.map (
11756         function
11757         | CallString s -> "\"" ^ s ^ "\""
11758         | CallOptString None -> "None"
11759         | CallOptString (Some s) -> sprintf "\"%s\"" s
11760         | CallStringList xs ->
11761             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11762         | CallInt i -> string_of_int i
11763         | CallInt64 i -> Int64.to_string i
11764         | CallBool b -> if b then "1" else "0"
11765         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11766       ) args
11767     )
11768   in
11769
11770   generate_lang_bindtests (
11771     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11772   );
11773
11774   pr "print \"EOF\"\n"
11775
11776 and generate_ruby_bindtests () =
11777   generate_header HashStyle GPLv2plus;
11778
11779   pr "\
11780 require 'guestfs'
11781
11782 g = Guestfs::create()
11783 ";
11784
11785   let mkargs args =
11786     String.concat ", " (
11787       List.map (
11788         function
11789         | CallString s -> "\"" ^ s ^ "\""
11790         | CallOptString None -> "nil"
11791         | CallOptString (Some s) -> sprintf "\"%s\"" s
11792         | CallStringList xs ->
11793             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11794         | CallInt i -> string_of_int i
11795         | CallInt64 i -> Int64.to_string i
11796         | CallBool b -> string_of_bool b
11797         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11798       ) args
11799     )
11800   in
11801
11802   generate_lang_bindtests (
11803     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11804   );
11805
11806   pr "print \"EOF\\n\"\n"
11807
11808 and generate_java_bindtests () =
11809   generate_header CStyle GPLv2plus;
11810
11811   pr "\
11812 import com.redhat.et.libguestfs.*;
11813
11814 public class Bindtests {
11815     public static void main (String[] argv)
11816     {
11817         try {
11818             GuestFS g = new GuestFS ();
11819 ";
11820
11821   let mkargs args =
11822     String.concat ", " (
11823       List.map (
11824         function
11825         | CallString s -> "\"" ^ s ^ "\""
11826         | CallOptString None -> "null"
11827         | CallOptString (Some s) -> sprintf "\"%s\"" s
11828         | CallStringList xs ->
11829             "new String[]{" ^
11830               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11831         | CallInt i -> string_of_int i
11832         | CallInt64 i -> Int64.to_string i
11833         | CallBool b -> string_of_bool b
11834         | CallBuffer s ->
11835             "new byte[] { " ^ String.concat "," (
11836               map_chars (fun c -> string_of_int (Char.code c)) s
11837             ) ^ " }"
11838       ) args
11839     )
11840   in
11841
11842   generate_lang_bindtests (
11843     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11844   );
11845
11846   pr "
11847             System.out.println (\"EOF\");
11848         }
11849         catch (Exception exn) {
11850             System.err.println (exn);
11851             System.exit (1);
11852         }
11853     }
11854 }
11855 "
11856
11857 and generate_haskell_bindtests () =
11858   generate_header HaskellStyle GPLv2plus;
11859
11860   pr "\
11861 module Bindtests where
11862 import qualified Guestfs
11863
11864 main = do
11865   g <- Guestfs.create
11866 ";
11867
11868   let mkargs args =
11869     String.concat " " (
11870       List.map (
11871         function
11872         | CallString s -> "\"" ^ s ^ "\""
11873         | CallOptString None -> "Nothing"
11874         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11875         | CallStringList xs ->
11876             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11877         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11878         | CallInt i -> string_of_int i
11879         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11880         | CallInt64 i -> Int64.to_string i
11881         | CallBool true -> "True"
11882         | CallBool false -> "False"
11883         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11884       ) args
11885     )
11886   in
11887
11888   generate_lang_bindtests (
11889     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11890   );
11891
11892   pr "  putStrLn \"EOF\"\n"
11893
11894 (* Language-independent bindings tests - we do it this way to
11895  * ensure there is parity in testing bindings across all languages.
11896  *)
11897 and generate_lang_bindtests call =
11898   call "test0" [CallString "abc"; CallOptString (Some "def");
11899                 CallStringList []; CallBool false;
11900                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11901                 CallBuffer "abc\000abc"];
11902   call "test0" [CallString "abc"; CallOptString None;
11903                 CallStringList []; CallBool false;
11904                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11905                 CallBuffer "abc\000abc"];
11906   call "test0" [CallString ""; CallOptString (Some "def");
11907                 CallStringList []; CallBool false;
11908                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11909                 CallBuffer "abc\000abc"];
11910   call "test0" [CallString ""; CallOptString (Some "");
11911                 CallStringList []; CallBool false;
11912                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11913                 CallBuffer "abc\000abc"];
11914   call "test0" [CallString "abc"; CallOptString (Some "def");
11915                 CallStringList ["1"]; CallBool false;
11916                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11917                 CallBuffer "abc\000abc"];
11918   call "test0" [CallString "abc"; CallOptString (Some "def");
11919                 CallStringList ["1"; "2"]; CallBool false;
11920                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11921                 CallBuffer "abc\000abc"];
11922   call "test0" [CallString "abc"; CallOptString (Some "def");
11923                 CallStringList ["1"]; CallBool true;
11924                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11925                 CallBuffer "abc\000abc"];
11926   call "test0" [CallString "abc"; CallOptString (Some "def");
11927                 CallStringList ["1"]; CallBool false;
11928                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11929                 CallBuffer "abc\000abc"];
11930   call "test0" [CallString "abc"; CallOptString (Some "def");
11931                 CallStringList ["1"]; CallBool false;
11932                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11933                 CallBuffer "abc\000abc"];
11934   call "test0" [CallString "abc"; CallOptString (Some "def");
11935                 CallStringList ["1"]; CallBool false;
11936                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11937                 CallBuffer "abc\000abc"];
11938   call "test0" [CallString "abc"; CallOptString (Some "def");
11939                 CallStringList ["1"]; CallBool false;
11940                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11941                 CallBuffer "abc\000abc"];
11942   call "test0" [CallString "abc"; CallOptString (Some "def");
11943                 CallStringList ["1"]; CallBool false;
11944                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11945                 CallBuffer "abc\000abc"];
11946   call "test0" [CallString "abc"; CallOptString (Some "def");
11947                 CallStringList ["1"]; CallBool false;
11948                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11949                 CallBuffer "abc\000abc"]
11950
11951 (* XXX Add here tests of the return and error functions. *)
11952
11953 (* Code to generator bindings for virt-inspector.  Currently only
11954  * implemented for OCaml code (for virt-p2v 2.0).
11955  *)
11956 let rng_input = "inspector/virt-inspector.rng"
11957
11958 (* Read the input file and parse it into internal structures.  This is
11959  * by no means a complete RELAX NG parser, but is just enough to be
11960  * able to parse the specific input file.
11961  *)
11962 type rng =
11963   | Element of string * rng list        (* <element name=name/> *)
11964   | Attribute of string * rng list        (* <attribute name=name/> *)
11965   | Interleave of rng list                (* <interleave/> *)
11966   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11967   | OneOrMore of rng                        (* <oneOrMore/> *)
11968   | Optional of rng                        (* <optional/> *)
11969   | Choice of string list                (* <choice><value/>*</choice> *)
11970   | Value of string                        (* <value>str</value> *)
11971   | Text                                (* <text/> *)
11972
11973 let rec string_of_rng = function
11974   | Element (name, xs) ->
11975       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11976   | Attribute (name, xs) ->
11977       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11978   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11979   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11980   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11981   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11982   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11983   | Value value -> "Value \"" ^ value ^ "\""
11984   | Text -> "Text"
11985
11986 and string_of_rng_list xs =
11987   String.concat ", " (List.map string_of_rng xs)
11988
11989 let rec parse_rng ?defines context = function
11990   | [] -> []
11991   | Xml.Element ("element", ["name", name], children) :: rest ->
11992       Element (name, parse_rng ?defines context children)
11993       :: parse_rng ?defines context rest
11994   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11995       Attribute (name, parse_rng ?defines context children)
11996       :: parse_rng ?defines context rest
11997   | Xml.Element ("interleave", [], children) :: rest ->
11998       Interleave (parse_rng ?defines context children)
11999       :: parse_rng ?defines context rest
12000   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
12001       let rng = parse_rng ?defines context [child] in
12002       (match rng with
12003        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
12004        | _ ->
12005            failwithf "%s: <zeroOrMore> contains more than one child element"
12006              context
12007       )
12008   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
12009       let rng = parse_rng ?defines context [child] in
12010       (match rng with
12011        | [child] -> OneOrMore child :: parse_rng ?defines context rest
12012        | _ ->
12013            failwithf "%s: <oneOrMore> contains more than one child element"
12014              context
12015       )
12016   | Xml.Element ("optional", [], [child]) :: rest ->
12017       let rng = parse_rng ?defines context [child] in
12018       (match rng with
12019        | [child] -> Optional child :: parse_rng ?defines context rest
12020        | _ ->
12021            failwithf "%s: <optional> contains more than one child element"
12022              context
12023       )
12024   | Xml.Element ("choice", [], children) :: rest ->
12025       let values = List.map (
12026         function Xml.Element ("value", [], [Xml.PCData value]) -> value
12027         | _ ->
12028             failwithf "%s: can't handle anything except <value> in <choice>"
12029               context
12030       ) children in
12031       Choice values
12032       :: parse_rng ?defines context rest
12033   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
12034       Value value :: parse_rng ?defines context rest
12035   | Xml.Element ("text", [], []) :: rest ->
12036       Text :: parse_rng ?defines context rest
12037   | Xml.Element ("ref", ["name", name], []) :: rest ->
12038       (* Look up the reference.  Because of limitations in this parser,
12039        * we can't handle arbitrarily nested <ref> yet.  You can only
12040        * use <ref> from inside <start>.
12041        *)
12042       (match defines with
12043        | None ->
12044            failwithf "%s: contains <ref>, but no refs are defined yet" context
12045        | Some map ->
12046            let rng = StringMap.find name map in
12047            rng @ parse_rng ?defines context rest
12048       )
12049   | x :: _ ->
12050       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
12051
12052 let grammar =
12053   let xml = Xml.parse_file rng_input in
12054   match xml with
12055   | Xml.Element ("grammar", _,
12056                  Xml.Element ("start", _, gram) :: defines) ->
12057       (* The <define/> elements are referenced in the <start> section,
12058        * so build a map of those first.
12059        *)
12060       let defines = List.fold_left (
12061         fun map ->
12062           function Xml.Element ("define", ["name", name], defn) ->
12063             StringMap.add name defn map
12064           | _ ->
12065               failwithf "%s: expected <define name=name/>" rng_input
12066       ) StringMap.empty defines in
12067       let defines = StringMap.mapi parse_rng defines in
12068
12069       (* Parse the <start> clause, passing the defines. *)
12070       parse_rng ~defines "<start>" gram
12071   | _ ->
12072       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
12073         rng_input
12074
12075 let name_of_field = function
12076   | Element (name, _) | Attribute (name, _)
12077   | ZeroOrMore (Element (name, _))
12078   | OneOrMore (Element (name, _))
12079   | Optional (Element (name, _)) -> name
12080   | Optional (Attribute (name, _)) -> name
12081   | Text -> (* an unnamed field in an element *)
12082       "data"
12083   | rng ->
12084       failwithf "name_of_field failed at: %s" (string_of_rng rng)
12085
12086 (* At the moment this function only generates OCaml types.  However we
12087  * should parameterize it later so it can generate types/structs in a
12088  * variety of languages.
12089  *)
12090 let generate_types xs =
12091   (* A simple type is one that can be printed out directly, eg.
12092    * "string option".  A complex type is one which has a name and has
12093    * to be defined via another toplevel definition, eg. a struct.
12094    *
12095    * generate_type generates code for either simple or complex types.
12096    * In the simple case, it returns the string ("string option").  In
12097    * the complex case, it returns the name ("mountpoint").  In the
12098    * complex case it has to print out the definition before returning,
12099    * so it should only be called when we are at the beginning of a
12100    * new line (BOL context).
12101    *)
12102   let rec generate_type = function
12103     | Text ->                                (* string *)
12104         "string", true
12105     | Choice values ->                        (* [`val1|`val2|...] *)
12106         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
12107     | ZeroOrMore rng ->                        (* <rng> list *)
12108         let t, is_simple = generate_type rng in
12109         t ^ " list (* 0 or more *)", is_simple
12110     | OneOrMore rng ->                        (* <rng> list *)
12111         let t, is_simple = generate_type rng in
12112         t ^ " list (* 1 or more *)", is_simple
12113                                         (* virt-inspector hack: bool *)
12114     | Optional (Attribute (name, [Value "1"])) ->
12115         "bool", true
12116     | Optional rng ->                        (* <rng> list *)
12117         let t, is_simple = generate_type rng in
12118         t ^ " option", is_simple
12119                                         (* type name = { fields ... } *)
12120     | Element (name, fields) when is_attrs_interleave fields ->
12121         generate_type_struct name (get_attrs_interleave fields)
12122     | Element (name, [field])                (* type name = field *)
12123     | Attribute (name, [field]) ->
12124         let t, is_simple = generate_type field in
12125         if is_simple then (t, true)
12126         else (
12127           pr "type %s = %s\n" name t;
12128           name, false
12129         )
12130     | Element (name, fields) ->              (* type name = { fields ... } *)
12131         generate_type_struct name fields
12132     | rng ->
12133         failwithf "generate_type failed at: %s" (string_of_rng rng)
12134
12135   and is_attrs_interleave = function
12136     | [Interleave _] -> true
12137     | Attribute _ :: fields -> is_attrs_interleave fields
12138     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
12139     | _ -> false
12140
12141   and get_attrs_interleave = function
12142     | [Interleave fields] -> fields
12143     | ((Attribute _) as field) :: fields
12144     | ((Optional (Attribute _)) as field) :: fields ->
12145         field :: get_attrs_interleave fields
12146     | _ -> assert false
12147
12148   and generate_types xs =
12149     List.iter (fun x -> ignore (generate_type x)) xs
12150
12151   and generate_type_struct name fields =
12152     (* Calculate the types of the fields first.  We have to do this
12153      * before printing anything so we are still in BOL context.
12154      *)
12155     let types = List.map fst (List.map generate_type fields) in
12156
12157     (* Special case of a struct containing just a string and another
12158      * field.  Turn it into an assoc list.
12159      *)
12160     match types with
12161     | ["string"; other] ->
12162         let fname1, fname2 =
12163           match fields with
12164           | [f1; f2] -> name_of_field f1, name_of_field f2
12165           | _ -> assert false in
12166         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
12167         name, false
12168
12169     | types ->
12170         pr "type %s = {\n" name;
12171         List.iter (
12172           fun (field, ftype) ->
12173             let fname = name_of_field field in
12174             pr "  %s_%s : %s;\n" name fname ftype
12175         ) (List.combine fields types);
12176         pr "}\n";
12177         (* Return the name of this type, and
12178          * false because it's not a simple type.
12179          *)
12180         name, false
12181   in
12182
12183   generate_types xs
12184
12185 let generate_parsers xs =
12186   (* As for generate_type above, generate_parser makes a parser for
12187    * some type, and returns the name of the parser it has generated.
12188    * Because it (may) need to print something, it should always be
12189    * called in BOL context.
12190    *)
12191   let rec generate_parser = function
12192     | Text ->                                (* string *)
12193         "string_child_or_empty"
12194     | Choice values ->                        (* [`val1|`val2|...] *)
12195         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
12196           (String.concat "|"
12197              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
12198     | ZeroOrMore rng ->                        (* <rng> list *)
12199         let pa = generate_parser rng in
12200         sprintf "(fun x -> List.map %s (Xml.children x))" pa
12201     | OneOrMore rng ->                        (* <rng> list *)
12202         let pa = generate_parser rng in
12203         sprintf "(fun x -> List.map %s (Xml.children x))" pa
12204                                         (* virt-inspector hack: bool *)
12205     | Optional (Attribute (name, [Value "1"])) ->
12206         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
12207     | Optional rng ->                        (* <rng> list *)
12208         let pa = generate_parser rng in
12209         sprintf "(function None -> None | Some x -> Some (%s x))" pa
12210                                         (* type name = { fields ... } *)
12211     | Element (name, fields) when is_attrs_interleave fields ->
12212         generate_parser_struct name (get_attrs_interleave fields)
12213     | Element (name, [field]) ->        (* type name = field *)
12214         let pa = generate_parser field in
12215         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12216         pr "let %s =\n" parser_name;
12217         pr "  %s\n" pa;
12218         pr "let parse_%s = %s\n" name parser_name;
12219         parser_name
12220     | Attribute (name, [field]) ->
12221         let pa = generate_parser field in
12222         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12223         pr "let %s =\n" parser_name;
12224         pr "  %s\n" pa;
12225         pr "let parse_%s = %s\n" name parser_name;
12226         parser_name
12227     | Element (name, fields) ->              (* type name = { fields ... } *)
12228         generate_parser_struct name ([], fields)
12229     | rng ->
12230         failwithf "generate_parser failed at: %s" (string_of_rng rng)
12231
12232   and is_attrs_interleave = function
12233     | [Interleave _] -> true
12234     | Attribute _ :: fields -> is_attrs_interleave fields
12235     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
12236     | _ -> false
12237
12238   and get_attrs_interleave = function
12239     | [Interleave fields] -> [], fields
12240     | ((Attribute _) as field) :: fields
12241     | ((Optional (Attribute _)) as field) :: fields ->
12242         let attrs, interleaves = get_attrs_interleave fields in
12243         (field :: attrs), interleaves
12244     | _ -> assert false
12245
12246   and generate_parsers xs =
12247     List.iter (fun x -> ignore (generate_parser x)) xs
12248
12249   and generate_parser_struct name (attrs, interleaves) =
12250     (* Generate parsers for the fields first.  We have to do this
12251      * before printing anything so we are still in BOL context.
12252      *)
12253     let fields = attrs @ interleaves in
12254     let pas = List.map generate_parser fields in
12255
12256     (* Generate an intermediate tuple from all the fields first.
12257      * If the type is just a string + another field, then we will
12258      * return this directly, otherwise it is turned into a record.
12259      *
12260      * RELAX NG note: This code treats <interleave> and plain lists of
12261      * fields the same.  In other words, it doesn't bother enforcing
12262      * any ordering of fields in the XML.
12263      *)
12264     pr "let parse_%s x =\n" name;
12265     pr "  let t = (\n    ";
12266     let comma = ref false in
12267     List.iter (
12268       fun x ->
12269         if !comma then pr ",\n    ";
12270         comma := true;
12271         match x with
12272         | Optional (Attribute (fname, [field])), pa ->
12273             pr "%s x" pa
12274         | Optional (Element (fname, [field])), pa ->
12275             pr "%s (optional_child %S x)" pa fname
12276         | Attribute (fname, [Text]), _ ->
12277             pr "attribute %S x" fname
12278         | (ZeroOrMore _ | OneOrMore _), pa ->
12279             pr "%s x" pa
12280         | Text, pa ->
12281             pr "%s x" pa
12282         | (field, pa) ->
12283             let fname = name_of_field field in
12284             pr "%s (child %S x)" pa fname
12285     ) (List.combine fields pas);
12286     pr "\n  ) in\n";
12287
12288     (match fields with
12289      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
12290          pr "  t\n"
12291
12292      | _ ->
12293          pr "  (Obj.magic t : %s)\n" name
12294 (*
12295          List.iter (
12296            function
12297            | (Optional (Attribute (fname, [field])), pa) ->
12298                pr "  %s_%s =\n" name fname;
12299                pr "    %s x;\n" pa
12300            | (Optional (Element (fname, [field])), pa) ->
12301                pr "  %s_%s =\n" name fname;
12302                pr "    (let x = optional_child %S x in\n" fname;
12303                pr "     %s x);\n" pa
12304            | (field, pa) ->
12305                let fname = name_of_field field in
12306                pr "  %s_%s =\n" name fname;
12307                pr "    (let x = child %S x in\n" fname;
12308                pr "     %s x);\n" pa
12309          ) (List.combine fields pas);
12310          pr "}\n"
12311 *)
12312     );
12313     sprintf "parse_%s" name
12314   in
12315
12316   generate_parsers xs
12317
12318 (* Generate ocaml/guestfs_inspector.mli. *)
12319 let generate_ocaml_inspector_mli () =
12320   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12321
12322   pr "\
12323 (** This is an OCaml language binding to the external [virt-inspector]
12324     program.
12325
12326     For more information, please read the man page [virt-inspector(1)].
12327 *)
12328
12329 ";
12330
12331   generate_types grammar;
12332   pr "(** The nested information returned from the {!inspect} function. *)\n";
12333   pr "\n";
12334
12335   pr "\
12336 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12337 (** To inspect a libvirt domain called [name], pass a singleton
12338     list: [inspect [name]].  When using libvirt only, you may
12339     optionally pass a libvirt URI using [inspect ~connect:uri ...].
12340
12341     To inspect a disk image or images, pass a list of the filenames
12342     of the disk images: [inspect filenames]
12343
12344     This function inspects the given guest or disk images and
12345     returns a list of operating system(s) found and a large amount
12346     of information about them.  In the vast majority of cases,
12347     a virtual machine only contains a single operating system.
12348
12349     If the optional [~xml] parameter is given, then this function
12350     skips running the external virt-inspector program and just
12351     parses the given XML directly (which is expected to be XML
12352     produced from a previous run of virt-inspector).  The list of
12353     names and connect URI are ignored in this case.
12354
12355     This function can throw a wide variety of exceptions, for example
12356     if the external virt-inspector program cannot be found, or if
12357     it doesn't generate valid XML.
12358 *)
12359 "
12360
12361 (* Generate ocaml/guestfs_inspector.ml. *)
12362 let generate_ocaml_inspector_ml () =
12363   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12364
12365   pr "open Unix\n";
12366   pr "\n";
12367
12368   generate_types grammar;
12369   pr "\n";
12370
12371   pr "\
12372 (* Misc functions which are used by the parser code below. *)
12373 let first_child = function
12374   | Xml.Element (_, _, c::_) -> c
12375   | Xml.Element (name, _, []) ->
12376       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12377   | Xml.PCData str ->
12378       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12379
12380 let string_child_or_empty = function
12381   | Xml.Element (_, _, [Xml.PCData s]) -> s
12382   | Xml.Element (_, _, []) -> \"\"
12383   | Xml.Element (x, _, _) ->
12384       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12385                 x ^ \" instead\")
12386   | Xml.PCData str ->
12387       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12388
12389 let optional_child name xml =
12390   let children = Xml.children xml in
12391   try
12392     Some (List.find (function
12393                      | Xml.Element (n, _, _) when n = name -> true
12394                      | _ -> false) children)
12395   with
12396     Not_found -> None
12397
12398 let child name xml =
12399   match optional_child name xml with
12400   | Some c -> c
12401   | None ->
12402       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12403
12404 let attribute name xml =
12405   try Xml.attrib xml name
12406   with Xml.No_attribute _ ->
12407     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12408
12409 ";
12410
12411   generate_parsers grammar;
12412   pr "\n";
12413
12414   pr "\
12415 (* Run external virt-inspector, then use parser to parse the XML. *)
12416 let inspect ?connect ?xml names =
12417   let xml =
12418     match xml with
12419     | None ->
12420         if names = [] then invalid_arg \"inspect: no names given\";
12421         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12422           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12423           names in
12424         let cmd = List.map Filename.quote cmd in
12425         let cmd = String.concat \" \" cmd in
12426         let chan = open_process_in cmd in
12427         let xml = Xml.parse_in chan in
12428         (match close_process_in chan with
12429          | WEXITED 0 -> ()
12430          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12431          | WSIGNALED i | WSTOPPED i ->
12432              failwith (\"external virt-inspector command died or stopped on sig \" ^
12433                        string_of_int i)
12434         );
12435         xml
12436     | Some doc ->
12437         Xml.parse_string doc in
12438   parse_operatingsystems xml
12439 "
12440
12441 and generate_max_proc_nr () =
12442   pr "%d\n" max_proc_nr
12443
12444 let output_to filename k =
12445   let filename_new = filename ^ ".new" in
12446   chan := open_out filename_new;
12447   k ();
12448   close_out !chan;
12449   chan := Pervasives.stdout;
12450
12451   (* Is the new file different from the current file? *)
12452   if Sys.file_exists filename && files_equal filename filename_new then
12453     unlink filename_new                 (* same, so skip it *)
12454   else (
12455     (* different, overwrite old one *)
12456     (try chmod filename 0o644 with Unix_error _ -> ());
12457     rename filename_new filename;
12458     chmod filename 0o444;
12459     printf "written %s\n%!" filename;
12460   )
12461
12462 let perror msg = function
12463   | Unix_error (err, _, _) ->
12464       eprintf "%s: %s\n" msg (error_message err)
12465   | exn ->
12466       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12467
12468 (* Main program. *)
12469 let () =
12470   let lock_fd =
12471     try openfile "HACKING" [O_RDWR] 0
12472     with
12473     | Unix_error (ENOENT, _, _) ->
12474         eprintf "\
12475 You are probably running this from the wrong directory.
12476 Run it from the top source directory using the command
12477   src/generator.ml
12478 ";
12479         exit 1
12480     | exn ->
12481         perror "open: HACKING" exn;
12482         exit 1 in
12483
12484   (* Acquire a lock so parallel builds won't try to run the generator
12485    * twice at the same time.  Subsequent builds will wait for the first
12486    * one to finish.  Note the lock is released implicitly when the
12487    * program exits.
12488    *)
12489   (try lockf lock_fd F_LOCK 1
12490    with exn ->
12491      perror "lock: HACKING" exn;
12492      exit 1);
12493
12494   check_functions ();
12495
12496   output_to "src/guestfs_protocol.x" generate_xdr;
12497   output_to "src/guestfs-structs.h" generate_structs_h;
12498   output_to "src/guestfs-actions.h" generate_actions_h;
12499   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12500   output_to "src/actions.c" generate_client_actions;
12501   output_to "src/bindtests.c" generate_bindtests;
12502   output_to "src/guestfs-structs.pod" generate_structs_pod;
12503   output_to "src/guestfs-actions.pod" generate_actions_pod;
12504   output_to "src/guestfs-availability.pod" generate_availability_pod;
12505   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12506   output_to "src/libguestfs.syms" generate_linker_script;
12507   output_to "daemon/actions.h" generate_daemon_actions_h;
12508   output_to "daemon/stubs.c" generate_daemon_actions;
12509   output_to "daemon/names.c" generate_daemon_names;
12510   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12511   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12512   output_to "capitests/tests.c" generate_tests;
12513   output_to "fish/cmds.c" generate_fish_cmds;
12514   output_to "fish/completion.c" generate_fish_completion;
12515   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12516   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12517   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12518   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12519   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12520   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12521   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12522   output_to "perl/Guestfs.xs" generate_perl_xs;
12523   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12524   output_to "perl/bindtests.pl" generate_perl_bindtests;
12525   output_to "python/guestfs-py.c" generate_python_c;
12526   output_to "python/guestfs.py" generate_python_py;
12527   output_to "python/bindtests.py" generate_python_bindtests;
12528   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12529   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12530   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12531
12532   List.iter (
12533     fun (typ, jtyp) ->
12534       let cols = cols_of_struct typ in
12535       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12536       output_to filename (generate_java_struct jtyp cols);
12537   ) java_structs;
12538
12539   output_to "java/Makefile.inc" generate_java_makefile_inc;
12540   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12541   output_to "java/Bindtests.java" generate_java_bindtests;
12542   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12543   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12544   output_to "csharp/Libguestfs.cs" generate_csharp;
12545
12546   (* Always generate this file last, and unconditionally.  It's used
12547    * by the Makefile to know when we must re-run the generator.
12548    *)
12549   let chan = open_out "src/stamp-generator" in
12550   fprintf chan "1\n";
12551   close_out chan;
12552
12553   printf "generated %d lines of code\n" !lines