New APIs: vfs-label and vfs-uuid return label and uuid for many fs types.
[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
178 type flags =
179   | ProtocolLimitWarning  (* display warning about protocol size limits *)
180   | DangerWillRobinson    (* flags particularly dangerous commands *)
181   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
182   | FishOutput of fish_output_t (* how to display output in guestfish *)
183   | NotInFish             (* do not export via guestfish *)
184   | NotInDocs             (* do not add this function to documentation *)
185   | DeprecatedBy of string (* function is deprecated, use .. instead *)
186   | Optional of string    (* function is part of an optional group *)
187
188 and fish_output_t =
189   | FishOutputOctal       (* for int return, print in octal *)
190   | FishOutputHexadecimal (* for int return, print in hex *)
191
192 (* You can supply zero or as many tests as you want per API call.
193  *
194  * Note that the test environment has 3 block devices, of size 500MB,
195  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196  * a fourth ISO block device with some known files on it (/dev/sdd).
197  *
198  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199  * Number of cylinders was 63 for IDE emulated disks with precisely
200  * the same size.  How exactly this is calculated is a mystery.
201  *
202  * The ISO block device (/dev/sdd) comes from images/test.iso.
203  *
204  * To be able to run the tests in a reasonable amount of time,
205  * the virtual machine and block devices are reused between tests.
206  * So don't try testing kill_subprocess :-x
207  *
208  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
209  *
210  * Don't assume anything about the previous contents of the block
211  * devices.  Use 'Init*' to create some initial scenarios.
212  *
213  * You can add a prerequisite clause to any individual test.  This
214  * is a run-time check, which, if it fails, causes the test to be
215  * skipped.  Useful if testing a command which might not work on
216  * all variations of libguestfs builds.  A test that has prerequisite
217  * of 'Always' is run unconditionally.
218  *
219  * In addition, packagers can skip individual tests by setting the
220  * environment variables:     eg:
221  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
222  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
223  *)
224 type tests = (test_init * test_prereq * test) list
225 and test =
226     (* Run the command sequence and just expect nothing to fail. *)
227   | TestRun of seq
228
229     (* Run the command sequence and expect the output of the final
230      * command to be the string.
231      *)
232   | TestOutput of seq * string
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the list of strings.
236      *)
237   | TestOutputList of seq * string list
238
239     (* Run the command sequence and expect the output of the final
240      * command to be the list of block devices (could be either
241      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242      * character of each string).
243      *)
244   | TestOutputListOfDevices of seq * string list
245
246     (* Run the command sequence and expect the output of the final
247      * command to be the integer.
248      *)
249   | TestOutputInt of seq * int
250
251     (* Run the command sequence and expect the output of the final
252      * command to be <op> <int>, eg. ">=", "1".
253      *)
254   | TestOutputIntOp of seq * string * int
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a true value (!= 0 or != NULL).
258      *)
259   | TestOutputTrue of seq
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a false value (== 0 or == NULL, but not an error).
263      *)
264   | TestOutputFalse of seq
265
266     (* Run the command sequence and expect the output of the final
267      * command to be a list of the given length (but don't care about
268      * content).
269      *)
270   | TestOutputLength of seq * int
271
272     (* Run the command sequence and expect the output of the final
273      * command to be a buffer (RBufferOut), ie. string + size.
274      *)
275   | TestOutputBuffer of seq * string
276
277     (* Run the command sequence and expect the output of the final
278      * command to be a structure.
279      *)
280   | TestOutputStruct of seq * test_field_compare list
281
282     (* Run the command sequence and expect the final command (only)
283      * to fail.
284      *)
285   | TestLastFail of seq
286
287 and test_field_compare =
288   | CompareWithInt of string * int
289   | CompareWithIntOp of string * string * int
290   | CompareWithString of string * string
291   | CompareFieldsIntEq of string * string
292   | CompareFieldsStrEq of string * string
293
294 (* Test prerequisites. *)
295 and test_prereq =
296     (* Test always runs. *)
297   | Always
298
299     (* Test is currently disabled - eg. it fails, or it tests some
300      * unimplemented feature.
301      *)
302   | Disabled
303
304     (* 'string' is some C code (a function body) that should return
305      * true or false.  The test will run if the code returns true.
306      *)
307   | If of string
308
309     (* As for 'If' but the test runs _unless_ the code returns true. *)
310   | Unless of string
311
312 (* Some initial scenarios for testing. *)
313 and test_init =
314     (* Do nothing, block devices could contain random stuff including
315      * LVM PVs, and some filesystems might be mounted.  This is usually
316      * a bad idea.
317      *)
318   | InitNone
319
320     (* Block devices are empty and no filesystems are mounted. *)
321   | InitEmpty
322
323     (* /dev/sda contains a single partition /dev/sda1, with random
324      * content.  /dev/sdb and /dev/sdc may have random content.
325      * No LVM.
326      *)
327   | InitPartition
328
329     (* /dev/sda contains a single partition /dev/sda1, which is formatted
330      * as ext2, empty [except for lost+found] and mounted on /.
331      * /dev/sdb and /dev/sdc may have random content.
332      * No LVM.
333      *)
334   | InitBasicFS
335
336     (* /dev/sda:
337      *   /dev/sda1 (is a PV):
338      *     /dev/VG/LV (size 8MB):
339      *       formatted as ext2, empty [except for lost+found], mounted on /
340      * /dev/sdb and /dev/sdc may have random content.
341      *)
342   | InitBasicFSonLVM
343
344     (* /dev/sdd (the ISO, see images/ directory in source)
345      * is mounted on /
346      *)
347   | InitISOFS
348
349 (* Sequence of commands for testing. *)
350 and seq = cmd list
351 and cmd = string list
352
353 (* Note about long descriptions: When referring to another
354  * action, use the format C<guestfs_other> (ie. the full name of
355  * the C function).  This will be replaced as appropriate in other
356  * language bindings.
357  *
358  * Apart from that, long descriptions are just perldoc paragraphs.
359  *)
360
361 (* Generate a random UUID (used in tests). *)
362 let uuidgen () =
363   let chan = open_process_in "uuidgen" in
364   let uuid = input_line chan in
365   (match close_process_in chan with
366    | WEXITED 0 -> ()
367    | WEXITED _ ->
368        failwith "uuidgen: process exited with non-zero status"
369    | WSIGNALED _ | WSTOPPED _ ->
370        failwith "uuidgen: process signalled or stopped by signal"
371   );
372   uuid
373
374 (* These test functions are used in the language binding tests. *)
375
376 let test_all_args = [
377   String "str";
378   OptString "optstr";
379   StringList "strlist";
380   Bool "b";
381   Int "integer";
382   Int64 "integer64";
383   FileIn "filein";
384   FileOut "fileout";
385   BufferIn "bufferin";
386 ]
387
388 let test_all_rets = [
389   (* except for RErr, which is tested thoroughly elsewhere *)
390   "test0rint",         RInt "valout";
391   "test0rint64",       RInt64 "valout";
392   "test0rbool",        RBool "valout";
393   "test0rconststring", RConstString "valout";
394   "test0rconstoptstring", RConstOptString "valout";
395   "test0rstring",      RString "valout";
396   "test0rstringlist",  RStringList "valout";
397   "test0rstruct",      RStruct ("valout", "lvm_pv");
398   "test0rstructlist",  RStructList ("valout", "lvm_pv");
399   "test0rhashtable",   RHashtable "valout";
400 ]
401
402 let test_functions = [
403   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
404    [],
405    "internal test function - do not use",
406    "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 parameter type correctly.
410
411 It echos the contents of each parameter to stdout.
412
413 You probably don't want to call this function.");
414 ] @ List.flatten (
415   List.map (
416     fun (name, ret) ->
417       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
418         [],
419         "internal test function - do not use",
420         "\
421 This is an internal test function which is used to test whether
422 the automatically generated bindings can handle every possible
423 return type correctly.
424
425 It converts string C<val> to the return type.
426
427 You probably don't want to call this function.");
428        (name ^ "err", (ret, []), -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 This function always returns an error.
437
438 You probably don't want to call this function.")]
439   ) test_all_rets
440 )
441
442 (* non_daemon_functions are any functions which don't get processed
443  * in the daemon, eg. functions for setting and getting local
444  * configuration values.
445  *)
446
447 let non_daemon_functions = test_functions @ [
448   ("launch", (RErr, []), -1, [FishAlias "run"],
449    [],
450    "launch the qemu subprocess",
451    "\
452 Internally libguestfs is implemented by running a virtual machine
453 using L<qemu(1)>.
454
455 You should call this after configuring the handle
456 (eg. adding drives) but before performing any actions.");
457
458   ("wait_ready", (RErr, []), -1, [NotInFish],
459    [],
460    "wait until the qemu subprocess launches (no op)",
461    "\
462 This function is a no op.
463
464 In versions of the API E<lt> 1.0.71 you had to call this function
465 just after calling C<guestfs_launch> to wait for the launch
466 to complete.  However this is no longer necessary because
467 C<guestfs_launch> now does the waiting.
468
469 If you see any calls to this function in code then you can just
470 remove them, unless you want to retain compatibility with older
471 versions of the API.");
472
473   ("kill_subprocess", (RErr, []), -1, [],
474    [],
475    "kill the qemu subprocess",
476    "\
477 This kills the qemu subprocess.  You should never need to call this.");
478
479   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
480    [],
481    "add an image to examine or modify",
482    "\
483 This function adds a virtual machine disk image C<filename> to the
484 guest.  The first time you call this function, the disk appears as IDE
485 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
486 so on.
487
488 You don't necessarily need to be root when using libguestfs.  However
489 you obviously do need sufficient permissions to access the filename
490 for whatever operations you want to perform (ie. read access if you
491 just want to read the image or write access if you want to modify the
492 image).
493
494 This is equivalent to the qemu parameter
495 C<-drive file=filename,cache=off,if=...>.
496
497 C<cache=off> is omitted in cases where it is not supported by
498 the underlying filesystem.
499
500 C<if=...> is set at compile time by the configuration option
501 C<./configure --with-drive-if=...>.  In the rare case where you
502 might need to change this at run time, use C<guestfs_add_drive_with_if>
503 or C<guestfs_add_drive_ro_with_if>.
504
505 Note that this call checks for the existence of C<filename>.  This
506 stops you from specifying other types of drive which are supported
507 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
508 the general C<guestfs_config> call instead.");
509
510   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
511    [],
512    "add a CD-ROM disk image to examine",
513    "\
514 This function adds a virtual CD-ROM disk image to the guest.
515
516 This is equivalent to the qemu parameter C<-cdrom filename>.
517
518 Notes:
519
520 =over 4
521
522 =item *
523
524 This call checks for the existence of C<filename>.  This
525 stops you from specifying other types of drive which are supported
526 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
527 the general C<guestfs_config> call instead.
528
529 =item *
530
531 If you just want to add an ISO file (often you use this as an
532 efficient way to transfer large files into the guest), then you
533 should probably use C<guestfs_add_drive_ro> instead.
534
535 =back");
536
537   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
538    [],
539    "add a drive in snapshot mode (read-only)",
540    "\
541 This adds a drive in snapshot mode, making it effectively
542 read-only.
543
544 Note that writes to the device are allowed, and will be seen for
545 the duration of the guestfs handle, but they are written
546 to a temporary file which is discarded as soon as the guestfs
547 handle is closed.  We don't currently have any method to enable
548 changes to be committed, although qemu can support this.
549
550 This is equivalent to the qemu parameter
551 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
552
553 C<if=...> is set at compile time by the configuration option
554 C<./configure --with-drive-if=...>.  In the rare case where you
555 might need to change this at run time, use C<guestfs_add_drive_with_if>
556 or C<guestfs_add_drive_ro_with_if>.
557
558 C<readonly=on> is only added where qemu supports this option.
559
560 Note that this call checks for the existence of C<filename>.  This
561 stops you from specifying other types of drive which are supported
562 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
563 the general C<guestfs_config> call instead.");
564
565   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
566    [],
567    "add qemu parameters",
568    "\
569 This can be used to add arbitrary qemu command line parameters
570 of the form C<-param value>.  Actually it's not quite arbitrary - we
571 prevent you from setting some parameters which would interfere with
572 parameters that we use.
573
574 The first character of C<param> string must be a C<-> (dash).
575
576 C<value> can be NULL.");
577
578   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
579    [],
580    "set the qemu binary",
581    "\
582 Set the qemu binary that we will use.
583
584 The default is chosen when the library was compiled by the
585 configure script.
586
587 You can also override this by setting the C<LIBGUESTFS_QEMU>
588 environment variable.
589
590 Setting C<qemu> to C<NULL> restores the default qemu binary.
591
592 Note that you should call this function as early as possible
593 after creating the handle.  This is because some pre-launch
594 operations depend on testing qemu features (by running C<qemu -help>).
595 If the qemu binary changes, we don't retest features, and
596 so you might see inconsistent results.  Using the environment
597 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
598 the qemu binary at the same time as the handle is created.");
599
600   ("get_qemu", (RConstString "qemu", []), -1, [],
601    [InitNone, Always, TestRun (
602       [["get_qemu"]])],
603    "get the qemu binary",
604    "\
605 Return the current qemu binary.
606
607 This is always non-NULL.  If it wasn't set already, then this will
608 return the default qemu binary name.");
609
610   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
611    [],
612    "set the search path",
613    "\
614 Set the path that libguestfs searches for kernel and initrd.img.
615
616 The default is C<$libdir/guestfs> unless overridden by setting
617 C<LIBGUESTFS_PATH> environment variable.
618
619 Setting C<path> to C<NULL> restores the default path.");
620
621   ("get_path", (RConstString "path", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_path"]])],
624    "get the search path",
625    "\
626 Return the current search path.
627
628 This is always non-NULL.  If it wasn't set already, then this will
629 return the default path.");
630
631   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
632    [],
633    "add options to kernel command line",
634    "\
635 This function is used to add additional options to the
636 guest kernel command line.
637
638 The default is C<NULL> unless overridden by setting
639 C<LIBGUESTFS_APPEND> environment variable.
640
641 Setting C<append> to C<NULL> means I<no> additional options
642 are passed (libguestfs always adds a few of its own).");
643
644   ("get_append", (RConstOptString "append", []), -1, [],
645    (* This cannot be tested with the current framework.  The
646     * function can return NULL in normal operations, which the
647     * test framework interprets as an error.
648     *)
649    [],
650    "get the additional kernel options",
651    "\
652 Return the additional kernel options which are added to the
653 guest kernel command line.
654
655 If C<NULL> then no options are added.");
656
657   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658    [],
659    "set autosync mode",
660    "\
661 If C<autosync> is true, this enables autosync.  Libguestfs will make a
662 best effort attempt to run C<guestfs_umount_all> followed by
663 C<guestfs_sync> when the handle is closed
664 (also if the program exits without closing handles).
665
666 This is disabled by default (except in guestfish where it is
667 enabled by default).");
668
669   ("get_autosync", (RBool "autosync", []), -1, [],
670    [InitNone, Always, TestRun (
671       [["get_autosync"]])],
672    "get autosync mode",
673    "\
674 Get the autosync flag.");
675
676   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677    [],
678    "set verbose mode",
679    "\
680 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
681
682 Verbose messages are disabled unless the environment variable
683 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
684
685   ("get_verbose", (RBool "verbose", []), -1, [],
686    [],
687    "get verbose mode",
688    "\
689 This returns the verbose messages flag.");
690
691   ("is_ready", (RBool "ready", []), -1, [],
692    [InitNone, Always, TestOutputTrue (
693       [["is_ready"]])],
694    "is ready to accept commands",
695    "\
696 This returns true iff this handle is ready to accept commands
697 (in the C<READY> state).
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("is_config", (RBool "config", []), -1, [],
702    [InitNone, Always, TestOutputFalse (
703       [["is_config"]])],
704    "is in configuration state",
705    "\
706 This returns true iff this handle is being configured
707 (in the C<CONFIG> state).
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("is_launching", (RBool "launching", []), -1, [],
712    [InitNone, Always, TestOutputFalse (
713       [["is_launching"]])],
714    "is launching subprocess",
715    "\
716 This returns true iff this handle is launching the subprocess
717 (in the C<LAUNCHING> state).
718
719 For more information on states, see L<guestfs(3)>.");
720
721   ("is_busy", (RBool "busy", []), -1, [],
722    [InitNone, Always, TestOutputFalse (
723       [["is_busy"]])],
724    "is busy processing a command",
725    "\
726 This returns true iff this handle is busy processing a command
727 (in the C<BUSY> state).
728
729 For more information on states, see L<guestfs(3)>.");
730
731   ("get_state", (RInt "state", []), -1, [],
732    [],
733    "get the current state",
734    "\
735 This returns the current state as an opaque integer.  This is
736 only useful for printing debug and internal error messages.
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
741    [InitNone, Always, TestOutputInt (
742       [["set_memsize"; "500"];
743        ["get_memsize"]], 500)],
744    "set memory allocated to the qemu subprocess",
745    "\
746 This sets the memory size in megabytes allocated to the
747 qemu subprocess.  This only has any effect if called before
748 C<guestfs_launch>.
749
750 You can also change this by setting the environment
751 variable C<LIBGUESTFS_MEMSIZE> before the handle is
752 created.
753
754 For more information on the architecture of libguestfs,
755 see L<guestfs(3)>.");
756
757   ("get_memsize", (RInt "memsize", []), -1, [],
758    [InitNone, Always, TestOutputIntOp (
759       [["get_memsize"]], ">=", 256)],
760    "get memory allocated to the qemu subprocess",
761    "\
762 This gets the memory size in megabytes allocated to the
763 qemu subprocess.
764
765 If C<guestfs_set_memsize> was not called
766 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
767 then this returns the compiled-in default value for memsize.
768
769 For more information on the architecture of libguestfs,
770 see L<guestfs(3)>.");
771
772   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
773    [InitNone, Always, TestOutputIntOp (
774       [["get_pid"]], ">=", 1)],
775    "get PID of qemu subprocess",
776    "\
777 Return the process ID of the qemu subprocess.  If there is no
778 qemu subprocess, then this will return an error.
779
780 This is an internal call used for debugging and testing.");
781
782   ("version", (RStruct ("version", "version"), []), -1, [],
783    [InitNone, Always, TestOutputStruct (
784       [["version"]], [CompareWithInt ("major", 1)])],
785    "get the library version number",
786    "\
787 Return the libguestfs version number that the program is linked
788 against.
789
790 Note that because of dynamic linking this is not necessarily
791 the version of libguestfs that you compiled against.  You can
792 compile the program, and then at runtime dynamically link
793 against a completely different C<libguestfs.so> library.
794
795 This call was added in version C<1.0.58>.  In previous
796 versions of libguestfs there was no way to get the version
797 number.  From C code you can use dynamic linker functions
798 to find out if this symbol exists (if it doesn't, then
799 it's an earlier version).
800
801 The call returns a structure with four elements.  The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet.  The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
806
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
809
810 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
811
812 I<Note:> Don't use this call to test for availability
813 of features.  In enterprise distributions we backport
814 features from later versions into earlier versions,
815 making this an unreliable way to test for features.
816 Use C<guestfs_available> instead.");
817
818   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
819    [InitNone, Always, TestOutputTrue (
820       [["set_selinux"; "true"];
821        ["get_selinux"]])],
822    "set SELinux enabled or disabled at appliance boot",
823    "\
824 This sets the selinux flag that is passed to the appliance
825 at boot time.  The default is C<selinux=0> (disabled).
826
827 Note that if SELinux is enabled, it is always in
828 Permissive mode (C<enforcing=0>).
829
830 For more information on the architecture of libguestfs,
831 see L<guestfs(3)>.");
832
833   ("get_selinux", (RBool "selinux", []), -1, [],
834    [],
835    "get SELinux enabled flag",
836    "\
837 This returns the current setting of the selinux flag which
838 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
839
840 For more information on the architecture of libguestfs,
841 see L<guestfs(3)>.");
842
843   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
844    [InitNone, Always, TestOutputFalse (
845       [["set_trace"; "false"];
846        ["get_trace"]])],
847    "enable or disable command traces",
848    "\
849 If the command trace flag is set to 1, then commands are
850 printed on stdout before they are executed in a format
851 which is very similar to the one used by guestfish.  In
852 other words, you can run a program with this enabled, and
853 you will get out a script which you can feed to guestfish
854 to perform the same set of actions.
855
856 If you want to trace C API calls into libguestfs (and
857 other libraries) then possibly a better way is to use
858 the external ltrace(1) command.
859
860 Command traces are disabled unless the environment variable
861 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
862
863   ("get_trace", (RBool "trace", []), -1, [],
864    [],
865    "get command trace enabled flag",
866    "\
867 Return the command trace flag.");
868
869   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
870    [InitNone, Always, TestOutputFalse (
871       [["set_direct"; "false"];
872        ["get_direct"]])],
873    "enable or disable direct appliance mode",
874    "\
875 If the direct appliance mode flag is enabled, then stdin and
876 stdout are passed directly through to the appliance once it
877 is launched.
878
879 One consequence of this is that log messages aren't caught
880 by the library and handled by C<guestfs_set_log_message_callback>,
881 but go straight to stdout.
882
883 You probably don't want to use this unless you know what you
884 are doing.
885
886 The default is disabled.");
887
888   ("get_direct", (RBool "direct", []), -1, [],
889    [],
890    "get direct appliance mode flag",
891    "\
892 Return the direct appliance mode flag.");
893
894   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
895    [InitNone, Always, TestOutputTrue (
896       [["set_recovery_proc"; "true"];
897        ["get_recovery_proc"]])],
898    "enable or disable the recovery process",
899    "\
900 If this is called with the parameter C<false> then
901 C<guestfs_launch> does not create a recovery process.  The
902 purpose of the recovery process is to stop runaway qemu
903 processes in the case where the main program aborts abruptly.
904
905 This only has any effect if called before C<guestfs_launch>,
906 and the default is true.
907
908 About the only time when you would want to disable this is
909 if the main process will fork itself into the background
910 (\"daemonize\" itself).  In this case the recovery process
911 thinks that the main program has disappeared and so kills
912 qemu, which is not very helpful.");
913
914   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
915    [],
916    "get recovery process enabled flag",
917    "\
918 Return the recovery process enabled flag.");
919
920   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
921    [],
922    "add a drive specifying the QEMU block emulation to use",
923    "\
924 This is the same as C<guestfs_add_drive> but it allows you
925 to specify the QEMU interface emulation to use at run time.");
926
927   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
928    [],
929    "add a drive read-only specifying the QEMU block emulation to use",
930    "\
931 This is the same as C<guestfs_add_drive_ro> but it allows you
932 to specify the QEMU interface emulation to use at run time.");
933
934 ]
935
936 (* daemon_functions are any functions which cause some action
937  * to take place in the daemon.
938  *)
939
940 let daemon_functions = [
941   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
942    [InitEmpty, Always, TestOutput (
943       [["part_disk"; "/dev/sda"; "mbr"];
944        ["mkfs"; "ext2"; "/dev/sda1"];
945        ["mount"; "/dev/sda1"; "/"];
946        ["write"; "/new"; "new file contents"];
947        ["cat"; "/new"]], "new file contents")],
948    "mount a guest disk at a position in the filesystem",
949    "\
950 Mount a guest disk at a position in the filesystem.  Block devices
951 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
952 the guest.  If those block devices contain partitions, they will have
953 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
954 names can be used.
955
956 The rules are the same as for L<mount(2)>:  A filesystem must
957 first be mounted on C</> before others can be mounted.  Other
958 filesystems can only be mounted on directories which already
959 exist.
960
961 The mounted filesystem is writable, if we have sufficient permissions
962 on the underlying device.
963
964 B<Important note:>
965 When you use this call, the filesystem options C<sync> and C<noatime>
966 are set implicitly.  This was originally done because we thought it
967 would improve reliability, but it turns out that I<-o sync> has a
968 very large negative performance impact and negligible effect on
969 reliability.  Therefore we recommend that you avoid using
970 C<guestfs_mount> in any code that needs performance, and instead
971 use C<guestfs_mount_options> (use an empty string for the first
972 parameter if you don't want any options).");
973
974   ("sync", (RErr, []), 2, [],
975    [ InitEmpty, Always, TestRun [["sync"]]],
976    "sync disks, writes are flushed through to the disk image",
977    "\
978 This syncs the disk, so that any writes are flushed through to the
979 underlying disk image.
980
981 You should always call this if you have modified a disk image, before
982 closing the handle.");
983
984   ("touch", (RErr, [Pathname "path"]), 3, [],
985    [InitBasicFS, Always, TestOutputTrue (
986       [["touch"; "/new"];
987        ["exists"; "/new"]])],
988    "update file timestamps or create a new file",
989    "\
990 Touch acts like the L<touch(1)> command.  It can be used to
991 update the timestamps on a file, or, if the file does not exist,
992 to create a new zero-length file.");
993
994   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
995    [InitISOFS, Always, TestOutput (
996       [["cat"; "/known-2"]], "abcdef\n")],
997    "list the contents of a file",
998    "\
999 Return the contents of the file named C<path>.
1000
1001 Note that this function cannot correctly handle binary files
1002 (specifically, files containing C<\\0> character which is treated
1003 as end of string).  For those you need to use the C<guestfs_read_file>
1004 or C<guestfs_download> functions which have a more complex interface.");
1005
1006   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1007    [], (* XXX Tricky to test because it depends on the exact format
1008         * of the 'ls -l' command, which changes between F10 and F11.
1009         *)
1010    "list the files in a directory (long format)",
1011    "\
1012 List the files in C<directory> (relative to the root directory,
1013 there is no cwd) in the format of 'ls -la'.
1014
1015 This command is mostly useful for interactive sessions.  It
1016 is I<not> intended that you try to parse the output string.");
1017
1018   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1019    [InitBasicFS, Always, TestOutputList (
1020       [["touch"; "/new"];
1021        ["touch"; "/newer"];
1022        ["touch"; "/newest"];
1023        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1024    "list the files in a directory",
1025    "\
1026 List the files in C<directory> (relative to the root directory,
1027 there is no cwd).  The '.' and '..' entries are not returned, but
1028 hidden files are shown.
1029
1030 This command is mostly useful for interactive sessions.  Programs
1031 should probably use C<guestfs_readdir> instead.");
1032
1033   ("list_devices", (RStringList "devices", []), 7, [],
1034    [InitEmpty, Always, TestOutputListOfDevices (
1035       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1036    "list the block devices",
1037    "\
1038 List all the block devices.
1039
1040 The full block device names are returned, eg. C</dev/sda>");
1041
1042   ("list_partitions", (RStringList "partitions", []), 8, [],
1043    [InitBasicFS, Always, TestOutputListOfDevices (
1044       [["list_partitions"]], ["/dev/sda1"]);
1045     InitEmpty, Always, TestOutputListOfDevices (
1046       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1047        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1048    "list the partitions",
1049    "\
1050 List all the partitions detected on all block devices.
1051
1052 The full partition device names are returned, eg. C</dev/sda1>
1053
1054 This does not return logical volumes.  For that you will need to
1055 call C<guestfs_lvs>.");
1056
1057   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1058    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1059       [["pvs"]], ["/dev/sda1"]);
1060     InitEmpty, Always, TestOutputListOfDevices (
1061       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1062        ["pvcreate"; "/dev/sda1"];
1063        ["pvcreate"; "/dev/sda2"];
1064        ["pvcreate"; "/dev/sda3"];
1065        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1066    "list the LVM physical volumes (PVs)",
1067    "\
1068 List all the physical volumes detected.  This is the equivalent
1069 of the L<pvs(8)> command.
1070
1071 This returns a list of just the device names that contain
1072 PVs (eg. C</dev/sda2>).
1073
1074 See also C<guestfs_pvs_full>.");
1075
1076   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1077    [InitBasicFSonLVM, Always, TestOutputList (
1078       [["vgs"]], ["VG"]);
1079     InitEmpty, Always, TestOutputList (
1080       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1081        ["pvcreate"; "/dev/sda1"];
1082        ["pvcreate"; "/dev/sda2"];
1083        ["pvcreate"; "/dev/sda3"];
1084        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1085        ["vgcreate"; "VG2"; "/dev/sda3"];
1086        ["vgs"]], ["VG1"; "VG2"])],
1087    "list the LVM volume groups (VGs)",
1088    "\
1089 List all the volumes groups detected.  This is the equivalent
1090 of the L<vgs(8)> command.
1091
1092 This returns a list of just the volume group names that were
1093 detected (eg. C<VolGroup00>).
1094
1095 See also C<guestfs_vgs_full>.");
1096
1097   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1098    [InitBasicFSonLVM, Always, TestOutputList (
1099       [["lvs"]], ["/dev/VG/LV"]);
1100     InitEmpty, Always, TestOutputList (
1101       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1102        ["pvcreate"; "/dev/sda1"];
1103        ["pvcreate"; "/dev/sda2"];
1104        ["pvcreate"; "/dev/sda3"];
1105        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1106        ["vgcreate"; "VG2"; "/dev/sda3"];
1107        ["lvcreate"; "LV1"; "VG1"; "50"];
1108        ["lvcreate"; "LV2"; "VG1"; "50"];
1109        ["lvcreate"; "LV3"; "VG2"; "50"];
1110        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1111    "list the LVM logical volumes (LVs)",
1112    "\
1113 List all the logical volumes detected.  This is the equivalent
1114 of the L<lvs(8)> command.
1115
1116 This returns a list of the logical volume device names
1117 (eg. C</dev/VolGroup00/LogVol00>).
1118
1119 See also C<guestfs_lvs_full>.");
1120
1121   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1122    [], (* XXX how to test? *)
1123    "list the LVM physical volumes (PVs)",
1124    "\
1125 List all the physical volumes detected.  This is the equivalent
1126 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1127
1128   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1129    [], (* XXX how to test? *)
1130    "list the LVM volume groups (VGs)",
1131    "\
1132 List all the volumes groups detected.  This is the equivalent
1133 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1134
1135   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1136    [], (* XXX how to test? *)
1137    "list the LVM logical volumes (LVs)",
1138    "\
1139 List all the logical volumes detected.  This is the equivalent
1140 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1141
1142   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1143    [InitISOFS, Always, TestOutputList (
1144       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1145     InitISOFS, Always, TestOutputList (
1146       [["read_lines"; "/empty"]], [])],
1147    "read file as lines",
1148    "\
1149 Return the contents of the file named C<path>.
1150
1151 The file contents are returned as a list of lines.  Trailing
1152 C<LF> and C<CRLF> character sequences are I<not> returned.
1153
1154 Note that this function cannot correctly handle binary files
1155 (specifically, files containing C<\\0> character which is treated
1156 as end of line).  For those you need to use the C<guestfs_read_file>
1157 function which has a more complex interface.");
1158
1159   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1160    [], (* XXX Augeas code needs tests. *)
1161    "create a new Augeas handle",
1162    "\
1163 Create a new Augeas handle for editing configuration files.
1164 If there was any previous Augeas handle associated with this
1165 guestfs session, then it is closed.
1166
1167 You must call this before using any other C<guestfs_aug_*>
1168 commands.
1169
1170 C<root> is the filesystem root.  C<root> must not be NULL,
1171 use C</> instead.
1172
1173 The flags are the same as the flags defined in
1174 E<lt>augeas.hE<gt>, the logical I<or> of the following
1175 integers:
1176
1177 =over 4
1178
1179 =item C<AUG_SAVE_BACKUP> = 1
1180
1181 Keep the original file with a C<.augsave> extension.
1182
1183 =item C<AUG_SAVE_NEWFILE> = 2
1184
1185 Save changes into a file with extension C<.augnew>, and
1186 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1187
1188 =item C<AUG_TYPE_CHECK> = 4
1189
1190 Typecheck lenses (can be expensive).
1191
1192 =item C<AUG_NO_STDINC> = 8
1193
1194 Do not use standard load path for modules.
1195
1196 =item C<AUG_SAVE_NOOP> = 16
1197
1198 Make save a no-op, just record what would have been changed.
1199
1200 =item C<AUG_NO_LOAD> = 32
1201
1202 Do not load the tree in C<guestfs_aug_init>.
1203
1204 =back
1205
1206 To close the handle, you can call C<guestfs_aug_close>.
1207
1208 To find out more about Augeas, see L<http://augeas.net/>.");
1209
1210   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1211    [], (* XXX Augeas code needs tests. *)
1212    "close the current Augeas handle",
1213    "\
1214 Close the current Augeas handle and free up any resources
1215 used by it.  After calling this, you have to call
1216 C<guestfs_aug_init> again before you can use any other
1217 Augeas functions.");
1218
1219   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "define an Augeas variable",
1222    "\
1223 Defines an Augeas variable C<name> whose value is the result
1224 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1225 undefined.
1226
1227 On success this returns the number of nodes in C<expr>, or
1228 C<0> if C<expr> evaluates to something which is not a nodeset.");
1229
1230   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1231    [], (* XXX Augeas code needs tests. *)
1232    "define an Augeas node",
1233    "\
1234 Defines a variable C<name> whose value is the result of
1235 evaluating C<expr>.
1236
1237 If C<expr> evaluates to an empty nodeset, a node is created,
1238 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1239 C<name> will be the nodeset containing that single node.
1240
1241 On success this returns a pair containing the
1242 number of nodes in the nodeset, and a boolean flag
1243 if a node was created.");
1244
1245   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1246    [], (* XXX Augeas code needs tests. *)
1247    "look up the value of an Augeas path",
1248    "\
1249 Look up the value associated with C<path>.  If C<path>
1250 matches exactly one node, the C<value> is returned.");
1251
1252   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1253    [], (* XXX Augeas code needs tests. *)
1254    "set Augeas path to value",
1255    "\
1256 Set the value associated with C<path> to C<val>.
1257
1258 In the Augeas API, it is possible to clear a node by setting
1259 the value to NULL.  Due to an oversight in the libguestfs API
1260 you cannot do that with this call.  Instead you must use the
1261 C<guestfs_aug_clear> call.");
1262
1263   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1264    [], (* XXX Augeas code needs tests. *)
1265    "insert a sibling Augeas node",
1266    "\
1267 Create a new sibling C<label> for C<path>, inserting it into
1268 the tree before or after C<path> (depending on the boolean
1269 flag C<before>).
1270
1271 C<path> must match exactly one existing node in the tree, and
1272 C<label> must be a label, ie. not contain C</>, C<*> or end
1273 with a bracketed index C<[N]>.");
1274
1275   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1276    [], (* XXX Augeas code needs tests. *)
1277    "remove an Augeas path",
1278    "\
1279 Remove C<path> and all of its children.
1280
1281 On success this returns the number of entries which were removed.");
1282
1283   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1284    [], (* XXX Augeas code needs tests. *)
1285    "move Augeas node",
1286    "\
1287 Move the node C<src> to C<dest>.  C<src> must match exactly
1288 one node.  C<dest> is overwritten if it exists.");
1289
1290   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1291    [], (* XXX Augeas code needs tests. *)
1292    "return Augeas nodes which match augpath",
1293    "\
1294 Returns a list of paths which match the path expression C<path>.
1295 The returned paths are sufficiently qualified so that they match
1296 exactly one node in the current tree.");
1297
1298   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1299    [], (* XXX Augeas code needs tests. *)
1300    "write all pending Augeas changes to disk",
1301    "\
1302 This writes all pending changes to disk.
1303
1304 The flags which were passed to C<guestfs_aug_init> affect exactly
1305 how files are saved.");
1306
1307   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1308    [], (* XXX Augeas code needs tests. *)
1309    "load files into the tree",
1310    "\
1311 Load files into the tree.
1312
1313 See C<aug_load> in the Augeas documentation for the full gory
1314 details.");
1315
1316   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1317    [], (* XXX Augeas code needs tests. *)
1318    "list Augeas nodes under augpath",
1319    "\
1320 This is just a shortcut for listing C<guestfs_aug_match>
1321 C<path/*> and sorting the resulting nodes into alphabetical order.");
1322
1323   ("rm", (RErr, [Pathname "path"]), 29, [],
1324    [InitBasicFS, Always, TestRun
1325       [["touch"; "/new"];
1326        ["rm"; "/new"]];
1327     InitBasicFS, Always, TestLastFail
1328       [["rm"; "/new"]];
1329     InitBasicFS, Always, TestLastFail
1330       [["mkdir"; "/new"];
1331        ["rm"; "/new"]]],
1332    "remove a file",
1333    "\
1334 Remove the single file C<path>.");
1335
1336   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1337    [InitBasicFS, Always, TestRun
1338       [["mkdir"; "/new"];
1339        ["rmdir"; "/new"]];
1340     InitBasicFS, Always, TestLastFail
1341       [["rmdir"; "/new"]];
1342     InitBasicFS, Always, TestLastFail
1343       [["touch"; "/new"];
1344        ["rmdir"; "/new"]]],
1345    "remove a directory",
1346    "\
1347 Remove the single directory C<path>.");
1348
1349   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1350    [InitBasicFS, Always, TestOutputFalse
1351       [["mkdir"; "/new"];
1352        ["mkdir"; "/new/foo"];
1353        ["touch"; "/new/foo/bar"];
1354        ["rm_rf"; "/new"];
1355        ["exists"; "/new"]]],
1356    "remove a file or directory recursively",
1357    "\
1358 Remove the file or directory C<path>, recursively removing the
1359 contents if its a directory.  This is like the C<rm -rf> shell
1360 command.");
1361
1362   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1363    [InitBasicFS, Always, TestOutputTrue
1364       [["mkdir"; "/new"];
1365        ["is_dir"; "/new"]];
1366     InitBasicFS, Always, TestLastFail
1367       [["mkdir"; "/new/foo/bar"]]],
1368    "create a directory",
1369    "\
1370 Create a directory named C<path>.");
1371
1372   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1373    [InitBasicFS, Always, TestOutputTrue
1374       [["mkdir_p"; "/new/foo/bar"];
1375        ["is_dir"; "/new/foo/bar"]];
1376     InitBasicFS, Always, TestOutputTrue
1377       [["mkdir_p"; "/new/foo/bar"];
1378        ["is_dir"; "/new/foo"]];
1379     InitBasicFS, Always, TestOutputTrue
1380       [["mkdir_p"; "/new/foo/bar"];
1381        ["is_dir"; "/new"]];
1382     (* Regression tests for RHBZ#503133: *)
1383     InitBasicFS, Always, TestRun
1384       [["mkdir"; "/new"];
1385        ["mkdir_p"; "/new"]];
1386     InitBasicFS, Always, TestLastFail
1387       [["touch"; "/new"];
1388        ["mkdir_p"; "/new"]]],
1389    "create a directory and parents",
1390    "\
1391 Create a directory named C<path>, creating any parent directories
1392 as necessary.  This is like the C<mkdir -p> shell command.");
1393
1394   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1395    [], (* XXX Need stat command to test *)
1396    "change file mode",
1397    "\
1398 Change the mode (permissions) of C<path> to C<mode>.  Only
1399 numeric modes are supported.
1400
1401 I<Note>: When using this command from guestfish, C<mode>
1402 by default would be decimal, unless you prefix it with
1403 C<0> to get octal, ie. use C<0700> not C<700>.
1404
1405 The mode actually set is affected by the umask.");
1406
1407   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1408    [], (* XXX Need stat command to test *)
1409    "change file owner and group",
1410    "\
1411 Change the file owner to C<owner> and group to C<group>.
1412
1413 Only numeric uid and gid are supported.  If you want to use
1414 names, you will need to locate and parse the password file
1415 yourself (Augeas support makes this relatively easy).");
1416
1417   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1418    [InitISOFS, Always, TestOutputTrue (
1419       [["exists"; "/empty"]]);
1420     InitISOFS, Always, TestOutputTrue (
1421       [["exists"; "/directory"]])],
1422    "test if file or directory exists",
1423    "\
1424 This returns C<true> if and only if there is a file, directory
1425 (or anything) with the given C<path> name.
1426
1427 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1428
1429   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1430    [InitISOFS, Always, TestOutputTrue (
1431       [["is_file"; "/known-1"]]);
1432     InitISOFS, Always, TestOutputFalse (
1433       [["is_file"; "/directory"]])],
1434    "test if file exists",
1435    "\
1436 This returns C<true> if and only if there is a file
1437 with the given C<path> name.  Note that it returns false for
1438 other objects like directories.
1439
1440 See also C<guestfs_stat>.");
1441
1442   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1443    [InitISOFS, Always, TestOutputFalse (
1444       [["is_dir"; "/known-3"]]);
1445     InitISOFS, Always, TestOutputTrue (
1446       [["is_dir"; "/directory"]])],
1447    "test if file exists",
1448    "\
1449 This returns C<true> if and only if there is a directory
1450 with the given C<path> name.  Note that it returns false for
1451 other objects like files.
1452
1453 See also C<guestfs_stat>.");
1454
1455   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1456    [InitEmpty, Always, TestOutputListOfDevices (
1457       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1458        ["pvcreate"; "/dev/sda1"];
1459        ["pvcreate"; "/dev/sda2"];
1460        ["pvcreate"; "/dev/sda3"];
1461        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1462    "create an LVM physical volume",
1463    "\
1464 This creates an LVM physical volume on the named C<device>,
1465 where C<device> should usually be a partition name such
1466 as C</dev/sda1>.");
1467
1468   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1469    [InitEmpty, Always, TestOutputList (
1470       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1471        ["pvcreate"; "/dev/sda1"];
1472        ["pvcreate"; "/dev/sda2"];
1473        ["pvcreate"; "/dev/sda3"];
1474        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1475        ["vgcreate"; "VG2"; "/dev/sda3"];
1476        ["vgs"]], ["VG1"; "VG2"])],
1477    "create an LVM volume group",
1478    "\
1479 This creates an LVM volume group called C<volgroup>
1480 from the non-empty list of physical volumes C<physvols>.");
1481
1482   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1483    [InitEmpty, Always, TestOutputList (
1484       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1485        ["pvcreate"; "/dev/sda1"];
1486        ["pvcreate"; "/dev/sda2"];
1487        ["pvcreate"; "/dev/sda3"];
1488        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1489        ["vgcreate"; "VG2"; "/dev/sda3"];
1490        ["lvcreate"; "LV1"; "VG1"; "50"];
1491        ["lvcreate"; "LV2"; "VG1"; "50"];
1492        ["lvcreate"; "LV3"; "VG2"; "50"];
1493        ["lvcreate"; "LV4"; "VG2"; "50"];
1494        ["lvcreate"; "LV5"; "VG2"; "50"];
1495        ["lvs"]],
1496       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1497        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1498    "create an LVM logical volume",
1499    "\
1500 This creates an LVM logical volume called C<logvol>
1501 on the volume group C<volgroup>, with C<size> megabytes.");
1502
1503   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1504    [InitEmpty, Always, TestOutput (
1505       [["part_disk"; "/dev/sda"; "mbr"];
1506        ["mkfs"; "ext2"; "/dev/sda1"];
1507        ["mount_options"; ""; "/dev/sda1"; "/"];
1508        ["write"; "/new"; "new file contents"];
1509        ["cat"; "/new"]], "new file contents")],
1510    "make a filesystem",
1511    "\
1512 This creates a filesystem on C<device> (usually a partition
1513 or LVM logical volume).  The filesystem type is C<fstype>, for
1514 example C<ext3>.");
1515
1516   ("sfdisk", (RErr, [Device "device";
1517                      Int "cyls"; Int "heads"; Int "sectors";
1518                      StringList "lines"]), 43, [DangerWillRobinson],
1519    [],
1520    "create partitions on a block device",
1521    "\
1522 This is a direct interface to the L<sfdisk(8)> program for creating
1523 partitions on block devices.
1524
1525 C<device> should be a block device, for example C</dev/sda>.
1526
1527 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1528 and sectors on the device, which are passed directly to sfdisk as
1529 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1530 of these, then the corresponding parameter is omitted.  Usually for
1531 'large' disks, you can just pass C<0> for these, but for small
1532 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1533 out the right geometry and you will need to tell it.
1534
1535 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1536 information refer to the L<sfdisk(8)> manpage.
1537
1538 To create a single partition occupying the whole disk, you would
1539 pass C<lines> as a single element list, when the single element being
1540 the string C<,> (comma).
1541
1542 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1543 C<guestfs_part_init>");
1544
1545   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1546    [],
1547    "create a file",
1548    "\
1549 This call creates a file called C<path>.  The contents of the
1550 file is the string C<content> (which can contain any 8 bit data),
1551 with length C<size>.
1552
1553 As a special case, if C<size> is C<0>
1554 then the length is calculated using C<strlen> (so in this case
1555 the content cannot contain embedded ASCII NULs).
1556
1557 I<NB.> Owing to a bug, writing content containing ASCII NUL
1558 characters does I<not> work, even if the length is specified.");
1559
1560   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1561    [InitEmpty, Always, TestOutputListOfDevices (
1562       [["part_disk"; "/dev/sda"; "mbr"];
1563        ["mkfs"; "ext2"; "/dev/sda1"];
1564        ["mount_options"; ""; "/dev/sda1"; "/"];
1565        ["mounts"]], ["/dev/sda1"]);
1566     InitEmpty, Always, TestOutputList (
1567       [["part_disk"; "/dev/sda"; "mbr"];
1568        ["mkfs"; "ext2"; "/dev/sda1"];
1569        ["mount_options"; ""; "/dev/sda1"; "/"];
1570        ["umount"; "/"];
1571        ["mounts"]], [])],
1572    "unmount a filesystem",
1573    "\
1574 This unmounts the given filesystem.  The filesystem may be
1575 specified either by its mountpoint (path) or the device which
1576 contains the filesystem.");
1577
1578   ("mounts", (RStringList "devices", []), 46, [],
1579    [InitBasicFS, Always, TestOutputListOfDevices (
1580       [["mounts"]], ["/dev/sda1"])],
1581    "show mounted filesystems",
1582    "\
1583 This returns the list of currently mounted filesystems.  It returns
1584 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1585
1586 Some internal mounts are not shown.
1587
1588 See also: C<guestfs_mountpoints>");
1589
1590   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1591    [InitBasicFS, Always, TestOutputList (
1592       [["umount_all"];
1593        ["mounts"]], []);
1594     (* check that umount_all can unmount nested mounts correctly: *)
1595     InitEmpty, Always, TestOutputList (
1596       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1597        ["mkfs"; "ext2"; "/dev/sda1"];
1598        ["mkfs"; "ext2"; "/dev/sda2"];
1599        ["mkfs"; "ext2"; "/dev/sda3"];
1600        ["mount_options"; ""; "/dev/sda1"; "/"];
1601        ["mkdir"; "/mp1"];
1602        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1603        ["mkdir"; "/mp1/mp2"];
1604        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1605        ["mkdir"; "/mp1/mp2/mp3"];
1606        ["umount_all"];
1607        ["mounts"]], [])],
1608    "unmount all filesystems",
1609    "\
1610 This unmounts all mounted filesystems.
1611
1612 Some internal mounts are not unmounted by this call.");
1613
1614   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1615    [],
1616    "remove all LVM LVs, VGs and PVs",
1617    "\
1618 This command removes all LVM logical volumes, volume groups
1619 and physical volumes.");
1620
1621   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1622    [InitISOFS, Always, TestOutput (
1623       [["file"; "/empty"]], "empty");
1624     InitISOFS, Always, TestOutput (
1625       [["file"; "/known-1"]], "ASCII text");
1626     InitISOFS, Always, TestLastFail (
1627       [["file"; "/notexists"]])],
1628    "determine file type",
1629    "\
1630 This call uses the standard L<file(1)> command to determine
1631 the type or contents of the file.  This also works on devices,
1632 for example to find out whether a partition contains a filesystem.
1633
1634 This call will also transparently look inside various types
1635 of compressed file.
1636
1637 The exact command which runs is C<file -zbsL path>.  Note in
1638 particular that the filename is not prepended to the output
1639 (the C<-b> option).");
1640
1641   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1642    [InitBasicFS, Always, TestOutput (
1643       [["upload"; "test-command"; "/test-command"];
1644        ["chmod"; "0o755"; "/test-command"];
1645        ["command"; "/test-command 1"]], "Result1");
1646     InitBasicFS, Always, TestOutput (
1647       [["upload"; "test-command"; "/test-command"];
1648        ["chmod"; "0o755"; "/test-command"];
1649        ["command"; "/test-command 2"]], "Result2\n");
1650     InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 3"]], "\nResult3");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 4"]], "\nResult4\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 5"]], "\nResult5\n\n");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 7"]], "");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 8"]], "\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 9"]], "\n\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1682     InitBasicFS, Always, TestOutput (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1686     InitBasicFS, Always, TestLastFail (
1687       [["upload"; "test-command"; "/test-command"];
1688        ["chmod"; "0o755"; "/test-command"];
1689        ["command"; "/test-command"]])],
1690    "run a command from the guest filesystem",
1691    "\
1692 This call runs a command from the guest filesystem.  The
1693 filesystem must be mounted, and must contain a compatible
1694 operating system (ie. something Linux, with the same
1695 or compatible processor architecture).
1696
1697 The single parameter is an argv-style list of arguments.
1698 The first element is the name of the program to run.
1699 Subsequent elements are parameters.  The list must be
1700 non-empty (ie. must contain a program name).  Note that
1701 the command runs directly, and is I<not> invoked via
1702 the shell (see C<guestfs_sh>).
1703
1704 The return value is anything printed to I<stdout> by
1705 the command.
1706
1707 If the command returns a non-zero exit status, then
1708 this function returns an error message.  The error message
1709 string is the content of I<stderr> from the command.
1710
1711 The C<$PATH> environment variable will contain at least
1712 C</usr/bin> and C</bin>.  If you require a program from
1713 another location, you should provide the full path in the
1714 first parameter.
1715
1716 Shared libraries and data files required by the program
1717 must be available on filesystems which are mounted in the
1718 correct places.  It is the caller's responsibility to ensure
1719 all filesystems that are needed are mounted at the right
1720 locations.");
1721
1722   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1723    [InitBasicFS, Always, TestOutputList (
1724       [["upload"; "test-command"; "/test-command"];
1725        ["chmod"; "0o755"; "/test-command"];
1726        ["command_lines"; "/test-command 1"]], ["Result1"]);
1727     InitBasicFS, Always, TestOutputList (
1728       [["upload"; "test-command"; "/test-command"];
1729        ["chmod"; "0o755"; "/test-command"];
1730        ["command_lines"; "/test-command 2"]], ["Result2"]);
1731     InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 7"]], []);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 8"]], [""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 9"]], ["";""]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1763     InitBasicFS, Always, TestOutputList (
1764       [["upload"; "test-command"; "/test-command"];
1765        ["chmod"; "0o755"; "/test-command"];
1766        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1767    "run a command, returning lines",
1768    "\
1769 This is the same as C<guestfs_command>, but splits the
1770 result into a list of lines.
1771
1772 See also: C<guestfs_sh_lines>");
1773
1774   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1775    [InitISOFS, Always, TestOutputStruct (
1776       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1777    "get file information",
1778    "\
1779 Returns file information for the given C<path>.
1780
1781 This is the same as the C<stat(2)> system call.");
1782
1783   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1784    [InitISOFS, Always, TestOutputStruct (
1785       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1786    "get file information for a symbolic link",
1787    "\
1788 Returns file information for the given C<path>.
1789
1790 This is the same as C<guestfs_stat> except that if C<path>
1791 is a symbolic link, then the link is stat-ed, not the file it
1792 refers to.
1793
1794 This is the same as the C<lstat(2)> system call.");
1795
1796   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1797    [InitISOFS, Always, TestOutputStruct (
1798       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1799    "get file system statistics",
1800    "\
1801 Returns file system statistics for any mounted file system.
1802 C<path> should be a file or directory in the mounted file system
1803 (typically it is the mount point itself, but it doesn't need to be).
1804
1805 This is the same as the C<statvfs(2)> system call.");
1806
1807   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1808    [], (* XXX test *)
1809    "get ext2/ext3/ext4 superblock details",
1810    "\
1811 This returns the contents of the ext2, ext3 or ext4 filesystem
1812 superblock on C<device>.
1813
1814 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1815 manpage for more details.  The list of fields returned isn't
1816 clearly defined, and depends on both the version of C<tune2fs>
1817 that libguestfs was built against, and the filesystem itself.");
1818
1819   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1820    [InitEmpty, Always, TestOutputTrue (
1821       [["blockdev_setro"; "/dev/sda"];
1822        ["blockdev_getro"; "/dev/sda"]])],
1823    "set block device to read-only",
1824    "\
1825 Sets the block device named C<device> to read-only.
1826
1827 This uses the L<blockdev(8)> command.");
1828
1829   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1830    [InitEmpty, Always, TestOutputFalse (
1831       [["blockdev_setrw"; "/dev/sda"];
1832        ["blockdev_getro"; "/dev/sda"]])],
1833    "set block device to read-write",
1834    "\
1835 Sets the block device named C<device> to read-write.
1836
1837 This uses the L<blockdev(8)> command.");
1838
1839   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1840    [InitEmpty, Always, TestOutputTrue (
1841       [["blockdev_setro"; "/dev/sda"];
1842        ["blockdev_getro"; "/dev/sda"]])],
1843    "is block device set to read-only",
1844    "\
1845 Returns a boolean indicating if the block device is read-only
1846 (true if read-only, false if not).
1847
1848 This uses the L<blockdev(8)> command.");
1849
1850   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1851    [InitEmpty, Always, TestOutputInt (
1852       [["blockdev_getss"; "/dev/sda"]], 512)],
1853    "get sectorsize of block device",
1854    "\
1855 This returns the size of sectors on a block device.
1856 Usually 512, but can be larger for modern devices.
1857
1858 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1859 for that).
1860
1861 This uses the L<blockdev(8)> command.");
1862
1863   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1864    [InitEmpty, Always, TestOutputInt (
1865       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1866    "get blocksize of block device",
1867    "\
1868 This returns the block size of a device.
1869
1870 (Note this is different from both I<size in blocks> and
1871 I<filesystem block size>).
1872
1873 This uses the L<blockdev(8)> command.");
1874
1875   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1876    [], (* XXX test *)
1877    "set blocksize of block device",
1878    "\
1879 This sets the block size of a device.
1880
1881 (Note this is different from both I<size in blocks> and
1882 I<filesystem block size>).
1883
1884 This uses the L<blockdev(8)> command.");
1885
1886   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1887    [InitEmpty, Always, TestOutputInt (
1888       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1889    "get total size of device in 512-byte sectors",
1890    "\
1891 This returns the size of the device in units of 512-byte sectors
1892 (even if the sectorsize isn't 512 bytes ... weird).
1893
1894 See also C<guestfs_blockdev_getss> for the real sector size of
1895 the device, and C<guestfs_blockdev_getsize64> for the more
1896 useful I<size in bytes>.
1897
1898 This uses the L<blockdev(8)> command.");
1899
1900   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1901    [InitEmpty, Always, TestOutputInt (
1902       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1903    "get total size of device in bytes",
1904    "\
1905 This returns the size of the device in bytes.
1906
1907 See also C<guestfs_blockdev_getsz>.
1908
1909 This uses the L<blockdev(8)> command.");
1910
1911   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1912    [InitEmpty, Always, TestRun
1913       [["blockdev_flushbufs"; "/dev/sda"]]],
1914    "flush device buffers",
1915    "\
1916 This tells the kernel to flush internal buffers associated
1917 with C<device>.
1918
1919 This uses the L<blockdev(8)> command.");
1920
1921   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1922    [InitEmpty, Always, TestRun
1923       [["blockdev_rereadpt"; "/dev/sda"]]],
1924    "reread partition table",
1925    "\
1926 Reread the partition table on C<device>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1931    [InitBasicFS, Always, TestOutput (
1932       (* Pick a file from cwd which isn't likely to change. *)
1933       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1934        ["checksum"; "md5"; "/COPYING.LIB"]],
1935       Digest.to_hex (Digest.file "COPYING.LIB"))],
1936    "upload a file from the local machine",
1937    "\
1938 Upload local file C<filename> to C<remotefilename> on the
1939 filesystem.
1940
1941 C<filename> can also be a named pipe.
1942
1943 See also C<guestfs_download>.");
1944
1945   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1946    [InitBasicFS, Always, TestOutput (
1947       (* Pick a file from cwd which isn't likely to change. *)
1948       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1949        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1950        ["upload"; "testdownload.tmp"; "/upload"];
1951        ["checksum"; "md5"; "/upload"]],
1952       Digest.to_hex (Digest.file "COPYING.LIB"))],
1953    "download a file to the local machine",
1954    "\
1955 Download file C<remotefilename> and save it as C<filename>
1956 on the local machine.
1957
1958 C<filename> can also be a named pipe.
1959
1960 See also C<guestfs_upload>, C<guestfs_cat>.");
1961
1962   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1963    [InitISOFS, Always, TestOutput (
1964       [["checksum"; "crc"; "/known-3"]], "2891671662");
1965     InitISOFS, Always, TestLastFail (
1966       [["checksum"; "crc"; "/notexists"]]);
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1977     InitISOFS, Always, TestOutput (
1978       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1979     (* Test for RHBZ#579608, absolute symbolic links. *)
1980     InitISOFS, Always, TestOutput (
1981       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1982    "compute MD5, SHAx or CRC checksum of file",
1983    "\
1984 This call computes the MD5, SHAx or CRC checksum of the
1985 file named C<path>.
1986
1987 The type of checksum to compute is given by the C<csumtype>
1988 parameter which must have one of the following values:
1989
1990 =over 4
1991
1992 =item C<crc>
1993
1994 Compute the cyclic redundancy check (CRC) specified by POSIX
1995 for the C<cksum> command.
1996
1997 =item C<md5>
1998
1999 Compute the MD5 hash (using the C<md5sum> program).
2000
2001 =item C<sha1>
2002
2003 Compute the SHA1 hash (using the C<sha1sum> program).
2004
2005 =item C<sha224>
2006
2007 Compute the SHA224 hash (using the C<sha224sum> program).
2008
2009 =item C<sha256>
2010
2011 Compute the SHA256 hash (using the C<sha256sum> program).
2012
2013 =item C<sha384>
2014
2015 Compute the SHA384 hash (using the C<sha384sum> program).
2016
2017 =item C<sha512>
2018
2019 Compute the SHA512 hash (using the C<sha512sum> program).
2020
2021 =back
2022
2023 The checksum is returned as a printable string.
2024
2025 To get the checksum for a device, use C<guestfs_checksum_device>.
2026
2027 To get the checksums for many files, use C<guestfs_checksums_out>.");
2028
2029   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2030    [InitBasicFS, Always, TestOutput (
2031       [["tar_in"; "../images/helloworld.tar"; "/"];
2032        ["cat"; "/hello"]], "hello\n")],
2033    "unpack tarfile to directory",
2034    "\
2035 This command uploads and unpacks local file C<tarfile> (an
2036 I<uncompressed> tar file) into C<directory>.
2037
2038 To upload a compressed tarball, use C<guestfs_tgz_in>
2039 or C<guestfs_txz_in>.");
2040
2041   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2042    [],
2043    "pack directory into tarfile",
2044    "\
2045 This command packs the contents of C<directory> and downloads
2046 it to local file C<tarfile>.
2047
2048 To download a compressed tarball, use C<guestfs_tgz_out>
2049 or C<guestfs_txz_out>.");
2050
2051   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2052    [InitBasicFS, Always, TestOutput (
2053       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2054        ["cat"; "/hello"]], "hello\n")],
2055    "unpack compressed tarball to directory",
2056    "\
2057 This command uploads and unpacks local file C<tarball> (a
2058 I<gzip compressed> tar file) into C<directory>.
2059
2060 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2061
2062   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2063    [],
2064    "pack directory into compressed tarball",
2065    "\
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarball>.
2068
2069 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2070
2071   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2072    [InitBasicFS, Always, TestLastFail (
2073       [["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["touch"; "/new"]]);
2076     InitBasicFS, Always, TestOutput (
2077       [["write"; "/new"; "data"];
2078        ["umount"; "/"];
2079        ["mount_ro"; "/dev/sda1"; "/"];
2080        ["cat"; "/new"]], "data")],
2081    "mount a guest disk, read-only",
2082    "\
2083 This is the same as the C<guestfs_mount> command, but it
2084 mounts the filesystem with the read-only (I<-o ro>) flag.");
2085
2086   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2087    [],
2088    "mount a guest disk with mount options",
2089    "\
2090 This is the same as the C<guestfs_mount> command, but it
2091 allows you to set the mount options as for the
2092 L<mount(8)> I<-o> flag.
2093
2094 If the C<options> parameter is an empty string, then
2095 no options are passed (all options default to whatever
2096 the filesystem uses).");
2097
2098   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2099    [],
2100    "mount a guest disk with mount options and vfstype",
2101    "\
2102 This is the same as the C<guestfs_mount> command, but it
2103 allows you to set both the mount options and the vfstype
2104 as for the L<mount(8)> I<-o> and I<-t> flags.");
2105
2106   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2107    [],
2108    "debugging and internals",
2109    "\
2110 The C<guestfs_debug> command exposes some internals of
2111 C<guestfsd> (the guestfs daemon) that runs inside the
2112 qemu subprocess.
2113
2114 There is no comprehensive help for this command.  You have
2115 to look at the file C<daemon/debug.c> in the libguestfs source
2116 to find out what you can do.");
2117
2118   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2119    [InitEmpty, Always, TestOutputList (
2120       [["part_disk"; "/dev/sda"; "mbr"];
2121        ["pvcreate"; "/dev/sda1"];
2122        ["vgcreate"; "VG"; "/dev/sda1"];
2123        ["lvcreate"; "LV1"; "VG"; "50"];
2124        ["lvcreate"; "LV2"; "VG"; "50"];
2125        ["lvremove"; "/dev/VG/LV1"];
2126        ["lvs"]], ["/dev/VG/LV2"]);
2127     InitEmpty, Always, TestOutputList (
2128       [["part_disk"; "/dev/sda"; "mbr"];
2129        ["pvcreate"; "/dev/sda1"];
2130        ["vgcreate"; "VG"; "/dev/sda1"];
2131        ["lvcreate"; "LV1"; "VG"; "50"];
2132        ["lvcreate"; "LV2"; "VG"; "50"];
2133        ["lvremove"; "/dev/VG"];
2134        ["lvs"]], []);
2135     InitEmpty, Always, TestOutputList (
2136       [["part_disk"; "/dev/sda"; "mbr"];
2137        ["pvcreate"; "/dev/sda1"];
2138        ["vgcreate"; "VG"; "/dev/sda1"];
2139        ["lvcreate"; "LV1"; "VG"; "50"];
2140        ["lvcreate"; "LV2"; "VG"; "50"];
2141        ["lvremove"; "/dev/VG"];
2142        ["vgs"]], ["VG"])],
2143    "remove an LVM logical volume",
2144    "\
2145 Remove an LVM logical volume C<device>, where C<device> is
2146 the path to the LV, such as C</dev/VG/LV>.
2147
2148 You can also remove all LVs in a volume group by specifying
2149 the VG name, C</dev/VG>.");
2150
2151   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2152    [InitEmpty, Always, TestOutputList (
2153       [["part_disk"; "/dev/sda"; "mbr"];
2154        ["pvcreate"; "/dev/sda1"];
2155        ["vgcreate"; "VG"; "/dev/sda1"];
2156        ["lvcreate"; "LV1"; "VG"; "50"];
2157        ["lvcreate"; "LV2"; "VG"; "50"];
2158        ["vgremove"; "VG"];
2159        ["lvs"]], []);
2160     InitEmpty, Always, TestOutputList (
2161       [["part_disk"; "/dev/sda"; "mbr"];
2162        ["pvcreate"; "/dev/sda1"];
2163        ["vgcreate"; "VG"; "/dev/sda1"];
2164        ["lvcreate"; "LV1"; "VG"; "50"];
2165        ["lvcreate"; "LV2"; "VG"; "50"];
2166        ["vgremove"; "VG"];
2167        ["vgs"]], [])],
2168    "remove an LVM volume group",
2169    "\
2170 Remove an LVM volume group C<vgname>, (for example C<VG>).
2171
2172 This also forcibly removes all logical volumes in the volume
2173 group (if any).");
2174
2175   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2176    [InitEmpty, Always, TestOutputListOfDevices (
2177       [["part_disk"; "/dev/sda"; "mbr"];
2178        ["pvcreate"; "/dev/sda1"];
2179        ["vgcreate"; "VG"; "/dev/sda1"];
2180        ["lvcreate"; "LV1"; "VG"; "50"];
2181        ["lvcreate"; "LV2"; "VG"; "50"];
2182        ["vgremove"; "VG"];
2183        ["pvremove"; "/dev/sda1"];
2184        ["lvs"]], []);
2185     InitEmpty, Always, TestOutputListOfDevices (
2186       [["part_disk"; "/dev/sda"; "mbr"];
2187        ["pvcreate"; "/dev/sda1"];
2188        ["vgcreate"; "VG"; "/dev/sda1"];
2189        ["lvcreate"; "LV1"; "VG"; "50"];
2190        ["lvcreate"; "LV2"; "VG"; "50"];
2191        ["vgremove"; "VG"];
2192        ["pvremove"; "/dev/sda1"];
2193        ["vgs"]], []);
2194     InitEmpty, Always, TestOutputListOfDevices (
2195       [["part_disk"; "/dev/sda"; "mbr"];
2196        ["pvcreate"; "/dev/sda1"];
2197        ["vgcreate"; "VG"; "/dev/sda1"];
2198        ["lvcreate"; "LV1"; "VG"; "50"];
2199        ["lvcreate"; "LV2"; "VG"; "50"];
2200        ["vgremove"; "VG"];
2201        ["pvremove"; "/dev/sda1"];
2202        ["pvs"]], [])],
2203    "remove an LVM physical volume",
2204    "\
2205 This wipes a physical volume C<device> so that LVM will no longer
2206 recognise it.
2207
2208 The implementation uses the C<pvremove> command which refuses to
2209 wipe physical volumes that contain any volume groups, so you have
2210 to remove those first.");
2211
2212   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2213    [InitBasicFS, Always, TestOutput (
2214       [["set_e2label"; "/dev/sda1"; "testlabel"];
2215        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2216    "set the ext2/3/4 filesystem label",
2217    "\
2218 This sets the ext2/3/4 filesystem label of the filesystem on
2219 C<device> to C<label>.  Filesystem labels are limited to
2220 16 characters.
2221
2222 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2223 to return the existing label on a filesystem.");
2224
2225   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2226    [],
2227    "get the ext2/3/4 filesystem label",
2228    "\
2229 This returns the ext2/3/4 filesystem label of the filesystem on
2230 C<device>.");
2231
2232   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2233    (let uuid = uuidgen () in
2234     [InitBasicFS, Always, TestOutput (
2235        [["set_e2uuid"; "/dev/sda1"; uuid];
2236         ["get_e2uuid"; "/dev/sda1"]], uuid);
2237      InitBasicFS, Always, TestOutput (
2238        [["set_e2uuid"; "/dev/sda1"; "clear"];
2239         ["get_e2uuid"; "/dev/sda1"]], "");
2240      (* We can't predict what UUIDs will be, so just check the commands run. *)
2241      InitBasicFS, Always, TestRun (
2242        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2243      InitBasicFS, Always, TestRun (
2244        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2245    "set the ext2/3/4 filesystem UUID",
2246    "\
2247 This sets the ext2/3/4 filesystem UUID of the filesystem on
2248 C<device> to C<uuid>.  The format of the UUID and alternatives
2249 such as C<clear>, C<random> and C<time> are described in the
2250 L<tune2fs(8)> manpage.
2251
2252 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2253 to return the existing UUID of a filesystem.");
2254
2255   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2256    [],
2257    "get the ext2/3/4 filesystem UUID",
2258    "\
2259 This returns the ext2/3/4 filesystem UUID of the filesystem on
2260 C<device>.");
2261
2262   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2263    [InitBasicFS, Always, TestOutputInt (
2264       [["umount"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2266     InitBasicFS, Always, TestOutputInt (
2267       [["umount"; "/dev/sda1"];
2268        ["zero"; "/dev/sda1"];
2269        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2270    "run the filesystem checker",
2271    "\
2272 This runs the filesystem checker (fsck) on C<device> which
2273 should have filesystem type C<fstype>.
2274
2275 The returned integer is the status.  See L<fsck(8)> for the
2276 list of status codes from C<fsck>.
2277
2278 Notes:
2279
2280 =over 4
2281
2282 =item *
2283
2284 Multiple status codes can be summed together.
2285
2286 =item *
2287
2288 A non-zero return code can mean \"success\", for example if
2289 errors have been corrected on the filesystem.
2290
2291 =item *
2292
2293 Checking or repairing NTFS volumes is not supported
2294 (by linux-ntfs).
2295
2296 =back
2297
2298 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2299
2300   ("zero", (RErr, [Device "device"]), 85, [],
2301    [InitBasicFS, Always, TestOutput (
2302       [["umount"; "/dev/sda1"];
2303        ["zero"; "/dev/sda1"];
2304        ["file"; "/dev/sda1"]], "data")],
2305    "write zeroes to the device",
2306    "\
2307 This command writes zeroes over the first few blocks of C<device>.
2308
2309 How many blocks are zeroed isn't specified (but it's I<not> enough
2310 to securely wipe the device).  It should be sufficient to remove
2311 any partition tables, filesystem superblocks and so on.
2312
2313 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2314
2315   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2316    (* Test disabled because grub-install incompatible with virtio-blk driver.
2317     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2318     *)
2319    [InitBasicFS, Disabled, TestOutputTrue (
2320       [["grub_install"; "/"; "/dev/sda1"];
2321        ["is_dir"; "/boot"]])],
2322    "install GRUB",
2323    "\
2324 This command installs GRUB (the Grand Unified Bootloader) on
2325 C<device>, with the root directory being C<root>.");
2326
2327   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2328    [InitBasicFS, Always, TestOutput (
2329       [["write"; "/old"; "file content"];
2330        ["cp"; "/old"; "/new"];
2331        ["cat"; "/new"]], "file content");
2332     InitBasicFS, Always, TestOutputTrue (
2333       [["write"; "/old"; "file content"];
2334        ["cp"; "/old"; "/new"];
2335        ["is_file"; "/old"]]);
2336     InitBasicFS, Always, TestOutput (
2337       [["write"; "/old"; "file content"];
2338        ["mkdir"; "/dir"];
2339        ["cp"; "/old"; "/dir/new"];
2340        ["cat"; "/dir/new"]], "file content")],
2341    "copy a file",
2342    "\
2343 This copies a file from C<src> to C<dest> where C<dest> is
2344 either a destination filename or destination directory.");
2345
2346   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2347    [InitBasicFS, Always, TestOutput (
2348       [["mkdir"; "/olddir"];
2349        ["mkdir"; "/newdir"];
2350        ["write"; "/olddir/file"; "file content"];
2351        ["cp_a"; "/olddir"; "/newdir"];
2352        ["cat"; "/newdir/olddir/file"]], "file content")],
2353    "copy a file or directory recursively",
2354    "\
2355 This copies a file or directory from C<src> to C<dest>
2356 recursively using the C<cp -a> command.");
2357
2358   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2359    [InitBasicFS, Always, TestOutput (
2360       [["write"; "/old"; "file content"];
2361        ["mv"; "/old"; "/new"];
2362        ["cat"; "/new"]], "file content");
2363     InitBasicFS, Always, TestOutputFalse (
2364       [["write"; "/old"; "file content"];
2365        ["mv"; "/old"; "/new"];
2366        ["is_file"; "/old"]])],
2367    "move a file",
2368    "\
2369 This moves a file from C<src> to C<dest> where C<dest> is
2370 either a destination filename or destination directory.");
2371
2372   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2373    [InitEmpty, Always, TestRun (
2374       [["drop_caches"; "3"]])],
2375    "drop kernel page cache, dentries and inodes",
2376    "\
2377 This instructs the guest kernel to drop its page cache,
2378 and/or dentries and inode caches.  The parameter C<whattodrop>
2379 tells the kernel what precisely to drop, see
2380 L<http://linux-mm.org/Drop_Caches>
2381
2382 Setting C<whattodrop> to 3 should drop everything.
2383
2384 This automatically calls L<sync(2)> before the operation,
2385 so that the maximum guest memory is freed.");
2386
2387   ("dmesg", (RString "kmsgs", []), 91, [],
2388    [InitEmpty, Always, TestRun (
2389       [["dmesg"]])],
2390    "return kernel messages",
2391    "\
2392 This returns the kernel messages (C<dmesg> output) from
2393 the guest kernel.  This is sometimes useful for extended
2394 debugging of problems.
2395
2396 Another way to get the same information is to enable
2397 verbose messages with C<guestfs_set_verbose> or by setting
2398 the environment variable C<LIBGUESTFS_DEBUG=1> before
2399 running the program.");
2400
2401   ("ping_daemon", (RErr, []), 92, [],
2402    [InitEmpty, Always, TestRun (
2403       [["ping_daemon"]])],
2404    "ping the guest daemon",
2405    "\
2406 This is a test probe into the guestfs daemon running inside
2407 the qemu subprocess.  Calling this function checks that the
2408 daemon responds to the ping message, without affecting the daemon
2409 or attached block device(s) in any other way.");
2410
2411   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2412    [InitBasicFS, Always, TestOutputTrue (
2413       [["write"; "/file1"; "contents of a file"];
2414        ["cp"; "/file1"; "/file2"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestOutputFalse (
2417       [["write"; "/file1"; "contents of a file"];
2418        ["write"; "/file2"; "contents of another file"];
2419        ["equal"; "/file1"; "/file2"]]);
2420     InitBasicFS, Always, TestLastFail (
2421       [["equal"; "/file1"; "/file2"]])],
2422    "test if two files have equal contents",
2423    "\
2424 This compares the two files C<file1> and C<file2> and returns
2425 true if their content is exactly equal, or false otherwise.
2426
2427 The external L<cmp(1)> program is used for the comparison.");
2428
2429   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2430    [InitISOFS, Always, TestOutputList (
2431       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2432     InitISOFS, Always, TestOutputList (
2433       [["strings"; "/empty"]], []);
2434     (* Test for RHBZ#579608, absolute symbolic links. *)
2435     InitISOFS, Always, TestRun (
2436       [["strings"; "/abssymlink"]])],
2437    "print the printable strings in a file",
2438    "\
2439 This runs the L<strings(1)> command on a file and returns
2440 the list of printable strings found.");
2441
2442   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2443    [InitISOFS, Always, TestOutputList (
2444       [["strings_e"; "b"; "/known-5"]], []);
2445     InitBasicFS, Always, TestOutputList (
2446       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2447        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2448    "print the printable strings in a file",
2449    "\
2450 This is like the C<guestfs_strings> command, but allows you to
2451 specify the encoding of strings that are looked for in
2452 the source file C<path>.
2453
2454 Allowed encodings are:
2455
2456 =over 4
2457
2458 =item s
2459
2460 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2461 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2462
2463 =item S
2464
2465 Single 8-bit-byte characters.
2466
2467 =item b
2468
2469 16-bit big endian strings such as those encoded in
2470 UTF-16BE or UCS-2BE.
2471
2472 =item l (lower case letter L)
2473
2474 16-bit little endian such as UTF-16LE and UCS-2LE.
2475 This is useful for examining binaries in Windows guests.
2476
2477 =item B
2478
2479 32-bit big endian such as UCS-4BE.
2480
2481 =item L
2482
2483 32-bit little endian such as UCS-4LE.
2484
2485 =back
2486
2487 The returned strings are transcoded to UTF-8.");
2488
2489   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2490    [InitISOFS, Always, TestOutput (
2491       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2492     (* Test for RHBZ#501888c2 regression which caused large hexdump
2493      * commands to segfault.
2494      *)
2495     InitISOFS, Always, TestRun (
2496       [["hexdump"; "/100krandom"]]);
2497     (* Test for RHBZ#579608, absolute symbolic links. *)
2498     InitISOFS, Always, TestRun (
2499       [["hexdump"; "/abssymlink"]])],
2500    "dump a file in hexadecimal",
2501    "\
2502 This runs C<hexdump -C> on the given C<path>.  The result is
2503 the human-readable, canonical hex dump of the file.");
2504
2505   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2506    [InitNone, Always, TestOutput (
2507       [["part_disk"; "/dev/sda"; "mbr"];
2508        ["mkfs"; "ext3"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["write"; "/new"; "test file"];
2511        ["umount"; "/dev/sda1"];
2512        ["zerofree"; "/dev/sda1"];
2513        ["mount_options"; ""; "/dev/sda1"; "/"];
2514        ["cat"; "/new"]], "test file")],
2515    "zero unused inodes and disk blocks on ext2/3 filesystem",
2516    "\
2517 This runs the I<zerofree> program on C<device>.  This program
2518 claims to zero unused inodes and disk blocks on an ext2/3
2519 filesystem, thus making it possible to compress the filesystem
2520 more effectively.
2521
2522 You should B<not> run this program if the filesystem is
2523 mounted.
2524
2525 It is possible that using this program can damage the filesystem
2526 or data on the filesystem.");
2527
2528   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2529    [],
2530    "resize an LVM physical volume",
2531    "\
2532 This resizes (expands or shrinks) an existing LVM physical
2533 volume to match the new size of the underlying device.");
2534
2535   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2536                        Int "cyls"; Int "heads"; Int "sectors";
2537                        String "line"]), 99, [DangerWillRobinson],
2538    [],
2539    "modify a single partition on a block device",
2540    "\
2541 This runs L<sfdisk(8)> option to modify just the single
2542 partition C<n> (note: C<n> counts from 1).
2543
2544 For other parameters, see C<guestfs_sfdisk>.  You should usually
2545 pass C<0> for the cyls/heads/sectors parameters.
2546
2547 See also: C<guestfs_part_add>");
2548
2549   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2550    [],
2551    "display the partition table",
2552    "\
2553 This displays the partition table on C<device>, in the
2554 human-readable output of the L<sfdisk(8)> command.  It is
2555 not intended to be parsed.
2556
2557 See also: C<guestfs_part_list>");
2558
2559   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2560    [],
2561    "display the kernel geometry",
2562    "\
2563 This displays the kernel's idea of the geometry of C<device>.
2564
2565 The result is in human-readable format, and not designed to
2566 be parsed.");
2567
2568   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2569    [],
2570    "display the disk geometry from the partition table",
2571    "\
2572 This displays the disk geometry of C<device> read from the
2573 partition table.  Especially in the case where the underlying
2574 block device has been resized, this can be different from the
2575 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2576
2577 The result is in human-readable format, and not designed to
2578 be parsed.");
2579
2580   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2581    [],
2582    "activate or deactivate all volume groups",
2583    "\
2584 This command activates or (if C<activate> is false) deactivates
2585 all logical volumes in all volume groups.
2586 If activated, then they are made known to the
2587 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2588 then those devices disappear.
2589
2590 This command is the same as running C<vgchange -a y|n>");
2591
2592   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2593    [],
2594    "activate or deactivate some volume groups",
2595    "\
2596 This command activates or (if C<activate> is false) deactivates
2597 all logical volumes in the listed volume groups C<volgroups>.
2598 If activated, then they are made known to the
2599 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2600 then those devices disappear.
2601
2602 This command is the same as running C<vgchange -a y|n volgroups...>
2603
2604 Note that if C<volgroups> is an empty list then B<all> volume groups
2605 are activated or deactivated.");
2606
2607   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2608    [InitNone, Always, TestOutput (
2609       [["part_disk"; "/dev/sda"; "mbr"];
2610        ["pvcreate"; "/dev/sda1"];
2611        ["vgcreate"; "VG"; "/dev/sda1"];
2612        ["lvcreate"; "LV"; "VG"; "10"];
2613        ["mkfs"; "ext2"; "/dev/VG/LV"];
2614        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2615        ["write"; "/new"; "test content"];
2616        ["umount"; "/"];
2617        ["lvresize"; "/dev/VG/LV"; "20"];
2618        ["e2fsck_f"; "/dev/VG/LV"];
2619        ["resize2fs"; "/dev/VG/LV"];
2620        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2621        ["cat"; "/new"]], "test content");
2622     InitNone, Always, TestRun (
2623       (* Make an LV smaller to test RHBZ#587484. *)
2624       [["part_disk"; "/dev/sda"; "mbr"];
2625        ["pvcreate"; "/dev/sda1"];
2626        ["vgcreate"; "VG"; "/dev/sda1"];
2627        ["lvcreate"; "LV"; "VG"; "20"];
2628        ["lvresize"; "/dev/VG/LV"; "10"]])],
2629    "resize an LVM logical volume",
2630    "\
2631 This resizes (expands or shrinks) an existing LVM logical
2632 volume to C<mbytes>.  When reducing, data in the reduced part
2633 is lost.");
2634
2635   ("resize2fs", (RErr, [Device "device"]), 106, [],
2636    [], (* lvresize tests this *)
2637    "resize an ext2/ext3 filesystem",
2638    "\
2639 This resizes an ext2 or ext3 filesystem to match the size of
2640 the underlying device.
2641
2642 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2643 on the C<device> before calling this command.  For unknown reasons
2644 C<resize2fs> sometimes gives an error about this and sometimes not.
2645 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2646 calling this function.");
2647
2648   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2649    [InitBasicFS, Always, TestOutputList (
2650       [["find"; "/"]], ["lost+found"]);
2651     InitBasicFS, Always, TestOutputList (
2652       [["touch"; "/a"];
2653        ["mkdir"; "/b"];
2654        ["touch"; "/b/c"];
2655        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2656     InitBasicFS, Always, TestOutputList (
2657       [["mkdir_p"; "/a/b/c"];
2658        ["touch"; "/a/b/c/d"];
2659        ["find"; "/a/b/"]], ["c"; "c/d"])],
2660    "find all files and directories",
2661    "\
2662 This command lists out all files and directories, recursively,
2663 starting at C<directory>.  It is essentially equivalent to
2664 running the shell command C<find directory -print> but some
2665 post-processing happens on the output, described below.
2666
2667 This returns a list of strings I<without any prefix>.  Thus
2668 if the directory structure was:
2669
2670  /tmp/a
2671  /tmp/b
2672  /tmp/c/d
2673
2674 then the returned list from C<guestfs_find> C</tmp> would be
2675 4 elements:
2676
2677  a
2678  b
2679  c
2680  c/d
2681
2682 If C<directory> is not a directory, then this command returns
2683 an error.
2684
2685 The returned list is sorted.
2686
2687 See also C<guestfs_find0>.");
2688
2689   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2690    [], (* lvresize tests this *)
2691    "check an ext2/ext3 filesystem",
2692    "\
2693 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2694 filesystem checker on C<device>, noninteractively (C<-p>),
2695 even if the filesystem appears to be clean (C<-f>).
2696
2697 This command is only needed because of C<guestfs_resize2fs>
2698 (q.v.).  Normally you should use C<guestfs_fsck>.");
2699
2700   ("sleep", (RErr, [Int "secs"]), 109, [],
2701    [InitNone, Always, TestRun (
2702       [["sleep"; "1"]])],
2703    "sleep for some seconds",
2704    "\
2705 Sleep for C<secs> seconds.");
2706
2707   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2708    [InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ntfs"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2712     InitNone, Always, TestOutputInt (
2713       [["part_disk"; "/dev/sda"; "mbr"];
2714        ["mkfs"; "ext2"; "/dev/sda1"];
2715        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2716    "probe NTFS volume",
2717    "\
2718 This command runs the L<ntfs-3g.probe(8)> command which probes
2719 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2720 be mounted read-write, and some cannot be mounted at all).
2721
2722 C<rw> is a boolean flag.  Set it to true if you want to test
2723 if the volume can be mounted read-write.  Set it to false if
2724 you want to test if the volume can be mounted read-only.
2725
2726 The return value is an integer which C<0> if the operation
2727 would succeed, or some non-zero value documented in the
2728 L<ntfs-3g.probe(8)> manual page.");
2729
2730   ("sh", (RString "output", [String "command"]), 111, [],
2731    [], (* XXX needs tests *)
2732    "run a command via the shell",
2733    "\
2734 This call runs a command from the guest filesystem via the
2735 guest's C</bin/sh>.
2736
2737 This is like C<guestfs_command>, but passes the command to:
2738
2739  /bin/sh -c \"command\"
2740
2741 Depending on the guest's shell, this usually results in
2742 wildcards being expanded, shell expressions being interpolated
2743 and so on.
2744
2745 All the provisos about C<guestfs_command> apply to this call.");
2746
2747   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2748    [], (* XXX needs tests *)
2749    "run a command via the shell returning lines",
2750    "\
2751 This is the same as C<guestfs_sh>, but splits the result
2752 into a list of lines.
2753
2754 See also: C<guestfs_command_lines>");
2755
2756   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2757    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2758     * code in stubs.c, since all valid glob patterns must start with "/".
2759     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2760     *)
2761    [InitBasicFS, Always, TestOutputList (
2762       [["mkdir_p"; "/a/b/c"];
2763        ["touch"; "/a/b/c/d"];
2764        ["touch"; "/a/b/c/e"];
2765        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2766     InitBasicFS, Always, TestOutputList (
2767       [["mkdir_p"; "/a/b/c"];
2768        ["touch"; "/a/b/c/d"];
2769        ["touch"; "/a/b/c/e"];
2770        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2771     InitBasicFS, Always, TestOutputList (
2772       [["mkdir_p"; "/a/b/c"];
2773        ["touch"; "/a/b/c/d"];
2774        ["touch"; "/a/b/c/e"];
2775        ["glob_expand"; "/a/*/x/*"]], [])],
2776    "expand a wildcard path",
2777    "\
2778 This command searches for all the pathnames matching
2779 C<pattern> according to the wildcard expansion rules
2780 used by the shell.
2781
2782 If no paths match, then this returns an empty list
2783 (note: not an error).
2784
2785 It is just a wrapper around the C L<glob(3)> function
2786 with flags C<GLOB_MARK|GLOB_BRACE>.
2787 See that manual page for more details.");
2788
2789   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2790    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2791       [["scrub_device"; "/dev/sdc"]])],
2792    "scrub (securely wipe) a device",
2793    "\
2794 This command writes patterns over C<device> to make data retrieval
2795 more difficult.
2796
2797 It is an interface to the L<scrub(1)> program.  See that
2798 manual page for more details.");
2799
2800   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2801    [InitBasicFS, Always, TestRun (
2802       [["write"; "/file"; "content"];
2803        ["scrub_file"; "/file"]])],
2804    "scrub (securely wipe) a file",
2805    "\
2806 This command writes patterns over a file to make data retrieval
2807 more difficult.
2808
2809 The file is I<removed> after scrubbing.
2810
2811 It is an interface to the L<scrub(1)> program.  See that
2812 manual page for more details.");
2813
2814   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2815    [], (* XXX needs testing *)
2816    "scrub (securely wipe) free space",
2817    "\
2818 This command creates the directory C<dir> and then fills it
2819 with files until the filesystem is full, and scrubs the files
2820 as for C<guestfs_scrub_file>, and deletes them.
2821 The intention is to scrub any free space on the partition
2822 containing C<dir>.
2823
2824 It is an interface to the L<scrub(1)> program.  See that
2825 manual page for more details.");
2826
2827   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2828    [InitBasicFS, Always, TestRun (
2829       [["mkdir"; "/tmp"];
2830        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2831    "create a temporary directory",
2832    "\
2833 This command creates a temporary directory.  The
2834 C<template> parameter should be a full pathname for the
2835 temporary directory name with the final six characters being
2836 \"XXXXXX\".
2837
2838 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2839 the second one being suitable for Windows filesystems.
2840
2841 The name of the temporary directory that was created
2842 is returned.
2843
2844 The temporary directory is created with mode 0700
2845 and is owned by root.
2846
2847 The caller is responsible for deleting the temporary
2848 directory and its contents after use.
2849
2850 See also: L<mkdtemp(3)>");
2851
2852   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2853    [InitISOFS, Always, TestOutputInt (
2854       [["wc_l"; "/10klines"]], 10000);
2855     (* Test for RHBZ#579608, absolute symbolic links. *)
2856     InitISOFS, Always, TestOutputInt (
2857       [["wc_l"; "/abssymlink"]], 10000)],
2858    "count lines in a file",
2859    "\
2860 This command counts the lines in a file, using the
2861 C<wc -l> external command.");
2862
2863   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2864    [InitISOFS, Always, TestOutputInt (
2865       [["wc_w"; "/10klines"]], 10000)],
2866    "count words in a file",
2867    "\
2868 This command counts the words in a file, using the
2869 C<wc -w> external command.");
2870
2871   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2872    [InitISOFS, Always, TestOutputInt (
2873       [["wc_c"; "/100kallspaces"]], 102400)],
2874    "count characters in a file",
2875    "\
2876 This command counts the characters in a file, using the
2877 C<wc -c> external command.");
2878
2879   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2880    [InitISOFS, Always, TestOutputList (
2881       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2882     (* Test for RHBZ#579608, absolute symbolic links. *)
2883     InitISOFS, Always, TestOutputList (
2884       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2885    "return first 10 lines of a file",
2886    "\
2887 This command returns up to the first 10 lines of a file as
2888 a list of strings.");
2889
2890   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2891    [InitISOFS, Always, TestOutputList (
2892       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2893     InitISOFS, Always, TestOutputList (
2894       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2895     InitISOFS, Always, TestOutputList (
2896       [["head_n"; "0"; "/10klines"]], [])],
2897    "return first N lines of a file",
2898    "\
2899 If the parameter C<nrlines> is a positive number, this returns the first
2900 C<nrlines> lines of the file C<path>.
2901
2902 If the parameter C<nrlines> is a negative number, this returns lines
2903 from the file C<path>, excluding the last C<nrlines> lines.
2904
2905 If the parameter C<nrlines> is zero, this returns an empty list.");
2906
2907   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2908    [InitISOFS, Always, TestOutputList (
2909       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2910    "return last 10 lines of a file",
2911    "\
2912 This command returns up to the last 10 lines of a file as
2913 a list of strings.");
2914
2915   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2916    [InitISOFS, Always, TestOutputList (
2917       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2918     InitISOFS, Always, TestOutputList (
2919       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2920     InitISOFS, Always, TestOutputList (
2921       [["tail_n"; "0"; "/10klines"]], [])],
2922    "return last N lines of a file",
2923    "\
2924 If the parameter C<nrlines> is a positive number, this returns the last
2925 C<nrlines> lines of the file C<path>.
2926
2927 If the parameter C<nrlines> is a negative number, this returns lines
2928 from the file C<path>, starting with the C<-nrlines>th line.
2929
2930 If the parameter C<nrlines> is zero, this returns an empty list.");
2931
2932   ("df", (RString "output", []), 125, [],
2933    [], (* XXX Tricky to test because it depends on the exact format
2934         * of the 'df' command and other imponderables.
2935         *)
2936    "report file system disk space usage",
2937    "\
2938 This command runs the C<df> command to report disk space used.
2939
2940 This command is mostly useful for interactive sessions.  It
2941 is I<not> intended that you try to parse the output string.
2942 Use C<statvfs> from programs.");
2943
2944   ("df_h", (RString "output", []), 126, [],
2945    [], (* XXX Tricky to test because it depends on the exact format
2946         * of the 'df' command and other imponderables.
2947         *)
2948    "report file system disk space usage (human readable)",
2949    "\
2950 This command runs the C<df -h> command to report disk space used
2951 in human-readable format.
2952
2953 This command is mostly useful for interactive sessions.  It
2954 is I<not> intended that you try to parse the output string.
2955 Use C<statvfs> from programs.");
2956
2957   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2958    [InitISOFS, Always, TestOutputInt (
2959       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2960    "estimate file space usage",
2961    "\
2962 This command runs the C<du -s> command to estimate file space
2963 usage for C<path>.
2964
2965 C<path> can be a file or a directory.  If C<path> is a directory
2966 then the estimate includes the contents of the directory and all
2967 subdirectories (recursively).
2968
2969 The result is the estimated size in I<kilobytes>
2970 (ie. units of 1024 bytes).");
2971
2972   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2973    [InitISOFS, Always, TestOutputList (
2974       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2975    "list files in an initrd",
2976    "\
2977 This command lists out files contained in an initrd.
2978
2979 The files are listed without any initial C</> character.  The
2980 files are listed in the order they appear (not necessarily
2981 alphabetical).  Directory names are listed as separate items.
2982
2983 Old Linux kernels (2.4 and earlier) used a compressed ext2
2984 filesystem as initrd.  We I<only> support the newer initramfs
2985 format (compressed cpio files).");
2986
2987   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2988    [],
2989    "mount a file using the loop device",
2990    "\
2991 This command lets you mount C<file> (a filesystem image
2992 in a file) on a mount point.  It is entirely equivalent to
2993 the command C<mount -o loop file mountpoint>.");
2994
2995   ("mkswap", (RErr, [Device "device"]), 130, [],
2996    [InitEmpty, Always, TestRun (
2997       [["part_disk"; "/dev/sda"; "mbr"];
2998        ["mkswap"; "/dev/sda1"]])],
2999    "create a swap partition",
3000    "\
3001 Create a swap partition on C<device>.");
3002
3003   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3004    [InitEmpty, Always, TestRun (
3005       [["part_disk"; "/dev/sda"; "mbr"];
3006        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3007    "create a swap partition with a label",
3008    "\
3009 Create a swap partition on C<device> with label C<label>.
3010
3011 Note that you cannot attach a swap label to a block device
3012 (eg. C</dev/sda>), just to a partition.  This appears to be
3013 a limitation of the kernel or swap tools.");
3014
3015   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3016    (let uuid = uuidgen () in
3017     [InitEmpty, Always, TestRun (
3018        [["part_disk"; "/dev/sda"; "mbr"];
3019         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3020    "create a swap partition with an explicit UUID",
3021    "\
3022 Create a swap partition on C<device> with UUID C<uuid>.");
3023
3024   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3025    [InitBasicFS, Always, TestOutputStruct (
3026       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3027        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3028        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3029     InitBasicFS, Always, TestOutputStruct (
3030       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3031        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3032    "make block, character or FIFO devices",
3033    "\
3034 This call creates block or character special devices, or
3035 named pipes (FIFOs).
3036
3037 The C<mode> parameter should be the mode, using the standard
3038 constants.  C<devmajor> and C<devminor> are the
3039 device major and minor numbers, only used when creating block
3040 and character special devices.
3041
3042 Note that, just like L<mknod(2)>, the mode must be bitwise
3043 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3044 just creates a regular file).  These constants are
3045 available in the standard Linux header files, or you can use
3046 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3047 which are wrappers around this command which bitwise OR
3048 in the appropriate constant for you.
3049
3050 The mode actually set is affected by the umask.");
3051
3052   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3053    [InitBasicFS, Always, TestOutputStruct (
3054       [["mkfifo"; "0o777"; "/node"];
3055        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3056    "make FIFO (named pipe)",
3057    "\
3058 This call creates a FIFO (named pipe) called C<path> with
3059 mode C<mode>.  It is just a convenient wrapper around
3060 C<guestfs_mknod>.
3061
3062 The mode actually set is affected by the umask.");
3063
3064   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3065    [InitBasicFS, Always, TestOutputStruct (
3066       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3067        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3068    "make block device node",
3069    "\
3070 This call creates a block device node called C<path> with
3071 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3072 It is just a convenient wrapper around C<guestfs_mknod>.
3073
3074 The mode actually set is affected by the umask.");
3075
3076   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3077    [InitBasicFS, Always, TestOutputStruct (
3078       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3079        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3080    "make char device node",
3081    "\
3082 This call creates a char device node called C<path> with
3083 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3084 It is just a convenient wrapper around C<guestfs_mknod>.
3085
3086 The mode actually set is affected by the umask.");
3087
3088   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3089    [InitEmpty, Always, TestOutputInt (
3090       [["umask"; "0o22"]], 0o22)],
3091    "set file mode creation mask (umask)",
3092    "\
3093 This function sets the mask used for creating new files and
3094 device nodes to C<mask & 0777>.
3095
3096 Typical umask values would be C<022> which creates new files
3097 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3098 C<002> which creates new files with permissions like
3099 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3100
3101 The default umask is C<022>.  This is important because it
3102 means that directories and device nodes will be created with
3103 C<0644> or C<0755> mode even if you specify C<0777>.
3104
3105 See also C<guestfs_get_umask>,
3106 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3107
3108 This call returns the previous umask.");
3109
3110   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3111    [],
3112    "read directories entries",
3113    "\
3114 This returns the list of directory entries in directory C<dir>.
3115
3116 All entries in the directory are returned, including C<.> and
3117 C<..>.  The entries are I<not> sorted, but returned in the same
3118 order as the underlying filesystem.
3119
3120 Also this call returns basic file type information about each
3121 file.  The C<ftyp> field will contain one of the following characters:
3122
3123 =over 4
3124
3125 =item 'b'
3126
3127 Block special
3128
3129 =item 'c'
3130
3131 Char special
3132
3133 =item 'd'
3134
3135 Directory
3136
3137 =item 'f'
3138
3139 FIFO (named pipe)
3140
3141 =item 'l'
3142
3143 Symbolic link
3144
3145 =item 'r'
3146
3147 Regular file
3148
3149 =item 's'
3150
3151 Socket
3152
3153 =item 'u'
3154
3155 Unknown file type
3156
3157 =item '?'
3158
3159 The L<readdir(3)> call returned a C<d_type> field with an
3160 unexpected value
3161
3162 =back
3163
3164 This function is primarily intended for use by programs.  To
3165 get a simple list of names, use C<guestfs_ls>.  To get a printable
3166 directory for human consumption, use C<guestfs_ll>.");
3167
3168   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3169    [],
3170    "create partitions on a block device",
3171    "\
3172 This is a simplified interface to the C<guestfs_sfdisk>
3173 command, where partition sizes are specified in megabytes
3174 only (rounded to the nearest cylinder) and you don't need
3175 to specify the cyls, heads and sectors parameters which
3176 were rarely if ever used anyway.
3177
3178 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3179 and C<guestfs_part_disk>");
3180
3181   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3182    [],
3183    "determine file type inside a compressed file",
3184    "\
3185 This command runs C<file> after first decompressing C<path>
3186 using C<method>.
3187
3188 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3189
3190 Since 1.0.63, use C<guestfs_file> instead which can now
3191 process compressed files.");
3192
3193   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3194    [],
3195    "list extended attributes of a file or directory",
3196    "\
3197 This call lists the extended attributes of the file or directory
3198 C<path>.
3199
3200 At the system call level, this is a combination of the
3201 L<listxattr(2)> and L<getxattr(2)> calls.
3202
3203 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3204
3205   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3206    [],
3207    "list extended attributes of a file or directory",
3208    "\
3209 This is the same as C<guestfs_getxattrs>, but if C<path>
3210 is a symbolic link, then it returns the extended attributes
3211 of the link itself.");
3212
3213   ("setxattr", (RErr, [String "xattr";
3214                        String "val"; Int "vallen"; (* will be BufferIn *)
3215                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3216    [],
3217    "set extended attribute of a file or directory",
3218    "\
3219 This call sets the extended attribute named C<xattr>
3220 of the file C<path> to the value C<val> (of length C<vallen>).
3221 The value is arbitrary 8 bit data.
3222
3223 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3224
3225   ("lsetxattr", (RErr, [String "xattr";
3226                         String "val"; Int "vallen"; (* will be BufferIn *)
3227                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3228    [],
3229    "set extended attribute of a file or directory",
3230    "\
3231 This is the same as C<guestfs_setxattr>, but if C<path>
3232 is a symbolic link, then it sets an extended attribute
3233 of the link itself.");
3234
3235   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3236    [],
3237    "remove extended attribute of a file or directory",
3238    "\
3239 This call removes the extended attribute named C<xattr>
3240 of the file C<path>.
3241
3242 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3243
3244   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3245    [],
3246    "remove extended attribute of a file or directory",
3247    "\
3248 This is the same as C<guestfs_removexattr>, but if C<path>
3249 is a symbolic link, then it removes an extended attribute
3250 of the link itself.");
3251
3252   ("mountpoints", (RHashtable "mps", []), 147, [],
3253    [],
3254    "show mountpoints",
3255    "\
3256 This call is similar to C<guestfs_mounts>.  That call returns
3257 a list of devices.  This one returns a hash table (map) of
3258 device name to directory where the device is mounted.");
3259
3260   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3261    (* This is a special case: while you would expect a parameter
3262     * of type "Pathname", that doesn't work, because it implies
3263     * NEED_ROOT in the generated calling code in stubs.c, and
3264     * this function cannot use NEED_ROOT.
3265     *)
3266    [],
3267    "create a mountpoint",
3268    "\
3269 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3270 specialized calls that can be used to create extra mountpoints
3271 before mounting the first filesystem.
3272
3273 These calls are I<only> necessary in some very limited circumstances,
3274 mainly the case where you want to mount a mix of unrelated and/or
3275 read-only filesystems together.
3276
3277 For example, live CDs often contain a \"Russian doll\" nest of
3278 filesystems, an ISO outer layer, with a squashfs image inside, with
3279 an ext2/3 image inside that.  You can unpack this as follows
3280 in guestfish:
3281
3282  add-ro Fedora-11-i686-Live.iso
3283  run
3284  mkmountpoint /cd
3285  mkmountpoint /squash
3286  mkmountpoint /ext3
3287  mount /dev/sda /cd
3288  mount-loop /cd/LiveOS/squashfs.img /squash
3289  mount-loop /squash/LiveOS/ext3fs.img /ext3
3290
3291 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3292
3293   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3294    [],
3295    "remove a mountpoint",
3296    "\
3297 This calls removes a mountpoint that was previously created
3298 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3299 for full details.");
3300
3301   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3302    [InitISOFS, Always, TestOutputBuffer (
3303       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3304     (* Test various near large, large and too large files (RHBZ#589039). *)
3305     InitBasicFS, Always, TestLastFail (
3306       [["touch"; "/a"];
3307        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3308        ["read_file"; "/a"]]);
3309     InitBasicFS, Always, TestLastFail (
3310       [["touch"; "/a"];
3311        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3312        ["read_file"; "/a"]]);
3313     InitBasicFS, Always, TestLastFail (
3314       [["touch"; "/a"];
3315        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3316        ["read_file"; "/a"]])],
3317    "read a file",
3318    "\
3319 This calls returns the contents of the file C<path> as a
3320 buffer.
3321
3322 Unlike C<guestfs_cat>, this function can correctly
3323 handle files that contain embedded ASCII NUL characters.
3324 However unlike C<guestfs_download>, this function is limited
3325 in the total size of file that can be handled.");
3326
3327   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3328    [InitISOFS, Always, TestOutputList (
3329       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3330     InitISOFS, Always, TestOutputList (
3331       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3332     (* Test for RHBZ#579608, absolute symbolic links. *)
3333     InitISOFS, Always, TestOutputList (
3334       [["grep"; "nomatch"; "/abssymlink"]], [])],
3335    "return lines matching a pattern",
3336    "\
3337 This calls the external C<grep> program and returns the
3338 matching lines.");
3339
3340   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3341    [InitISOFS, Always, TestOutputList (
3342       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3343    "return lines matching a pattern",
3344    "\
3345 This calls the external C<egrep> program and returns the
3346 matching lines.");
3347
3348   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3349    [InitISOFS, Always, TestOutputList (
3350       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3351    "return lines matching a pattern",
3352    "\
3353 This calls the external C<fgrep> program and returns the
3354 matching lines.");
3355
3356   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3357    [InitISOFS, Always, TestOutputList (
3358       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3359    "return lines matching a pattern",
3360    "\
3361 This calls the external C<grep -i> program and returns the
3362 matching lines.");
3363
3364   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3365    [InitISOFS, Always, TestOutputList (
3366       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3367    "return lines matching a pattern",
3368    "\
3369 This calls the external C<egrep -i> program and returns the
3370 matching lines.");
3371
3372   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3373    [InitISOFS, Always, TestOutputList (
3374       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3375    "return lines matching a pattern",
3376    "\
3377 This calls the external C<fgrep -i> program and returns the
3378 matching lines.");
3379
3380   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3381    [InitISOFS, Always, TestOutputList (
3382       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3383    "return lines matching a pattern",
3384    "\
3385 This calls the external C<zgrep> program and returns the
3386 matching lines.");
3387
3388   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3389    [InitISOFS, Always, TestOutputList (
3390       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3391    "return lines matching a pattern",
3392    "\
3393 This calls the external C<zegrep> program and returns the
3394 matching lines.");
3395
3396   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3397    [InitISOFS, Always, TestOutputList (
3398       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3399    "return lines matching a pattern",
3400    "\
3401 This calls the external C<zfgrep> program and returns the
3402 matching lines.");
3403
3404   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3405    [InitISOFS, Always, TestOutputList (
3406       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3407    "return lines matching a pattern",
3408    "\
3409 This calls the external C<zgrep -i> program and returns the
3410 matching lines.");
3411
3412   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3413    [InitISOFS, Always, TestOutputList (
3414       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3415    "return lines matching a pattern",
3416    "\
3417 This calls the external C<zegrep -i> program and returns the
3418 matching lines.");
3419
3420   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3421    [InitISOFS, Always, TestOutputList (
3422       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3423    "return lines matching a pattern",
3424    "\
3425 This calls the external C<zfgrep -i> program and returns the
3426 matching lines.");
3427
3428   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3429    [InitISOFS, Always, TestOutput (
3430       [["realpath"; "/../directory"]], "/directory")],
3431    "canonicalized absolute pathname",
3432    "\
3433 Return the canonicalized absolute pathname of C<path>.  The
3434 returned path has no C<.>, C<..> or symbolic link path elements.");
3435
3436   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3437    [InitBasicFS, Always, TestOutputStruct (
3438       [["touch"; "/a"];
3439        ["ln"; "/a"; "/b"];
3440        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3441    "create a hard link",
3442    "\
3443 This command creates a hard link using the C<ln> command.");
3444
3445   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3446    [InitBasicFS, Always, TestOutputStruct (
3447       [["touch"; "/a"];
3448        ["touch"; "/b"];
3449        ["ln_f"; "/a"; "/b"];
3450        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3451    "create a hard link",
3452    "\
3453 This command creates a hard link using the C<ln -f> command.
3454 The C<-f> option removes the link (C<linkname>) if it exists already.");
3455
3456   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3457    [InitBasicFS, Always, TestOutputStruct (
3458       [["touch"; "/a"];
3459        ["ln_s"; "a"; "/b"];
3460        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3461    "create a symbolic link",
3462    "\
3463 This command creates a symbolic link using the C<ln -s> command.");
3464
3465   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3466    [InitBasicFS, Always, TestOutput (
3467       [["mkdir_p"; "/a/b"];
3468        ["touch"; "/a/b/c"];
3469        ["ln_sf"; "../d"; "/a/b/c"];
3470        ["readlink"; "/a/b/c"]], "../d")],
3471    "create a symbolic link",
3472    "\
3473 This command creates a symbolic link using the C<ln -sf> command,
3474 The C<-f> option removes the link (C<linkname>) if it exists already.");
3475
3476   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3477    [] (* XXX tested above *),
3478    "read the target of a symbolic link",
3479    "\
3480 This command reads the target of a symbolic link.");
3481
3482   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3483    [InitBasicFS, Always, TestOutputStruct (
3484       [["fallocate"; "/a"; "1000000"];
3485        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3486    "preallocate a file in the guest filesystem",
3487    "\
3488 This command preallocates a file (containing zero bytes) named
3489 C<path> of size C<len> bytes.  If the file exists already, it
3490 is overwritten.
3491
3492 Do not confuse this with the guestfish-specific
3493 C<alloc> command which allocates a file in the host and
3494 attaches it as a device.");
3495
3496   ("swapon_device", (RErr, [Device "device"]), 170, [],
3497    [InitPartition, Always, TestRun (
3498       [["mkswap"; "/dev/sda1"];
3499        ["swapon_device"; "/dev/sda1"];
3500        ["swapoff_device"; "/dev/sda1"]])],
3501    "enable swap on device",
3502    "\
3503 This command enables the libguestfs appliance to use the
3504 swap device or partition named C<device>.  The increased
3505 memory is made available for all commands, for example
3506 those run using C<guestfs_command> or C<guestfs_sh>.
3507
3508 Note that you should not swap to existing guest swap
3509 partitions unless you know what you are doing.  They may
3510 contain hibernation information, or other information that
3511 the guest doesn't want you to trash.  You also risk leaking
3512 information about the host to the guest this way.  Instead,
3513 attach a new host device to the guest and swap on that.");
3514
3515   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3516    [], (* XXX tested by swapon_device *)
3517    "disable swap on device",
3518    "\
3519 This command disables the libguestfs appliance swap
3520 device or partition named C<device>.
3521 See C<guestfs_swapon_device>.");
3522
3523   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3524    [InitBasicFS, Always, TestRun (
3525       [["fallocate"; "/swap"; "8388608"];
3526        ["mkswap_file"; "/swap"];
3527        ["swapon_file"; "/swap"];
3528        ["swapoff_file"; "/swap"]])],
3529    "enable swap on file",
3530    "\
3531 This command enables swap to a file.
3532 See C<guestfs_swapon_device> for other notes.");
3533
3534   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3535    [], (* XXX tested by swapon_file *)
3536    "disable swap on file",
3537    "\
3538 This command disables the libguestfs appliance swap on file.");
3539
3540   ("swapon_label", (RErr, [String "label"]), 174, [],
3541    [InitEmpty, Always, TestRun (
3542       [["part_disk"; "/dev/sdb"; "mbr"];
3543        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3544        ["swapon_label"; "swapit"];
3545        ["swapoff_label"; "swapit"];
3546        ["zero"; "/dev/sdb"];
3547        ["blockdev_rereadpt"; "/dev/sdb"]])],
3548    "enable swap on labeled swap partition",
3549    "\
3550 This command enables swap to a labeled swap partition.
3551 See C<guestfs_swapon_device> for other notes.");
3552
3553   ("swapoff_label", (RErr, [String "label"]), 175, [],
3554    [], (* XXX tested by swapon_label *)
3555    "disable swap on labeled swap partition",
3556    "\
3557 This command disables the libguestfs appliance swap on
3558 labeled swap partition.");
3559
3560   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3561    (let uuid = uuidgen () in
3562     [InitEmpty, Always, TestRun (
3563        [["mkswap_U"; uuid; "/dev/sdb"];
3564         ["swapon_uuid"; uuid];
3565         ["swapoff_uuid"; uuid]])]),
3566    "enable swap on swap partition by UUID",
3567    "\
3568 This command enables swap to a swap partition with the given UUID.
3569 See C<guestfs_swapon_device> for other notes.");
3570
3571   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3572    [], (* XXX tested by swapon_uuid *)
3573    "disable swap on swap partition by UUID",
3574    "\
3575 This command disables the libguestfs appliance swap partition
3576 with the given UUID.");
3577
3578   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3579    [InitBasicFS, Always, TestRun (
3580       [["fallocate"; "/swap"; "8388608"];
3581        ["mkswap_file"; "/swap"]])],
3582    "create a swap file",
3583    "\
3584 Create a swap file.
3585
3586 This command just writes a swap file signature to an existing
3587 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3588
3589   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3590    [InitISOFS, Always, TestRun (
3591       [["inotify_init"; "0"]])],
3592    "create an inotify handle",
3593    "\
3594 This command creates a new inotify handle.
3595 The inotify subsystem can be used to notify events which happen to
3596 objects in the guest filesystem.
3597
3598 C<maxevents> is the maximum number of events which will be
3599 queued up between calls to C<guestfs_inotify_read> or
3600 C<guestfs_inotify_files>.
3601 If this is passed as C<0>, then the kernel (or previously set)
3602 default is used.  For Linux 2.6.29 the default was 16384 events.
3603 Beyond this limit, the kernel throws away events, but records
3604 the fact that it threw them away by setting a flag
3605 C<IN_Q_OVERFLOW> in the returned structure list (see
3606 C<guestfs_inotify_read>).
3607
3608 Before any events are generated, you have to add some
3609 watches to the internal watch list.  See:
3610 C<guestfs_inotify_add_watch>,
3611 C<guestfs_inotify_rm_watch> and
3612 C<guestfs_inotify_watch_all>.
3613
3614 Queued up events should be read periodically by calling
3615 C<guestfs_inotify_read>
3616 (or C<guestfs_inotify_files> which is just a helpful
3617 wrapper around C<guestfs_inotify_read>).  If you don't
3618 read the events out often enough then you risk the internal
3619 queue overflowing.
3620
3621 The handle should be closed after use by calling
3622 C<guestfs_inotify_close>.  This also removes any
3623 watches automatically.
3624
3625 See also L<inotify(7)> for an overview of the inotify interface
3626 as exposed by the Linux kernel, which is roughly what we expose
3627 via libguestfs.  Note that there is one global inotify handle
3628 per libguestfs instance.");
3629
3630   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3631    [InitBasicFS, Always, TestOutputList (
3632       [["inotify_init"; "0"];
3633        ["inotify_add_watch"; "/"; "1073741823"];
3634        ["touch"; "/a"];
3635        ["touch"; "/b"];
3636        ["inotify_files"]], ["a"; "b"])],
3637    "add an inotify watch",
3638    "\
3639 Watch C<path> for the events listed in C<mask>.
3640
3641 Note that if C<path> is a directory then events within that
3642 directory are watched, but this does I<not> happen recursively
3643 (in subdirectories).
3644
3645 Note for non-C or non-Linux callers: the inotify events are
3646 defined by the Linux kernel ABI and are listed in
3647 C</usr/include/sys/inotify.h>.");
3648
3649   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3650    [],
3651    "remove an inotify watch",
3652    "\
3653 Remove a previously defined inotify watch.
3654 See C<guestfs_inotify_add_watch>.");
3655
3656   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3657    [],
3658    "return list of inotify events",
3659    "\
3660 Return the complete queue of events that have happened
3661 since the previous read call.
3662
3663 If no events have happened, this returns an empty list.
3664
3665 I<Note>: In order to make sure that all events have been
3666 read, you must call this function repeatedly until it
3667 returns an empty list.  The reason is that the call will
3668 read events up to the maximum appliance-to-host message
3669 size and leave remaining events in the queue.");
3670
3671   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3672    [],
3673    "return list of watched files that had events",
3674    "\
3675 This function is a helpful wrapper around C<guestfs_inotify_read>
3676 which just returns a list of pathnames of objects that were
3677 touched.  The returned pathnames are sorted and deduplicated.");
3678
3679   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3680    [],
3681    "close the inotify handle",
3682    "\
3683 This closes the inotify handle which was previously
3684 opened by inotify_init.  It removes all watches, throws
3685 away any pending events, and deallocates all resources.");
3686
3687   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3688    [],
3689    "set SELinux security context",
3690    "\
3691 This sets the SELinux security context of the daemon
3692 to the string C<context>.
3693
3694 See the documentation about SELINUX in L<guestfs(3)>.");
3695
3696   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3697    [],
3698    "get SELinux security context",
3699    "\
3700 This gets the SELinux security context of the daemon.
3701
3702 See the documentation about SELINUX in L<guestfs(3)>,
3703 and C<guestfs_setcon>");
3704
3705   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3706    [InitEmpty, Always, TestOutput (
3707       [["part_disk"; "/dev/sda"; "mbr"];
3708        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3709        ["mount_options"; ""; "/dev/sda1"; "/"];
3710        ["write"; "/new"; "new file contents"];
3711        ["cat"; "/new"]], "new file contents")],
3712    "make a filesystem with block size",
3713    "\
3714 This call is similar to C<guestfs_mkfs>, but it allows you to
3715 control the block size of the resulting filesystem.  Supported
3716 block sizes depend on the filesystem type, but typically they
3717 are C<1024>, C<2048> or C<4096> only.");
3718
3719   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3720    [InitEmpty, Always, TestOutput (
3721       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3722        ["mke2journal"; "4096"; "/dev/sda1"];
3723        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3724        ["mount_options"; ""; "/dev/sda2"; "/"];
3725        ["write"; "/new"; "new file contents"];
3726        ["cat"; "/new"]], "new file contents")],
3727    "make ext2/3/4 external journal",
3728    "\
3729 This creates an ext2 external journal on C<device>.  It is equivalent
3730 to the command:
3731
3732  mke2fs -O journal_dev -b blocksize device");
3733
3734   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3735    [InitEmpty, Always, TestOutput (
3736       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3737        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3738        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3739        ["mount_options"; ""; "/dev/sda2"; "/"];
3740        ["write"; "/new"; "new file contents"];
3741        ["cat"; "/new"]], "new file contents")],
3742    "make ext2/3/4 external journal with label",
3743    "\
3744 This creates an ext2 external journal on C<device> with label C<label>.");
3745
3746   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3747    (let uuid = uuidgen () in
3748     [InitEmpty, Always, TestOutput (
3749        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3750         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3751         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3752         ["mount_options"; ""; "/dev/sda2"; "/"];
3753         ["write"; "/new"; "new file contents"];
3754         ["cat"; "/new"]], "new file contents")]),
3755    "make ext2/3/4 external journal with UUID",
3756    "\
3757 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3758
3759   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3760    [],
3761    "make ext2/3/4 filesystem with external journal",
3762    "\
3763 This creates an ext2/3/4 filesystem on C<device> with
3764 an external journal on C<journal>.  It is equivalent
3765 to the command:
3766
3767  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3768
3769 See also C<guestfs_mke2journal>.");
3770
3771   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3772    [],
3773    "make ext2/3/4 filesystem with external journal",
3774    "\
3775 This creates an ext2/3/4 filesystem on C<device> with
3776 an external journal on the journal labeled C<label>.
3777
3778 See also C<guestfs_mke2journal_L>.");
3779
3780   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3781    [],
3782    "make ext2/3/4 filesystem with external journal",
3783    "\
3784 This creates an ext2/3/4 filesystem on C<device> with
3785 an external journal on the journal with UUID C<uuid>.
3786
3787 See also C<guestfs_mke2journal_U>.");
3788
3789   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3790    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3791    "load a kernel module",
3792    "\
3793 This loads a kernel module in the appliance.
3794
3795 The kernel module must have been whitelisted when libguestfs
3796 was built (see C<appliance/kmod.whitelist.in> in the source).");
3797
3798   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3799    [InitNone, Always, TestOutput (
3800       [["echo_daemon"; "This is a test"]], "This is a test"
3801     )],
3802    "echo arguments back to the client",
3803    "\
3804 This command concatenates the list of C<words> passed with single spaces
3805 between them and returns the resulting string.
3806
3807 You can use this command to test the connection through to the daemon.
3808
3809 See also C<guestfs_ping_daemon>.");
3810
3811   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3812    [], (* There is a regression test for this. *)
3813    "find all files and directories, returning NUL-separated list",
3814    "\
3815 This command lists out all files and directories, recursively,
3816 starting at C<directory>, placing the resulting list in the
3817 external file called C<files>.
3818
3819 This command works the same way as C<guestfs_find> with the
3820 following exceptions:
3821
3822 =over 4
3823
3824 =item *
3825
3826 The resulting list is written to an external file.
3827
3828 =item *
3829
3830 Items (filenames) in the result are separated
3831 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3832
3833 =item *
3834
3835 This command is not limited in the number of names that it
3836 can return.
3837
3838 =item *
3839
3840 The result list is not sorted.
3841
3842 =back");
3843
3844   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3845    [InitISOFS, Always, TestOutput (
3846       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3847     InitISOFS, Always, TestOutput (
3848       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3849     InitISOFS, Always, TestOutput (
3850       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3851     InitISOFS, Always, TestLastFail (
3852       [["case_sensitive_path"; "/Known-1/"]]);
3853     InitBasicFS, Always, TestOutput (
3854       [["mkdir"; "/a"];
3855        ["mkdir"; "/a/bbb"];
3856        ["touch"; "/a/bbb/c"];
3857        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3858     InitBasicFS, Always, TestOutput (
3859       [["mkdir"; "/a"];
3860        ["mkdir"; "/a/bbb"];
3861        ["touch"; "/a/bbb/c"];
3862        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3863     InitBasicFS, Always, TestLastFail (
3864       [["mkdir"; "/a"];
3865        ["mkdir"; "/a/bbb"];
3866        ["touch"; "/a/bbb/c"];
3867        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3868    "return true path on case-insensitive filesystem",
3869    "\
3870 This can be used to resolve case insensitive paths on
3871 a filesystem which is case sensitive.  The use case is
3872 to resolve paths which you have read from Windows configuration
3873 files or the Windows Registry, to the true path.
3874
3875 The command handles a peculiarity of the Linux ntfs-3g
3876 filesystem driver (and probably others), which is that although
3877 the underlying filesystem is case-insensitive, the driver
3878 exports the filesystem to Linux as case-sensitive.
3879
3880 One consequence of this is that special directories such
3881 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3882 (or other things) depending on the precise details of how
3883 they were created.  In Windows itself this would not be
3884 a problem.
3885
3886 Bug or feature?  You decide:
3887 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3888
3889 This function resolves the true case of each element in the
3890 path and returns the case-sensitive path.
3891
3892 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3893 might return C<\"/WINDOWS/system32\"> (the exact return value
3894 would depend on details of how the directories were originally
3895 created under Windows).
3896
3897 I<Note>:
3898 This function does not handle drive names, backslashes etc.
3899
3900 See also C<guestfs_realpath>.");
3901
3902   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3903    [InitBasicFS, Always, TestOutput (
3904       [["vfs_type"; "/dev/sda1"]], "ext2")],
3905    "get the Linux VFS type corresponding to a mounted device",
3906    "\
3907 This command gets the filesystem type corresponding to
3908 the filesystem on C<device>.
3909
3910 For most filesystems, the result is the name of the Linux
3911 VFS module which would be used to mount this filesystem
3912 if you mounted it without specifying the filesystem type.
3913 For example a string such as C<ext3> or C<ntfs>.");
3914
3915   ("truncate", (RErr, [Pathname "path"]), 199, [],
3916    [InitBasicFS, Always, TestOutputStruct (
3917       [["write"; "/test"; "some stuff so size is not zero"];
3918        ["truncate"; "/test"];
3919        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3920    "truncate a file to zero size",
3921    "\
3922 This command truncates C<path> to a zero-length file.  The
3923 file must exist already.");
3924
3925   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3926    [InitBasicFS, Always, TestOutputStruct (
3927       [["touch"; "/test"];
3928        ["truncate_size"; "/test"; "1000"];
3929        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3930    "truncate a file to a particular size",
3931    "\
3932 This command truncates C<path> to size C<size> bytes.  The file
3933 must exist already.
3934
3935 If the current file size is less than C<size> then
3936 the file is extended to the required size with zero bytes.
3937 This creates a sparse file (ie. disk blocks are not allocated
3938 for the file until you write to it).  To create a non-sparse
3939 file of zeroes, use C<guestfs_fallocate64> instead.");
3940
3941   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3942    [InitBasicFS, Always, TestOutputStruct (
3943       [["touch"; "/test"];
3944        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3945        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3946    "set timestamp of a file with nanosecond precision",
3947    "\
3948 This command sets the timestamps of a file with nanosecond
3949 precision.
3950
3951 C<atsecs, atnsecs> are the last access time (atime) in secs and
3952 nanoseconds from the epoch.
3953
3954 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3955 secs and nanoseconds from the epoch.
3956
3957 If the C<*nsecs> field contains the special value C<-1> then
3958 the corresponding timestamp is set to the current time.  (The
3959 C<*secs> field is ignored in this case).
3960
3961 If the C<*nsecs> field contains the special value C<-2> then
3962 the corresponding timestamp is left unchanged.  (The
3963 C<*secs> field is ignored in this case).");
3964
3965   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3966    [InitBasicFS, Always, TestOutputStruct (
3967       [["mkdir_mode"; "/test"; "0o111"];
3968        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3969    "create a directory with a particular mode",
3970    "\
3971 This command creates a directory, setting the initial permissions
3972 of the directory to C<mode>.
3973
3974 For common Linux filesystems, the actual mode which is set will
3975 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3976 interpret the mode in other ways.
3977
3978 See also C<guestfs_mkdir>, C<guestfs_umask>");
3979
3980   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3981    [], (* XXX *)
3982    "change file owner and group",
3983    "\
3984 Change the file owner to C<owner> and group to C<group>.
3985 This is like C<guestfs_chown> but if C<path> is a symlink then
3986 the link itself is changed, not the target.
3987
3988 Only numeric uid and gid are supported.  If you want to use
3989 names, you will need to locate and parse the password file
3990 yourself (Augeas support makes this relatively easy).");
3991
3992   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3993    [], (* XXX *)
3994    "lstat on multiple files",
3995    "\
3996 This call allows you to perform the C<guestfs_lstat> operation
3997 on multiple files, where all files are in the directory C<path>.
3998 C<names> is the list of files from this directory.
3999
4000 On return you get a list of stat structs, with a one-to-one
4001 correspondence to the C<names> list.  If any name did not exist
4002 or could not be lstat'd, then the C<ino> field of that structure
4003 is set to C<-1>.
4004
4005 This call is intended for programs that want to efficiently
4006 list a directory contents without making many round-trips.
4007 See also C<guestfs_lxattrlist> for a similarly efficient call
4008 for getting extended attributes.  Very long directory listings
4009 might cause the protocol message size to be exceeded, causing
4010 this call to fail.  The caller must split up such requests
4011 into smaller groups of names.");
4012
4013   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4014    [], (* XXX *)
4015    "lgetxattr on multiple files",
4016    "\
4017 This call allows you to get the extended attributes
4018 of multiple files, where all files are in the directory C<path>.
4019 C<names> is the list of files from this directory.
4020
4021 On return you get a flat list of xattr structs which must be
4022 interpreted sequentially.  The first xattr struct always has a zero-length
4023 C<attrname>.  C<attrval> in this struct is zero-length
4024 to indicate there was an error doing C<lgetxattr> for this
4025 file, I<or> is a C string which is a decimal number
4026 (the number of following attributes for this file, which could
4027 be C<\"0\">).  Then after the first xattr struct are the
4028 zero or more attributes for the first named file.
4029 This repeats for the second and subsequent files.
4030
4031 This call is intended for programs that want to efficiently
4032 list a directory contents without making many round-trips.
4033 See also C<guestfs_lstatlist> for a similarly efficient call
4034 for getting standard stats.  Very long directory listings
4035 might cause the protocol message size to be exceeded, causing
4036 this call to fail.  The caller must split up such requests
4037 into smaller groups of names.");
4038
4039   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4040    [], (* XXX *)
4041    "readlink on multiple files",
4042    "\
4043 This call allows you to do a C<readlink> operation
4044 on multiple files, where all files are in the directory C<path>.
4045 C<names> is the list of files from this directory.
4046
4047 On return you get a list of strings, with a one-to-one
4048 correspondence to the C<names> list.  Each string is the
4049 value of the symbolic link.
4050
4051 If the C<readlink(2)> operation fails on any name, then
4052 the corresponding result string is the empty string C<\"\">.
4053 However the whole operation is completed even if there
4054 were C<readlink(2)> errors, and so you can call this
4055 function with names where you don't know if they are
4056 symbolic links already (albeit slightly less efficient).
4057
4058 This call is intended for programs that want to efficiently
4059 list a directory contents without making many round-trips.
4060 Very long directory listings might cause the protocol
4061 message size to be exceeded, causing
4062 this call to fail.  The caller must split up such requests
4063 into smaller groups of names.");
4064
4065   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4066    [InitISOFS, Always, TestOutputBuffer (
4067       [["pread"; "/known-4"; "1"; "3"]], "\n");
4068     InitISOFS, Always, TestOutputBuffer (
4069       [["pread"; "/empty"; "0"; "100"]], "")],
4070    "read part of a file",
4071    "\
4072 This command lets you read part of a file.  It reads C<count>
4073 bytes of the file, starting at C<offset>, from file C<path>.
4074
4075 This may read fewer bytes than requested.  For further details
4076 see the L<pread(2)> system call.
4077
4078 See also C<guestfs_pwrite>.");
4079
4080   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4081    [InitEmpty, Always, TestRun (
4082       [["part_init"; "/dev/sda"; "gpt"]])],
4083    "create an empty partition table",
4084    "\
4085 This creates an empty partition table on C<device> of one of the
4086 partition types listed below.  Usually C<parttype> should be
4087 either C<msdos> or C<gpt> (for large disks).
4088
4089 Initially there are no partitions.  Following this, you should
4090 call C<guestfs_part_add> for each partition required.
4091
4092 Possible values for C<parttype> are:
4093
4094 =over 4
4095
4096 =item B<efi> | B<gpt>
4097
4098 Intel EFI / GPT partition table.
4099
4100 This is recommended for >= 2 TB partitions that will be accessed
4101 from Linux and Intel-based Mac OS X.  It also has limited backwards
4102 compatibility with the C<mbr> format.
4103
4104 =item B<mbr> | B<msdos>
4105
4106 The standard PC \"Master Boot Record\" (MBR) format used
4107 by MS-DOS and Windows.  This partition type will B<only> work
4108 for device sizes up to 2 TB.  For large disks we recommend
4109 using C<gpt>.
4110
4111 =back
4112
4113 Other partition table types that may work but are not
4114 supported include:
4115
4116 =over 4
4117
4118 =item B<aix>
4119
4120 AIX disk labels.
4121
4122 =item B<amiga> | B<rdb>
4123
4124 Amiga \"Rigid Disk Block\" format.
4125
4126 =item B<bsd>
4127
4128 BSD disk labels.
4129
4130 =item B<dasd>
4131
4132 DASD, used on IBM mainframes.
4133
4134 =item B<dvh>
4135
4136 MIPS/SGI volumes.
4137
4138 =item B<mac>
4139
4140 Old Mac partition format.  Modern Macs use C<gpt>.
4141
4142 =item B<pc98>
4143
4144 NEC PC-98 format, common in Japan apparently.
4145
4146 =item B<sun>
4147
4148 Sun disk labels.
4149
4150 =back");
4151
4152   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4153    [InitEmpty, Always, TestRun (
4154       [["part_init"; "/dev/sda"; "mbr"];
4155        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4156     InitEmpty, Always, TestRun (
4157       [["part_init"; "/dev/sda"; "gpt"];
4158        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4159        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4160     InitEmpty, Always, TestRun (
4161       [["part_init"; "/dev/sda"; "mbr"];
4162        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4163        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4164        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4165        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4166    "add a partition to the device",
4167    "\
4168 This command adds a partition to C<device>.  If there is no partition
4169 table on the device, call C<guestfs_part_init> first.
4170
4171 The C<prlogex> parameter is the type of partition.  Normally you
4172 should pass C<p> or C<primary> here, but MBR partition tables also
4173 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4174 types.
4175
4176 C<startsect> and C<endsect> are the start and end of the partition
4177 in I<sectors>.  C<endsect> may be negative, which means it counts
4178 backwards from the end of the disk (C<-1> is the last sector).
4179
4180 Creating a partition which covers the whole disk is not so easy.
4181 Use C<guestfs_part_disk> to do that.");
4182
4183   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4184    [InitEmpty, Always, TestRun (
4185       [["part_disk"; "/dev/sda"; "mbr"]]);
4186     InitEmpty, Always, TestRun (
4187       [["part_disk"; "/dev/sda"; "gpt"]])],
4188    "partition whole disk with a single primary partition",
4189    "\
4190 This command is simply a combination of C<guestfs_part_init>
4191 followed by C<guestfs_part_add> to create a single primary partition
4192 covering the whole disk.
4193
4194 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4195 but other possible values are described in C<guestfs_part_init>.");
4196
4197   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4198    [InitEmpty, Always, TestRun (
4199       [["part_disk"; "/dev/sda"; "mbr"];
4200        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4201    "make a partition bootable",
4202    "\
4203 This sets the bootable flag on partition numbered C<partnum> on
4204 device C<device>.  Note that partitions are numbered from 1.
4205
4206 The bootable flag is used by some operating systems (notably
4207 Windows) to determine which partition to boot from.  It is by
4208 no means universally recognized.");
4209
4210   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4211    [InitEmpty, Always, TestRun (
4212       [["part_disk"; "/dev/sda"; "gpt"];
4213        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4214    "set partition name",
4215    "\
4216 This sets the partition name on partition numbered C<partnum> on
4217 device C<device>.  Note that partitions are numbered from 1.
4218
4219 The partition name can only be set on certain types of partition
4220 table.  This works on C<gpt> but not on C<mbr> partitions.");
4221
4222   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4223    [], (* XXX Add a regression test for this. *)
4224    "list partitions on a device",
4225    "\
4226 This command parses the partition table on C<device> and
4227 returns the list of partitions found.
4228
4229 The fields in the returned structure are:
4230
4231 =over 4
4232
4233 =item B<part_num>
4234
4235 Partition number, counting from 1.
4236
4237 =item B<part_start>
4238
4239 Start of the partition I<in bytes>.  To get sectors you have to
4240 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4241
4242 =item B<part_end>
4243
4244 End of the partition in bytes.
4245
4246 =item B<part_size>
4247
4248 Size of the partition in bytes.
4249
4250 =back");
4251
4252   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4253    [InitEmpty, Always, TestOutput (
4254       [["part_disk"; "/dev/sda"; "gpt"];
4255        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4256    "get the partition table type",
4257    "\
4258 This command examines the partition table on C<device> and
4259 returns the partition table type (format) being used.
4260
4261 Common return values include: C<msdos> (a DOS/Windows style MBR
4262 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4263 values are possible, although unusual.  See C<guestfs_part_init>
4264 for a full list.");
4265
4266   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4267    [InitBasicFS, Always, TestOutputBuffer (
4268       [["fill"; "0x63"; "10"; "/test"];
4269        ["read_file"; "/test"]], "cccccccccc")],
4270    "fill a file with octets",
4271    "\
4272 This command creates a new file called C<path>.  The initial
4273 content of the file is C<len> octets of C<c>, where C<c>
4274 must be a number in the range C<[0..255]>.
4275
4276 To fill a file with zero bytes (sparsely), it is
4277 much more efficient to use C<guestfs_truncate_size>.
4278 To create a file with a pattern of repeating bytes
4279 use C<guestfs_fill_pattern>.");
4280
4281   ("available", (RErr, [StringList "groups"]), 216, [],
4282    [InitNone, Always, TestRun [["available"; ""]]],
4283    "test availability of some parts of the API",
4284    "\
4285 This command is used to check the availability of some
4286 groups of functionality in the appliance, which not all builds of
4287 the libguestfs appliance will be able to provide.
4288
4289 The libguestfs groups, and the functions that those
4290 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4291 You can also fetch this list at runtime by calling
4292 C<guestfs_available_all_groups>.
4293
4294 The argument C<groups> is a list of group names, eg:
4295 C<[\"inotify\", \"augeas\"]> would check for the availability of
4296 the Linux inotify functions and Augeas (configuration file
4297 editing) functions.
4298
4299 The command returns no error if I<all> requested groups are available.
4300
4301 It fails with an error if one or more of the requested
4302 groups is unavailable in the appliance.
4303
4304 If an unknown group name is included in the
4305 list of groups then an error is always returned.
4306
4307 I<Notes:>
4308
4309 =over 4
4310
4311 =item *
4312
4313 You must call C<guestfs_launch> before calling this function.
4314
4315 The reason is because we don't know what groups are
4316 supported by the appliance/daemon until it is running and can
4317 be queried.
4318
4319 =item *
4320
4321 If a group of functions is available, this does not necessarily
4322 mean that they will work.  You still have to check for errors
4323 when calling individual API functions even if they are
4324 available.
4325
4326 =item *
4327
4328 It is usually the job of distro packagers to build
4329 complete functionality into the libguestfs appliance.
4330 Upstream libguestfs, if built from source with all
4331 requirements satisfied, will support everything.
4332
4333 =item *
4334
4335 This call was added in version C<1.0.80>.  In previous
4336 versions of libguestfs all you could do would be to speculatively
4337 execute a command to find out if the daemon implemented it.
4338 See also C<guestfs_version>.
4339
4340 =back");
4341
4342   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4343    [InitBasicFS, Always, TestOutputBuffer (
4344       [["write"; "/src"; "hello, world"];
4345        ["dd"; "/src"; "/dest"];
4346        ["read_file"; "/dest"]], "hello, world")],
4347    "copy from source to destination using dd",
4348    "\
4349 This command copies from one source device or file C<src>
4350 to another destination device or file C<dest>.  Normally you
4351 would use this to copy to or from a device or partition, for
4352 example to duplicate a filesystem.
4353
4354 If the destination is a device, it must be as large or larger
4355 than the source file or device, otherwise the copy will fail.
4356 This command cannot do partial copies (see C<guestfs_copy_size>).");
4357
4358   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4359    [InitBasicFS, Always, TestOutputInt (
4360       [["write"; "/file"; "hello, world"];
4361        ["filesize"; "/file"]], 12)],
4362    "return the size of the file in bytes",
4363    "\
4364 This command returns the size of C<file> in bytes.
4365
4366 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4367 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4368 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4369
4370   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4371    [InitBasicFSonLVM, Always, TestOutputList (
4372       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4373        ["lvs"]], ["/dev/VG/LV2"])],
4374    "rename an LVM logical volume",
4375    "\
4376 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4377
4378   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4379    [InitBasicFSonLVM, Always, TestOutputList (
4380       [["umount"; "/"];
4381        ["vg_activate"; "false"; "VG"];
4382        ["vgrename"; "VG"; "VG2"];
4383        ["vg_activate"; "true"; "VG2"];
4384        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4385        ["vgs"]], ["VG2"])],
4386    "rename an LVM volume group",
4387    "\
4388 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4389
4390   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4391    [InitISOFS, Always, TestOutputBuffer (
4392       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4393    "list the contents of a single file in an initrd",
4394    "\
4395 This command unpacks the file C<filename> from the initrd file
4396 called C<initrdpath>.  The filename must be given I<without> the
4397 initial C</> character.
4398
4399 For example, in guestfish you could use the following command
4400 to examine the boot script (usually called C</init>)
4401 contained in a Linux initrd or initramfs image:
4402
4403  initrd-cat /boot/initrd-<version>.img init
4404
4405 See also C<guestfs_initrd_list>.");
4406
4407   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4408    [],
4409    "get the UUID of a physical volume",
4410    "\
4411 This command returns the UUID of the LVM PV C<device>.");
4412
4413   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4414    [],
4415    "get the UUID of a volume group",
4416    "\
4417 This command returns the UUID of the LVM VG named C<vgname>.");
4418
4419   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4420    [],
4421    "get the UUID of a logical volume",
4422    "\
4423 This command returns the UUID of the LVM LV C<device>.");
4424
4425   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4426    [],
4427    "get the PV UUIDs containing the volume group",
4428    "\
4429 Given a VG called C<vgname>, this returns the UUIDs of all
4430 the physical volumes that this volume group resides on.
4431
4432 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4433 calls to associate physical volumes and volume groups.
4434
4435 See also C<guestfs_vglvuuids>.");
4436
4437   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4438    [],
4439    "get the LV UUIDs of all LVs in the volume group",
4440    "\
4441 Given a VG called C<vgname>, this returns the UUIDs of all
4442 the logical volumes created in this volume group.
4443
4444 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4445 calls to associate logical volumes and volume groups.
4446
4447 See also C<guestfs_vgpvuuids>.");
4448
4449   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4450    [InitBasicFS, Always, TestOutputBuffer (
4451       [["write"; "/src"; "hello, world"];
4452        ["copy_size"; "/src"; "/dest"; "5"];
4453        ["read_file"; "/dest"]], "hello")],
4454    "copy size bytes from source to destination using dd",
4455    "\
4456 This command copies exactly C<size> bytes from one source device
4457 or file C<src> to another destination device or file C<dest>.
4458
4459 Note this will fail if the source is too short or if the destination
4460 is not large enough.");
4461
4462   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4463    [InitBasicFSonLVM, Always, TestRun (
4464       [["zero_device"; "/dev/VG/LV"]])],
4465    "write zeroes to an entire device",
4466    "\
4467 This command writes zeroes over the entire C<device>.  Compare
4468 with C<guestfs_zero> which just zeroes the first few blocks of
4469 a device.");
4470
4471   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4472    [InitBasicFS, Always, TestOutput (
4473       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4474        ["cat"; "/hello"]], "hello\n")],
4475    "unpack compressed tarball to directory",
4476    "\
4477 This command uploads and unpacks local file C<tarball> (an
4478 I<xz compressed> tar file) into C<directory>.");
4479
4480   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4481    [],
4482    "pack directory into compressed tarball",
4483    "\
4484 This command packs the contents of C<directory> and downloads
4485 it to local file C<tarball> (as an xz compressed tar archive).");
4486
4487   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4488    [],
4489    "resize an NTFS filesystem",
4490    "\
4491 This command resizes an NTFS filesystem, expanding or
4492 shrinking it to the size of the underlying device.
4493 See also L<ntfsresize(8)>.");
4494
4495   ("vgscan", (RErr, []), 232, [],
4496    [InitEmpty, Always, TestRun (
4497       [["vgscan"]])],
4498    "rescan for LVM physical volumes, volume groups and logical volumes",
4499    "\
4500 This rescans all block devices and rebuilds the list of LVM
4501 physical volumes, volume groups and logical volumes.");
4502
4503   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4504    [InitEmpty, Always, TestRun (
4505       [["part_init"; "/dev/sda"; "mbr"];
4506        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4507        ["part_del"; "/dev/sda"; "1"]])],
4508    "delete a partition",
4509    "\
4510 This command deletes the partition numbered C<partnum> on C<device>.
4511
4512 Note that in the case of MBR partitioning, deleting an
4513 extended partition also deletes any logical partitions
4514 it contains.");
4515
4516   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4517    [InitEmpty, Always, TestOutputTrue (
4518       [["part_init"; "/dev/sda"; "mbr"];
4519        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4520        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4521        ["part_get_bootable"; "/dev/sda"; "1"]])],
4522    "return true if a partition is bootable",
4523    "\
4524 This command returns true if the partition C<partnum> on
4525 C<device> has the bootable flag set.
4526
4527 See also C<guestfs_part_set_bootable>.");
4528
4529   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4530    [InitEmpty, Always, TestOutputInt (
4531       [["part_init"; "/dev/sda"; "mbr"];
4532        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4533        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4534        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4535    "get the MBR type byte (ID byte) from a partition",
4536    "\
4537 Returns the MBR type byte (also known as the ID byte) from
4538 the numbered partition C<partnum>.
4539
4540 Note that only MBR (old DOS-style) partitions have type bytes.
4541 You will get undefined results for other partition table
4542 types (see C<guestfs_part_get_parttype>).");
4543
4544   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4545    [], (* tested by part_get_mbr_id *)
4546    "set the MBR type byte (ID byte) of a partition",
4547    "\
4548 Sets the MBR type byte (also known as the ID byte) of
4549 the numbered partition C<partnum> to C<idbyte>.  Note
4550 that the type bytes quoted in most documentation are
4551 in fact hexadecimal numbers, but usually documented
4552 without any leading \"0x\" which might be confusing.
4553
4554 Note that only MBR (old DOS-style) partitions have type bytes.
4555 You will get undefined results for other partition table
4556 types (see C<guestfs_part_get_parttype>).");
4557
4558   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4559    [InitISOFS, Always, TestOutput (
4560       [["checksum_device"; "md5"; "/dev/sdd"]],
4561       (Digest.to_hex (Digest.file "images/test.iso")))],
4562    "compute MD5, SHAx or CRC checksum of the contents of a device",
4563    "\
4564 This call computes the MD5, SHAx or CRC checksum of the
4565 contents of the device named C<device>.  For the types of
4566 checksums supported see the C<guestfs_checksum> command.");
4567
4568   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4569    [InitNone, Always, TestRun (
4570       [["part_disk"; "/dev/sda"; "mbr"];
4571        ["pvcreate"; "/dev/sda1"];
4572        ["vgcreate"; "VG"; "/dev/sda1"];
4573        ["lvcreate"; "LV"; "VG"; "10"];
4574        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4575    "expand an LV to fill free space",
4576    "\
4577 This expands an existing logical volume C<lv> so that it fills
4578 C<pc>% of the remaining free space in the volume group.  Commonly
4579 you would call this with pc = 100 which expands the logical volume
4580 as much as possible, using all remaining free space in the volume
4581 group.");
4582
4583   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4584    [], (* XXX Augeas code needs tests. *)
4585    "clear Augeas path",
4586    "\
4587 Set the value associated with C<path> to C<NULL>.  This
4588 is the same as the L<augtool(1)> C<clear> command.");
4589
4590   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4591    [InitEmpty, Always, TestOutputInt (
4592       [["get_umask"]], 0o22)],
4593    "get the current umask",
4594    "\
4595 Return the current umask.  By default the umask is C<022>
4596 unless it has been set by calling C<guestfs_umask>.");
4597
4598   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4599    [],
4600    "upload a file to the appliance (internal use only)",
4601    "\
4602 The C<guestfs_debug_upload> command uploads a file to
4603 the libguestfs appliance.
4604
4605 There is no comprehensive help for this command.  You have
4606 to look at the file C<daemon/debug.c> in the libguestfs source
4607 to find out what it is for.");
4608
4609   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4610    [InitBasicFS, Always, TestOutput (
4611       [["base64_in"; "../images/hello.b64"; "/hello"];
4612        ["cat"; "/hello"]], "hello\n")],
4613    "upload base64-encoded data to file",
4614    "\
4615 This command uploads base64-encoded data from C<base64file>
4616 to C<filename>.");
4617
4618   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4619    [],
4620    "download file and encode as base64",
4621    "\
4622 This command downloads the contents of C<filename>, writing
4623 it out to local file C<base64file> encoded as base64.");
4624
4625   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4626    [],
4627    "compute MD5, SHAx or CRC checksum of files in a directory",
4628    "\
4629 This command computes the checksums of all regular files in
4630 C<directory> and then emits a list of those checksums to
4631 the local output file C<sumsfile>.
4632
4633 This can be used for verifying the integrity of a virtual
4634 machine.  However to be properly secure you should pay
4635 attention to the output of the checksum command (it uses
4636 the ones from GNU coreutils).  In particular when the
4637 filename is not printable, coreutils uses a special
4638 backslash syntax.  For more information, see the GNU
4639 coreutils info file.");
4640
4641   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4642    [InitBasicFS, Always, TestOutputBuffer (
4643       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4644        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4645    "fill a file with a repeating pattern of bytes",
4646    "\
4647 This function is like C<guestfs_fill> except that it creates
4648 a new file of length C<len> containing the repeating pattern
4649 of bytes in C<pattern>.  The pattern is truncated if necessary
4650 to ensure the length of the file is exactly C<len> bytes.");
4651
4652   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4653    [InitBasicFS, Always, TestOutput (
4654       [["write"; "/new"; "new file contents"];
4655        ["cat"; "/new"]], "new file contents");
4656     InitBasicFS, Always, TestOutput (
4657       [["write"; "/new"; "\nnew file contents\n"];
4658        ["cat"; "/new"]], "\nnew file contents\n");
4659     InitBasicFS, Always, TestOutput (
4660       [["write"; "/new"; "\n\n"];
4661        ["cat"; "/new"]], "\n\n");
4662     InitBasicFS, Always, TestOutput (
4663       [["write"; "/new"; ""];
4664        ["cat"; "/new"]], "");
4665     InitBasicFS, Always, TestOutput (
4666       [["write"; "/new"; "\n\n\n"];
4667        ["cat"; "/new"]], "\n\n\n");
4668     InitBasicFS, Always, TestOutput (
4669       [["write"; "/new"; "\n"];
4670        ["cat"; "/new"]], "\n")],
4671    "create a new file",
4672    "\
4673 This call creates a file called C<path>.  The content of the
4674 file is the string C<content> (which can contain any 8 bit data).");
4675
4676   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4677    [InitBasicFS, Always, TestOutput (
4678       [["write"; "/new"; "new file contents"];
4679        ["pwrite"; "/new"; "data"; "4"];
4680        ["cat"; "/new"]], "new data contents");
4681     InitBasicFS, Always, TestOutput (
4682       [["write"; "/new"; "new file contents"];
4683        ["pwrite"; "/new"; "is extended"; "9"];
4684        ["cat"; "/new"]], "new file is extended");
4685     InitBasicFS, Always, TestOutput (
4686       [["write"; "/new"; "new file contents"];
4687        ["pwrite"; "/new"; ""; "4"];
4688        ["cat"; "/new"]], "new file contents")],
4689    "write to part of a file",
4690    "\
4691 This command writes to part of a file.  It writes the data
4692 buffer C<content> to the file C<path> starting at offset C<offset>.
4693
4694 This command implements the L<pwrite(2)> system call, and like
4695 that system call it may not write the full data requested.  The
4696 return value is the number of bytes that were actually written
4697 to the file.  This could even be 0, although short writes are
4698 unlikely for regular files in ordinary circumstances.
4699
4700 See also C<guestfs_pread>.");
4701
4702   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4703    [],
4704    "resize an ext2/ext3 filesystem (with size)",
4705    "\
4706 This command is the same as C<guestfs_resize2fs> except that it
4707 allows you to specify the new size (in bytes) explicitly.");
4708
4709   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4710    [],
4711    "resize an LVM physical volume (with size)",
4712    "\
4713 This command is the same as C<guestfs_pvresize> except that it
4714 allows you to specify the new size (in bytes) explicitly.");
4715
4716   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4717    [],
4718    "resize an NTFS filesystem (with size)",
4719    "\
4720 This command is the same as C<guestfs_ntfsresize> except that it
4721 allows you to specify the new size (in bytes) explicitly.");
4722
4723   ("available_all_groups", (RStringList "groups", []), 251, [],
4724    [InitNone, Always, TestRun [["available_all_groups"]]],
4725    "return a list of all optional groups",
4726    "\
4727 This command returns a list of all optional groups that this
4728 daemon knows about.  Note this returns both supported and unsupported
4729 groups.  To find out which ones the daemon can actually support
4730 you have to call C<guestfs_available> on each member of the
4731 returned list.
4732
4733 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4734
4735   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4736    [InitBasicFS, Always, TestOutputStruct (
4737       [["fallocate64"; "/a"; "1000000"];
4738        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4739    "preallocate a file in the guest filesystem",
4740    "\
4741 This command preallocates a file (containing zero bytes) named
4742 C<path> of size C<len> bytes.  If the file exists already, it
4743 is overwritten.
4744
4745 Note that this call allocates disk blocks for the file.
4746 To create a sparse file use C<guestfs_truncate_size> instead.
4747
4748 The deprecated call C<guestfs_fallocate> does the same,
4749 but owing to an oversight it only allowed 30 bit lengths
4750 to be specified, effectively limiting the maximum size
4751 of files created through that call to 1GB.
4752
4753 Do not confuse this with the guestfish-specific
4754 C<alloc> and C<sparse> commands which create
4755 a file in the host and attach it as a device.");
4756
4757   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4758    [InitBasicFS, Always, TestOutput (
4759        [["set_e2label"; "/dev/sda1"; "LTEST"];
4760         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4761    "get the filesystem label",
4762    "\
4763 This returns the filesystem label of the filesystem on
4764 C<device>.
4765
4766 If the filesystem is unlabeled, this returns the empty string.");
4767
4768   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4769    (let uuid = uuidgen () in
4770     [InitBasicFS, Always, TestOutput (
4771        [["set_e2uuid"; "/dev/sda1"; uuid];
4772         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4773    "get the filesystem UUID",
4774    "\
4775 This returns the filesystem UUID of the filesystem on
4776 C<device>.
4777
4778 If the filesystem does not have a UUID, this returns the empty string.");
4779
4780 ]
4781
4782 let all_functions = non_daemon_functions @ daemon_functions
4783
4784 (* In some places we want the functions to be displayed sorted
4785  * alphabetically, so this is useful:
4786  *)
4787 let all_functions_sorted =
4788   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4789                compare n1 n2) all_functions
4790
4791 (* This is used to generate the src/MAX_PROC_NR file which
4792  * contains the maximum procedure number, a surrogate for the
4793  * ABI version number.  See src/Makefile.am for the details.
4794  *)
4795 let max_proc_nr =
4796   let proc_nrs = List.map (
4797     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4798   ) daemon_functions in
4799   List.fold_left max 0 proc_nrs
4800
4801 (* Field types for structures. *)
4802 type field =
4803   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4804   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4805   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4806   | FUInt32
4807   | FInt32
4808   | FUInt64
4809   | FInt64
4810   | FBytes                      (* Any int measure that counts bytes. *)
4811   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4812   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4813
4814 (* Because we generate extra parsing code for LVM command line tools,
4815  * we have to pull out the LVM columns separately here.
4816  *)
4817 let lvm_pv_cols = [
4818   "pv_name", FString;
4819   "pv_uuid", FUUID;
4820   "pv_fmt", FString;
4821   "pv_size", FBytes;
4822   "dev_size", FBytes;
4823   "pv_free", FBytes;
4824   "pv_used", FBytes;
4825   "pv_attr", FString (* XXX *);
4826   "pv_pe_count", FInt64;
4827   "pv_pe_alloc_count", FInt64;
4828   "pv_tags", FString;
4829   "pe_start", FBytes;
4830   "pv_mda_count", FInt64;
4831   "pv_mda_free", FBytes;
4832   (* Not in Fedora 10:
4833      "pv_mda_size", FBytes;
4834   *)
4835 ]
4836 let lvm_vg_cols = [
4837   "vg_name", FString;
4838   "vg_uuid", FUUID;
4839   "vg_fmt", FString;
4840   "vg_attr", FString (* XXX *);
4841   "vg_size", FBytes;
4842   "vg_free", FBytes;
4843   "vg_sysid", FString;
4844   "vg_extent_size", FBytes;
4845   "vg_extent_count", FInt64;
4846   "vg_free_count", FInt64;
4847   "max_lv", FInt64;
4848   "max_pv", FInt64;
4849   "pv_count", FInt64;
4850   "lv_count", FInt64;
4851   "snap_count", FInt64;
4852   "vg_seqno", FInt64;
4853   "vg_tags", FString;
4854   "vg_mda_count", FInt64;
4855   "vg_mda_free", FBytes;
4856   (* Not in Fedora 10:
4857      "vg_mda_size", FBytes;
4858   *)
4859 ]
4860 let lvm_lv_cols = [
4861   "lv_name", FString;
4862   "lv_uuid", FUUID;
4863   "lv_attr", FString (* XXX *);
4864   "lv_major", FInt64;
4865   "lv_minor", FInt64;
4866   "lv_kernel_major", FInt64;
4867   "lv_kernel_minor", FInt64;
4868   "lv_size", FBytes;
4869   "seg_count", FInt64;
4870   "origin", FString;
4871   "snap_percent", FOptPercent;
4872   "copy_percent", FOptPercent;
4873   "move_pv", FString;
4874   "lv_tags", FString;
4875   "mirror_log", FString;
4876   "modules", FString;
4877 ]
4878
4879 (* Names and fields in all structures (in RStruct and RStructList)
4880  * that we support.
4881  *)
4882 let structs = [
4883   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4884    * not use this struct in any new code.
4885    *)
4886   "int_bool", [
4887     "i", FInt32;                (* for historical compatibility *)
4888     "b", FInt32;                (* for historical compatibility *)
4889   ];
4890
4891   (* LVM PVs, VGs, LVs. *)
4892   "lvm_pv", lvm_pv_cols;
4893   "lvm_vg", lvm_vg_cols;
4894   "lvm_lv", lvm_lv_cols;
4895
4896   (* Column names and types from stat structures.
4897    * NB. Can't use things like 'st_atime' because glibc header files
4898    * define some of these as macros.  Ugh.
4899    *)
4900   "stat", [
4901     "dev", FInt64;
4902     "ino", FInt64;
4903     "mode", FInt64;
4904     "nlink", FInt64;
4905     "uid", FInt64;
4906     "gid", FInt64;
4907     "rdev", FInt64;
4908     "size", FInt64;
4909     "blksize", FInt64;
4910     "blocks", FInt64;
4911     "atime", FInt64;
4912     "mtime", FInt64;
4913     "ctime", FInt64;
4914   ];
4915   "statvfs", [
4916     "bsize", FInt64;
4917     "frsize", FInt64;
4918     "blocks", FInt64;
4919     "bfree", FInt64;
4920     "bavail", FInt64;
4921     "files", FInt64;
4922     "ffree", FInt64;
4923     "favail", FInt64;
4924     "fsid", FInt64;
4925     "flag", FInt64;
4926     "namemax", FInt64;
4927   ];
4928
4929   (* Column names in dirent structure. *)
4930   "dirent", [
4931     "ino", FInt64;
4932     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4933     "ftyp", FChar;
4934     "name", FString;
4935   ];
4936
4937   (* Version numbers. *)
4938   "version", [
4939     "major", FInt64;
4940     "minor", FInt64;
4941     "release", FInt64;
4942     "extra", FString;
4943   ];
4944
4945   (* Extended attribute. *)
4946   "xattr", [
4947     "attrname", FString;
4948     "attrval", FBuffer;
4949   ];
4950
4951   (* Inotify events. *)
4952   "inotify_event", [
4953     "in_wd", FInt64;
4954     "in_mask", FUInt32;
4955     "in_cookie", FUInt32;
4956     "in_name", FString;
4957   ];
4958
4959   (* Partition table entry. *)
4960   "partition", [
4961     "part_num", FInt32;
4962     "part_start", FBytes;
4963     "part_end", FBytes;
4964     "part_size", FBytes;
4965   ];
4966 ] (* end of structs *)
4967
4968 (* Ugh, Java has to be different ..
4969  * These names are also used by the Haskell bindings.
4970  *)
4971 let java_structs = [
4972   "int_bool", "IntBool";
4973   "lvm_pv", "PV";
4974   "lvm_vg", "VG";
4975   "lvm_lv", "LV";
4976   "stat", "Stat";
4977   "statvfs", "StatVFS";
4978   "dirent", "Dirent";
4979   "version", "Version";
4980   "xattr", "XAttr";
4981   "inotify_event", "INotifyEvent";
4982   "partition", "Partition";
4983 ]
4984
4985 (* What structs are actually returned. *)
4986 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4987
4988 (* Returns a list of RStruct/RStructList structs that are returned
4989  * by any function.  Each element of returned list is a pair:
4990  *
4991  * (structname, RStructOnly)
4992  *    == there exists function which returns RStruct (_, structname)
4993  * (structname, RStructListOnly)
4994  *    == there exists function which returns RStructList (_, structname)
4995  * (structname, RStructAndList)
4996  *    == there are functions returning both RStruct (_, structname)
4997  *                                      and RStructList (_, structname)
4998  *)
4999 let rstructs_used_by functions =
5000   (* ||| is a "logical OR" for rstructs_used_t *)
5001   let (|||) a b =
5002     match a, b with
5003     | RStructAndList, _
5004     | _, RStructAndList -> RStructAndList
5005     | RStructOnly, RStructListOnly
5006     | RStructListOnly, RStructOnly -> RStructAndList
5007     | RStructOnly, RStructOnly -> RStructOnly
5008     | RStructListOnly, RStructListOnly -> RStructListOnly
5009   in
5010
5011   let h = Hashtbl.create 13 in
5012
5013   (* if elem->oldv exists, update entry using ||| operator,
5014    * else just add elem->newv to the hash
5015    *)
5016   let update elem newv =
5017     try  let oldv = Hashtbl.find h elem in
5018          Hashtbl.replace h elem (newv ||| oldv)
5019     with Not_found -> Hashtbl.add h elem newv
5020   in
5021
5022   List.iter (
5023     fun (_, style, _, _, _, _, _) ->
5024       match fst style with
5025       | RStruct (_, structname) -> update structname RStructOnly
5026       | RStructList (_, structname) -> update structname RStructListOnly
5027       | _ -> ()
5028   ) functions;
5029
5030   (* return key->values as a list of (key,value) *)
5031   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5032
5033 (* Used for testing language bindings. *)
5034 type callt =
5035   | CallString of string
5036   | CallOptString of string option
5037   | CallStringList of string list
5038   | CallInt of int
5039   | CallInt64 of int64
5040   | CallBool of bool
5041   | CallBuffer of string
5042
5043 (* Used to memoize the result of pod2text. *)
5044 let pod2text_memo_filename = "src/.pod2text.data"
5045 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5046   try
5047     let chan = open_in pod2text_memo_filename in
5048     let v = input_value chan in
5049     close_in chan;
5050     v
5051   with
5052     _ -> Hashtbl.create 13
5053 let pod2text_memo_updated () =
5054   let chan = open_out pod2text_memo_filename in
5055   output_value chan pod2text_memo;
5056   close_out chan
5057
5058 (* Useful functions.
5059  * Note we don't want to use any external OCaml libraries which
5060  * makes this a bit harder than it should be.
5061  *)
5062 module StringMap = Map.Make (String)
5063
5064 let failwithf fs = ksprintf failwith fs
5065
5066 let unique = let i = ref 0 in fun () -> incr i; !i
5067
5068 let replace_char s c1 c2 =
5069   let s2 = String.copy s in
5070   let r = ref false in
5071   for i = 0 to String.length s2 - 1 do
5072     if String.unsafe_get s2 i = c1 then (
5073       String.unsafe_set s2 i c2;
5074       r := true
5075     )
5076   done;
5077   if not !r then s else s2
5078
5079 let isspace c =
5080   c = ' '
5081   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5082
5083 let triml ?(test = isspace) str =
5084   let i = ref 0 in
5085   let n = ref (String.length str) in
5086   while !n > 0 && test str.[!i]; do
5087     decr n;
5088     incr i
5089   done;
5090   if !i = 0 then str
5091   else String.sub str !i !n
5092
5093 let trimr ?(test = isspace) str =
5094   let n = ref (String.length str) in
5095   while !n > 0 && test str.[!n-1]; do
5096     decr n
5097   done;
5098   if !n = String.length str then str
5099   else String.sub str 0 !n
5100
5101 let trim ?(test = isspace) str =
5102   trimr ~test (triml ~test str)
5103
5104 let rec find s sub =
5105   let len = String.length s in
5106   let sublen = String.length sub in
5107   let rec loop i =
5108     if i <= len-sublen then (
5109       let rec loop2 j =
5110         if j < sublen then (
5111           if s.[i+j] = sub.[j] then loop2 (j+1)
5112           else -1
5113         ) else
5114           i (* found *)
5115       in
5116       let r = loop2 0 in
5117       if r = -1 then loop (i+1) else r
5118     ) else
5119       -1 (* not found *)
5120   in
5121   loop 0
5122
5123 let rec replace_str s s1 s2 =
5124   let len = String.length s in
5125   let sublen = String.length s1 in
5126   let i = find s s1 in
5127   if i = -1 then s
5128   else (
5129     let s' = String.sub s 0 i in
5130     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5131     s' ^ s2 ^ replace_str s'' s1 s2
5132   )
5133
5134 let rec string_split sep str =
5135   let len = String.length str in
5136   let seplen = String.length sep in
5137   let i = find str sep in
5138   if i = -1 then [str]
5139   else (
5140     let s' = String.sub str 0 i in
5141     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5142     s' :: string_split sep s''
5143   )
5144
5145 let files_equal n1 n2 =
5146   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5147   match Sys.command cmd with
5148   | 0 -> true
5149   | 1 -> false
5150   | i -> failwithf "%s: failed with error code %d" cmd i
5151
5152 let rec filter_map f = function
5153   | [] -> []
5154   | x :: xs ->
5155       match f x with
5156       | Some y -> y :: filter_map f xs
5157       | None -> filter_map f xs
5158
5159 let rec find_map f = function
5160   | [] -> raise Not_found
5161   | x :: xs ->
5162       match f x with
5163       | Some y -> y
5164       | None -> find_map f xs
5165
5166 let iteri f xs =
5167   let rec loop i = function
5168     | [] -> ()
5169     | x :: xs -> f i x; loop (i+1) xs
5170   in
5171   loop 0 xs
5172
5173 let mapi f xs =
5174   let rec loop i = function
5175     | [] -> []
5176     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5177   in
5178   loop 0 xs
5179
5180 let count_chars c str =
5181   let count = ref 0 in
5182   for i = 0 to String.length str - 1 do
5183     if c = String.unsafe_get str i then incr count
5184   done;
5185   !count
5186
5187 let explode str =
5188   let r = ref [] in
5189   for i = 0 to String.length str - 1 do
5190     let c = String.unsafe_get str i in
5191     r := c :: !r;
5192   done;
5193   List.rev !r
5194
5195 let map_chars f str =
5196   List.map f (explode str)
5197
5198 let name_of_argt = function
5199   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5200   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5201   | FileIn n | FileOut n | BufferIn n -> n
5202
5203 let java_name_of_struct typ =
5204   try List.assoc typ java_structs
5205   with Not_found ->
5206     failwithf
5207       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5208
5209 let cols_of_struct typ =
5210   try List.assoc typ structs
5211   with Not_found ->
5212     failwithf "cols_of_struct: unknown struct %s" typ
5213
5214 let seq_of_test = function
5215   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5216   | TestOutputListOfDevices (s, _)
5217   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5218   | TestOutputTrue s | TestOutputFalse s
5219   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5220   | TestOutputStruct (s, _)
5221   | TestLastFail s -> s
5222
5223 (* Handling for function flags. *)
5224 let protocol_limit_warning =
5225   "Because of the message protocol, there is a transfer limit
5226 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5227
5228 let danger_will_robinson =
5229   "B<This command is dangerous.  Without careful use you
5230 can easily destroy all your data>."
5231
5232 let deprecation_notice flags =
5233   try
5234     let alt =
5235       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5236     let txt =
5237       sprintf "This function is deprecated.
5238 In new code, use the C<%s> call instead.
5239
5240 Deprecated functions will not be removed from the API, but the
5241 fact that they are deprecated indicates that there are problems
5242 with correct use of these functions." alt in
5243     Some txt
5244   with
5245     Not_found -> None
5246
5247 (* Create list of optional groups. *)
5248 let optgroups =
5249   let h = Hashtbl.create 13 in
5250   List.iter (
5251     fun (name, _, _, flags, _, _, _) ->
5252       List.iter (
5253         function
5254         | Optional group ->
5255             let names = try Hashtbl.find h group with Not_found -> [] in
5256             Hashtbl.replace h group (name :: names)
5257         | _ -> ()
5258       ) flags
5259   ) daemon_functions;
5260   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5261   let groups =
5262     List.map (
5263       fun group -> group, List.sort compare (Hashtbl.find h group)
5264     ) groups in
5265   List.sort (fun x y -> compare (fst x) (fst y)) groups
5266
5267 (* Check function names etc. for consistency. *)
5268 let check_functions () =
5269   let contains_uppercase str =
5270     let len = String.length str in
5271     let rec loop i =
5272       if i >= len then false
5273       else (
5274         let c = str.[i] in
5275         if c >= 'A' && c <= 'Z' then true
5276         else loop (i+1)
5277       )
5278     in
5279     loop 0
5280   in
5281
5282   (* Check function names. *)
5283   List.iter (
5284     fun (name, _, _, _, _, _, _) ->
5285       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5286         failwithf "function name %s does not need 'guestfs' prefix" name;
5287       if name = "" then
5288         failwithf "function name is empty";
5289       if name.[0] < 'a' || name.[0] > 'z' then
5290         failwithf "function name %s must start with lowercase a-z" name;
5291       if String.contains name '-' then
5292         failwithf "function name %s should not contain '-', use '_' instead."
5293           name
5294   ) all_functions;
5295
5296   (* Check function parameter/return names. *)
5297   List.iter (
5298     fun (name, style, _, _, _, _, _) ->
5299       let check_arg_ret_name n =
5300         if contains_uppercase n then
5301           failwithf "%s param/ret %s should not contain uppercase chars"
5302             name n;
5303         if String.contains n '-' || String.contains n '_' then
5304           failwithf "%s param/ret %s should not contain '-' or '_'"
5305             name n;
5306         if n = "value" then
5307           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;
5308         if n = "int" || n = "char" || n = "short" || n = "long" then
5309           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5310         if n = "i" || n = "n" then
5311           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5312         if n = "argv" || n = "args" then
5313           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5314
5315         (* List Haskell, OCaml and C keywords here.
5316          * http://www.haskell.org/haskellwiki/Keywords
5317          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5318          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5319          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5320          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5321          * Omitting _-containing words, since they're handled above.
5322          * Omitting the OCaml reserved word, "val", is ok,
5323          * and saves us from renaming several parameters.
5324          *)
5325         let reserved = [
5326           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5327           "char"; "class"; "const"; "constraint"; "continue"; "data";
5328           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5329           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5330           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5331           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5332           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5333           "interface";
5334           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5335           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5336           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5337           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5338           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5339           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5340           "volatile"; "when"; "where"; "while";
5341           ] in
5342         if List.mem n reserved then
5343           failwithf "%s has param/ret using reserved word %s" name n;
5344       in
5345
5346       (match fst style with
5347        | RErr -> ()
5348        | RInt n | RInt64 n | RBool n
5349        | RConstString n | RConstOptString n | RString n
5350        | RStringList n | RStruct (n, _) | RStructList (n, _)
5351        | RHashtable n | RBufferOut n ->
5352            check_arg_ret_name n
5353       );
5354       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5355   ) all_functions;
5356
5357   (* Check short descriptions. *)
5358   List.iter (
5359     fun (name, _, _, _, _, shortdesc, _) ->
5360       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5361         failwithf "short description of %s should begin with lowercase." name;
5362       let c = shortdesc.[String.length shortdesc-1] in
5363       if c = '\n' || c = '.' then
5364         failwithf "short description of %s should not end with . or \\n." name
5365   ) all_functions;
5366
5367   (* Check long descriptions. *)
5368   List.iter (
5369     fun (name, _, _, _, _, _, longdesc) ->
5370       if longdesc.[String.length longdesc-1] = '\n' then
5371         failwithf "long description of %s should not end with \\n." name
5372   ) all_functions;
5373
5374   (* Check proc_nrs. *)
5375   List.iter (
5376     fun (name, _, proc_nr, _, _, _, _) ->
5377       if proc_nr <= 0 then
5378         failwithf "daemon function %s should have proc_nr > 0" name
5379   ) daemon_functions;
5380
5381   List.iter (
5382     fun (name, _, proc_nr, _, _, _, _) ->
5383       if proc_nr <> -1 then
5384         failwithf "non-daemon function %s should have proc_nr -1" name
5385   ) non_daemon_functions;
5386
5387   let proc_nrs =
5388     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5389       daemon_functions in
5390   let proc_nrs =
5391     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5392   let rec loop = function
5393     | [] -> ()
5394     | [_] -> ()
5395     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5396         loop rest
5397     | (name1,nr1) :: (name2,nr2) :: _ ->
5398         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5399           name1 name2 nr1 nr2
5400   in
5401   loop proc_nrs;
5402
5403   (* Check tests. *)
5404   List.iter (
5405     function
5406       (* Ignore functions that have no tests.  We generate a
5407        * warning when the user does 'make check' instead.
5408        *)
5409     | name, _, _, _, [], _, _ -> ()
5410     | name, _, _, _, tests, _, _ ->
5411         let funcs =
5412           List.map (
5413             fun (_, _, test) ->
5414               match seq_of_test test with
5415               | [] ->
5416                   failwithf "%s has a test containing an empty sequence" name
5417               | cmds -> List.map List.hd cmds
5418           ) tests in
5419         let funcs = List.flatten funcs in
5420
5421         let tested = List.mem name funcs in
5422
5423         if not tested then
5424           failwithf "function %s has tests but does not test itself" name
5425   ) all_functions
5426
5427 (* 'pr' prints to the current output file. *)
5428 let chan = ref Pervasives.stdout
5429 let lines = ref 0
5430 let pr fs =
5431   ksprintf
5432     (fun str ->
5433        let i = count_chars '\n' str in
5434        lines := !lines + i;
5435        output_string !chan str
5436     ) fs
5437
5438 let copyright_years =
5439   let this_year = 1900 + (localtime (time ())).tm_year in
5440   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5441
5442 (* Generate a header block in a number of standard styles. *)
5443 type comment_style =
5444     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5445 type license = GPLv2plus | LGPLv2plus
5446
5447 let generate_header ?(extra_inputs = []) comment license =
5448   let inputs = "src/generator.ml" :: extra_inputs in
5449   let c = match comment with
5450     | CStyle ->         pr "/* "; " *"
5451     | CPlusPlusStyle -> pr "// "; "//"
5452     | HashStyle ->      pr "# ";  "#"
5453     | OCamlStyle ->     pr "(* "; " *"
5454     | HaskellStyle ->   pr "{- "; "  " in
5455   pr "libguestfs generated file\n";
5456   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5457   List.iter (pr "%s   %s\n" c) inputs;
5458   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5459   pr "%s\n" c;
5460   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5461   pr "%s\n" c;
5462   (match license with
5463    | GPLv2plus ->
5464        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5465        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5466        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5467        pr "%s (at your option) any later version.\n" c;
5468        pr "%s\n" c;
5469        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5470        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5471        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5472        pr "%s GNU General Public License for more details.\n" c;
5473        pr "%s\n" c;
5474        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5475        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5476        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5477
5478    | LGPLv2plus ->
5479        pr "%s This library is free software; you can redistribute it and/or\n" c;
5480        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5481        pr "%s License as published by the Free Software Foundation; either\n" c;
5482        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5483        pr "%s\n" c;
5484        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5485        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5486        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5487        pr "%s Lesser General Public License for more details.\n" c;
5488        pr "%s\n" c;
5489        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5490        pr "%s License along with this library; if not, write to the Free Software\n" c;
5491        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5492   );
5493   (match comment with
5494    | CStyle -> pr " */\n"
5495    | CPlusPlusStyle
5496    | HashStyle -> ()
5497    | OCamlStyle -> pr " *)\n"
5498    | HaskellStyle -> pr "-}\n"
5499   );
5500   pr "\n"
5501
5502 (* Start of main code generation functions below this line. *)
5503
5504 (* Generate the pod documentation for the C API. *)
5505 let rec generate_actions_pod () =
5506   List.iter (
5507     fun (shortname, style, _, flags, _, _, longdesc) ->
5508       if not (List.mem NotInDocs flags) then (
5509         let name = "guestfs_" ^ shortname in
5510         pr "=head2 %s\n\n" name;
5511         pr " ";
5512         generate_prototype ~extern:false ~handle:"g" name style;
5513         pr "\n\n";
5514         pr "%s\n\n" longdesc;
5515         (match fst style with
5516          | RErr ->
5517              pr "This function returns 0 on success or -1 on error.\n\n"
5518          | RInt _ ->
5519              pr "On error this function returns -1.\n\n"
5520          | RInt64 _ ->
5521              pr "On error this function returns -1.\n\n"
5522          | RBool _ ->
5523              pr "This function returns a C truth value on success or -1 on error.\n\n"
5524          | RConstString _ ->
5525              pr "This function returns a string, or NULL on error.
5526 The string is owned by the guest handle and must I<not> be freed.\n\n"
5527          | RConstOptString _ ->
5528              pr "This function returns a string which may be NULL.
5529 There is way to return an error from this function.
5530 The string is owned by the guest handle and must I<not> be freed.\n\n"
5531          | RString _ ->
5532              pr "This function returns a string, or NULL on error.
5533 I<The caller must free the returned string after use>.\n\n"
5534          | RStringList _ ->
5535              pr "This function returns a NULL-terminated array of strings
5536 (like L<environ(3)>), or NULL if there was an error.
5537 I<The caller must free the strings and the array after use>.\n\n"
5538          | RStruct (_, typ) ->
5539              pr "This function returns a C<struct guestfs_%s *>,
5540 or NULL if there was an error.
5541 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5542          | RStructList (_, typ) ->
5543              pr "This function returns a C<struct guestfs_%s_list *>
5544 (see E<lt>guestfs-structs.hE<gt>),
5545 or NULL if there was an error.
5546 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5547          | RHashtable _ ->
5548              pr "This function returns a NULL-terminated array of
5549 strings, or NULL if there was an error.
5550 The array of strings will always have length C<2n+1>, where
5551 C<n> keys and values alternate, followed by the trailing NULL entry.
5552 I<The caller must free the strings and the array after use>.\n\n"
5553          | RBufferOut _ ->
5554              pr "This function returns a buffer, or NULL on error.
5555 The size of the returned buffer is written to C<*size_r>.
5556 I<The caller must free the returned buffer after use>.\n\n"
5557         );
5558         if List.mem ProtocolLimitWarning flags then
5559           pr "%s\n\n" protocol_limit_warning;
5560         if List.mem DangerWillRobinson flags then
5561           pr "%s\n\n" danger_will_robinson;
5562         match deprecation_notice flags with
5563         | None -> ()
5564         | Some txt -> pr "%s\n\n" txt
5565       )
5566   ) all_functions_sorted
5567
5568 and generate_structs_pod () =
5569   (* Structs documentation. *)
5570   List.iter (
5571     fun (typ, cols) ->
5572       pr "=head2 guestfs_%s\n" typ;
5573       pr "\n";
5574       pr " struct guestfs_%s {\n" typ;
5575       List.iter (
5576         function
5577         | name, FChar -> pr "   char %s;\n" name
5578         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5579         | name, FInt32 -> pr "   int32_t %s;\n" name
5580         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5581         | name, FInt64 -> pr "   int64_t %s;\n" name
5582         | name, FString -> pr "   char *%s;\n" name
5583         | name, FBuffer ->
5584             pr "   /* The next two fields describe a byte array. */\n";
5585             pr "   uint32_t %s_len;\n" name;
5586             pr "   char *%s;\n" name
5587         | name, FUUID ->
5588             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5589             pr "   char %s[32];\n" name
5590         | name, FOptPercent ->
5591             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5592             pr "   float %s;\n" name
5593       ) cols;
5594       pr " };\n";
5595       pr " \n";
5596       pr " struct guestfs_%s_list {\n" typ;
5597       pr "   uint32_t len; /* Number of elements in list. */\n";
5598       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5599       pr " };\n";
5600       pr " \n";
5601       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5602       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5603         typ typ;
5604       pr "\n"
5605   ) structs
5606
5607 and generate_availability_pod () =
5608   (* Availability documentation. *)
5609   pr "=over 4\n";
5610   pr "\n";
5611   List.iter (
5612     fun (group, functions) ->
5613       pr "=item B<%s>\n" group;
5614       pr "\n";
5615       pr "The following functions:\n";
5616       List.iter (pr "L</guestfs_%s>\n") functions;
5617       pr "\n"
5618   ) optgroups;
5619   pr "=back\n";
5620   pr "\n"
5621
5622 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5623  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5624  *
5625  * We have to use an underscore instead of a dash because otherwise
5626  * rpcgen generates incorrect code.
5627  *
5628  * This header is NOT exported to clients, but see also generate_structs_h.
5629  *)
5630 and generate_xdr () =
5631   generate_header CStyle LGPLv2plus;
5632
5633   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5634   pr "typedef string str<>;\n";
5635   pr "\n";
5636
5637   (* Internal structures. *)
5638   List.iter (
5639     function
5640     | typ, cols ->
5641         pr "struct guestfs_int_%s {\n" typ;
5642         List.iter (function
5643                    | name, FChar -> pr "  char %s;\n" name
5644                    | name, FString -> pr "  string %s<>;\n" name
5645                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5646                    | name, FUUID -> pr "  opaque %s[32];\n" name
5647                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5648                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5649                    | name, FOptPercent -> pr "  float %s;\n" name
5650                   ) cols;
5651         pr "};\n";
5652         pr "\n";
5653         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5654         pr "\n";
5655   ) structs;
5656
5657   List.iter (
5658     fun (shortname, style, _, _, _, _, _) ->
5659       let name = "guestfs_" ^ shortname in
5660
5661       (match snd style with
5662        | [] -> ()
5663        | args ->
5664            pr "struct %s_args {\n" name;
5665            List.iter (
5666              function
5667              | Pathname n | Device n | Dev_or_Path n | String n ->
5668                  pr "  string %s<>;\n" n
5669              | OptString n -> pr "  str *%s;\n" n
5670              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5671              | Bool n -> pr "  bool %s;\n" n
5672              | Int n -> pr "  int %s;\n" n
5673              | Int64 n -> pr "  hyper %s;\n" n
5674              | BufferIn n ->
5675                  pr "  opaque %s<>;\n" n
5676              | FileIn _ | FileOut _ -> ()
5677            ) args;
5678            pr "};\n\n"
5679       );
5680       (match fst style with
5681        | RErr -> ()
5682        | RInt n ->
5683            pr "struct %s_ret {\n" name;
5684            pr "  int %s;\n" n;
5685            pr "};\n\n"
5686        | RInt64 n ->
5687            pr "struct %s_ret {\n" name;
5688            pr "  hyper %s;\n" n;
5689            pr "};\n\n"
5690        | RBool n ->
5691            pr "struct %s_ret {\n" name;
5692            pr "  bool %s;\n" n;
5693            pr "};\n\n"
5694        | RConstString _ | RConstOptString _ ->
5695            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5696        | RString n ->
5697            pr "struct %s_ret {\n" name;
5698            pr "  string %s<>;\n" n;
5699            pr "};\n\n"
5700        | RStringList n ->
5701            pr "struct %s_ret {\n" name;
5702            pr "  str %s<>;\n" n;
5703            pr "};\n\n"
5704        | RStruct (n, typ) ->
5705            pr "struct %s_ret {\n" name;
5706            pr "  guestfs_int_%s %s;\n" typ n;
5707            pr "};\n\n"
5708        | RStructList (n, typ) ->
5709            pr "struct %s_ret {\n" name;
5710            pr "  guestfs_int_%s_list %s;\n" typ n;
5711            pr "};\n\n"
5712        | RHashtable n ->
5713            pr "struct %s_ret {\n" name;
5714            pr "  str %s<>;\n" n;
5715            pr "};\n\n"
5716        | RBufferOut n ->
5717            pr "struct %s_ret {\n" name;
5718            pr "  opaque %s<>;\n" n;
5719            pr "};\n\n"
5720       );
5721   ) daemon_functions;
5722
5723   (* Table of procedure numbers. *)
5724   pr "enum guestfs_procedure {\n";
5725   List.iter (
5726     fun (shortname, _, proc_nr, _, _, _, _) ->
5727       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5728   ) daemon_functions;
5729   pr "  GUESTFS_PROC_NR_PROCS\n";
5730   pr "};\n";
5731   pr "\n";
5732
5733   (* Having to choose a maximum message size is annoying for several
5734    * reasons (it limits what we can do in the API), but it (a) makes
5735    * the protocol a lot simpler, and (b) provides a bound on the size
5736    * of the daemon which operates in limited memory space.
5737    *)
5738   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5739   pr "\n";
5740
5741   (* Message header, etc. *)
5742   pr "\
5743 /* The communication protocol is now documented in the guestfs(3)
5744  * manpage.
5745  */
5746
5747 const GUESTFS_PROGRAM = 0x2000F5F5;
5748 const GUESTFS_PROTOCOL_VERSION = 1;
5749
5750 /* These constants must be larger than any possible message length. */
5751 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5752 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5753
5754 enum guestfs_message_direction {
5755   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5756   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5757 };
5758
5759 enum guestfs_message_status {
5760   GUESTFS_STATUS_OK = 0,
5761   GUESTFS_STATUS_ERROR = 1
5762 };
5763
5764 const GUESTFS_ERROR_LEN = 256;
5765
5766 struct guestfs_message_error {
5767   string error_message<GUESTFS_ERROR_LEN>;
5768 };
5769
5770 struct guestfs_message_header {
5771   unsigned prog;                     /* GUESTFS_PROGRAM */
5772   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5773   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5774   guestfs_message_direction direction;
5775   unsigned serial;                   /* message serial number */
5776   guestfs_message_status status;
5777 };
5778
5779 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5780
5781 struct guestfs_chunk {
5782   int cancel;                        /* if non-zero, transfer is cancelled */
5783   /* data size is 0 bytes if the transfer has finished successfully */
5784   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5785 };
5786 "
5787
5788 (* Generate the guestfs-structs.h file. *)
5789 and generate_structs_h () =
5790   generate_header CStyle LGPLv2plus;
5791
5792   (* This is a public exported header file containing various
5793    * structures.  The structures are carefully written to have
5794    * exactly the same in-memory format as the XDR structures that
5795    * we use on the wire to the daemon.  The reason for creating
5796    * copies of these structures here is just so we don't have to
5797    * export the whole of guestfs_protocol.h (which includes much
5798    * unrelated and XDR-dependent stuff that we don't want to be
5799    * public, or required by clients).
5800    *
5801    * To reiterate, we will pass these structures to and from the
5802    * client with a simple assignment or memcpy, so the format
5803    * must be identical to what rpcgen / the RFC defines.
5804    *)
5805
5806   (* Public structures. *)
5807   List.iter (
5808     fun (typ, cols) ->
5809       pr "struct guestfs_%s {\n" typ;
5810       List.iter (
5811         function
5812         | name, FChar -> pr "  char %s;\n" name
5813         | name, FString -> pr "  char *%s;\n" name
5814         | name, FBuffer ->
5815             pr "  uint32_t %s_len;\n" name;
5816             pr "  char *%s;\n" name
5817         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5818         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5819         | name, FInt32 -> pr "  int32_t %s;\n" name
5820         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5821         | name, FInt64 -> pr "  int64_t %s;\n" name
5822         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5823       ) cols;
5824       pr "};\n";
5825       pr "\n";
5826       pr "struct guestfs_%s_list {\n" typ;
5827       pr "  uint32_t len;\n";
5828       pr "  struct guestfs_%s *val;\n" typ;
5829       pr "};\n";
5830       pr "\n";
5831       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5832       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5833       pr "\n"
5834   ) structs
5835
5836 (* Generate the guestfs-actions.h file. *)
5837 and generate_actions_h () =
5838   generate_header CStyle LGPLv2plus;
5839   List.iter (
5840     fun (shortname, style, _, _, _, _, _) ->
5841       let name = "guestfs_" ^ shortname in
5842       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5843         name style
5844   ) all_functions
5845
5846 (* Generate the guestfs-internal-actions.h file. *)
5847 and generate_internal_actions_h () =
5848   generate_header CStyle LGPLv2plus;
5849   List.iter (
5850     fun (shortname, style, _, _, _, _, _) ->
5851       let name = "guestfs__" ^ shortname in
5852       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5853         name style
5854   ) non_daemon_functions
5855
5856 (* Generate the client-side dispatch stubs. *)
5857 and generate_client_actions () =
5858   generate_header CStyle LGPLv2plus;
5859
5860   pr "\
5861 #include <stdio.h>
5862 #include <stdlib.h>
5863 #include <stdint.h>
5864 #include <string.h>
5865 #include <inttypes.h>
5866
5867 #include \"guestfs.h\"
5868 #include \"guestfs-internal.h\"
5869 #include \"guestfs-internal-actions.h\"
5870 #include \"guestfs_protocol.h\"
5871
5872 #define error guestfs_error
5873 //#define perrorf guestfs_perrorf
5874 #define safe_malloc guestfs_safe_malloc
5875 #define safe_realloc guestfs_safe_realloc
5876 //#define safe_strdup guestfs_safe_strdup
5877 #define safe_memdup guestfs_safe_memdup
5878
5879 /* Check the return message from a call for validity. */
5880 static int
5881 check_reply_header (guestfs_h *g,
5882                     const struct guestfs_message_header *hdr,
5883                     unsigned int proc_nr, unsigned int serial)
5884 {
5885   if (hdr->prog != GUESTFS_PROGRAM) {
5886     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5887     return -1;
5888   }
5889   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5890     error (g, \"wrong protocol version (%%d/%%d)\",
5891            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5892     return -1;
5893   }
5894   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5895     error (g, \"unexpected message direction (%%d/%%d)\",
5896            hdr->direction, GUESTFS_DIRECTION_REPLY);
5897     return -1;
5898   }
5899   if (hdr->proc != proc_nr) {
5900     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5901     return -1;
5902   }
5903   if (hdr->serial != serial) {
5904     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5905     return -1;
5906   }
5907
5908   return 0;
5909 }
5910
5911 /* Check we are in the right state to run a high-level action. */
5912 static int
5913 check_state (guestfs_h *g, const char *caller)
5914 {
5915   if (!guestfs__is_ready (g)) {
5916     if (guestfs__is_config (g) || guestfs__is_launching (g))
5917       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5918         caller);
5919     else
5920       error (g, \"%%s called from the wrong state, %%d != READY\",
5921         caller, guestfs__get_state (g));
5922     return -1;
5923   }
5924   return 0;
5925 }
5926
5927 ";
5928
5929   let error_code_of = function
5930     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5931     | RConstString _ | RConstOptString _
5932     | RString _ | RStringList _
5933     | RStruct _ | RStructList _
5934     | RHashtable _ | RBufferOut _ -> "NULL"
5935   in
5936
5937   (* Generate code to check String-like parameters are not passed in
5938    * as NULL (returning an error if they are).
5939    *)
5940   let check_null_strings shortname style =
5941     let pr_newline = ref false in
5942     List.iter (
5943       function
5944       (* parameters which should not be NULL *)
5945       | String n
5946       | Device n
5947       | Pathname n
5948       | Dev_or_Path n
5949       | FileIn n
5950       | FileOut n
5951       | BufferIn n
5952       | StringList n
5953       | DeviceList n ->
5954           pr "  if (%s == NULL) {\n" n;
5955           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5956           pr "           \"%s\", \"%s\");\n" shortname n;
5957           pr "    return %s;\n" (error_code_of (fst style));
5958           pr "  }\n";
5959           pr_newline := true
5960
5961       (* can be NULL *)
5962       | OptString _
5963
5964       (* not applicable *)
5965       | Bool _
5966       | Int _
5967       | Int64 _ -> ()
5968     ) (snd style);
5969
5970     if !pr_newline then pr "\n";
5971   in
5972
5973   (* Generate code to generate guestfish call traces. *)
5974   let trace_call shortname style =
5975     pr "  if (guestfs__get_trace (g)) {\n";
5976
5977     let needs_i =
5978       List.exists (function
5979                    | StringList _ | DeviceList _ -> true
5980                    | _ -> false) (snd style) in
5981     if needs_i then (
5982       pr "    int i;\n";
5983       pr "\n"
5984     );
5985
5986     pr "    printf (\"%s\");\n" shortname;
5987     List.iter (
5988       function
5989       | String n                        (* strings *)
5990       | Device n
5991       | Pathname n
5992       | Dev_or_Path n
5993       | FileIn n
5994       | FileOut n
5995       | BufferIn n ->
5996           (* guestfish doesn't support string escaping, so neither do we *)
5997           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5998       | OptString n ->                  (* string option *)
5999           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6000           pr "    else printf (\" null\");\n"
6001       | StringList n
6002       | DeviceList n ->                 (* string list *)
6003           pr "    putchar (' ');\n";
6004           pr "    putchar ('\"');\n";
6005           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6006           pr "      if (i > 0) putchar (' ');\n";
6007           pr "      fputs (%s[i], stdout);\n" n;
6008           pr "    }\n";
6009           pr "    putchar ('\"');\n";
6010       | Bool n ->                       (* boolean *)
6011           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6012       | Int n ->                        (* int *)
6013           pr "    printf (\" %%d\", %s);\n" n
6014       | Int64 n ->
6015           pr "    printf (\" %%\" PRIi64, %s);\n" n
6016     ) (snd style);
6017     pr "    putchar ('\\n');\n";
6018     pr "  }\n";
6019     pr "\n";
6020   in
6021
6022   (* For non-daemon functions, generate a wrapper around each function. *)
6023   List.iter (
6024     fun (shortname, style, _, _, _, _, _) ->
6025       let name = "guestfs_" ^ shortname in
6026
6027       generate_prototype ~extern:false ~semicolon:false ~newline:true
6028         ~handle:"g" name style;
6029       pr "{\n";
6030       check_null_strings shortname style;
6031       trace_call shortname style;
6032       pr "  return guestfs__%s " shortname;
6033       generate_c_call_args ~handle:"g" style;
6034       pr ";\n";
6035       pr "}\n";
6036       pr "\n"
6037   ) non_daemon_functions;
6038
6039   (* Client-side stubs for each function. *)
6040   List.iter (
6041     fun (shortname, style, _, _, _, _, _) ->
6042       let name = "guestfs_" ^ shortname in
6043       let error_code = error_code_of (fst style) in
6044
6045       (* Generate the action stub. *)
6046       generate_prototype ~extern:false ~semicolon:false ~newline:true
6047         ~handle:"g" name style;
6048
6049       pr "{\n";
6050
6051       (match snd style with
6052        | [] -> ()
6053        | _ -> pr "  struct %s_args args;\n" name
6054       );
6055
6056       pr "  guestfs_message_header hdr;\n";
6057       pr "  guestfs_message_error err;\n";
6058       let has_ret =
6059         match fst style with
6060         | RErr -> false
6061         | RConstString _ | RConstOptString _ ->
6062             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6063         | RInt _ | RInt64 _
6064         | RBool _ | RString _ | RStringList _
6065         | RStruct _ | RStructList _
6066         | RHashtable _ | RBufferOut _ ->
6067             pr "  struct %s_ret ret;\n" name;
6068             true in
6069
6070       pr "  int serial;\n";
6071       pr "  int r;\n";
6072       pr "\n";
6073       check_null_strings shortname style;
6074       trace_call shortname style;
6075       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6076         shortname error_code;
6077       pr "  guestfs___set_busy (g);\n";
6078       pr "\n";
6079
6080       (* Send the main header and arguments. *)
6081       (match snd style with
6082        | [] ->
6083            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6084              (String.uppercase shortname)
6085        | args ->
6086            List.iter (
6087              function
6088              | Pathname n | Device n | Dev_or_Path n | String n ->
6089                  pr "  args.%s = (char *) %s;\n" n n
6090              | OptString n ->
6091                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6092              | StringList n | DeviceList n ->
6093                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6094                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6095              | Bool n ->
6096                  pr "  args.%s = %s;\n" n n
6097              | Int n ->
6098                  pr "  args.%s = %s;\n" n n
6099              | Int64 n ->
6100                  pr "  args.%s = %s;\n" n n
6101              | FileIn _ | FileOut _ -> ()
6102              | BufferIn n ->
6103                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6104                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6105                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6106                    shortname;
6107                  pr "    guestfs___end_busy (g);\n";
6108                  pr "    return %s;\n" error_code;
6109                  pr "  }\n";
6110                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6111                  pr "  args.%s.%s_len = %s_size;\n" n n n
6112            ) args;
6113            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6114              (String.uppercase shortname);
6115            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6116              name;
6117       );
6118       pr "  if (serial == -1) {\n";
6119       pr "    guestfs___end_busy (g);\n";
6120       pr "    return %s;\n" error_code;
6121       pr "  }\n";
6122       pr "\n";
6123
6124       (* Send any additional files (FileIn) requested. *)
6125       let need_read_reply_label = ref false in
6126       List.iter (
6127         function
6128         | FileIn n ->
6129             pr "  r = guestfs___send_file (g, %s);\n" n;
6130             pr "  if (r == -1) {\n";
6131             pr "    guestfs___end_busy (g);\n";
6132             pr "    return %s;\n" error_code;
6133             pr "  }\n";
6134             pr "  if (r == -2) /* daemon cancelled */\n";
6135             pr "    goto read_reply;\n";
6136             need_read_reply_label := true;
6137             pr "\n";
6138         | _ -> ()
6139       ) (snd style);
6140
6141       (* Wait for the reply from the remote end. *)
6142       if !need_read_reply_label then pr " read_reply:\n";
6143       pr "  memset (&hdr, 0, sizeof hdr);\n";
6144       pr "  memset (&err, 0, sizeof err);\n";
6145       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6146       pr "\n";
6147       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6148       if not has_ret then
6149         pr "NULL, NULL"
6150       else
6151         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6152       pr ");\n";
6153
6154       pr "  if (r == -1) {\n";
6155       pr "    guestfs___end_busy (g);\n";
6156       pr "    return %s;\n" error_code;
6157       pr "  }\n";
6158       pr "\n";
6159
6160       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6161         (String.uppercase shortname);
6162       pr "    guestfs___end_busy (g);\n";
6163       pr "    return %s;\n" error_code;
6164       pr "  }\n";
6165       pr "\n";
6166
6167       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6168       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6169       pr "    free (err.error_message);\n";
6170       pr "    guestfs___end_busy (g);\n";
6171       pr "    return %s;\n" error_code;
6172       pr "  }\n";
6173       pr "\n";
6174
6175       (* Expecting to receive further files (FileOut)? *)
6176       List.iter (
6177         function
6178         | FileOut n ->
6179             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6180             pr "    guestfs___end_busy (g);\n";
6181             pr "    return %s;\n" error_code;
6182             pr "  }\n";
6183             pr "\n";
6184         | _ -> ()
6185       ) (snd style);
6186
6187       pr "  guestfs___end_busy (g);\n";
6188
6189       (match fst style with
6190        | RErr -> pr "  return 0;\n"
6191        | RInt n | RInt64 n | RBool n ->
6192            pr "  return ret.%s;\n" n
6193        | RConstString _ | RConstOptString _ ->
6194            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6195        | RString n ->
6196            pr "  return ret.%s; /* caller will free */\n" n
6197        | RStringList n | RHashtable n ->
6198            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6199            pr "  ret.%s.%s_val =\n" n n;
6200            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6201            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6202              n n;
6203            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6204            pr "  return ret.%s.%s_val;\n" n n
6205        | RStruct (n, _) ->
6206            pr "  /* caller will free this */\n";
6207            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6208        | RStructList (n, _) ->
6209            pr "  /* caller will free this */\n";
6210            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6211        | RBufferOut n ->
6212            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6213            pr "   * _val might be NULL here.  To make the API saner for\n";
6214            pr "   * callers, we turn this case into a unique pointer (using\n";
6215            pr "   * malloc(1)).\n";
6216            pr "   */\n";
6217            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6218            pr "    *size_r = ret.%s.%s_len;\n" n n;
6219            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6220            pr "  } else {\n";
6221            pr "    free (ret.%s.%s_val);\n" n n;
6222            pr "    char *p = safe_malloc (g, 1);\n";
6223            pr "    *size_r = ret.%s.%s_len;\n" n n;
6224            pr "    return p;\n";
6225            pr "  }\n";
6226       );
6227
6228       pr "}\n\n"
6229   ) daemon_functions;
6230
6231   (* Functions to free structures. *)
6232   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6233   pr " * structure format is identical to the XDR format.  See note in\n";
6234   pr " * generator.ml.\n";
6235   pr " */\n";
6236   pr "\n";
6237
6238   List.iter (
6239     fun (typ, _) ->
6240       pr "void\n";
6241       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6242       pr "{\n";
6243       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6244       pr "  free (x);\n";
6245       pr "}\n";
6246       pr "\n";
6247
6248       pr "void\n";
6249       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6250       pr "{\n";
6251       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6252       pr "  free (x);\n";
6253       pr "}\n";
6254       pr "\n";
6255
6256   ) structs;
6257
6258 (* Generate daemon/actions.h. *)
6259 and generate_daemon_actions_h () =
6260   generate_header CStyle GPLv2plus;
6261
6262   pr "#include \"../src/guestfs_protocol.h\"\n";
6263   pr "\n";
6264
6265   List.iter (
6266     fun (name, style, _, _, _, _, _) ->
6267       generate_prototype
6268         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6269         name style;
6270   ) daemon_functions
6271
6272 (* Generate the linker script which controls the visibility of
6273  * symbols in the public ABI and ensures no other symbols get
6274  * exported accidentally.
6275  *)
6276 and generate_linker_script () =
6277   generate_header HashStyle GPLv2plus;
6278
6279   let globals = [
6280     "guestfs_create";
6281     "guestfs_close";
6282     "guestfs_get_error_handler";
6283     "guestfs_get_out_of_memory_handler";
6284     "guestfs_last_error";
6285     "guestfs_set_error_handler";
6286     "guestfs_set_launch_done_callback";
6287     "guestfs_set_log_message_callback";
6288     "guestfs_set_out_of_memory_handler";
6289     "guestfs_set_subprocess_quit_callback";
6290
6291     (* Unofficial parts of the API: the bindings code use these
6292      * functions, so it is useful to export them.
6293      *)
6294     "guestfs_safe_calloc";
6295     "guestfs_safe_malloc";
6296   ] in
6297   let functions =
6298     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6299       all_functions in
6300   let structs =
6301     List.concat (
6302       List.map (fun (typ, _) ->
6303                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6304         structs
6305     ) in
6306   let globals = List.sort compare (globals @ functions @ structs) in
6307
6308   pr "{\n";
6309   pr "    global:\n";
6310   List.iter (pr "        %s;\n") globals;
6311   pr "\n";
6312
6313   pr "    local:\n";
6314   pr "        *;\n";
6315   pr "};\n"
6316
6317 (* Generate the server-side stubs. *)
6318 and generate_daemon_actions () =
6319   generate_header CStyle GPLv2plus;
6320
6321   pr "#include <config.h>\n";
6322   pr "\n";
6323   pr "#include <stdio.h>\n";
6324   pr "#include <stdlib.h>\n";
6325   pr "#include <string.h>\n";
6326   pr "#include <inttypes.h>\n";
6327   pr "#include <rpc/types.h>\n";
6328   pr "#include <rpc/xdr.h>\n";
6329   pr "\n";
6330   pr "#include \"daemon.h\"\n";
6331   pr "#include \"c-ctype.h\"\n";
6332   pr "#include \"../src/guestfs_protocol.h\"\n";
6333   pr "#include \"actions.h\"\n";
6334   pr "\n";
6335
6336   List.iter (
6337     fun (name, style, _, _, _, _, _) ->
6338       (* Generate server-side stubs. *)
6339       pr "static void %s_stub (XDR *xdr_in)\n" name;
6340       pr "{\n";
6341       let error_code =
6342         match fst style with
6343         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6344         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6345         | RBool _ -> pr "  int r;\n"; "-1"
6346         | RConstString _ | RConstOptString _ ->
6347             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6348         | RString _ -> pr "  char *r;\n"; "NULL"
6349         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6350         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6351         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6352         | RBufferOut _ ->
6353             pr "  size_t size = 1;\n";
6354             pr "  char *r;\n";
6355             "NULL" in
6356
6357       (match snd style with
6358        | [] -> ()
6359        | args ->
6360            pr "  struct guestfs_%s_args args;\n" name;
6361            List.iter (
6362              function
6363              | Device n | Dev_or_Path n
6364              | Pathname n
6365              | String n -> ()
6366              | OptString n -> pr "  char *%s;\n" n
6367              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6368              | Bool n -> pr "  int %s;\n" n
6369              | Int n -> pr "  int %s;\n" n
6370              | Int64 n -> pr "  int64_t %s;\n" n
6371              | FileIn _ | FileOut _ -> ()
6372              | BufferIn n ->
6373                  pr "  const char *%s;\n" n;
6374                  pr "  size_t %s_size;\n" n
6375            ) args
6376       );
6377       pr "\n";
6378
6379       let is_filein =
6380         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6381
6382       (match snd style with
6383        | [] -> ()
6384        | args ->
6385            pr "  memset (&args, 0, sizeof args);\n";
6386            pr "\n";
6387            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6388            if is_filein then
6389              pr "    if (cancel_receive () != -2)\n";
6390            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6391            pr "    goto done;\n";
6392            pr "  }\n";
6393            let pr_args n =
6394              pr "  char *%s = args.%s;\n" n n
6395            in
6396            let pr_list_handling_code n =
6397              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6398              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6399              pr "  if (%s == NULL) {\n" n;
6400              if is_filein then
6401                pr "    if (cancel_receive () != -2)\n";
6402              pr "      reply_with_perror (\"realloc\");\n";
6403              pr "    goto done;\n";
6404              pr "  }\n";
6405              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6406              pr "  args.%s.%s_val = %s;\n" n n n;
6407            in
6408            List.iter (
6409              function
6410              | Pathname n ->
6411                  pr_args n;
6412                  pr "  ABS_PATH (%s, %s, goto done);\n"
6413                    n (if is_filein then "cancel_receive ()" else "0");
6414              | Device n ->
6415                  pr_args n;
6416                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6417                    n (if is_filein then "cancel_receive ()" else "0");
6418              | Dev_or_Path n ->
6419                  pr_args n;
6420                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6421                    n (if is_filein then "cancel_receive ()" else "0");
6422              | String n -> pr_args n
6423              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6424              | StringList n ->
6425                  pr_list_handling_code n;
6426              | DeviceList n ->
6427                  pr_list_handling_code n;
6428                  pr "  /* Ensure that each is a device,\n";
6429                  pr "   * and perform device name translation. */\n";
6430                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6431                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6432                    (if is_filein then "cancel_receive ()" else "0");
6433                  pr "  }\n";
6434              | Bool n -> pr "  %s = args.%s;\n" n n
6435              | Int n -> pr "  %s = args.%s;\n" n n
6436              | Int64 n -> pr "  %s = args.%s;\n" n n
6437              | FileIn _ | FileOut _ -> ()
6438              | BufferIn n ->
6439                  pr "  %s = args.%s.%s_val;\n" n n n;
6440                  pr "  %s_size = args.%s.%s_len;\n" n n n
6441            ) args;
6442            pr "\n"
6443       );
6444
6445       (* this is used at least for do_equal *)
6446       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6447         (* Emit NEED_ROOT just once, even when there are two or
6448            more Pathname args *)
6449         pr "  NEED_ROOT (%s, goto done);\n"
6450           (if is_filein then "cancel_receive ()" else "0");
6451       );
6452
6453       (* Don't want to call the impl with any FileIn or FileOut
6454        * parameters, since these go "outside" the RPC protocol.
6455        *)
6456       let args' =
6457         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6458           (snd style) in
6459       pr "  r = do_%s " name;
6460       generate_c_call_args (fst style, args');
6461       pr ";\n";
6462
6463       (match fst style with
6464        | RErr | RInt _ | RInt64 _ | RBool _
6465        | RConstString _ | RConstOptString _
6466        | RString _ | RStringList _ | RHashtable _
6467        | RStruct (_, _) | RStructList (_, _) ->
6468            pr "  if (r == %s)\n" error_code;
6469            pr "    /* do_%s has already called reply_with_error */\n" name;
6470            pr "    goto done;\n";
6471            pr "\n"
6472        | RBufferOut _ ->
6473            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6474            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6475            pr "   */\n";
6476            pr "  if (size == 1 && r == %s)\n" error_code;
6477            pr "    /* do_%s has already called reply_with_error */\n" name;
6478            pr "    goto done;\n";
6479            pr "\n"
6480       );
6481
6482       (* If there are any FileOut parameters, then the impl must
6483        * send its own reply.
6484        *)
6485       let no_reply =
6486         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6487       if no_reply then
6488         pr "  /* do_%s has already sent a reply */\n" name
6489       else (
6490         match fst style with
6491         | RErr -> pr "  reply (NULL, NULL);\n"
6492         | RInt n | RInt64 n | RBool n ->
6493             pr "  struct guestfs_%s_ret ret;\n" name;
6494             pr "  ret.%s = r;\n" n;
6495             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6496               name
6497         | RConstString _ | RConstOptString _ ->
6498             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6499         | RString n ->
6500             pr "  struct guestfs_%s_ret ret;\n" name;
6501             pr "  ret.%s = r;\n" n;
6502             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6503               name;
6504             pr "  free (r);\n"
6505         | RStringList n | RHashtable n ->
6506             pr "  struct guestfs_%s_ret ret;\n" name;
6507             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6508             pr "  ret.%s.%s_val = r;\n" n n;
6509             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6510               name;
6511             pr "  free_strings (r);\n"
6512         | RStruct (n, _) ->
6513             pr "  struct guestfs_%s_ret ret;\n" name;
6514             pr "  ret.%s = *r;\n" n;
6515             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6516               name;
6517             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6518               name
6519         | RStructList (n, _) ->
6520             pr "  struct guestfs_%s_ret ret;\n" name;
6521             pr "  ret.%s = *r;\n" n;
6522             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6523               name;
6524             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6525               name
6526         | RBufferOut n ->
6527             pr "  struct guestfs_%s_ret ret;\n" name;
6528             pr "  ret.%s.%s_val = r;\n" n n;
6529             pr "  ret.%s.%s_len = size;\n" n n;
6530             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6531               name;
6532             pr "  free (r);\n"
6533       );
6534
6535       (* Free the args. *)
6536       pr "done:\n";
6537       (match snd style with
6538        | [] -> ()
6539        | _ ->
6540            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6541              name
6542       );
6543       pr "  return;\n";
6544       pr "}\n\n";
6545   ) daemon_functions;
6546
6547   (* Dispatch function. *)
6548   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6549   pr "{\n";
6550   pr "  switch (proc_nr) {\n";
6551
6552   List.iter (
6553     fun (name, style, _, _, _, _, _) ->
6554       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6555       pr "      %s_stub (xdr_in);\n" name;
6556       pr "      break;\n"
6557   ) daemon_functions;
6558
6559   pr "    default:\n";
6560   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";
6561   pr "  }\n";
6562   pr "}\n";
6563   pr "\n";
6564
6565   (* LVM columns and tokenization functions. *)
6566   (* XXX This generates crap code.  We should rethink how we
6567    * do this parsing.
6568    *)
6569   List.iter (
6570     function
6571     | typ, cols ->
6572         pr "static const char *lvm_%s_cols = \"%s\";\n"
6573           typ (String.concat "," (List.map fst cols));
6574         pr "\n";
6575
6576         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6577         pr "{\n";
6578         pr "  char *tok, *p, *next;\n";
6579         pr "  int i, j;\n";
6580         pr "\n";
6581         (*
6582           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6583           pr "\n";
6584         *)
6585         pr "  if (!str) {\n";
6586         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6587         pr "    return -1;\n";
6588         pr "  }\n";
6589         pr "  if (!*str || c_isspace (*str)) {\n";
6590         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6591         pr "    return -1;\n";
6592         pr "  }\n";
6593         pr "  tok = str;\n";
6594         List.iter (
6595           fun (name, coltype) ->
6596             pr "  if (!tok) {\n";
6597             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6598             pr "    return -1;\n";
6599             pr "  }\n";
6600             pr "  p = strchrnul (tok, ',');\n";
6601             pr "  if (*p) next = p+1; else next = NULL;\n";
6602             pr "  *p = '\\0';\n";
6603             (match coltype with
6604              | FString ->
6605                  pr "  r->%s = strdup (tok);\n" name;
6606                  pr "  if (r->%s == NULL) {\n" name;
6607                  pr "    perror (\"strdup\");\n";
6608                  pr "    return -1;\n";
6609                  pr "  }\n"
6610              | FUUID ->
6611                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6612                  pr "    if (tok[j] == '\\0') {\n";
6613                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6614                  pr "      return -1;\n";
6615                  pr "    } else if (tok[j] != '-')\n";
6616                  pr "      r->%s[i++] = tok[j];\n" name;
6617                  pr "  }\n";
6618              | FBytes ->
6619                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6620                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6621                  pr "    return -1;\n";
6622                  pr "  }\n";
6623              | FInt64 ->
6624                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6625                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6626                  pr "    return -1;\n";
6627                  pr "  }\n";
6628              | FOptPercent ->
6629                  pr "  if (tok[0] == '\\0')\n";
6630                  pr "    r->%s = -1;\n" name;
6631                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6632                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6633                  pr "    return -1;\n";
6634                  pr "  }\n";
6635              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6636                  assert false (* can never be an LVM column *)
6637             );
6638             pr "  tok = next;\n";
6639         ) cols;
6640
6641         pr "  if (tok != NULL) {\n";
6642         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6643         pr "    return -1;\n";
6644         pr "  }\n";
6645         pr "  return 0;\n";
6646         pr "}\n";
6647         pr "\n";
6648
6649         pr "guestfs_int_lvm_%s_list *\n" typ;
6650         pr "parse_command_line_%ss (void)\n" typ;
6651         pr "{\n";
6652         pr "  char *out, *err;\n";
6653         pr "  char *p, *pend;\n";
6654         pr "  int r, i;\n";
6655         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6656         pr "  void *newp;\n";
6657         pr "\n";
6658         pr "  ret = malloc (sizeof *ret);\n";
6659         pr "  if (!ret) {\n";
6660         pr "    reply_with_perror (\"malloc\");\n";
6661         pr "    return NULL;\n";
6662         pr "  }\n";
6663         pr "\n";
6664         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6665         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6666         pr "\n";
6667         pr "  r = command (&out, &err,\n";
6668         pr "           \"lvm\", \"%ss\",\n" typ;
6669         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6670         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6671         pr "  if (r == -1) {\n";
6672         pr "    reply_with_error (\"%%s\", err);\n";
6673         pr "    free (out);\n";
6674         pr "    free (err);\n";
6675         pr "    free (ret);\n";
6676         pr "    return NULL;\n";
6677         pr "  }\n";
6678         pr "\n";
6679         pr "  free (err);\n";
6680         pr "\n";
6681         pr "  /* Tokenize each line of the output. */\n";
6682         pr "  p = out;\n";
6683         pr "  i = 0;\n";
6684         pr "  while (p) {\n";
6685         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6686         pr "    if (pend) {\n";
6687         pr "      *pend = '\\0';\n";
6688         pr "      pend++;\n";
6689         pr "    }\n";
6690         pr "\n";
6691         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6692         pr "      p++;\n";
6693         pr "\n";
6694         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6695         pr "      p = pend;\n";
6696         pr "      continue;\n";
6697         pr "    }\n";
6698         pr "\n";
6699         pr "    /* Allocate some space to store this next entry. */\n";
6700         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6701         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6702         pr "    if (newp == NULL) {\n";
6703         pr "      reply_with_perror (\"realloc\");\n";
6704         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6705         pr "      free (ret);\n";
6706         pr "      free (out);\n";
6707         pr "      return NULL;\n";
6708         pr "    }\n";
6709         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6710         pr "\n";
6711         pr "    /* Tokenize the next entry. */\n";
6712         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6713         pr "    if (r == -1) {\n";
6714         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6715         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6716         pr "      free (ret);\n";
6717         pr "      free (out);\n";
6718         pr "      return NULL;\n";
6719         pr "    }\n";
6720         pr "\n";
6721         pr "    ++i;\n";
6722         pr "    p = pend;\n";
6723         pr "  }\n";
6724         pr "\n";
6725         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6726         pr "\n";
6727         pr "  free (out);\n";
6728         pr "  return ret;\n";
6729         pr "}\n"
6730
6731   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6732
6733 (* Generate a list of function names, for debugging in the daemon.. *)
6734 and generate_daemon_names () =
6735   generate_header CStyle GPLv2plus;
6736
6737   pr "#include <config.h>\n";
6738   pr "\n";
6739   pr "#include \"daemon.h\"\n";
6740   pr "\n";
6741
6742   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6743   pr "const char *function_names[] = {\n";
6744   List.iter (
6745     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6746   ) daemon_functions;
6747   pr "};\n";
6748
6749 (* Generate the optional groups for the daemon to implement
6750  * guestfs_available.
6751  *)
6752 and generate_daemon_optgroups_c () =
6753   generate_header CStyle GPLv2plus;
6754
6755   pr "#include <config.h>\n";
6756   pr "\n";
6757   pr "#include \"daemon.h\"\n";
6758   pr "#include \"optgroups.h\"\n";
6759   pr "\n";
6760
6761   pr "struct optgroup optgroups[] = {\n";
6762   List.iter (
6763     fun (group, _) ->
6764       pr "  { \"%s\", optgroup_%s_available },\n" group group
6765   ) optgroups;
6766   pr "  { NULL, NULL }\n";
6767   pr "};\n"
6768
6769 and generate_daemon_optgroups_h () =
6770   generate_header CStyle GPLv2plus;
6771
6772   List.iter (
6773     fun (group, _) ->
6774       pr "extern int optgroup_%s_available (void);\n" group
6775   ) optgroups
6776
6777 (* Generate the tests. *)
6778 and generate_tests () =
6779   generate_header CStyle GPLv2plus;
6780
6781   pr "\
6782 #include <stdio.h>
6783 #include <stdlib.h>
6784 #include <string.h>
6785 #include <unistd.h>
6786 #include <sys/types.h>
6787 #include <fcntl.h>
6788
6789 #include \"guestfs.h\"
6790 #include \"guestfs-internal.h\"
6791
6792 static guestfs_h *g;
6793 static int suppress_error = 0;
6794
6795 static void print_error (guestfs_h *g, void *data, const char *msg)
6796 {
6797   if (!suppress_error)
6798     fprintf (stderr, \"%%s\\n\", msg);
6799 }
6800
6801 /* FIXME: nearly identical code appears in fish.c */
6802 static void print_strings (char *const *argv)
6803 {
6804   int argc;
6805
6806   for (argc = 0; argv[argc] != NULL; ++argc)
6807     printf (\"\\t%%s\\n\", argv[argc]);
6808 }
6809
6810 /*
6811 static void print_table (char const *const *argv)
6812 {
6813   int i;
6814
6815   for (i = 0; argv[i] != NULL; i += 2)
6816     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6817 }
6818 */
6819
6820 ";
6821
6822   (* Generate a list of commands which are not tested anywhere. *)
6823   pr "static void no_test_warnings (void)\n";
6824   pr "{\n";
6825
6826   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6827   List.iter (
6828     fun (_, _, _, _, tests, _, _) ->
6829       let tests = filter_map (
6830         function
6831         | (_, (Always|If _|Unless _), test) -> Some test
6832         | (_, Disabled, _) -> None
6833       ) tests in
6834       let seq = List.concat (List.map seq_of_test tests) in
6835       let cmds_tested = List.map List.hd seq in
6836       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6837   ) all_functions;
6838
6839   List.iter (
6840     fun (name, _, _, _, _, _, _) ->
6841       if not (Hashtbl.mem hash name) then
6842         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6843   ) all_functions;
6844
6845   pr "}\n";
6846   pr "\n";
6847
6848   (* Generate the actual tests.  Note that we generate the tests
6849    * in reverse order, deliberately, so that (in general) the
6850    * newest tests run first.  This makes it quicker and easier to
6851    * debug them.
6852    *)
6853   let test_names =
6854     List.map (
6855       fun (name, _, _, flags, tests, _, _) ->
6856         mapi (generate_one_test name flags) tests
6857     ) (List.rev all_functions) in
6858   let test_names = List.concat test_names in
6859   let nr_tests = List.length test_names in
6860
6861   pr "\
6862 int main (int argc, char *argv[])
6863 {
6864   char c = 0;
6865   unsigned long int n_failed = 0;
6866   const char *filename;
6867   int fd;
6868   int nr_tests, test_num = 0;
6869
6870   setbuf (stdout, NULL);
6871
6872   no_test_warnings ();
6873
6874   g = guestfs_create ();
6875   if (g == NULL) {
6876     printf (\"guestfs_create FAILED\\n\");
6877     exit (EXIT_FAILURE);
6878   }
6879
6880   guestfs_set_error_handler (g, print_error, NULL);
6881
6882   guestfs_set_path (g, \"../appliance\");
6883
6884   filename = \"test1.img\";
6885   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6886   if (fd == -1) {
6887     perror (filename);
6888     exit (EXIT_FAILURE);
6889   }
6890   if (lseek (fd, %d, SEEK_SET) == -1) {
6891     perror (\"lseek\");
6892     close (fd);
6893     unlink (filename);
6894     exit (EXIT_FAILURE);
6895   }
6896   if (write (fd, &c, 1) == -1) {
6897     perror (\"write\");
6898     close (fd);
6899     unlink (filename);
6900     exit (EXIT_FAILURE);
6901   }
6902   if (close (fd) == -1) {
6903     perror (filename);
6904     unlink (filename);
6905     exit (EXIT_FAILURE);
6906   }
6907   if (guestfs_add_drive (g, filename) == -1) {
6908     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6909     exit (EXIT_FAILURE);
6910   }
6911
6912   filename = \"test2.img\";
6913   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6914   if (fd == -1) {
6915     perror (filename);
6916     exit (EXIT_FAILURE);
6917   }
6918   if (lseek (fd, %d, SEEK_SET) == -1) {
6919     perror (\"lseek\");
6920     close (fd);
6921     unlink (filename);
6922     exit (EXIT_FAILURE);
6923   }
6924   if (write (fd, &c, 1) == -1) {
6925     perror (\"write\");
6926     close (fd);
6927     unlink (filename);
6928     exit (EXIT_FAILURE);
6929   }
6930   if (close (fd) == -1) {
6931     perror (filename);
6932     unlink (filename);
6933     exit (EXIT_FAILURE);
6934   }
6935   if (guestfs_add_drive (g, filename) == -1) {
6936     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6937     exit (EXIT_FAILURE);
6938   }
6939
6940   filename = \"test3.img\";
6941   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6942   if (fd == -1) {
6943     perror (filename);
6944     exit (EXIT_FAILURE);
6945   }
6946   if (lseek (fd, %d, SEEK_SET) == -1) {
6947     perror (\"lseek\");
6948     close (fd);
6949     unlink (filename);
6950     exit (EXIT_FAILURE);
6951   }
6952   if (write (fd, &c, 1) == -1) {
6953     perror (\"write\");
6954     close (fd);
6955     unlink (filename);
6956     exit (EXIT_FAILURE);
6957   }
6958   if (close (fd) == -1) {
6959     perror (filename);
6960     unlink (filename);
6961     exit (EXIT_FAILURE);
6962   }
6963   if (guestfs_add_drive (g, filename) == -1) {
6964     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6965     exit (EXIT_FAILURE);
6966   }
6967
6968   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6969     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6970     exit (EXIT_FAILURE);
6971   }
6972
6973   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6974   alarm (600);
6975
6976   if (guestfs_launch (g) == -1) {
6977     printf (\"guestfs_launch FAILED\\n\");
6978     exit (EXIT_FAILURE);
6979   }
6980
6981   /* Cancel previous alarm. */
6982   alarm (0);
6983
6984   nr_tests = %d;
6985
6986 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6987
6988   iteri (
6989     fun i test_name ->
6990       pr "  test_num++;\n";
6991       pr "  if (guestfs_get_verbose (g))\n";
6992       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6993       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6994       pr "  if (%s () == -1) {\n" test_name;
6995       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6996       pr "    n_failed++;\n";
6997       pr "  }\n";
6998   ) test_names;
6999   pr "\n";
7000
7001   pr "  guestfs_close (g);\n";
7002   pr "  unlink (\"test1.img\");\n";
7003   pr "  unlink (\"test2.img\");\n";
7004   pr "  unlink (\"test3.img\");\n";
7005   pr "\n";
7006
7007   pr "  if (n_failed > 0) {\n";
7008   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7009   pr "    exit (EXIT_FAILURE);\n";
7010   pr "  }\n";
7011   pr "\n";
7012
7013   pr "  exit (EXIT_SUCCESS);\n";
7014   pr "}\n"
7015
7016 and generate_one_test name flags i (init, prereq, test) =
7017   let test_name = sprintf "test_%s_%d" name i in
7018
7019   pr "\
7020 static int %s_skip (void)
7021 {
7022   const char *str;
7023
7024   str = getenv (\"TEST_ONLY\");
7025   if (str)
7026     return strstr (str, \"%s\") == NULL;
7027   str = getenv (\"SKIP_%s\");
7028   if (str && STREQ (str, \"1\")) return 1;
7029   str = getenv (\"SKIP_TEST_%s\");
7030   if (str && STREQ (str, \"1\")) return 1;
7031   return 0;
7032 }
7033
7034 " test_name name (String.uppercase test_name) (String.uppercase name);
7035
7036   (match prereq with
7037    | Disabled | Always -> ()
7038    | If code | Unless code ->
7039        pr "static int %s_prereq (void)\n" test_name;
7040        pr "{\n";
7041        pr "  %s\n" code;
7042        pr "}\n";
7043        pr "\n";
7044   );
7045
7046   pr "\
7047 static int %s (void)
7048 {
7049   if (%s_skip ()) {
7050     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7051     return 0;
7052   }
7053
7054 " test_name test_name test_name;
7055
7056   (* Optional functions should only be tested if the relevant
7057    * support is available in the daemon.
7058    *)
7059   List.iter (
7060     function
7061     | Optional group ->
7062         pr "  {\n";
7063         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
7064         pr "    int r;\n";
7065         pr "    suppress_error = 1;\n";
7066         pr "    r = guestfs_available (g, (char **) groups);\n";
7067         pr "    suppress_error = 0;\n";
7068         pr "    if (r == -1) {\n";
7069         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7070         pr "      return 0;\n";
7071         pr "    }\n";
7072         pr "  }\n";
7073     | _ -> ()
7074   ) flags;
7075
7076   (match prereq with
7077    | Disabled ->
7078        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7079    | If _ ->
7080        pr "  if (! %s_prereq ()) {\n" test_name;
7081        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7082        pr "    return 0;\n";
7083        pr "  }\n";
7084        pr "\n";
7085        generate_one_test_body name i test_name init test;
7086    | Unless _ ->
7087        pr "  if (%s_prereq ()) {\n" test_name;
7088        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7089        pr "    return 0;\n";
7090        pr "  }\n";
7091        pr "\n";
7092        generate_one_test_body name i test_name init test;
7093    | Always ->
7094        generate_one_test_body name i test_name init test
7095   );
7096
7097   pr "  return 0;\n";
7098   pr "}\n";
7099   pr "\n";
7100   test_name
7101
7102 and generate_one_test_body name i test_name init test =
7103   (match init with
7104    | InitNone (* XXX at some point, InitNone and InitEmpty became
7105                * folded together as the same thing.  Really we should
7106                * make InitNone do nothing at all, but the tests may
7107                * need to be checked to make sure this is OK.
7108                *)
7109    | InitEmpty ->
7110        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7111        List.iter (generate_test_command_call test_name)
7112          [["blockdev_setrw"; "/dev/sda"];
7113           ["umount_all"];
7114           ["lvm_remove_all"]]
7115    | InitPartition ->
7116        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7117        List.iter (generate_test_command_call test_name)
7118          [["blockdev_setrw"; "/dev/sda"];
7119           ["umount_all"];
7120           ["lvm_remove_all"];
7121           ["part_disk"; "/dev/sda"; "mbr"]]
7122    | InitBasicFS ->
7123        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7124        List.iter (generate_test_command_call test_name)
7125          [["blockdev_setrw"; "/dev/sda"];
7126           ["umount_all"];
7127           ["lvm_remove_all"];
7128           ["part_disk"; "/dev/sda"; "mbr"];
7129           ["mkfs"; "ext2"; "/dev/sda1"];
7130           ["mount_options"; ""; "/dev/sda1"; "/"]]
7131    | InitBasicFSonLVM ->
7132        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7133          test_name;
7134        List.iter (generate_test_command_call test_name)
7135          [["blockdev_setrw"; "/dev/sda"];
7136           ["umount_all"];
7137           ["lvm_remove_all"];
7138           ["part_disk"; "/dev/sda"; "mbr"];
7139           ["pvcreate"; "/dev/sda1"];
7140           ["vgcreate"; "VG"; "/dev/sda1"];
7141           ["lvcreate"; "LV"; "VG"; "8"];
7142           ["mkfs"; "ext2"; "/dev/VG/LV"];
7143           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7144    | InitISOFS ->
7145        pr "  /* InitISOFS for %s */\n" test_name;
7146        List.iter (generate_test_command_call test_name)
7147          [["blockdev_setrw"; "/dev/sda"];
7148           ["umount_all"];
7149           ["lvm_remove_all"];
7150           ["mount_ro"; "/dev/sdd"; "/"]]
7151   );
7152
7153   let get_seq_last = function
7154     | [] ->
7155         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7156           test_name
7157     | seq ->
7158         let seq = List.rev seq in
7159         List.rev (List.tl seq), List.hd seq
7160   in
7161
7162   match test with
7163   | TestRun seq ->
7164       pr "  /* TestRun for %s (%d) */\n" name i;
7165       List.iter (generate_test_command_call test_name) seq
7166   | TestOutput (seq, expected) ->
7167       pr "  /* TestOutput for %s (%d) */\n" name i;
7168       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7169       let seq, last = get_seq_last seq in
7170       let test () =
7171         pr "    if (STRNEQ (r, expected)) {\n";
7172         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7173         pr "      return -1;\n";
7174         pr "    }\n"
7175       in
7176       List.iter (generate_test_command_call test_name) seq;
7177       generate_test_command_call ~test test_name last
7178   | TestOutputList (seq, expected) ->
7179       pr "  /* TestOutputList for %s (%d) */\n" name i;
7180       let seq, last = get_seq_last seq in
7181       let test () =
7182         iteri (
7183           fun i str ->
7184             pr "    if (!r[%d]) {\n" i;
7185             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7186             pr "      print_strings (r);\n";
7187             pr "      return -1;\n";
7188             pr "    }\n";
7189             pr "    {\n";
7190             pr "      const char *expected = \"%s\";\n" (c_quote str);
7191             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7192             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7193             pr "        return -1;\n";
7194             pr "      }\n";
7195             pr "    }\n"
7196         ) expected;
7197         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7198         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7199           test_name;
7200         pr "      print_strings (r);\n";
7201         pr "      return -1;\n";
7202         pr "    }\n"
7203       in
7204       List.iter (generate_test_command_call test_name) seq;
7205       generate_test_command_call ~test test_name last
7206   | TestOutputListOfDevices (seq, expected) ->
7207       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7208       let seq, last = get_seq_last seq in
7209       let test () =
7210         iteri (
7211           fun i str ->
7212             pr "    if (!r[%d]) {\n" i;
7213             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7214             pr "      print_strings (r);\n";
7215             pr "      return -1;\n";
7216             pr "    }\n";
7217             pr "    {\n";
7218             pr "      const char *expected = \"%s\";\n" (c_quote str);
7219             pr "      r[%d][5] = 's';\n" i;
7220             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7221             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7222             pr "        return -1;\n";
7223             pr "      }\n";
7224             pr "    }\n"
7225         ) expected;
7226         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7227         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7228           test_name;
7229         pr "      print_strings (r);\n";
7230         pr "      return -1;\n";
7231         pr "    }\n"
7232       in
7233       List.iter (generate_test_command_call test_name) seq;
7234       generate_test_command_call ~test test_name last
7235   | TestOutputInt (seq, expected) ->
7236       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7237       let seq, last = get_seq_last seq in
7238       let test () =
7239         pr "    if (r != %d) {\n" expected;
7240         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7241           test_name expected;
7242         pr "               (int) r);\n";
7243         pr "      return -1;\n";
7244         pr "    }\n"
7245       in
7246       List.iter (generate_test_command_call test_name) seq;
7247       generate_test_command_call ~test test_name last
7248   | TestOutputIntOp (seq, op, expected) ->
7249       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7250       let seq, last = get_seq_last seq in
7251       let test () =
7252         pr "    if (! (r %s %d)) {\n" op expected;
7253         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7254           test_name op expected;
7255         pr "               (int) r);\n";
7256         pr "      return -1;\n";
7257         pr "    }\n"
7258       in
7259       List.iter (generate_test_command_call test_name) seq;
7260       generate_test_command_call ~test test_name last
7261   | TestOutputTrue seq ->
7262       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7263       let seq, last = get_seq_last seq in
7264       let test () =
7265         pr "    if (!r) {\n";
7266         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7267           test_name;
7268         pr "      return -1;\n";
7269         pr "    }\n"
7270       in
7271       List.iter (generate_test_command_call test_name) seq;
7272       generate_test_command_call ~test test_name last
7273   | TestOutputFalse seq ->
7274       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7275       let seq, last = get_seq_last seq in
7276       let test () =
7277         pr "    if (r) {\n";
7278         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7279           test_name;
7280         pr "      return -1;\n";
7281         pr "    }\n"
7282       in
7283       List.iter (generate_test_command_call test_name) seq;
7284       generate_test_command_call ~test test_name last
7285   | TestOutputLength (seq, expected) ->
7286       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7287       let seq, last = get_seq_last seq in
7288       let test () =
7289         pr "    int j;\n";
7290         pr "    for (j = 0; j < %d; ++j)\n" expected;
7291         pr "      if (r[j] == NULL) {\n";
7292         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7293           test_name;
7294         pr "        print_strings (r);\n";
7295         pr "        return -1;\n";
7296         pr "      }\n";
7297         pr "    if (r[j] != NULL) {\n";
7298         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7299           test_name;
7300         pr "      print_strings (r);\n";
7301         pr "      return -1;\n";
7302         pr "    }\n"
7303       in
7304       List.iter (generate_test_command_call test_name) seq;
7305       generate_test_command_call ~test test_name last
7306   | TestOutputBuffer (seq, expected) ->
7307       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7308       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7309       let seq, last = get_seq_last seq in
7310       let len = String.length expected in
7311       let test () =
7312         pr "    if (size != %d) {\n" len;
7313         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7314         pr "      return -1;\n";
7315         pr "    }\n";
7316         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7317         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7318         pr "      return -1;\n";
7319         pr "    }\n"
7320       in
7321       List.iter (generate_test_command_call test_name) seq;
7322       generate_test_command_call ~test test_name last
7323   | TestOutputStruct (seq, checks) ->
7324       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7325       let seq, last = get_seq_last seq in
7326       let test () =
7327         List.iter (
7328           function
7329           | CompareWithInt (field, expected) ->
7330               pr "    if (r->%s != %d) {\n" field expected;
7331               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7332                 test_name field expected;
7333               pr "               (int) r->%s);\n" field;
7334               pr "      return -1;\n";
7335               pr "    }\n"
7336           | CompareWithIntOp (field, op, expected) ->
7337               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7338               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7339                 test_name field op expected;
7340               pr "               (int) r->%s);\n" field;
7341               pr "      return -1;\n";
7342               pr "    }\n"
7343           | CompareWithString (field, expected) ->
7344               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7345               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7346                 test_name field expected;
7347               pr "               r->%s);\n" field;
7348               pr "      return -1;\n";
7349               pr "    }\n"
7350           | CompareFieldsIntEq (field1, field2) ->
7351               pr "    if (r->%s != r->%s) {\n" field1 field2;
7352               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7353                 test_name field1 field2;
7354               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7355               pr "      return -1;\n";
7356               pr "    }\n"
7357           | CompareFieldsStrEq (field1, field2) ->
7358               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7359               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7360                 test_name field1 field2;
7361               pr "               r->%s, r->%s);\n" field1 field2;
7362               pr "      return -1;\n";
7363               pr "    }\n"
7364         ) checks
7365       in
7366       List.iter (generate_test_command_call test_name) seq;
7367       generate_test_command_call ~test test_name last
7368   | TestLastFail seq ->
7369       pr "  /* TestLastFail for %s (%d) */\n" name i;
7370       let seq, last = get_seq_last seq in
7371       List.iter (generate_test_command_call test_name) seq;
7372       generate_test_command_call test_name ~expect_error:true last
7373
7374 (* Generate the code to run a command, leaving the result in 'r'.
7375  * If you expect to get an error then you should set expect_error:true.
7376  *)
7377 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7378   match cmd with
7379   | [] -> assert false
7380   | name :: args ->
7381       (* Look up the command to find out what args/ret it has. *)
7382       let style =
7383         try
7384           let _, style, _, _, _, _, _ =
7385             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7386           style
7387         with Not_found ->
7388           failwithf "%s: in test, command %s was not found" test_name name in
7389
7390       if List.length (snd style) <> List.length args then
7391         failwithf "%s: in test, wrong number of args given to %s"
7392           test_name name;
7393
7394       pr "  {\n";
7395
7396       List.iter (
7397         function
7398         | OptString n, "NULL" -> ()
7399         | Pathname n, arg
7400         | Device n, arg
7401         | Dev_or_Path n, arg
7402         | String n, arg
7403         | OptString n, arg ->
7404             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7405         | BufferIn n, arg ->
7406             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7407             pr "    size_t %s_size = %d;\n" n (String.length arg)
7408         | Int _, _
7409         | Int64 _, _
7410         | Bool _, _
7411         | FileIn _, _ | FileOut _, _ -> ()
7412         | StringList n, "" | DeviceList n, "" ->
7413             pr "    const char *const %s[1] = { NULL };\n" n
7414         | StringList n, arg | DeviceList n, arg ->
7415             let strs = string_split " " arg in
7416             iteri (
7417               fun i str ->
7418                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7419             ) strs;
7420             pr "    const char *const %s[] = {\n" n;
7421             iteri (
7422               fun i _ -> pr "      %s_%d,\n" n i
7423             ) strs;
7424             pr "      NULL\n";
7425             pr "    };\n";
7426       ) (List.combine (snd style) args);
7427
7428       let error_code =
7429         match fst style with
7430         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7431         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7432         | RConstString _ | RConstOptString _ ->
7433             pr "    const char *r;\n"; "NULL"
7434         | RString _ -> pr "    char *r;\n"; "NULL"
7435         | RStringList _ | RHashtable _ ->
7436             pr "    char **r;\n";
7437             pr "    int i;\n";
7438             "NULL"
7439         | RStruct (_, typ) ->
7440             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7441         | RStructList (_, typ) ->
7442             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7443         | RBufferOut _ ->
7444             pr "    char *r;\n";
7445             pr "    size_t size;\n";
7446             "NULL" in
7447
7448       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7449       pr "    r = guestfs_%s (g" name;
7450
7451       (* Generate the parameters. *)
7452       List.iter (
7453         function
7454         | OptString _, "NULL" -> pr ", NULL"
7455         | Pathname n, _
7456         | Device n, _ | Dev_or_Path n, _
7457         | String n, _
7458         | OptString n, _ ->
7459             pr ", %s" n
7460         | BufferIn n, _ ->
7461             pr ", %s, %s_size" n n
7462         | FileIn _, arg | FileOut _, arg ->
7463             pr ", \"%s\"" (c_quote arg)
7464         | StringList n, _ | DeviceList n, _ ->
7465             pr ", (char **) %s" n
7466         | Int _, arg ->
7467             let i =
7468               try int_of_string arg
7469               with Failure "int_of_string" ->
7470                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7471             pr ", %d" i
7472         | Int64 _, arg ->
7473             let i =
7474               try Int64.of_string arg
7475               with Failure "int_of_string" ->
7476                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7477             pr ", %Ld" i
7478         | Bool _, arg ->
7479             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7480       ) (List.combine (snd style) args);
7481
7482       (match fst style with
7483        | RBufferOut _ -> pr ", &size"
7484        | _ -> ()
7485       );
7486
7487       pr ");\n";
7488
7489       if not expect_error then
7490         pr "    if (r == %s)\n" error_code
7491       else
7492         pr "    if (r != %s)\n" error_code;
7493       pr "      return -1;\n";
7494
7495       (* Insert the test code. *)
7496       (match test with
7497        | None -> ()
7498        | Some f -> f ()
7499       );
7500
7501       (match fst style with
7502        | RErr | RInt _ | RInt64 _ | RBool _
7503        | RConstString _ | RConstOptString _ -> ()
7504        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7505        | RStringList _ | RHashtable _ ->
7506            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7507            pr "      free (r[i]);\n";
7508            pr "    free (r);\n"
7509        | RStruct (_, typ) ->
7510            pr "    guestfs_free_%s (r);\n" typ
7511        | RStructList (_, typ) ->
7512            pr "    guestfs_free_%s_list (r);\n" typ
7513       );
7514
7515       pr "  }\n"
7516
7517 and c_quote str =
7518   let str = replace_str str "\r" "\\r" in
7519   let str = replace_str str "\n" "\\n" in
7520   let str = replace_str str "\t" "\\t" in
7521   let str = replace_str str "\000" "\\0" in
7522   str
7523
7524 (* Generate a lot of different functions for guestfish. *)
7525 and generate_fish_cmds () =
7526   generate_header CStyle GPLv2plus;
7527
7528   let all_functions =
7529     List.filter (
7530       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7531     ) all_functions in
7532   let all_functions_sorted =
7533     List.filter (
7534       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7535     ) all_functions_sorted in
7536
7537   pr "#include <config.h>\n";
7538   pr "\n";
7539   pr "#include <stdio.h>\n";
7540   pr "#include <stdlib.h>\n";
7541   pr "#include <string.h>\n";
7542   pr "#include <inttypes.h>\n";
7543   pr "\n";
7544   pr "#include <guestfs.h>\n";
7545   pr "#include \"c-ctype.h\"\n";
7546   pr "#include \"full-write.h\"\n";
7547   pr "#include \"xstrtol.h\"\n";
7548   pr "#include \"fish.h\"\n";
7549   pr "\n";
7550   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7551   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7552   pr "\n";
7553
7554   (* list_commands function, which implements guestfish -h *)
7555   pr "void list_commands (void)\n";
7556   pr "{\n";
7557   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7558   pr "  list_builtin_commands ();\n";
7559   List.iter (
7560     fun (name, _, _, flags, _, shortdesc, _) ->
7561       let name = replace_char name '_' '-' in
7562       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7563         name shortdesc
7564   ) all_functions_sorted;
7565   pr "  printf (\"    %%s\\n\",";
7566   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7567   pr "}\n";
7568   pr "\n";
7569
7570   (* display_command function, which implements guestfish -h cmd *)
7571   pr "void display_command (const char *cmd)\n";
7572   pr "{\n";
7573   List.iter (
7574     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7575       let name2 = replace_char name '_' '-' in
7576       let alias =
7577         try find_map (function FishAlias n -> Some n | _ -> None) flags
7578         with Not_found -> name in
7579       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7580       let synopsis =
7581         match snd style with
7582         | [] -> name2
7583         | args ->
7584             sprintf "%s %s"
7585               name2 (String.concat " " (List.map name_of_argt args)) in
7586
7587       let warnings =
7588         if List.mem ProtocolLimitWarning flags then
7589           ("\n\n" ^ protocol_limit_warning)
7590         else "" in
7591
7592       (* For DangerWillRobinson commands, we should probably have
7593        * guestfish prompt before allowing you to use them (especially
7594        * in interactive mode). XXX
7595        *)
7596       let warnings =
7597         warnings ^
7598           if List.mem DangerWillRobinson flags then
7599             ("\n\n" ^ danger_will_robinson)
7600           else "" in
7601
7602       let warnings =
7603         warnings ^
7604           match deprecation_notice flags with
7605           | None -> ""
7606           | Some txt -> "\n\n" ^ txt in
7607
7608       let describe_alias =
7609         if name <> alias then
7610           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7611         else "" in
7612
7613       pr "  if (";
7614       pr "STRCASEEQ (cmd, \"%s\")" name;
7615       if name <> name2 then
7616         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7617       if name <> alias then
7618         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7619       pr ")\n";
7620       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7621         name2 shortdesc
7622         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7623          "=head1 DESCRIPTION\n\n" ^
7624          longdesc ^ warnings ^ describe_alias);
7625       pr "  else\n"
7626   ) all_functions;
7627   pr "    display_builtin_command (cmd);\n";
7628   pr "}\n";
7629   pr "\n";
7630
7631   let emit_print_list_function typ =
7632     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7633       typ typ typ;
7634     pr "{\n";
7635     pr "  unsigned int i;\n";
7636     pr "\n";
7637     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7638     pr "    printf (\"[%%d] = {\\n\", i);\n";
7639     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7640     pr "    printf (\"}\\n\");\n";
7641     pr "  }\n";
7642     pr "}\n";
7643     pr "\n";
7644   in
7645
7646   (* print_* functions *)
7647   List.iter (
7648     fun (typ, cols) ->
7649       let needs_i =
7650         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7651
7652       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7653       pr "{\n";
7654       if needs_i then (
7655         pr "  unsigned int i;\n";
7656         pr "\n"
7657       );
7658       List.iter (
7659         function
7660         | name, FString ->
7661             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7662         | name, FUUID ->
7663             pr "  printf (\"%%s%s: \", indent);\n" name;
7664             pr "  for (i = 0; i < 32; ++i)\n";
7665             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7666             pr "  printf (\"\\n\");\n"
7667         | name, FBuffer ->
7668             pr "  printf (\"%%s%s: \", indent);\n" name;
7669             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7670             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7671             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7672             pr "    else\n";
7673             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7674             pr "  printf (\"\\n\");\n"
7675         | name, (FUInt64|FBytes) ->
7676             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7677               name typ name
7678         | name, FInt64 ->
7679             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7680               name typ name
7681         | name, FUInt32 ->
7682             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7683               name typ name
7684         | name, FInt32 ->
7685             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7686               name typ name
7687         | name, FChar ->
7688             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7689               name typ name
7690         | name, FOptPercent ->
7691             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7692               typ name name typ name;
7693             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7694       ) cols;
7695       pr "}\n";
7696       pr "\n";
7697   ) structs;
7698
7699   (* Emit a print_TYPE_list function definition only if that function is used. *)
7700   List.iter (
7701     function
7702     | typ, (RStructListOnly | RStructAndList) ->
7703         (* generate the function for typ *)
7704         emit_print_list_function typ
7705     | typ, _ -> () (* empty *)
7706   ) (rstructs_used_by all_functions);
7707
7708   (* Emit a print_TYPE function definition only if that function is used. *)
7709   List.iter (
7710     function
7711     | typ, (RStructOnly | RStructAndList) ->
7712         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7713         pr "{\n";
7714         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7715         pr "}\n";
7716         pr "\n";
7717     | typ, _ -> () (* empty *)
7718   ) (rstructs_used_by all_functions);
7719
7720   (* run_<action> actions *)
7721   List.iter (
7722     fun (name, style, _, flags, _, _, _) ->
7723       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7724       pr "{\n";
7725       (match fst style with
7726        | RErr
7727        | RInt _
7728        | RBool _ -> pr "  int r;\n"
7729        | RInt64 _ -> pr "  int64_t r;\n"
7730        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7731        | RString _ -> pr "  char *r;\n"
7732        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7733        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7734        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7735        | RBufferOut _ ->
7736            pr "  char *r;\n";
7737            pr "  size_t size;\n";
7738       );
7739       List.iter (
7740         function
7741         | Device n
7742         | String n
7743         | OptString n -> pr "  const char *%s;\n" n
7744         | Pathname n
7745         | Dev_or_Path n
7746         | FileIn n
7747         | FileOut n -> pr "  char *%s;\n" n
7748         | BufferIn n ->
7749             pr "  const char *%s;\n" n;
7750             pr "  size_t %s_size;\n" n
7751         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7752         | Bool n -> pr "  int %s;\n" n
7753         | Int n -> pr "  int %s;\n" n
7754         | Int64 n -> pr "  int64_t %s;\n" n
7755       ) (snd style);
7756
7757       (* Check and convert parameters. *)
7758       let argc_expected = List.length (snd style) in
7759       pr "  if (argc != %d) {\n" argc_expected;
7760       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7761         argc_expected;
7762       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7763       pr "    return -1;\n";
7764       pr "  }\n";
7765
7766       let parse_integer fn fntyp rtyp range name i =
7767         pr "  {\n";
7768         pr "    strtol_error xerr;\n";
7769         pr "    %s r;\n" fntyp;
7770         pr "\n";
7771         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7772         pr "    if (xerr != LONGINT_OK) {\n";
7773         pr "      fprintf (stderr,\n";
7774         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7775         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7776         pr "      return -1;\n";
7777         pr "    }\n";
7778         (match range with
7779          | None -> ()
7780          | Some (min, max, comment) ->
7781              pr "    /* %s */\n" comment;
7782              pr "    if (r < %s || r > %s) {\n" min max;
7783              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7784                name;
7785              pr "      return -1;\n";
7786              pr "    }\n";
7787              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7788         );
7789         pr "    %s = r;\n" name;
7790         pr "  }\n";
7791       in
7792
7793       iteri (
7794         fun i ->
7795           function
7796           | Device name
7797           | String name ->
7798               pr "  %s = argv[%d];\n" name i
7799           | Pathname name
7800           | Dev_or_Path name ->
7801               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7802               pr "  if (%s == NULL) return -1;\n" name
7803           | OptString name ->
7804               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7805                 name i i
7806           | BufferIn name ->
7807               pr "  %s = argv[%d];\n" name i;
7808               pr "  %s_size = strlen (argv[%d]);\n" name i
7809           | FileIn name ->
7810               pr "  %s = file_in (argv[%d]);\n" name i;
7811               pr "  if (%s == NULL) return -1;\n" name
7812           | FileOut name ->
7813               pr "  %s = file_out (argv[%d]);\n" name i;
7814               pr "  if (%s == NULL) return -1;\n" name
7815           | StringList name | DeviceList name ->
7816               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7817               pr "  if (%s == NULL) return -1;\n" name;
7818           | Bool name ->
7819               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7820           | Int name ->
7821               let range =
7822                 let min = "(-(2LL<<30))"
7823                 and max = "((2LL<<30)-1)"
7824                 and comment =
7825                   "The Int type in the generator is a signed 31 bit int." in
7826                 Some (min, max, comment) in
7827               parse_integer "xstrtoll" "long long" "int" range name i
7828           | Int64 name ->
7829               parse_integer "xstrtoll" "long long" "int64_t" None name i
7830       ) (snd style);
7831
7832       (* Call C API function. *)
7833       pr "  r = guestfs_%s " name;
7834       generate_c_call_args ~handle:"g" style;
7835       pr ";\n";
7836
7837       List.iter (
7838         function
7839         | Device name | String name
7840         | OptString name | Bool name
7841         | Int name | Int64 name
7842         | BufferIn name -> ()
7843         | Pathname name | Dev_or_Path name | FileOut name ->
7844             pr "  free (%s);\n" name
7845         | FileIn name ->
7846             pr "  free_file_in (%s);\n" name
7847         | StringList name | DeviceList name ->
7848             pr "  free_strings (%s);\n" name
7849       ) (snd style);
7850
7851       (* Any output flags? *)
7852       let fish_output =
7853         let flags = filter_map (
7854           function FishOutput flag -> Some flag | _ -> None
7855         ) flags in
7856         match flags with
7857         | [] -> None
7858         | [f] -> Some f
7859         | _ ->
7860             failwithf "%s: more than one FishOutput flag is not allowed" name in
7861
7862       (* Check return value for errors and display command results. *)
7863       (match fst style with
7864        | RErr -> pr "  return r;\n"
7865        | RInt _ ->
7866            pr "  if (r == -1) return -1;\n";
7867            (match fish_output with
7868             | None ->
7869                 pr "  printf (\"%%d\\n\", r);\n";
7870             | Some FishOutputOctal ->
7871                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7872             | Some FishOutputHexadecimal ->
7873                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7874            pr "  return 0;\n"
7875        | RInt64 _ ->
7876            pr "  if (r == -1) return -1;\n";
7877            (match fish_output with
7878             | None ->
7879                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7880             | Some FishOutputOctal ->
7881                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7882             | Some FishOutputHexadecimal ->
7883                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7884            pr "  return 0;\n"
7885        | RBool _ ->
7886            pr "  if (r == -1) return -1;\n";
7887            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7888            pr "  return 0;\n"
7889        | RConstString _ ->
7890            pr "  if (r == NULL) return -1;\n";
7891            pr "  printf (\"%%s\\n\", r);\n";
7892            pr "  return 0;\n"
7893        | RConstOptString _ ->
7894            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7895            pr "  return 0;\n"
7896        | RString _ ->
7897            pr "  if (r == NULL) return -1;\n";
7898            pr "  printf (\"%%s\\n\", r);\n";
7899            pr "  free (r);\n";
7900            pr "  return 0;\n"
7901        | RStringList _ ->
7902            pr "  if (r == NULL) return -1;\n";
7903            pr "  print_strings (r);\n";
7904            pr "  free_strings (r);\n";
7905            pr "  return 0;\n"
7906        | RStruct (_, typ) ->
7907            pr "  if (r == NULL) return -1;\n";
7908            pr "  print_%s (r);\n" typ;
7909            pr "  guestfs_free_%s (r);\n" typ;
7910            pr "  return 0;\n"
7911        | RStructList (_, typ) ->
7912            pr "  if (r == NULL) return -1;\n";
7913            pr "  print_%s_list (r);\n" typ;
7914            pr "  guestfs_free_%s_list (r);\n" typ;
7915            pr "  return 0;\n"
7916        | RHashtable _ ->
7917            pr "  if (r == NULL) return -1;\n";
7918            pr "  print_table (r);\n";
7919            pr "  free_strings (r);\n";
7920            pr "  return 0;\n"
7921        | RBufferOut _ ->
7922            pr "  if (r == NULL) return -1;\n";
7923            pr "  if (full_write (1, r, size) != size) {\n";
7924            pr "    perror (\"write\");\n";
7925            pr "    free (r);\n";
7926            pr "    return -1;\n";
7927            pr "  }\n";
7928            pr "  free (r);\n";
7929            pr "  return 0;\n"
7930       );
7931       pr "}\n";
7932       pr "\n"
7933   ) all_functions;
7934
7935   (* run_action function *)
7936   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7937   pr "{\n";
7938   List.iter (
7939     fun (name, _, _, flags, _, _, _) ->
7940       let name2 = replace_char name '_' '-' in
7941       let alias =
7942         try find_map (function FishAlias n -> Some n | _ -> None) flags
7943         with Not_found -> name in
7944       pr "  if (";
7945       pr "STRCASEEQ (cmd, \"%s\")" name;
7946       if name <> name2 then
7947         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7948       if name <> alias then
7949         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7950       pr ")\n";
7951       pr "    return run_%s (cmd, argc, argv);\n" name;
7952       pr "  else\n";
7953   ) all_functions;
7954   pr "    {\n";
7955   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7956   pr "      if (command_num == 1)\n";
7957   pr "        extended_help_message ();\n";
7958   pr "      return -1;\n";
7959   pr "    }\n";
7960   pr "  return 0;\n";
7961   pr "}\n";
7962   pr "\n"
7963
7964 (* Readline completion for guestfish. *)
7965 and generate_fish_completion () =
7966   generate_header CStyle GPLv2plus;
7967
7968   let all_functions =
7969     List.filter (
7970       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7971     ) all_functions in
7972
7973   pr "\
7974 #include <config.h>
7975
7976 #include <stdio.h>
7977 #include <stdlib.h>
7978 #include <string.h>
7979
7980 #ifdef HAVE_LIBREADLINE
7981 #include <readline/readline.h>
7982 #endif
7983
7984 #include \"fish.h\"
7985
7986 #ifdef HAVE_LIBREADLINE
7987
7988 static const char *const commands[] = {
7989   BUILTIN_COMMANDS_FOR_COMPLETION,
7990 ";
7991
7992   (* Get the commands, including the aliases.  They don't need to be
7993    * sorted - the generator() function just does a dumb linear search.
7994    *)
7995   let commands =
7996     List.map (
7997       fun (name, _, _, flags, _, _, _) ->
7998         let name2 = replace_char name '_' '-' in
7999         let alias =
8000           try find_map (function FishAlias n -> Some n | _ -> None) flags
8001           with Not_found -> name in
8002
8003         if name <> alias then [name2; alias] else [name2]
8004     ) all_functions in
8005   let commands = List.flatten commands in
8006
8007   List.iter (pr "  \"%s\",\n") commands;
8008
8009   pr "  NULL
8010 };
8011
8012 static char *
8013 generator (const char *text, int state)
8014 {
8015   static int index, len;
8016   const char *name;
8017
8018   if (!state) {
8019     index = 0;
8020     len = strlen (text);
8021   }
8022
8023   rl_attempted_completion_over = 1;
8024
8025   while ((name = commands[index]) != NULL) {
8026     index++;
8027     if (STRCASEEQLEN (name, text, len))
8028       return strdup (name);
8029   }
8030
8031   return NULL;
8032 }
8033
8034 #endif /* HAVE_LIBREADLINE */
8035
8036 #ifdef HAVE_RL_COMPLETION_MATCHES
8037 #define RL_COMPLETION_MATCHES rl_completion_matches
8038 #else
8039 #ifdef HAVE_COMPLETION_MATCHES
8040 #define RL_COMPLETION_MATCHES completion_matches
8041 #endif
8042 #endif /* else just fail if we don't have either symbol */
8043
8044 char **
8045 do_completion (const char *text, int start, int end)
8046 {
8047   char **matches = NULL;
8048
8049 #ifdef HAVE_LIBREADLINE
8050   rl_completion_append_character = ' ';
8051
8052   if (start == 0)
8053     matches = RL_COMPLETION_MATCHES (text, generator);
8054   else if (complete_dest_paths)
8055     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8056 #endif
8057
8058   return matches;
8059 }
8060 ";
8061
8062 (* Generate the POD documentation for guestfish. *)
8063 and generate_fish_actions_pod () =
8064   let all_functions_sorted =
8065     List.filter (
8066       fun (_, _, _, flags, _, _, _) ->
8067         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8068     ) all_functions_sorted in
8069
8070   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8071
8072   List.iter (
8073     fun (name, style, _, flags, _, _, longdesc) ->
8074       let longdesc =
8075         Str.global_substitute rex (
8076           fun s ->
8077             let sub =
8078               try Str.matched_group 1 s
8079               with Not_found ->
8080                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8081             "C<" ^ replace_char sub '_' '-' ^ ">"
8082         ) longdesc in
8083       let name = replace_char name '_' '-' in
8084       let alias =
8085         try find_map (function FishAlias n -> Some n | _ -> None) flags
8086         with Not_found -> name in
8087
8088       pr "=head2 %s" name;
8089       if name <> alias then
8090         pr " | %s" alias;
8091       pr "\n";
8092       pr "\n";
8093       pr " %s" name;
8094       List.iter (
8095         function
8096         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8097         | OptString n -> pr " %s" n
8098         | StringList n | DeviceList n -> pr " '%s ...'" n
8099         | Bool _ -> pr " true|false"
8100         | Int n -> pr " %s" n
8101         | Int64 n -> pr " %s" n
8102         | FileIn n | FileOut n -> pr " (%s|-)" n
8103         | BufferIn n -> pr " %s" n
8104       ) (snd style);
8105       pr "\n";
8106       pr "\n";
8107       pr "%s\n\n" longdesc;
8108
8109       if List.exists (function FileIn _ | FileOut _ -> true
8110                       | _ -> false) (snd style) then
8111         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8112
8113       if List.mem ProtocolLimitWarning flags then
8114         pr "%s\n\n" protocol_limit_warning;
8115
8116       if List.mem DangerWillRobinson flags then
8117         pr "%s\n\n" danger_will_robinson;
8118
8119       match deprecation_notice flags with
8120       | None -> ()
8121       | Some txt -> pr "%s\n\n" txt
8122   ) all_functions_sorted
8123
8124 (* Generate a C function prototype. *)
8125 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8126     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8127     ?(prefix = "")
8128     ?handle name style =
8129   if extern then pr "extern ";
8130   if static then pr "static ";
8131   (match fst style with
8132    | RErr -> pr "int "
8133    | RInt _ -> pr "int "
8134    | RInt64 _ -> pr "int64_t "
8135    | RBool _ -> pr "int "
8136    | RConstString _ | RConstOptString _ -> pr "const char *"
8137    | RString _ | RBufferOut _ -> pr "char *"
8138    | RStringList _ | RHashtable _ -> pr "char **"
8139    | RStruct (_, typ) ->
8140        if not in_daemon then pr "struct guestfs_%s *" typ
8141        else pr "guestfs_int_%s *" typ
8142    | RStructList (_, typ) ->
8143        if not in_daemon then pr "struct guestfs_%s_list *" typ
8144        else pr "guestfs_int_%s_list *" typ
8145   );
8146   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8147   pr "%s%s (" prefix name;
8148   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8149     pr "void"
8150   else (
8151     let comma = ref false in
8152     (match handle with
8153      | None -> ()
8154      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8155     );
8156     let next () =
8157       if !comma then (
8158         if single_line then pr ", " else pr ",\n\t\t"
8159       );
8160       comma := true
8161     in
8162     List.iter (
8163       function
8164       | Pathname n
8165       | Device n | Dev_or_Path n
8166       | String n
8167       | OptString n ->
8168           next ();
8169           pr "const char *%s" n
8170       | StringList n | DeviceList n ->
8171           next ();
8172           pr "char *const *%s" n
8173       | Bool n -> next (); pr "int %s" n
8174       | Int n -> next (); pr "int %s" n
8175       | Int64 n -> next (); pr "int64_t %s" n
8176       | FileIn n
8177       | FileOut n ->
8178           if not in_daemon then (next (); pr "const char *%s" n)
8179       | BufferIn n ->
8180           next ();
8181           pr "const char *%s" n;
8182           next ();
8183           pr "size_t %s_size" n
8184     ) (snd style);
8185     if is_RBufferOut then (next (); pr "size_t *size_r");
8186   );
8187   pr ")";
8188   if semicolon then pr ";";
8189   if newline then pr "\n"
8190
8191 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8192 and generate_c_call_args ?handle ?(decl = false) style =
8193   pr "(";
8194   let comma = ref false in
8195   let next () =
8196     if !comma then pr ", ";
8197     comma := true
8198   in
8199   (match handle with
8200    | None -> ()
8201    | Some handle -> pr "%s" handle; comma := true
8202   );
8203   List.iter (
8204     function
8205     | BufferIn n ->
8206         next ();
8207         pr "%s, %s_size" n n
8208     | arg ->
8209         next ();
8210         pr "%s" (name_of_argt arg)
8211   ) (snd style);
8212   (* For RBufferOut calls, add implicit &size parameter. *)
8213   if not decl then (
8214     match fst style with
8215     | RBufferOut _ ->
8216         next ();
8217         pr "&size"
8218     | _ -> ()
8219   );
8220   pr ")"
8221
8222 (* Generate the OCaml bindings interface. *)
8223 and generate_ocaml_mli () =
8224   generate_header OCamlStyle LGPLv2plus;
8225
8226   pr "\
8227 (** For API documentation you should refer to the C API
8228     in the guestfs(3) manual page.  The OCaml API uses almost
8229     exactly the same calls. *)
8230
8231 type t
8232 (** A [guestfs_h] handle. *)
8233
8234 exception Error of string
8235 (** This exception is raised when there is an error. *)
8236
8237 exception Handle_closed of string
8238 (** This exception is raised if you use a {!Guestfs.t} handle
8239     after calling {!close} on it.  The string is the name of
8240     the function. *)
8241
8242 val create : unit -> t
8243 (** Create a {!Guestfs.t} handle. *)
8244
8245 val close : t -> unit
8246 (** Close the {!Guestfs.t} handle and free up all resources used
8247     by it immediately.
8248
8249     Handles are closed by the garbage collector when they become
8250     unreferenced, but callers can call this in order to provide
8251     predictable cleanup. *)
8252
8253 ";
8254   generate_ocaml_structure_decls ();
8255
8256   (* The actions. *)
8257   List.iter (
8258     fun (name, style, _, _, _, shortdesc, _) ->
8259       generate_ocaml_prototype name style;
8260       pr "(** %s *)\n" shortdesc;
8261       pr "\n"
8262   ) all_functions_sorted
8263
8264 (* Generate the OCaml bindings implementation. *)
8265 and generate_ocaml_ml () =
8266   generate_header OCamlStyle LGPLv2plus;
8267
8268   pr "\
8269 type t
8270
8271 exception Error of string
8272 exception Handle_closed of string
8273
8274 external create : unit -> t = \"ocaml_guestfs_create\"
8275 external close : t -> unit = \"ocaml_guestfs_close\"
8276
8277 (* Give the exceptions names, so they can be raised from the C code. *)
8278 let () =
8279   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8280   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8281
8282 ";
8283
8284   generate_ocaml_structure_decls ();
8285
8286   (* The actions. *)
8287   List.iter (
8288     fun (name, style, _, _, _, shortdesc, _) ->
8289       generate_ocaml_prototype ~is_external:true name style;
8290   ) all_functions_sorted
8291
8292 (* Generate the OCaml bindings C implementation. *)
8293 and generate_ocaml_c () =
8294   generate_header CStyle LGPLv2plus;
8295
8296   pr "\
8297 #include <stdio.h>
8298 #include <stdlib.h>
8299 #include <string.h>
8300
8301 #include <caml/config.h>
8302 #include <caml/alloc.h>
8303 #include <caml/callback.h>
8304 #include <caml/fail.h>
8305 #include <caml/memory.h>
8306 #include <caml/mlvalues.h>
8307 #include <caml/signals.h>
8308
8309 #include <guestfs.h>
8310
8311 #include \"guestfs_c.h\"
8312
8313 /* Copy a hashtable of string pairs into an assoc-list.  We return
8314  * the list in reverse order, but hashtables aren't supposed to be
8315  * ordered anyway.
8316  */
8317 static CAMLprim value
8318 copy_table (char * const * argv)
8319 {
8320   CAMLparam0 ();
8321   CAMLlocal5 (rv, pairv, kv, vv, cons);
8322   int i;
8323
8324   rv = Val_int (0);
8325   for (i = 0; argv[i] != NULL; i += 2) {
8326     kv = caml_copy_string (argv[i]);
8327     vv = caml_copy_string (argv[i+1]);
8328     pairv = caml_alloc (2, 0);
8329     Store_field (pairv, 0, kv);
8330     Store_field (pairv, 1, vv);
8331     cons = caml_alloc (2, 0);
8332     Store_field (cons, 1, rv);
8333     rv = cons;
8334     Store_field (cons, 0, pairv);
8335   }
8336
8337   CAMLreturn (rv);
8338 }
8339
8340 ";
8341
8342   (* Struct copy functions. *)
8343
8344   let emit_ocaml_copy_list_function typ =
8345     pr "static CAMLprim value\n";
8346     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8347     pr "{\n";
8348     pr "  CAMLparam0 ();\n";
8349     pr "  CAMLlocal2 (rv, v);\n";
8350     pr "  unsigned int i;\n";
8351     pr "\n";
8352     pr "  if (%ss->len == 0)\n" typ;
8353     pr "    CAMLreturn (Atom (0));\n";
8354     pr "  else {\n";
8355     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8356     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8357     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8358     pr "      caml_modify (&Field (rv, i), v);\n";
8359     pr "    }\n";
8360     pr "    CAMLreturn (rv);\n";
8361     pr "  }\n";
8362     pr "}\n";
8363     pr "\n";
8364   in
8365
8366   List.iter (
8367     fun (typ, cols) ->
8368       let has_optpercent_col =
8369         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8370
8371       pr "static CAMLprim value\n";
8372       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8373       pr "{\n";
8374       pr "  CAMLparam0 ();\n";
8375       if has_optpercent_col then
8376         pr "  CAMLlocal3 (rv, v, v2);\n"
8377       else
8378         pr "  CAMLlocal2 (rv, v);\n";
8379       pr "\n";
8380       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8381       iteri (
8382         fun i col ->
8383           (match col with
8384            | name, FString ->
8385                pr "  v = caml_copy_string (%s->%s);\n" typ name
8386            | name, FBuffer ->
8387                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8388                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8389                  typ name typ name
8390            | name, FUUID ->
8391                pr "  v = caml_alloc_string (32);\n";
8392                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8393            | name, (FBytes|FInt64|FUInt64) ->
8394                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8395            | name, (FInt32|FUInt32) ->
8396                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8397            | name, FOptPercent ->
8398                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8399                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8400                pr "    v = caml_alloc (1, 0);\n";
8401                pr "    Store_field (v, 0, v2);\n";
8402                pr "  } else /* None */\n";
8403                pr "    v = Val_int (0);\n";
8404            | name, FChar ->
8405                pr "  v = Val_int (%s->%s);\n" typ name
8406           );
8407           pr "  Store_field (rv, %d, v);\n" i
8408       ) cols;
8409       pr "  CAMLreturn (rv);\n";
8410       pr "}\n";
8411       pr "\n";
8412   ) structs;
8413
8414   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8415   List.iter (
8416     function
8417     | typ, (RStructListOnly | RStructAndList) ->
8418         (* generate the function for typ *)
8419         emit_ocaml_copy_list_function typ
8420     | typ, _ -> () (* empty *)
8421   ) (rstructs_used_by all_functions);
8422
8423   (* The wrappers. *)
8424   List.iter (
8425     fun (name, style, _, _, _, _, _) ->
8426       pr "/* Automatically generated wrapper for function\n";
8427       pr " * ";
8428       generate_ocaml_prototype name style;
8429       pr " */\n";
8430       pr "\n";
8431
8432       let params =
8433         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8434
8435       let needs_extra_vs =
8436         match fst style with RConstOptString _ -> true | _ -> false in
8437
8438       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8439       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8440       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8441       pr "\n";
8442
8443       pr "CAMLprim value\n";
8444       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8445       List.iter (pr ", value %s") (List.tl params);
8446       pr ")\n";
8447       pr "{\n";
8448
8449       (match params with
8450        | [p1; p2; p3; p4; p5] ->
8451            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8452        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8453            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8454            pr "  CAMLxparam%d (%s);\n"
8455              (List.length rest) (String.concat ", " rest)
8456        | ps ->
8457            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8458       );
8459       if not needs_extra_vs then
8460         pr "  CAMLlocal1 (rv);\n"
8461       else
8462         pr "  CAMLlocal3 (rv, v, v2);\n";
8463       pr "\n";
8464
8465       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8466       pr "  if (g == NULL)\n";
8467       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8468       pr "\n";
8469
8470       List.iter (
8471         function
8472         | Pathname n
8473         | Device n | Dev_or_Path n
8474         | String n
8475         | FileIn n
8476         | FileOut n ->
8477             pr "  const char *%s = String_val (%sv);\n" n n
8478         | OptString n ->
8479             pr "  const char *%s =\n" n;
8480             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8481               n n
8482         | BufferIn n ->
8483             pr "  const char *%s = String_val (%sv);\n" n n;
8484             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8485         | StringList n | DeviceList n ->
8486             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8487         | Bool n ->
8488             pr "  int %s = Bool_val (%sv);\n" n n
8489         | Int n ->
8490             pr "  int %s = Int_val (%sv);\n" n n
8491         | Int64 n ->
8492             pr "  int64_t %s = Int64_val (%sv);\n" n n
8493       ) (snd style);
8494       let error_code =
8495         match fst style with
8496         | RErr -> pr "  int r;\n"; "-1"
8497         | RInt _ -> pr "  int r;\n"; "-1"
8498         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8499         | RBool _ -> pr "  int r;\n"; "-1"
8500         | RConstString _ | RConstOptString _ ->
8501             pr "  const char *r;\n"; "NULL"
8502         | RString _ -> pr "  char *r;\n"; "NULL"
8503         | RStringList _ ->
8504             pr "  int i;\n";
8505             pr "  char **r;\n";
8506             "NULL"
8507         | RStruct (_, typ) ->
8508             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8509         | RStructList (_, typ) ->
8510             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8511         | RHashtable _ ->
8512             pr "  int i;\n";
8513             pr "  char **r;\n";
8514             "NULL"
8515         | RBufferOut _ ->
8516             pr "  char *r;\n";
8517             pr "  size_t size;\n";
8518             "NULL" in
8519       pr "\n";
8520
8521       pr "  caml_enter_blocking_section ();\n";
8522       pr "  r = guestfs_%s " name;
8523       generate_c_call_args ~handle:"g" style;
8524       pr ";\n";
8525       pr "  caml_leave_blocking_section ();\n";
8526
8527       List.iter (
8528         function
8529         | StringList n | DeviceList n ->
8530             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8531         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8532         | Bool _ | Int _ | Int64 _
8533         | FileIn _ | FileOut _ | BufferIn _ -> ()
8534       ) (snd style);
8535
8536       pr "  if (r == %s)\n" error_code;
8537       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8538       pr "\n";
8539
8540       (match fst style with
8541        | RErr -> pr "  rv = Val_unit;\n"
8542        | RInt _ -> pr "  rv = Val_int (r);\n"
8543        | RInt64 _ ->
8544            pr "  rv = caml_copy_int64 (r);\n"
8545        | RBool _ -> pr "  rv = Val_bool (r);\n"
8546        | RConstString _ ->
8547            pr "  rv = caml_copy_string (r);\n"
8548        | RConstOptString _ ->
8549            pr "  if (r) { /* Some string */\n";
8550            pr "    v = caml_alloc (1, 0);\n";
8551            pr "    v2 = caml_copy_string (r);\n";
8552            pr "    Store_field (v, 0, v2);\n";
8553            pr "  } else /* None */\n";
8554            pr "    v = Val_int (0);\n";
8555        | RString _ ->
8556            pr "  rv = caml_copy_string (r);\n";
8557            pr "  free (r);\n"
8558        | RStringList _ ->
8559            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8560            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8561            pr "  free (r);\n"
8562        | RStruct (_, typ) ->
8563            pr "  rv = copy_%s (r);\n" typ;
8564            pr "  guestfs_free_%s (r);\n" typ;
8565        | RStructList (_, typ) ->
8566            pr "  rv = copy_%s_list (r);\n" typ;
8567            pr "  guestfs_free_%s_list (r);\n" typ;
8568        | RHashtable _ ->
8569            pr "  rv = copy_table (r);\n";
8570            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8571            pr "  free (r);\n";
8572        | RBufferOut _ ->
8573            pr "  rv = caml_alloc_string (size);\n";
8574            pr "  memcpy (String_val (rv), r, size);\n";
8575       );
8576
8577       pr "  CAMLreturn (rv);\n";
8578       pr "}\n";
8579       pr "\n";
8580
8581       if List.length params > 5 then (
8582         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8583         pr "CAMLprim value ";
8584         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8585         pr "CAMLprim value\n";
8586         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8587         pr "{\n";
8588         pr "  return ocaml_guestfs_%s (argv[0]" name;
8589         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8590         pr ");\n";
8591         pr "}\n";
8592         pr "\n"
8593       )
8594   ) all_functions_sorted
8595
8596 and generate_ocaml_structure_decls () =
8597   List.iter (
8598     fun (typ, cols) ->
8599       pr "type %s = {\n" typ;
8600       List.iter (
8601         function
8602         | name, FString -> pr "  %s : string;\n" name
8603         | name, FBuffer -> pr "  %s : string;\n" name
8604         | name, FUUID -> pr "  %s : string;\n" name
8605         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8606         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8607         | name, FChar -> pr "  %s : char;\n" name
8608         | name, FOptPercent -> pr "  %s : float option;\n" name
8609       ) cols;
8610       pr "}\n";
8611       pr "\n"
8612   ) structs
8613
8614 and generate_ocaml_prototype ?(is_external = false) name style =
8615   if is_external then pr "external " else pr "val ";
8616   pr "%s : t -> " name;
8617   List.iter (
8618     function
8619     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8620     | BufferIn _ -> pr "string -> "
8621     | OptString _ -> pr "string option -> "
8622     | StringList _ | DeviceList _ -> pr "string array -> "
8623     | Bool _ -> pr "bool -> "
8624     | Int _ -> pr "int -> "
8625     | Int64 _ -> pr "int64 -> "
8626   ) (snd style);
8627   (match fst style with
8628    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8629    | RInt _ -> pr "int"
8630    | RInt64 _ -> pr "int64"
8631    | RBool _ -> pr "bool"
8632    | RConstString _ -> pr "string"
8633    | RConstOptString _ -> pr "string option"
8634    | RString _ | RBufferOut _ -> pr "string"
8635    | RStringList _ -> pr "string array"
8636    | RStruct (_, typ) -> pr "%s" typ
8637    | RStructList (_, typ) -> pr "%s array" typ
8638    | RHashtable _ -> pr "(string * string) list"
8639   );
8640   if is_external then (
8641     pr " = ";
8642     if List.length (snd style) + 1 > 5 then
8643       pr "\"ocaml_guestfs_%s_byte\" " name;
8644     pr "\"ocaml_guestfs_%s\"" name
8645   );
8646   pr "\n"
8647
8648 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8649 and generate_perl_xs () =
8650   generate_header CStyle LGPLv2plus;
8651
8652   pr "\
8653 #include \"EXTERN.h\"
8654 #include \"perl.h\"
8655 #include \"XSUB.h\"
8656
8657 #include <guestfs.h>
8658
8659 #ifndef PRId64
8660 #define PRId64 \"lld\"
8661 #endif
8662
8663 static SV *
8664 my_newSVll(long long val) {
8665 #ifdef USE_64_BIT_ALL
8666   return newSViv(val);
8667 #else
8668   char buf[100];
8669   int len;
8670   len = snprintf(buf, 100, \"%%\" PRId64, val);
8671   return newSVpv(buf, len);
8672 #endif
8673 }
8674
8675 #ifndef PRIu64
8676 #define PRIu64 \"llu\"
8677 #endif
8678
8679 static SV *
8680 my_newSVull(unsigned long long val) {
8681 #ifdef USE_64_BIT_ALL
8682   return newSVuv(val);
8683 #else
8684   char buf[100];
8685   int len;
8686   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8687   return newSVpv(buf, len);
8688 #endif
8689 }
8690
8691 /* http://www.perlmonks.org/?node_id=680842 */
8692 static char **
8693 XS_unpack_charPtrPtr (SV *arg) {
8694   char **ret;
8695   AV *av;
8696   I32 i;
8697
8698   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8699     croak (\"array reference expected\");
8700
8701   av = (AV *)SvRV (arg);
8702   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8703   if (!ret)
8704     croak (\"malloc failed\");
8705
8706   for (i = 0; i <= av_len (av); i++) {
8707     SV **elem = av_fetch (av, i, 0);
8708
8709     if (!elem || !*elem)
8710       croak (\"missing element in list\");
8711
8712     ret[i] = SvPV_nolen (*elem);
8713   }
8714
8715   ret[i] = NULL;
8716
8717   return ret;
8718 }
8719
8720 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8721
8722 PROTOTYPES: ENABLE
8723
8724 guestfs_h *
8725 _create ()
8726    CODE:
8727       RETVAL = guestfs_create ();
8728       if (!RETVAL)
8729         croak (\"could not create guestfs handle\");
8730       guestfs_set_error_handler (RETVAL, NULL, NULL);
8731  OUTPUT:
8732       RETVAL
8733
8734 void
8735 DESTROY (g)
8736       guestfs_h *g;
8737  PPCODE:
8738       guestfs_close (g);
8739
8740 ";
8741
8742   List.iter (
8743     fun (name, style, _, _, _, _, _) ->
8744       (match fst style with
8745        | RErr -> pr "void\n"
8746        | RInt _ -> pr "SV *\n"
8747        | RInt64 _ -> pr "SV *\n"
8748        | RBool _ -> pr "SV *\n"
8749        | RConstString _ -> pr "SV *\n"
8750        | RConstOptString _ -> pr "SV *\n"
8751        | RString _ -> pr "SV *\n"
8752        | RBufferOut _ -> pr "SV *\n"
8753        | RStringList _
8754        | RStruct _ | RStructList _
8755        | RHashtable _ ->
8756            pr "void\n" (* all lists returned implictly on the stack *)
8757       );
8758       (* Call and arguments. *)
8759       pr "%s (g" name;
8760       List.iter (
8761         fun arg -> pr ", %s" (name_of_argt arg)
8762       ) (snd style);
8763       pr ")\n";
8764       pr "      guestfs_h *g;\n";
8765       iteri (
8766         fun i ->
8767           function
8768           | Pathname n | Device n | Dev_or_Path n | String n
8769           | FileIn n | FileOut n ->
8770               pr "      char *%s;\n" n
8771           | BufferIn n ->
8772               pr "      char *%s;\n" n;
8773               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8774           | OptString n ->
8775               (* http://www.perlmonks.org/?node_id=554277
8776                * Note that the implicit handle argument means we have
8777                * to add 1 to the ST(x) operator.
8778                *)
8779               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8780           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8781           | Bool n -> pr "      int %s;\n" n
8782           | Int n -> pr "      int %s;\n" n
8783           | Int64 n -> pr "      int64_t %s;\n" n
8784       ) (snd style);
8785
8786       let do_cleanups () =
8787         List.iter (
8788           function
8789           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8790           | Bool _ | Int _ | Int64 _
8791           | FileIn _ | FileOut _
8792           | BufferIn _ -> ()
8793           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8794         ) (snd style)
8795       in
8796
8797       (* Code. *)
8798       (match fst style with
8799        | RErr ->
8800            pr "PREINIT:\n";
8801            pr "      int r;\n";
8802            pr " PPCODE:\n";
8803            pr "      r = guestfs_%s " name;
8804            generate_c_call_args ~handle:"g" style;
8805            pr ";\n";
8806            do_cleanups ();
8807            pr "      if (r == -1)\n";
8808            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8809        | RInt n
8810        | RBool n ->
8811            pr "PREINIT:\n";
8812            pr "      int %s;\n" n;
8813            pr "   CODE:\n";
8814            pr "      %s = guestfs_%s " n name;
8815            generate_c_call_args ~handle:"g" style;
8816            pr ";\n";
8817            do_cleanups ();
8818            pr "      if (%s == -1)\n" n;
8819            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8820            pr "      RETVAL = newSViv (%s);\n" n;
8821            pr " OUTPUT:\n";
8822            pr "      RETVAL\n"
8823        | RInt64 n ->
8824            pr "PREINIT:\n";
8825            pr "      int64_t %s;\n" n;
8826            pr "   CODE:\n";
8827            pr "      %s = guestfs_%s " n name;
8828            generate_c_call_args ~handle:"g" style;
8829            pr ";\n";
8830            do_cleanups ();
8831            pr "      if (%s == -1)\n" n;
8832            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8833            pr "      RETVAL = my_newSVll (%s);\n" n;
8834            pr " OUTPUT:\n";
8835            pr "      RETVAL\n"
8836        | RConstString n ->
8837            pr "PREINIT:\n";
8838            pr "      const char *%s;\n" n;
8839            pr "   CODE:\n";
8840            pr "      %s = guestfs_%s " n name;
8841            generate_c_call_args ~handle:"g" style;
8842            pr ";\n";
8843            do_cleanups ();
8844            pr "      if (%s == NULL)\n" n;
8845            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8846            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8847            pr " OUTPUT:\n";
8848            pr "      RETVAL\n"
8849        | RConstOptString n ->
8850            pr "PREINIT:\n";
8851            pr "      const char *%s;\n" n;
8852            pr "   CODE:\n";
8853            pr "      %s = guestfs_%s " n name;
8854            generate_c_call_args ~handle:"g" style;
8855            pr ";\n";
8856            do_cleanups ();
8857            pr "      if (%s == NULL)\n" n;
8858            pr "        RETVAL = &PL_sv_undef;\n";
8859            pr "      else\n";
8860            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8861            pr " OUTPUT:\n";
8862            pr "      RETVAL\n"
8863        | RString n ->
8864            pr "PREINIT:\n";
8865            pr "      char *%s;\n" n;
8866            pr "   CODE:\n";
8867            pr "      %s = guestfs_%s " n name;
8868            generate_c_call_args ~handle:"g" style;
8869            pr ";\n";
8870            do_cleanups ();
8871            pr "      if (%s == NULL)\n" n;
8872            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8873            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8874            pr "      free (%s);\n" n;
8875            pr " OUTPUT:\n";
8876            pr "      RETVAL\n"
8877        | RStringList n | RHashtable n ->
8878            pr "PREINIT:\n";
8879            pr "      char **%s;\n" n;
8880            pr "      int i, n;\n";
8881            pr " PPCODE:\n";
8882            pr "      %s = guestfs_%s " n name;
8883            generate_c_call_args ~handle:"g" style;
8884            pr ";\n";
8885            do_cleanups ();
8886            pr "      if (%s == NULL)\n" n;
8887            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8888            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8889            pr "      EXTEND (SP, n);\n";
8890            pr "      for (i = 0; i < n; ++i) {\n";
8891            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8892            pr "        free (%s[i]);\n" n;
8893            pr "      }\n";
8894            pr "      free (%s);\n" n;
8895        | RStruct (n, typ) ->
8896            let cols = cols_of_struct typ in
8897            generate_perl_struct_code typ cols name style n do_cleanups
8898        | RStructList (n, typ) ->
8899            let cols = cols_of_struct typ in
8900            generate_perl_struct_list_code typ cols name style n do_cleanups
8901        | RBufferOut n ->
8902            pr "PREINIT:\n";
8903            pr "      char *%s;\n" n;
8904            pr "      size_t size;\n";
8905            pr "   CODE:\n";
8906            pr "      %s = guestfs_%s " n name;
8907            generate_c_call_args ~handle:"g" style;
8908            pr ";\n";
8909            do_cleanups ();
8910            pr "      if (%s == NULL)\n" n;
8911            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8912            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8913            pr "      free (%s);\n" n;
8914            pr " OUTPUT:\n";
8915            pr "      RETVAL\n"
8916       );
8917
8918       pr "\n"
8919   ) all_functions
8920
8921 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8922   pr "PREINIT:\n";
8923   pr "      struct guestfs_%s_list *%s;\n" typ n;
8924   pr "      int i;\n";
8925   pr "      HV *hv;\n";
8926   pr " PPCODE:\n";
8927   pr "      %s = guestfs_%s " n name;
8928   generate_c_call_args ~handle:"g" style;
8929   pr ";\n";
8930   do_cleanups ();
8931   pr "      if (%s == NULL)\n" n;
8932   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8933   pr "      EXTEND (SP, %s->len);\n" n;
8934   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8935   pr "        hv = newHV ();\n";
8936   List.iter (
8937     function
8938     | name, FString ->
8939         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8940           name (String.length name) n name
8941     | name, FUUID ->
8942         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8943           name (String.length name) n name
8944     | name, FBuffer ->
8945         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8946           name (String.length name) n name n name
8947     | name, (FBytes|FUInt64) ->
8948         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8949           name (String.length name) n name
8950     | name, FInt64 ->
8951         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8952           name (String.length name) n name
8953     | name, (FInt32|FUInt32) ->
8954         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8955           name (String.length name) n name
8956     | name, FChar ->
8957         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8958           name (String.length name) n name
8959     | name, FOptPercent ->
8960         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8961           name (String.length name) n name
8962   ) cols;
8963   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8964   pr "      }\n";
8965   pr "      guestfs_free_%s_list (%s);\n" typ n
8966
8967 and generate_perl_struct_code typ cols name style n do_cleanups =
8968   pr "PREINIT:\n";
8969   pr "      struct guestfs_%s *%s;\n" typ n;
8970   pr " PPCODE:\n";
8971   pr "      %s = guestfs_%s " n name;
8972   generate_c_call_args ~handle:"g" style;
8973   pr ";\n";
8974   do_cleanups ();
8975   pr "      if (%s == NULL)\n" n;
8976   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8977   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8978   List.iter (
8979     fun ((name, _) as col) ->
8980       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8981
8982       match col with
8983       | name, FString ->
8984           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8985             n name
8986       | name, FBuffer ->
8987           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8988             n name n name
8989       | name, FUUID ->
8990           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8991             n name
8992       | name, (FBytes|FUInt64) ->
8993           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8994             n name
8995       | name, FInt64 ->
8996           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8997             n name
8998       | name, (FInt32|FUInt32) ->
8999           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9000             n name
9001       | name, FChar ->
9002           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9003             n name
9004       | name, FOptPercent ->
9005           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9006             n name
9007   ) cols;
9008   pr "      free (%s);\n" n
9009
9010 (* Generate Sys/Guestfs.pm. *)
9011 and generate_perl_pm () =
9012   generate_header HashStyle LGPLv2plus;
9013
9014   pr "\
9015 =pod
9016
9017 =head1 NAME
9018
9019 Sys::Guestfs - Perl bindings for libguestfs
9020
9021 =head1 SYNOPSIS
9022
9023  use Sys::Guestfs;
9024
9025  my $h = Sys::Guestfs->new ();
9026  $h->add_drive ('guest.img');
9027  $h->launch ();
9028  $h->mount ('/dev/sda1', '/');
9029  $h->touch ('/hello');
9030  $h->sync ();
9031
9032 =head1 DESCRIPTION
9033
9034 The C<Sys::Guestfs> module provides a Perl XS binding to the
9035 libguestfs API for examining and modifying virtual machine
9036 disk images.
9037
9038 Amongst the things this is good for: making batch configuration
9039 changes to guests, getting disk used/free statistics (see also:
9040 virt-df), migrating between virtualization systems (see also:
9041 virt-p2v), performing partial backups, performing partial guest
9042 clones, cloning guests and changing registry/UUID/hostname info, and
9043 much else besides.
9044
9045 Libguestfs uses Linux kernel and qemu code, and can access any type of
9046 guest filesystem that Linux and qemu can, including but not limited
9047 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9048 schemes, qcow, qcow2, vmdk.
9049
9050 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9051 LVs, what filesystem is in each LV, etc.).  It can also run commands
9052 in the context of the guest.  Also you can access filesystems over
9053 FUSE.
9054
9055 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9056 functions for using libguestfs from Perl, including integration
9057 with libvirt.
9058
9059 =head1 ERRORS
9060
9061 All errors turn into calls to C<croak> (see L<Carp(3)>).
9062
9063 =head1 METHODS
9064
9065 =over 4
9066
9067 =cut
9068
9069 package Sys::Guestfs;
9070
9071 use strict;
9072 use warnings;
9073
9074 # This version number changes whenever a new function
9075 # is added to the libguestfs API.  It is not directly
9076 # related to the libguestfs version number.
9077 use vars qw($VERSION);
9078 $VERSION = '0.%d';
9079
9080 require XSLoader;
9081 XSLoader::load ('Sys::Guestfs');
9082
9083 =item $h = Sys::Guestfs->new ();
9084
9085 Create a new guestfs handle.
9086
9087 =cut
9088
9089 sub new {
9090   my $proto = shift;
9091   my $class = ref ($proto) || $proto;
9092
9093   my $self = Sys::Guestfs::_create ();
9094   bless $self, $class;
9095   return $self;
9096 }
9097
9098 " max_proc_nr;
9099
9100   (* Actions.  We only need to print documentation for these as
9101    * they are pulled in from the XS code automatically.
9102    *)
9103   List.iter (
9104     fun (name, style, _, flags, _, _, longdesc) ->
9105       if not (List.mem NotInDocs flags) then (
9106         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9107         pr "=item ";
9108         generate_perl_prototype name style;
9109         pr "\n\n";
9110         pr "%s\n\n" longdesc;
9111         if List.mem ProtocolLimitWarning flags then
9112           pr "%s\n\n" protocol_limit_warning;
9113         if List.mem DangerWillRobinson flags then
9114           pr "%s\n\n" danger_will_robinson;
9115         match deprecation_notice flags with
9116         | None -> ()
9117         | Some txt -> pr "%s\n\n" txt
9118       )
9119   ) all_functions_sorted;
9120
9121   (* End of file. *)
9122   pr "\
9123 =cut
9124
9125 1;
9126
9127 =back
9128
9129 =head1 COPYRIGHT
9130
9131 Copyright (C) %s Red Hat Inc.
9132
9133 =head1 LICENSE
9134
9135 Please see the file COPYING.LIB for the full license.
9136
9137 =head1 SEE ALSO
9138
9139 L<guestfs(3)>,
9140 L<guestfish(1)>,
9141 L<http://libguestfs.org>,
9142 L<Sys::Guestfs::Lib(3)>.
9143
9144 =cut
9145 " copyright_years
9146
9147 and generate_perl_prototype name style =
9148   (match fst style with
9149    | RErr -> ()
9150    | RBool n
9151    | RInt n
9152    | RInt64 n
9153    | RConstString n
9154    | RConstOptString n
9155    | RString n
9156    | RBufferOut n -> pr "$%s = " n
9157    | RStruct (n,_)
9158    | RHashtable n -> pr "%%%s = " n
9159    | RStringList n
9160    | RStructList (n,_) -> pr "@%s = " n
9161   );
9162   pr "$h->%s (" name;
9163   let comma = ref false in
9164   List.iter (
9165     fun arg ->
9166       if !comma then pr ", ";
9167       comma := true;
9168       match arg with
9169       | Pathname n | Device n | Dev_or_Path n | String n
9170       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9171       | BufferIn n ->
9172           pr "$%s" n
9173       | StringList n | DeviceList n ->
9174           pr "\\@%s" n
9175   ) (snd style);
9176   pr ");"
9177
9178 (* Generate Python C module. *)
9179 and generate_python_c () =
9180   generate_header CStyle LGPLv2plus;
9181
9182   pr "\
9183 #define PY_SSIZE_T_CLEAN 1
9184 #include <Python.h>
9185
9186 #if PY_VERSION_HEX < 0x02050000
9187 typedef int Py_ssize_t;
9188 #define PY_SSIZE_T_MAX INT_MAX
9189 #define PY_SSIZE_T_MIN INT_MIN
9190 #endif
9191
9192 #include <stdio.h>
9193 #include <stdlib.h>
9194 #include <assert.h>
9195
9196 #include \"guestfs.h\"
9197
9198 typedef struct {
9199   PyObject_HEAD
9200   guestfs_h *g;
9201 } Pyguestfs_Object;
9202
9203 static guestfs_h *
9204 get_handle (PyObject *obj)
9205 {
9206   assert (obj);
9207   assert (obj != Py_None);
9208   return ((Pyguestfs_Object *) obj)->g;
9209 }
9210
9211 static PyObject *
9212 put_handle (guestfs_h *g)
9213 {
9214   assert (g);
9215   return
9216     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9217 }
9218
9219 /* This list should be freed (but not the strings) after use. */
9220 static char **
9221 get_string_list (PyObject *obj)
9222 {
9223   int i, len;
9224   char **r;
9225
9226   assert (obj);
9227
9228   if (!PyList_Check (obj)) {
9229     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9230     return NULL;
9231   }
9232
9233   len = PyList_Size (obj);
9234   r = malloc (sizeof (char *) * (len+1));
9235   if (r == NULL) {
9236     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9237     return NULL;
9238   }
9239
9240   for (i = 0; i < len; ++i)
9241     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9242   r[len] = NULL;
9243
9244   return r;
9245 }
9246
9247 static PyObject *
9248 put_string_list (char * const * const argv)
9249 {
9250   PyObject *list;
9251   int argc, i;
9252
9253   for (argc = 0; argv[argc] != NULL; ++argc)
9254     ;
9255
9256   list = PyList_New (argc);
9257   for (i = 0; i < argc; ++i)
9258     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9259
9260   return list;
9261 }
9262
9263 static PyObject *
9264 put_table (char * const * const argv)
9265 {
9266   PyObject *list, *item;
9267   int argc, i;
9268
9269   for (argc = 0; argv[argc] != NULL; ++argc)
9270     ;
9271
9272   list = PyList_New (argc >> 1);
9273   for (i = 0; i < argc; i += 2) {
9274     item = PyTuple_New (2);
9275     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9276     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9277     PyList_SetItem (list, i >> 1, item);
9278   }
9279
9280   return list;
9281 }
9282
9283 static void
9284 free_strings (char **argv)
9285 {
9286   int argc;
9287
9288   for (argc = 0; argv[argc] != NULL; ++argc)
9289     free (argv[argc]);
9290   free (argv);
9291 }
9292
9293 static PyObject *
9294 py_guestfs_create (PyObject *self, PyObject *args)
9295 {
9296   guestfs_h *g;
9297
9298   g = guestfs_create ();
9299   if (g == NULL) {
9300     PyErr_SetString (PyExc_RuntimeError,
9301                      \"guestfs.create: failed to allocate handle\");
9302     return NULL;
9303   }
9304   guestfs_set_error_handler (g, NULL, NULL);
9305   return put_handle (g);
9306 }
9307
9308 static PyObject *
9309 py_guestfs_close (PyObject *self, PyObject *args)
9310 {
9311   PyObject *py_g;
9312   guestfs_h *g;
9313
9314   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9315     return NULL;
9316   g = get_handle (py_g);
9317
9318   guestfs_close (g);
9319
9320   Py_INCREF (Py_None);
9321   return Py_None;
9322 }
9323
9324 ";
9325
9326   let emit_put_list_function typ =
9327     pr "static PyObject *\n";
9328     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9329     pr "{\n";
9330     pr "  PyObject *list;\n";
9331     pr "  int i;\n";
9332     pr "\n";
9333     pr "  list = PyList_New (%ss->len);\n" typ;
9334     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9335     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9336     pr "  return list;\n";
9337     pr "};\n";
9338     pr "\n"
9339   in
9340
9341   (* Structures, turned into Python dictionaries. *)
9342   List.iter (
9343     fun (typ, cols) ->
9344       pr "static PyObject *\n";
9345       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9346       pr "{\n";
9347       pr "  PyObject *dict;\n";
9348       pr "\n";
9349       pr "  dict = PyDict_New ();\n";
9350       List.iter (
9351         function
9352         | name, FString ->
9353             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9354             pr "                        PyString_FromString (%s->%s));\n"
9355               typ name
9356         | name, FBuffer ->
9357             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9358             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9359               typ name typ name
9360         | name, FUUID ->
9361             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9362             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9363               typ name
9364         | name, (FBytes|FUInt64) ->
9365             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9366             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9367               typ name
9368         | name, FInt64 ->
9369             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9370             pr "                        PyLong_FromLongLong (%s->%s));\n"
9371               typ name
9372         | name, FUInt32 ->
9373             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9374             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9375               typ name
9376         | name, FInt32 ->
9377             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9378             pr "                        PyLong_FromLong (%s->%s));\n"
9379               typ name
9380         | name, FOptPercent ->
9381             pr "  if (%s->%s >= 0)\n" typ name;
9382             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9383             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9384               typ name;
9385             pr "  else {\n";
9386             pr "    Py_INCREF (Py_None);\n";
9387             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9388             pr "  }\n"
9389         | name, FChar ->
9390             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9391             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9392       ) cols;
9393       pr "  return dict;\n";
9394       pr "};\n";
9395       pr "\n";
9396
9397   ) structs;
9398
9399   (* Emit a put_TYPE_list function definition only if that function is used. *)
9400   List.iter (
9401     function
9402     | typ, (RStructListOnly | RStructAndList) ->
9403         (* generate the function for typ *)
9404         emit_put_list_function typ
9405     | typ, _ -> () (* empty *)
9406   ) (rstructs_used_by all_functions);
9407
9408   (* Python wrapper functions. *)
9409   List.iter (
9410     fun (name, style, _, _, _, _, _) ->
9411       pr "static PyObject *\n";
9412       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9413       pr "{\n";
9414
9415       pr "  PyObject *py_g;\n";
9416       pr "  guestfs_h *g;\n";
9417       pr "  PyObject *py_r;\n";
9418
9419       let error_code =
9420         match fst style with
9421         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9422         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9423         | RConstString _ | RConstOptString _ ->
9424             pr "  const char *r;\n"; "NULL"
9425         | RString _ -> pr "  char *r;\n"; "NULL"
9426         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9427         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9428         | RStructList (_, typ) ->
9429             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9430         | RBufferOut _ ->
9431             pr "  char *r;\n";
9432             pr "  size_t size;\n";
9433             "NULL" in
9434
9435       List.iter (
9436         function
9437         | Pathname n | Device n | Dev_or_Path n | String n
9438         | FileIn n | FileOut n ->
9439             pr "  const char *%s;\n" n
9440         | OptString n -> pr "  const char *%s;\n" n
9441         | BufferIn n ->
9442             pr "  const char *%s;\n" n;
9443             pr "  Py_ssize_t %s_size;\n" n
9444         | StringList n | DeviceList n ->
9445             pr "  PyObject *py_%s;\n" n;
9446             pr "  char **%s;\n" n
9447         | Bool n -> pr "  int %s;\n" n
9448         | Int n -> pr "  int %s;\n" n
9449         | Int64 n -> pr "  long long %s;\n" n
9450       ) (snd style);
9451
9452       pr "\n";
9453
9454       (* Convert the parameters. *)
9455       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9456       List.iter (
9457         function
9458         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9459         | OptString _ -> pr "z"
9460         | StringList _ | DeviceList _ -> pr "O"
9461         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9462         | Int _ -> pr "i"
9463         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9464                              * emulate C's int/long/long long in Python?
9465                              *)
9466         | BufferIn _ -> pr "s#"
9467       ) (snd style);
9468       pr ":guestfs_%s\",\n" name;
9469       pr "                         &py_g";
9470       List.iter (
9471         function
9472         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9473         | OptString n -> pr ", &%s" n
9474         | StringList n | DeviceList n -> pr ", &py_%s" n
9475         | Bool n -> pr ", &%s" n
9476         | Int n -> pr ", &%s" n
9477         | Int64 n -> pr ", &%s" n
9478         | BufferIn n -> pr ", &%s, &%s_size" n n
9479       ) (snd style);
9480
9481       pr "))\n";
9482       pr "    return NULL;\n";
9483
9484       pr "  g = get_handle (py_g);\n";
9485       List.iter (
9486         function
9487         | Pathname _ | Device _ | Dev_or_Path _ | String _
9488         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9489         | BufferIn _ -> ()
9490         | StringList n | DeviceList n ->
9491             pr "  %s = get_string_list (py_%s);\n" n n;
9492             pr "  if (!%s) return NULL;\n" n
9493       ) (snd style);
9494
9495       pr "\n";
9496
9497       pr "  r = guestfs_%s " name;
9498       generate_c_call_args ~handle:"g" style;
9499       pr ";\n";
9500
9501       List.iter (
9502         function
9503         | Pathname _ | Device _ | Dev_or_Path _ | String _
9504         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9505         | BufferIn _ -> ()
9506         | StringList n | DeviceList n ->
9507             pr "  free (%s);\n" n
9508       ) (snd style);
9509
9510       pr "  if (r == %s) {\n" error_code;
9511       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9512       pr "    return NULL;\n";
9513       pr "  }\n";
9514       pr "\n";
9515
9516       (match fst style with
9517        | RErr ->
9518            pr "  Py_INCREF (Py_None);\n";
9519            pr "  py_r = Py_None;\n"
9520        | RInt _
9521        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9522        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9523        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9524        | RConstOptString _ ->
9525            pr "  if (r)\n";
9526            pr "    py_r = PyString_FromString (r);\n";
9527            pr "  else {\n";
9528            pr "    Py_INCREF (Py_None);\n";
9529            pr "    py_r = Py_None;\n";
9530            pr "  }\n"
9531        | RString _ ->
9532            pr "  py_r = PyString_FromString (r);\n";
9533            pr "  free (r);\n"
9534        | RStringList _ ->
9535            pr "  py_r = put_string_list (r);\n";
9536            pr "  free_strings (r);\n"
9537        | RStruct (_, typ) ->
9538            pr "  py_r = put_%s (r);\n" typ;
9539            pr "  guestfs_free_%s (r);\n" typ
9540        | RStructList (_, typ) ->
9541            pr "  py_r = put_%s_list (r);\n" typ;
9542            pr "  guestfs_free_%s_list (r);\n" typ
9543        | RHashtable n ->
9544            pr "  py_r = put_table (r);\n";
9545            pr "  free_strings (r);\n"
9546        | RBufferOut _ ->
9547            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9548            pr "  free (r);\n"
9549       );
9550
9551       pr "  return py_r;\n";
9552       pr "}\n";
9553       pr "\n"
9554   ) all_functions;
9555
9556   (* Table of functions. *)
9557   pr "static PyMethodDef methods[] = {\n";
9558   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9559   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9560   List.iter (
9561     fun (name, _, _, _, _, _, _) ->
9562       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9563         name name
9564   ) all_functions;
9565   pr "  { NULL, NULL, 0, NULL }\n";
9566   pr "};\n";
9567   pr "\n";
9568
9569   (* Init function. *)
9570   pr "\
9571 void
9572 initlibguestfsmod (void)
9573 {
9574   static int initialized = 0;
9575
9576   if (initialized) return;
9577   Py_InitModule ((char *) \"libguestfsmod\", methods);
9578   initialized = 1;
9579 }
9580 "
9581
9582 (* Generate Python module. *)
9583 and generate_python_py () =
9584   generate_header HashStyle LGPLv2plus;
9585
9586   pr "\
9587 u\"\"\"Python bindings for libguestfs
9588
9589 import guestfs
9590 g = guestfs.GuestFS ()
9591 g.add_drive (\"guest.img\")
9592 g.launch ()
9593 parts = g.list_partitions ()
9594
9595 The guestfs module provides a Python binding to the libguestfs API
9596 for examining and modifying virtual machine disk images.
9597
9598 Amongst the things this is good for: making batch configuration
9599 changes to guests, getting disk used/free statistics (see also:
9600 virt-df), migrating between virtualization systems (see also:
9601 virt-p2v), performing partial backups, performing partial guest
9602 clones, cloning guests and changing registry/UUID/hostname info, and
9603 much else besides.
9604
9605 Libguestfs uses Linux kernel and qemu code, and can access any type of
9606 guest filesystem that Linux and qemu can, including but not limited
9607 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9608 schemes, qcow, qcow2, vmdk.
9609
9610 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9611 LVs, what filesystem is in each LV, etc.).  It can also run commands
9612 in the context of the guest.  Also you can access filesystems over
9613 FUSE.
9614
9615 Errors which happen while using the API are turned into Python
9616 RuntimeError exceptions.
9617
9618 To create a guestfs handle you usually have to perform the following
9619 sequence of calls:
9620
9621 # Create the handle, call add_drive at least once, and possibly
9622 # several times if the guest has multiple block devices:
9623 g = guestfs.GuestFS ()
9624 g.add_drive (\"guest.img\")
9625
9626 # Launch the qemu subprocess and wait for it to become ready:
9627 g.launch ()
9628
9629 # Now you can issue commands, for example:
9630 logvols = g.lvs ()
9631
9632 \"\"\"
9633
9634 import libguestfsmod
9635
9636 class GuestFS:
9637     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9638
9639     def __init__ (self):
9640         \"\"\"Create a new libguestfs handle.\"\"\"
9641         self._o = libguestfsmod.create ()
9642
9643     def __del__ (self):
9644         libguestfsmod.close (self._o)
9645
9646 ";
9647
9648   List.iter (
9649     fun (name, style, _, flags, _, _, longdesc) ->
9650       pr "    def %s " name;
9651       generate_py_call_args ~handle:"self" (snd style);
9652       pr ":\n";
9653
9654       if not (List.mem NotInDocs flags) then (
9655         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9656         let doc =
9657           match fst style with
9658           | RErr | RInt _ | RInt64 _ | RBool _
9659           | RConstOptString _ | RConstString _
9660           | RString _ | RBufferOut _ -> doc
9661           | RStringList _ ->
9662               doc ^ "\n\nThis function returns a list of strings."
9663           | RStruct (_, typ) ->
9664               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9665           | RStructList (_, typ) ->
9666               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9667           | RHashtable _ ->
9668               doc ^ "\n\nThis function returns a dictionary." in
9669         let doc =
9670           if List.mem ProtocolLimitWarning flags then
9671             doc ^ "\n\n" ^ protocol_limit_warning
9672           else doc in
9673         let doc =
9674           if List.mem DangerWillRobinson flags then
9675             doc ^ "\n\n" ^ danger_will_robinson
9676           else doc in
9677         let doc =
9678           match deprecation_notice flags with
9679           | None -> doc
9680           | Some txt -> doc ^ "\n\n" ^ txt in
9681         let doc = pod2text ~width:60 name doc in
9682         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9683         let doc = String.concat "\n        " doc in
9684         pr "        u\"\"\"%s\"\"\"\n" doc;
9685       );
9686       pr "        return libguestfsmod.%s " name;
9687       generate_py_call_args ~handle:"self._o" (snd style);
9688       pr "\n";
9689       pr "\n";
9690   ) all_functions
9691
9692 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9693 and generate_py_call_args ~handle args =
9694   pr "(%s" handle;
9695   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9696   pr ")"
9697
9698 (* Useful if you need the longdesc POD text as plain text.  Returns a
9699  * list of lines.
9700  *
9701  * Because this is very slow (the slowest part of autogeneration),
9702  * we memoize the results.
9703  *)
9704 and pod2text ~width name longdesc =
9705   let key = width, name, longdesc in
9706   try Hashtbl.find pod2text_memo key
9707   with Not_found ->
9708     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9709     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9710     close_out chan;
9711     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9712     let chan = open_process_in cmd in
9713     let lines = ref [] in
9714     let rec loop i =
9715       let line = input_line chan in
9716       if i = 1 then             (* discard the first line of output *)
9717         loop (i+1)
9718       else (
9719         let line = triml line in
9720         lines := line :: !lines;
9721         loop (i+1)
9722       ) in
9723     let lines = try loop 1 with End_of_file -> List.rev !lines in
9724     unlink filename;
9725     (match close_process_in chan with
9726      | WEXITED 0 -> ()
9727      | WEXITED i ->
9728          failwithf "pod2text: process exited with non-zero status (%d)" i
9729      | WSIGNALED i | WSTOPPED i ->
9730          failwithf "pod2text: process signalled or stopped by signal %d" i
9731     );
9732     Hashtbl.add pod2text_memo key lines;
9733     pod2text_memo_updated ();
9734     lines
9735
9736 (* Generate ruby bindings. *)
9737 and generate_ruby_c () =
9738   generate_header CStyle LGPLv2plus;
9739
9740   pr "\
9741 #include <stdio.h>
9742 #include <stdlib.h>
9743
9744 #include <ruby.h>
9745
9746 #include \"guestfs.h\"
9747
9748 #include \"extconf.h\"
9749
9750 /* For Ruby < 1.9 */
9751 #ifndef RARRAY_LEN
9752 #define RARRAY_LEN(r) (RARRAY((r))->len)
9753 #endif
9754
9755 static VALUE m_guestfs;                 /* guestfs module */
9756 static VALUE c_guestfs;                 /* guestfs_h handle */
9757 static VALUE e_Error;                   /* used for all errors */
9758
9759 static void ruby_guestfs_free (void *p)
9760 {
9761   if (!p) return;
9762   guestfs_close ((guestfs_h *) p);
9763 }
9764
9765 static VALUE ruby_guestfs_create (VALUE m)
9766 {
9767   guestfs_h *g;
9768
9769   g = guestfs_create ();
9770   if (!g)
9771     rb_raise (e_Error, \"failed to create guestfs handle\");
9772
9773   /* Don't print error messages to stderr by default. */
9774   guestfs_set_error_handler (g, NULL, NULL);
9775
9776   /* Wrap it, and make sure the close function is called when the
9777    * handle goes away.
9778    */
9779   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9780 }
9781
9782 static VALUE ruby_guestfs_close (VALUE gv)
9783 {
9784   guestfs_h *g;
9785   Data_Get_Struct (gv, guestfs_h, g);
9786
9787   ruby_guestfs_free (g);
9788   DATA_PTR (gv) = NULL;
9789
9790   return Qnil;
9791 }
9792
9793 ";
9794
9795   List.iter (
9796     fun (name, style, _, _, _, _, _) ->
9797       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9798       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9799       pr ")\n";
9800       pr "{\n";
9801       pr "  guestfs_h *g;\n";
9802       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9803       pr "  if (!g)\n";
9804       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9805         name;
9806       pr "\n";
9807
9808       List.iter (
9809         function
9810         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9811             pr "  Check_Type (%sv, T_STRING);\n" n;
9812             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9813             pr "  if (!%s)\n" n;
9814             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9815             pr "              \"%s\", \"%s\");\n" n name
9816         | BufferIn n ->
9817             pr "  Check_Type (%sv, T_STRING);\n" n;
9818             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9819             pr "  if (!%s)\n" n;
9820             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9821             pr "              \"%s\", \"%s\");\n" n name;
9822             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9823         | OptString n ->
9824             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9825         | StringList n | DeviceList n ->
9826             pr "  char **%s;\n" n;
9827             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9828             pr "  {\n";
9829             pr "    int i, len;\n";
9830             pr "    len = RARRAY_LEN (%sv);\n" n;
9831             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9832               n;
9833             pr "    for (i = 0; i < len; ++i) {\n";
9834             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9835             pr "      %s[i] = StringValueCStr (v);\n" n;
9836             pr "    }\n";
9837             pr "    %s[len] = NULL;\n" n;
9838             pr "  }\n";
9839         | Bool n ->
9840             pr "  int %s = RTEST (%sv);\n" n n
9841         | Int n ->
9842             pr "  int %s = NUM2INT (%sv);\n" n n
9843         | Int64 n ->
9844             pr "  long long %s = NUM2LL (%sv);\n" n n
9845       ) (snd style);
9846       pr "\n";
9847
9848       let error_code =
9849         match fst style with
9850         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9851         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9852         | RConstString _ | RConstOptString _ ->
9853             pr "  const char *r;\n"; "NULL"
9854         | RString _ -> pr "  char *r;\n"; "NULL"
9855         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9856         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9857         | RStructList (_, typ) ->
9858             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9859         | RBufferOut _ ->
9860             pr "  char *r;\n";
9861             pr "  size_t size;\n";
9862             "NULL" in
9863       pr "\n";
9864
9865       pr "  r = guestfs_%s " name;
9866       generate_c_call_args ~handle:"g" style;
9867       pr ";\n";
9868
9869       List.iter (
9870         function
9871         | Pathname _ | Device _ | Dev_or_Path _ | String _
9872         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9873         | BufferIn _ -> ()
9874         | StringList n | DeviceList n ->
9875             pr "  free (%s);\n" n
9876       ) (snd style);
9877
9878       pr "  if (r == %s)\n" error_code;
9879       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9880       pr "\n";
9881
9882       (match fst style with
9883        | RErr ->
9884            pr "  return Qnil;\n"
9885        | RInt _ | RBool _ ->
9886            pr "  return INT2NUM (r);\n"
9887        | RInt64 _ ->
9888            pr "  return ULL2NUM (r);\n"
9889        | RConstString _ ->
9890            pr "  return rb_str_new2 (r);\n";
9891        | RConstOptString _ ->
9892            pr "  if (r)\n";
9893            pr "    return rb_str_new2 (r);\n";
9894            pr "  else\n";
9895            pr "    return Qnil;\n";
9896        | RString _ ->
9897            pr "  VALUE rv = rb_str_new2 (r);\n";
9898            pr "  free (r);\n";
9899            pr "  return rv;\n";
9900        | RStringList _ ->
9901            pr "  int i, len = 0;\n";
9902            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9903            pr "  VALUE rv = rb_ary_new2 (len);\n";
9904            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9905            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9906            pr "    free (r[i]);\n";
9907            pr "  }\n";
9908            pr "  free (r);\n";
9909            pr "  return rv;\n"
9910        | RStruct (_, typ) ->
9911            let cols = cols_of_struct typ in
9912            generate_ruby_struct_code typ cols
9913        | RStructList (_, typ) ->
9914            let cols = cols_of_struct typ in
9915            generate_ruby_struct_list_code typ cols
9916        | RHashtable _ ->
9917            pr "  VALUE rv = rb_hash_new ();\n";
9918            pr "  int i;\n";
9919            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9920            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9921            pr "    free (r[i]);\n";
9922            pr "    free (r[i+1]);\n";
9923            pr "  }\n";
9924            pr "  free (r);\n";
9925            pr "  return rv;\n"
9926        | RBufferOut _ ->
9927            pr "  VALUE rv = rb_str_new (r, size);\n";
9928            pr "  free (r);\n";
9929            pr "  return rv;\n";
9930       );
9931
9932       pr "}\n";
9933       pr "\n"
9934   ) all_functions;
9935
9936   pr "\
9937 /* Initialize the module. */
9938 void Init__guestfs ()
9939 {
9940   m_guestfs = rb_define_module (\"Guestfs\");
9941   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9942   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9943
9944   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9945   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9946
9947 ";
9948   (* Define the rest of the methods. *)
9949   List.iter (
9950     fun (name, style, _, _, _, _, _) ->
9951       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9952       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9953   ) all_functions;
9954
9955   pr "}\n"
9956
9957 (* Ruby code to return a struct. *)
9958 and generate_ruby_struct_code typ cols =
9959   pr "  VALUE rv = rb_hash_new ();\n";
9960   List.iter (
9961     function
9962     | name, FString ->
9963         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9964     | name, FBuffer ->
9965         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9966     | name, FUUID ->
9967         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9968     | name, (FBytes|FUInt64) ->
9969         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9970     | name, FInt64 ->
9971         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9972     | name, FUInt32 ->
9973         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9974     | name, FInt32 ->
9975         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9976     | name, FOptPercent ->
9977         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9978     | name, FChar -> (* XXX wrong? *)
9979         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9980   ) cols;
9981   pr "  guestfs_free_%s (r);\n" typ;
9982   pr "  return rv;\n"
9983
9984 (* Ruby code to return a struct list. *)
9985 and generate_ruby_struct_list_code typ cols =
9986   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9987   pr "  int i;\n";
9988   pr "  for (i = 0; i < r->len; ++i) {\n";
9989   pr "    VALUE hv = rb_hash_new ();\n";
9990   List.iter (
9991     function
9992     | name, FString ->
9993         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9994     | name, FBuffer ->
9995         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
9996     | name, FUUID ->
9997         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9998     | name, (FBytes|FUInt64) ->
9999         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10000     | name, FInt64 ->
10001         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10002     | name, FUInt32 ->
10003         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10004     | name, FInt32 ->
10005         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10006     | name, FOptPercent ->
10007         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10008     | name, FChar -> (* XXX wrong? *)
10009         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10010   ) cols;
10011   pr "    rb_ary_push (rv, hv);\n";
10012   pr "  }\n";
10013   pr "  guestfs_free_%s_list (r);\n" typ;
10014   pr "  return rv;\n"
10015
10016 (* Generate Java bindings GuestFS.java file. *)
10017 and generate_java_java () =
10018   generate_header CStyle LGPLv2plus;
10019
10020   pr "\
10021 package com.redhat.et.libguestfs;
10022
10023 import java.util.HashMap;
10024 import com.redhat.et.libguestfs.LibGuestFSException;
10025 import com.redhat.et.libguestfs.PV;
10026 import com.redhat.et.libguestfs.VG;
10027 import com.redhat.et.libguestfs.LV;
10028 import com.redhat.et.libguestfs.Stat;
10029 import com.redhat.et.libguestfs.StatVFS;
10030 import com.redhat.et.libguestfs.IntBool;
10031 import com.redhat.et.libguestfs.Dirent;
10032
10033 /**
10034  * The GuestFS object is a libguestfs handle.
10035  *
10036  * @author rjones
10037  */
10038 public class GuestFS {
10039   // Load the native code.
10040   static {
10041     System.loadLibrary (\"guestfs_jni\");
10042   }
10043
10044   /**
10045    * The native guestfs_h pointer.
10046    */
10047   long g;
10048
10049   /**
10050    * Create a libguestfs handle.
10051    *
10052    * @throws LibGuestFSException
10053    */
10054   public GuestFS () throws LibGuestFSException
10055   {
10056     g = _create ();
10057   }
10058   private native long _create () throws LibGuestFSException;
10059
10060   /**
10061    * Close a libguestfs handle.
10062    *
10063    * You can also leave handles to be collected by the garbage
10064    * collector, but this method ensures that the resources used
10065    * by the handle are freed up immediately.  If you call any
10066    * other methods after closing the handle, you will get an
10067    * exception.
10068    *
10069    * @throws LibGuestFSException
10070    */
10071   public void close () throws LibGuestFSException
10072   {
10073     if (g != 0)
10074       _close (g);
10075     g = 0;
10076   }
10077   private native void _close (long g) throws LibGuestFSException;
10078
10079   public void finalize () throws LibGuestFSException
10080   {
10081     close ();
10082   }
10083
10084 ";
10085
10086   List.iter (
10087     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10088       if not (List.mem NotInDocs flags); then (
10089         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10090         let doc =
10091           if List.mem ProtocolLimitWarning flags then
10092             doc ^ "\n\n" ^ protocol_limit_warning
10093           else doc in
10094         let doc =
10095           if List.mem DangerWillRobinson flags then
10096             doc ^ "\n\n" ^ danger_will_robinson
10097           else doc in
10098         let doc =
10099           match deprecation_notice flags with
10100           | None -> doc
10101           | Some txt -> doc ^ "\n\n" ^ txt in
10102         let doc = pod2text ~width:60 name doc in
10103         let doc = List.map (            (* RHBZ#501883 *)
10104           function
10105           | "" -> "<p>"
10106           | nonempty -> nonempty
10107         ) doc in
10108         let doc = String.concat "\n   * " doc in
10109
10110         pr "  /**\n";
10111         pr "   * %s\n" shortdesc;
10112         pr "   * <p>\n";
10113         pr "   * %s\n" doc;
10114         pr "   * @throws LibGuestFSException\n";
10115         pr "   */\n";
10116         pr "  ";
10117       );
10118       generate_java_prototype ~public:true ~semicolon:false name style;
10119       pr "\n";
10120       pr "  {\n";
10121       pr "    if (g == 0)\n";
10122       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10123         name;
10124       pr "    ";
10125       if fst style <> RErr then pr "return ";
10126       pr "_%s " name;
10127       generate_java_call_args ~handle:"g" (snd style);
10128       pr ";\n";
10129       pr "  }\n";
10130       pr "  ";
10131       generate_java_prototype ~privat:true ~native:true name style;
10132       pr "\n";
10133       pr "\n";
10134   ) all_functions;
10135
10136   pr "}\n"
10137
10138 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10139 and generate_java_call_args ~handle args =
10140   pr "(%s" handle;
10141   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10142   pr ")"
10143
10144 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10145     ?(semicolon=true) name style =
10146   if privat then pr "private ";
10147   if public then pr "public ";
10148   if native then pr "native ";
10149
10150   (* return type *)
10151   (match fst style with
10152    | RErr -> pr "void ";
10153    | RInt _ -> pr "int ";
10154    | RInt64 _ -> pr "long ";
10155    | RBool _ -> pr "boolean ";
10156    | RConstString _ | RConstOptString _ | RString _
10157    | RBufferOut _ -> pr "String ";
10158    | RStringList _ -> pr "String[] ";
10159    | RStruct (_, typ) ->
10160        let name = java_name_of_struct typ in
10161        pr "%s " name;
10162    | RStructList (_, typ) ->
10163        let name = java_name_of_struct typ in
10164        pr "%s[] " name;
10165    | RHashtable _ -> pr "HashMap<String,String> ";
10166   );
10167
10168   if native then pr "_%s " name else pr "%s " name;
10169   pr "(";
10170   let needs_comma = ref false in
10171   if native then (
10172     pr "long g";
10173     needs_comma := true
10174   );
10175
10176   (* args *)
10177   List.iter (
10178     fun arg ->
10179       if !needs_comma then pr ", ";
10180       needs_comma := true;
10181
10182       match arg with
10183       | Pathname n
10184       | Device n | Dev_or_Path n
10185       | String n
10186       | OptString n
10187       | FileIn n
10188       | FileOut n ->
10189           pr "String %s" n
10190       | BufferIn n ->
10191           pr "byte[] %s" n
10192       | StringList n | DeviceList n ->
10193           pr "String[] %s" n
10194       | Bool n ->
10195           pr "boolean %s" n
10196       | Int n ->
10197           pr "int %s" n
10198       | Int64 n ->
10199           pr "long %s" n
10200   ) (snd style);
10201
10202   pr ")\n";
10203   pr "    throws LibGuestFSException";
10204   if semicolon then pr ";"
10205
10206 and generate_java_struct jtyp cols () =
10207   generate_header CStyle LGPLv2plus;
10208
10209   pr "\
10210 package com.redhat.et.libguestfs;
10211
10212 /**
10213  * Libguestfs %s structure.
10214  *
10215  * @author rjones
10216  * @see GuestFS
10217  */
10218 public class %s {
10219 " jtyp jtyp;
10220
10221   List.iter (
10222     function
10223     | name, FString
10224     | name, FUUID
10225     | name, FBuffer -> pr "  public String %s;\n" name
10226     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10227     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10228     | name, FChar -> pr "  public char %s;\n" name
10229     | name, FOptPercent ->
10230         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10231         pr "  public float %s;\n" name
10232   ) cols;
10233
10234   pr "}\n"
10235
10236 and generate_java_c () =
10237   generate_header CStyle LGPLv2plus;
10238
10239   pr "\
10240 #include <stdio.h>
10241 #include <stdlib.h>
10242 #include <string.h>
10243
10244 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10245 #include \"guestfs.h\"
10246
10247 /* Note that this function returns.  The exception is not thrown
10248  * until after the wrapper function returns.
10249  */
10250 static void
10251 throw_exception (JNIEnv *env, const char *msg)
10252 {
10253   jclass cl;
10254   cl = (*env)->FindClass (env,
10255                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10256   (*env)->ThrowNew (env, cl, msg);
10257 }
10258
10259 JNIEXPORT jlong JNICALL
10260 Java_com_redhat_et_libguestfs_GuestFS__1create
10261   (JNIEnv *env, jobject obj)
10262 {
10263   guestfs_h *g;
10264
10265   g = guestfs_create ();
10266   if (g == NULL) {
10267     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10268     return 0;
10269   }
10270   guestfs_set_error_handler (g, NULL, NULL);
10271   return (jlong) (long) g;
10272 }
10273
10274 JNIEXPORT void JNICALL
10275 Java_com_redhat_et_libguestfs_GuestFS__1close
10276   (JNIEnv *env, jobject obj, jlong jg)
10277 {
10278   guestfs_h *g = (guestfs_h *) (long) jg;
10279   guestfs_close (g);
10280 }
10281
10282 ";
10283
10284   List.iter (
10285     fun (name, style, _, _, _, _, _) ->
10286       pr "JNIEXPORT ";
10287       (match fst style with
10288        | RErr -> pr "void ";
10289        | RInt _ -> pr "jint ";
10290        | RInt64 _ -> pr "jlong ";
10291        | RBool _ -> pr "jboolean ";
10292        | RConstString _ | RConstOptString _ | RString _
10293        | RBufferOut _ -> pr "jstring ";
10294        | RStruct _ | RHashtable _ ->
10295            pr "jobject ";
10296        | RStringList _ | RStructList _ ->
10297            pr "jobjectArray ";
10298       );
10299       pr "JNICALL\n";
10300       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10301       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10302       pr "\n";
10303       pr "  (JNIEnv *env, jobject obj, jlong jg";
10304       List.iter (
10305         function
10306         | Pathname n
10307         | Device n | Dev_or_Path n
10308         | String n
10309         | OptString n
10310         | FileIn n
10311         | FileOut n ->
10312             pr ", jstring j%s" n
10313         | BufferIn n ->
10314             pr ", jbyteArray j%s" n
10315         | StringList n | DeviceList n ->
10316             pr ", jobjectArray j%s" n
10317         | Bool n ->
10318             pr ", jboolean j%s" n
10319         | Int n ->
10320             pr ", jint j%s" n
10321         | Int64 n ->
10322             pr ", jlong j%s" n
10323       ) (snd style);
10324       pr ")\n";
10325       pr "{\n";
10326       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10327       let error_code, no_ret =
10328         match fst style with
10329         | RErr -> pr "  int r;\n"; "-1", ""
10330         | RBool _
10331         | RInt _ -> pr "  int r;\n"; "-1", "0"
10332         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10333         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10334         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10335         | RString _ ->
10336             pr "  jstring jr;\n";
10337             pr "  char *r;\n"; "NULL", "NULL"
10338         | RStringList _ ->
10339             pr "  jobjectArray jr;\n";
10340             pr "  int r_len;\n";
10341             pr "  jclass cl;\n";
10342             pr "  jstring jstr;\n";
10343             pr "  char **r;\n"; "NULL", "NULL"
10344         | RStruct (_, typ) ->
10345             pr "  jobject jr;\n";
10346             pr "  jclass cl;\n";
10347             pr "  jfieldID fl;\n";
10348             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10349         | RStructList (_, typ) ->
10350             pr "  jobjectArray jr;\n";
10351             pr "  jclass cl;\n";
10352             pr "  jfieldID fl;\n";
10353             pr "  jobject jfl;\n";
10354             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10355         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10356         | RBufferOut _ ->
10357             pr "  jstring jr;\n";
10358             pr "  char *r;\n";
10359             pr "  size_t size;\n";
10360             "NULL", "NULL" in
10361       List.iter (
10362         function
10363         | Pathname n
10364         | Device n | Dev_or_Path n
10365         | String n
10366         | OptString n
10367         | FileIn n
10368         | FileOut n ->
10369             pr "  const char *%s;\n" n
10370         | BufferIn n ->
10371             pr "  jbyte *%s;\n" n;
10372             pr "  size_t %s_size;\n" n
10373         | StringList n | DeviceList n ->
10374             pr "  int %s_len;\n" n;
10375             pr "  const char **%s;\n" n
10376         | Bool n
10377         | Int n ->
10378             pr "  int %s;\n" n
10379         | Int64 n ->
10380             pr "  int64_t %s;\n" n
10381       ) (snd style);
10382
10383       let needs_i =
10384         (match fst style with
10385          | RStringList _ | RStructList _ -> true
10386          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10387          | RConstOptString _
10388          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10389           List.exists (function
10390                        | StringList _ -> true
10391                        | DeviceList _ -> true
10392                        | _ -> false) (snd style) in
10393       if needs_i then
10394         pr "  int i;\n";
10395
10396       pr "\n";
10397
10398       (* Get the parameters. *)
10399       List.iter (
10400         function
10401         | Pathname n
10402         | Device n | Dev_or_Path n
10403         | String n
10404         | FileIn n
10405         | FileOut n ->
10406             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10407         | OptString n ->
10408             (* This is completely undocumented, but Java null becomes
10409              * a NULL parameter.
10410              *)
10411             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10412         | BufferIn n ->
10413             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10414             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10415         | StringList n | DeviceList n ->
10416             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10417             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10418             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10419             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10420               n;
10421             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10422             pr "  }\n";
10423             pr "  %s[%s_len] = NULL;\n" n n;
10424         | Bool n
10425         | Int n
10426         | Int64 n ->
10427             pr "  %s = j%s;\n" n n
10428       ) (snd style);
10429
10430       (* Make the call. *)
10431       pr "  r = guestfs_%s " name;
10432       generate_c_call_args ~handle:"g" style;
10433       pr ";\n";
10434
10435       (* Release the parameters. *)
10436       List.iter (
10437         function
10438         | Pathname n
10439         | Device n | Dev_or_Path n
10440         | String n
10441         | FileIn n
10442         | FileOut n ->
10443             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10444         | OptString n ->
10445             pr "  if (j%s)\n" n;
10446             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10447         | BufferIn n ->
10448             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10449         | StringList n | DeviceList n ->
10450             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10451             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10452               n;
10453             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10454             pr "  }\n";
10455             pr "  free (%s);\n" n
10456         | Bool n
10457         | Int n
10458         | Int64 n -> ()
10459       ) (snd style);
10460
10461       (* Check for errors. *)
10462       pr "  if (r == %s) {\n" error_code;
10463       pr "    throw_exception (env, guestfs_last_error (g));\n";
10464       pr "    return %s;\n" no_ret;
10465       pr "  }\n";
10466
10467       (* Return value. *)
10468       (match fst style with
10469        | RErr -> ()
10470        | RInt _ -> pr "  return (jint) r;\n"
10471        | RBool _ -> pr "  return (jboolean) r;\n"
10472        | RInt64 _ -> pr "  return (jlong) r;\n"
10473        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10474        | RConstOptString _ ->
10475            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10476        | RString _ ->
10477            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10478            pr "  free (r);\n";
10479            pr "  return jr;\n"
10480        | RStringList _ ->
10481            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10482            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10483            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10484            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10485            pr "  for (i = 0; i < r_len; ++i) {\n";
10486            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10487            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10488            pr "    free (r[i]);\n";
10489            pr "  }\n";
10490            pr "  free (r);\n";
10491            pr "  return jr;\n"
10492        | RStruct (_, typ) ->
10493            let jtyp = java_name_of_struct typ in
10494            let cols = cols_of_struct typ in
10495            generate_java_struct_return typ jtyp cols
10496        | RStructList (_, typ) ->
10497            let jtyp = java_name_of_struct typ in
10498            let cols = cols_of_struct typ in
10499            generate_java_struct_list_return typ jtyp cols
10500        | RHashtable _ ->
10501            (* XXX *)
10502            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10503            pr "  return NULL;\n"
10504        | RBufferOut _ ->
10505            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10506            pr "  free (r);\n";
10507            pr "  return jr;\n"
10508       );
10509
10510       pr "}\n";
10511       pr "\n"
10512   ) all_functions
10513
10514 and generate_java_struct_return typ jtyp cols =
10515   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10516   pr "  jr = (*env)->AllocObject (env, cl);\n";
10517   List.iter (
10518     function
10519     | name, FString ->
10520         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10521         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10522     | name, FUUID ->
10523         pr "  {\n";
10524         pr "    char s[33];\n";
10525         pr "    memcpy (s, r->%s, 32);\n" name;
10526         pr "    s[32] = 0;\n";
10527         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10528         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10529         pr "  }\n";
10530     | name, FBuffer ->
10531         pr "  {\n";
10532         pr "    int len = r->%s_len;\n" name;
10533         pr "    char s[len+1];\n";
10534         pr "    memcpy (s, r->%s, len);\n" name;
10535         pr "    s[len] = 0;\n";
10536         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10537         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10538         pr "  }\n";
10539     | name, (FBytes|FUInt64|FInt64) ->
10540         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10541         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10542     | name, (FUInt32|FInt32) ->
10543         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10544         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10545     | name, FOptPercent ->
10546         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10547         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10548     | name, FChar ->
10549         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10550         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10551   ) cols;
10552   pr "  free (r);\n";
10553   pr "  return jr;\n"
10554
10555 and generate_java_struct_list_return typ jtyp cols =
10556   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10557   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10558   pr "  for (i = 0; i < r->len; ++i) {\n";
10559   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10560   List.iter (
10561     function
10562     | name, FString ->
10563         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10564         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10565     | name, FUUID ->
10566         pr "    {\n";
10567         pr "      char s[33];\n";
10568         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10569         pr "      s[32] = 0;\n";
10570         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10571         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10572         pr "    }\n";
10573     | name, FBuffer ->
10574         pr "    {\n";
10575         pr "      int len = r->val[i].%s_len;\n" name;
10576         pr "      char s[len+1];\n";
10577         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10578         pr "      s[len] = 0;\n";
10579         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10580         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10581         pr "    }\n";
10582     | name, (FBytes|FUInt64|FInt64) ->
10583         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10584         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10585     | name, (FUInt32|FInt32) ->
10586         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10587         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10588     | name, FOptPercent ->
10589         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10590         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10591     | name, FChar ->
10592         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10593         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10594   ) cols;
10595   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10596   pr "  }\n";
10597   pr "  guestfs_free_%s_list (r);\n" typ;
10598   pr "  return jr;\n"
10599
10600 and generate_java_makefile_inc () =
10601   generate_header HashStyle GPLv2plus;
10602
10603   pr "java_built_sources = \\\n";
10604   List.iter (
10605     fun (typ, jtyp) ->
10606         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10607   ) java_structs;
10608   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10609
10610 and generate_haskell_hs () =
10611   generate_header HaskellStyle LGPLv2plus;
10612
10613   (* XXX We only know how to generate partial FFI for Haskell
10614    * at the moment.  Please help out!
10615    *)
10616   let can_generate style =
10617     match style with
10618     | RErr, _
10619     | RInt _, _
10620     | RInt64 _, _ -> true
10621     | RBool _, _
10622     | RConstString _, _
10623     | RConstOptString _, _
10624     | RString _, _
10625     | RStringList _, _
10626     | RStruct _, _
10627     | RStructList _, _
10628     | RHashtable _, _
10629     | RBufferOut _, _ -> false in
10630
10631   pr "\
10632 {-# INCLUDE <guestfs.h> #-}
10633 {-# LANGUAGE ForeignFunctionInterface #-}
10634
10635 module Guestfs (
10636   create";
10637
10638   (* List out the names of the actions we want to export. *)
10639   List.iter (
10640     fun (name, style, _, _, _, _, _) ->
10641       if can_generate style then pr ",\n  %s" name
10642   ) all_functions;
10643
10644   pr "
10645   ) where
10646
10647 -- Unfortunately some symbols duplicate ones already present
10648 -- in Prelude.  We don't know which, so we hard-code a list
10649 -- here.
10650 import Prelude hiding (truncate)
10651
10652 import Foreign
10653 import Foreign.C
10654 import Foreign.C.Types
10655 import IO
10656 import Control.Exception
10657 import Data.Typeable
10658
10659 data GuestfsS = GuestfsS            -- represents the opaque C struct
10660 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10661 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10662
10663 -- XXX define properly later XXX
10664 data PV = PV
10665 data VG = VG
10666 data LV = LV
10667 data IntBool = IntBool
10668 data Stat = Stat
10669 data StatVFS = StatVFS
10670 data Hashtable = Hashtable
10671
10672 foreign import ccall unsafe \"guestfs_create\" c_create
10673   :: IO GuestfsP
10674 foreign import ccall unsafe \"&guestfs_close\" c_close
10675   :: FunPtr (GuestfsP -> IO ())
10676 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10677   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10678
10679 create :: IO GuestfsH
10680 create = do
10681   p <- c_create
10682   c_set_error_handler p nullPtr nullPtr
10683   h <- newForeignPtr c_close p
10684   return h
10685
10686 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10687   :: GuestfsP -> IO CString
10688
10689 -- last_error :: GuestfsH -> IO (Maybe String)
10690 -- last_error h = do
10691 --   str <- withForeignPtr h (\\p -> c_last_error p)
10692 --   maybePeek peekCString str
10693
10694 last_error :: GuestfsH -> IO (String)
10695 last_error h = do
10696   str <- withForeignPtr h (\\p -> c_last_error p)
10697   if (str == nullPtr)
10698     then return \"no error\"
10699     else peekCString str
10700
10701 ";
10702
10703   (* Generate wrappers for each foreign function. *)
10704   List.iter (
10705     fun (name, style, _, _, _, _, _) ->
10706       if can_generate style then (
10707         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10708         pr "  :: ";
10709         generate_haskell_prototype ~handle:"GuestfsP" style;
10710         pr "\n";
10711         pr "\n";
10712         pr "%s :: " name;
10713         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10714         pr "\n";
10715         pr "%s %s = do\n" name
10716           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10717         pr "  r <- ";
10718         (* Convert pointer arguments using with* functions. *)
10719         List.iter (
10720           function
10721           | FileIn n
10722           | FileOut n
10723           | Pathname n | Device n | Dev_or_Path n | String n ->
10724               pr "withCString %s $ \\%s -> " n n
10725           | BufferIn n ->
10726               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10727           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10728           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10729           | Bool _ | Int _ | Int64 _ -> ()
10730         ) (snd style);
10731         (* Convert integer arguments. *)
10732         let args =
10733           List.map (
10734             function
10735             | Bool n -> sprintf "(fromBool %s)" n
10736             | Int n -> sprintf "(fromIntegral %s)" n
10737             | Int64 n -> sprintf "(fromIntegral %s)" n
10738             | FileIn n | FileOut n
10739             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10740             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10741           ) (snd style) in
10742         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10743           (String.concat " " ("p" :: args));
10744         (match fst style with
10745          | RErr | RInt _ | RInt64 _ | RBool _ ->
10746              pr "  if (r == -1)\n";
10747              pr "    then do\n";
10748              pr "      err <- last_error h\n";
10749              pr "      fail err\n";
10750          | RConstString _ | RConstOptString _ | RString _
10751          | RStringList _ | RStruct _
10752          | RStructList _ | RHashtable _ | RBufferOut _ ->
10753              pr "  if (r == nullPtr)\n";
10754              pr "    then do\n";
10755              pr "      err <- last_error h\n";
10756              pr "      fail err\n";
10757         );
10758         (match fst style with
10759          | RErr ->
10760              pr "    else return ()\n"
10761          | RInt _ ->
10762              pr "    else return (fromIntegral r)\n"
10763          | RInt64 _ ->
10764              pr "    else return (fromIntegral r)\n"
10765          | RBool _ ->
10766              pr "    else return (toBool r)\n"
10767          | RConstString _
10768          | RConstOptString _
10769          | RString _
10770          | RStringList _
10771          | RStruct _
10772          | RStructList _
10773          | RHashtable _
10774          | RBufferOut _ ->
10775              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10776         );
10777         pr "\n";
10778       )
10779   ) all_functions
10780
10781 and generate_haskell_prototype ~handle ?(hs = false) style =
10782   pr "%s -> " handle;
10783   let string = if hs then "String" else "CString" in
10784   let int = if hs then "Int" else "CInt" in
10785   let bool = if hs then "Bool" else "CInt" in
10786   let int64 = if hs then "Integer" else "Int64" in
10787   List.iter (
10788     fun arg ->
10789       (match arg with
10790        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10791        | BufferIn _ ->
10792            if hs then pr "String"
10793            else pr "CString -> CInt"
10794        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10795        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10796        | Bool _ -> pr "%s" bool
10797        | Int _ -> pr "%s" int
10798        | Int64 _ -> pr "%s" int
10799        | FileIn _ -> pr "%s" string
10800        | FileOut _ -> pr "%s" string
10801       );
10802       pr " -> ";
10803   ) (snd style);
10804   pr "IO (";
10805   (match fst style with
10806    | RErr -> if not hs then pr "CInt"
10807    | RInt _ -> pr "%s" int
10808    | RInt64 _ -> pr "%s" int64
10809    | RBool _ -> pr "%s" bool
10810    | RConstString _ -> pr "%s" string
10811    | RConstOptString _ -> pr "Maybe %s" string
10812    | RString _ -> pr "%s" string
10813    | RStringList _ -> pr "[%s]" string
10814    | RStruct (_, typ) ->
10815        let name = java_name_of_struct typ in
10816        pr "%s" name
10817    | RStructList (_, typ) ->
10818        let name = java_name_of_struct typ in
10819        pr "[%s]" name
10820    | RHashtable _ -> pr "Hashtable"
10821    | RBufferOut _ -> pr "%s" string
10822   );
10823   pr ")"
10824
10825 and generate_csharp () =
10826   generate_header CPlusPlusStyle LGPLv2plus;
10827
10828   (* XXX Make this configurable by the C# assembly users. *)
10829   let library = "libguestfs.so.0" in
10830
10831   pr "\
10832 // These C# bindings are highly experimental at present.
10833 //
10834 // Firstly they only work on Linux (ie. Mono).  In order to get them
10835 // to work on Windows (ie. .Net) you would need to port the library
10836 // itself to Windows first.
10837 //
10838 // The second issue is that some calls are known to be incorrect and
10839 // can cause Mono to segfault.  Particularly: calls which pass or
10840 // return string[], or return any structure value.  This is because
10841 // we haven't worked out the correct way to do this from C#.
10842 //
10843 // The third issue is that when compiling you get a lot of warnings.
10844 // We are not sure whether the warnings are important or not.
10845 //
10846 // Fourthly we do not routinely build or test these bindings as part
10847 // of the make && make check cycle, which means that regressions might
10848 // go unnoticed.
10849 //
10850 // Suggestions and patches are welcome.
10851
10852 // To compile:
10853 //
10854 // gmcs Libguestfs.cs
10855 // mono Libguestfs.exe
10856 //
10857 // (You'll probably want to add a Test class / static main function
10858 // otherwise this won't do anything useful).
10859
10860 using System;
10861 using System.IO;
10862 using System.Runtime.InteropServices;
10863 using System.Runtime.Serialization;
10864 using System.Collections;
10865
10866 namespace Guestfs
10867 {
10868   class Error : System.ApplicationException
10869   {
10870     public Error (string message) : base (message) {}
10871     protected Error (SerializationInfo info, StreamingContext context) {}
10872   }
10873
10874   class Guestfs
10875   {
10876     IntPtr _handle;
10877
10878     [DllImport (\"%s\")]
10879     static extern IntPtr guestfs_create ();
10880
10881     public Guestfs ()
10882     {
10883       _handle = guestfs_create ();
10884       if (_handle == IntPtr.Zero)
10885         throw new Error (\"could not create guestfs handle\");
10886     }
10887
10888     [DllImport (\"%s\")]
10889     static extern void guestfs_close (IntPtr h);
10890
10891     ~Guestfs ()
10892     {
10893       guestfs_close (_handle);
10894     }
10895
10896     [DllImport (\"%s\")]
10897     static extern string guestfs_last_error (IntPtr h);
10898
10899 " library library library;
10900
10901   (* Generate C# structure bindings.  We prefix struct names with
10902    * underscore because C# cannot have conflicting struct names and
10903    * method names (eg. "class stat" and "stat").
10904    *)
10905   List.iter (
10906     fun (typ, cols) ->
10907       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10908       pr "    public class _%s {\n" typ;
10909       List.iter (
10910         function
10911         | name, FChar -> pr "      char %s;\n" name
10912         | name, FString -> pr "      string %s;\n" name
10913         | name, FBuffer ->
10914             pr "      uint %s_len;\n" name;
10915             pr "      string %s;\n" name
10916         | name, FUUID ->
10917             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10918             pr "      string %s;\n" name
10919         | name, FUInt32 -> pr "      uint %s;\n" name
10920         | name, FInt32 -> pr "      int %s;\n" name
10921         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10922         | name, FInt64 -> pr "      long %s;\n" name
10923         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10924       ) cols;
10925       pr "    }\n";
10926       pr "\n"
10927   ) structs;
10928
10929   (* Generate C# function bindings. *)
10930   List.iter (
10931     fun (name, style, _, _, _, shortdesc, _) ->
10932       let rec csharp_return_type () =
10933         match fst style with
10934         | RErr -> "void"
10935         | RBool n -> "bool"
10936         | RInt n -> "int"
10937         | RInt64 n -> "long"
10938         | RConstString n
10939         | RConstOptString n
10940         | RString n
10941         | RBufferOut n -> "string"
10942         | RStruct (_,n) -> "_" ^ n
10943         | RHashtable n -> "Hashtable"
10944         | RStringList n -> "string[]"
10945         | RStructList (_,n) -> sprintf "_%s[]" n
10946
10947       and c_return_type () =
10948         match fst style with
10949         | RErr
10950         | RBool _
10951         | RInt _ -> "int"
10952         | RInt64 _ -> "long"
10953         | RConstString _
10954         | RConstOptString _
10955         | RString _
10956         | RBufferOut _ -> "string"
10957         | RStruct (_,n) -> "_" ^ n
10958         | RHashtable _
10959         | RStringList _ -> "string[]"
10960         | RStructList (_,n) -> sprintf "_%s[]" n
10961
10962       and c_error_comparison () =
10963         match fst style with
10964         | RErr
10965         | RBool _
10966         | RInt _
10967         | RInt64 _ -> "== -1"
10968         | RConstString _
10969         | RConstOptString _
10970         | RString _
10971         | RBufferOut _
10972         | RStruct (_,_)
10973         | RHashtable _
10974         | RStringList _
10975         | RStructList (_,_) -> "== null"
10976
10977       and generate_extern_prototype () =
10978         pr "    static extern %s guestfs_%s (IntPtr h"
10979           (c_return_type ()) name;
10980         List.iter (
10981           function
10982           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10983           | FileIn n | FileOut n
10984           | BufferIn n ->
10985               pr ", [In] string %s" n
10986           | StringList n | DeviceList n ->
10987               pr ", [In] string[] %s" n
10988           | Bool n ->
10989               pr ", bool %s" n
10990           | Int n ->
10991               pr ", int %s" n
10992           | Int64 n ->
10993               pr ", long %s" n
10994         ) (snd style);
10995         pr ");\n"
10996
10997       and generate_public_prototype () =
10998         pr "    public %s %s (" (csharp_return_type ()) name;
10999         let comma = ref false in
11000         let next () =
11001           if !comma then pr ", ";
11002           comma := true
11003         in
11004         List.iter (
11005           function
11006           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11007           | FileIn n | FileOut n
11008           | BufferIn n ->
11009               next (); pr "string %s" n
11010           | StringList n | DeviceList n ->
11011               next (); pr "string[] %s" n
11012           | Bool n ->
11013               next (); pr "bool %s" n
11014           | Int n ->
11015               next (); pr "int %s" n
11016           | Int64 n ->
11017               next (); pr "long %s" n
11018         ) (snd style);
11019         pr ")\n"
11020
11021       and generate_call () =
11022         pr "guestfs_%s (_handle" name;
11023         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11024         pr ");\n";
11025       in
11026
11027       pr "    [DllImport (\"%s\")]\n" library;
11028       generate_extern_prototype ();
11029       pr "\n";
11030       pr "    /// <summary>\n";
11031       pr "    /// %s\n" shortdesc;
11032       pr "    /// </summary>\n";
11033       generate_public_prototype ();
11034       pr "    {\n";
11035       pr "      %s r;\n" (c_return_type ());
11036       pr "      r = ";
11037       generate_call ();
11038       pr "      if (r %s)\n" (c_error_comparison ());
11039       pr "        throw new Error (guestfs_last_error (_handle));\n";
11040       (match fst style with
11041        | RErr -> ()
11042        | RBool _ ->
11043            pr "      return r != 0 ? true : false;\n"
11044        | RHashtable _ ->
11045            pr "      Hashtable rr = new Hashtable ();\n";
11046            pr "      for (int i = 0; i < r.Length; i += 2)\n";
11047            pr "        rr.Add (r[i], r[i+1]);\n";
11048            pr "      return rr;\n"
11049        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11050        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11051        | RStructList _ ->
11052            pr "      return r;\n"
11053       );
11054       pr "    }\n";
11055       pr "\n";
11056   ) all_functions_sorted;
11057
11058   pr "  }
11059 }
11060 "
11061
11062 and generate_bindtests () =
11063   generate_header CStyle LGPLv2plus;
11064
11065   pr "\
11066 #include <stdio.h>
11067 #include <stdlib.h>
11068 #include <inttypes.h>
11069 #include <string.h>
11070
11071 #include \"guestfs.h\"
11072 #include \"guestfs-internal.h\"
11073 #include \"guestfs-internal-actions.h\"
11074 #include \"guestfs_protocol.h\"
11075
11076 #define error guestfs_error
11077 #define safe_calloc guestfs_safe_calloc
11078 #define safe_malloc guestfs_safe_malloc
11079
11080 static void
11081 print_strings (char *const *argv)
11082 {
11083   int argc;
11084
11085   printf (\"[\");
11086   for (argc = 0; argv[argc] != NULL; ++argc) {
11087     if (argc > 0) printf (\", \");
11088     printf (\"\\\"%%s\\\"\", argv[argc]);
11089   }
11090   printf (\"]\\n\");
11091 }
11092
11093 /* The test0 function prints its parameters to stdout. */
11094 ";
11095
11096   let test0, tests =
11097     match test_functions with
11098     | [] -> assert false
11099     | test0 :: tests -> test0, tests in
11100
11101   let () =
11102     let (name, style, _, _, _, _, _) = test0 in
11103     generate_prototype ~extern:false ~semicolon:false ~newline:true
11104       ~handle:"g" ~prefix:"guestfs__" name style;
11105     pr "{\n";
11106     List.iter (
11107       function
11108       | Pathname n
11109       | Device n | Dev_or_Path n
11110       | String n
11111       | FileIn n
11112       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11113       | BufferIn n ->
11114           pr "  {\n";
11115           pr "    size_t i;\n";
11116           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11117           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11118           pr "    printf (\"\\n\");\n";
11119           pr "  }\n";
11120       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11121       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11122       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11123       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11124       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11125     ) (snd style);
11126     pr "  /* Java changes stdout line buffering so we need this: */\n";
11127     pr "  fflush (stdout);\n";
11128     pr "  return 0;\n";
11129     pr "}\n";
11130     pr "\n" in
11131
11132   List.iter (
11133     fun (name, style, _, _, _, _, _) ->
11134       if String.sub name (String.length name - 3) 3 <> "err" then (
11135         pr "/* Test normal return. */\n";
11136         generate_prototype ~extern:false ~semicolon:false ~newline:true
11137           ~handle:"g" ~prefix:"guestfs__" name style;
11138         pr "{\n";
11139         (match fst style with
11140          | RErr ->
11141              pr "  return 0;\n"
11142          | RInt _ ->
11143              pr "  int r;\n";
11144              pr "  sscanf (val, \"%%d\", &r);\n";
11145              pr "  return r;\n"
11146          | RInt64 _ ->
11147              pr "  int64_t r;\n";
11148              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11149              pr "  return r;\n"
11150          | RBool _ ->
11151              pr "  return STREQ (val, \"true\");\n"
11152          | RConstString _
11153          | RConstOptString _ ->
11154              (* Can't return the input string here.  Return a static
11155               * string so we ensure we get a segfault if the caller
11156               * tries to free it.
11157               *)
11158              pr "  return \"static string\";\n"
11159          | RString _ ->
11160              pr "  return strdup (val);\n"
11161          | RStringList _ ->
11162              pr "  char **strs;\n";
11163              pr "  int n, i;\n";
11164              pr "  sscanf (val, \"%%d\", &n);\n";
11165              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11166              pr "  for (i = 0; i < n; ++i) {\n";
11167              pr "    strs[i] = safe_malloc (g, 16);\n";
11168              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11169              pr "  }\n";
11170              pr "  strs[n] = NULL;\n";
11171              pr "  return strs;\n"
11172          | RStruct (_, typ) ->
11173              pr "  struct guestfs_%s *r;\n" typ;
11174              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11175              pr "  return r;\n"
11176          | RStructList (_, typ) ->
11177              pr "  struct guestfs_%s_list *r;\n" typ;
11178              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11179              pr "  sscanf (val, \"%%d\", &r->len);\n";
11180              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11181              pr "  return r;\n"
11182          | RHashtable _ ->
11183              pr "  char **strs;\n";
11184              pr "  int n, i;\n";
11185              pr "  sscanf (val, \"%%d\", &n);\n";
11186              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11187              pr "  for (i = 0; i < n; ++i) {\n";
11188              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11189              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11190              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11191              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11192              pr "  }\n";
11193              pr "  strs[n*2] = NULL;\n";
11194              pr "  return strs;\n"
11195          | RBufferOut _ ->
11196              pr "  return strdup (val);\n"
11197         );
11198         pr "}\n";
11199         pr "\n"
11200       ) else (
11201         pr "/* Test error return. */\n";
11202         generate_prototype ~extern:false ~semicolon:false ~newline:true
11203           ~handle:"g" ~prefix:"guestfs__" name style;
11204         pr "{\n";
11205         pr "  error (g, \"error\");\n";
11206         (match fst style with
11207          | RErr | RInt _ | RInt64 _ | RBool _ ->
11208              pr "  return -1;\n"
11209          | RConstString _ | RConstOptString _
11210          | RString _ | RStringList _ | RStruct _
11211          | RStructList _
11212          | RHashtable _
11213          | RBufferOut _ ->
11214              pr "  return NULL;\n"
11215         );
11216         pr "}\n";
11217         pr "\n"
11218       )
11219   ) tests
11220
11221 and generate_ocaml_bindtests () =
11222   generate_header OCamlStyle GPLv2plus;
11223
11224   pr "\
11225 let () =
11226   let g = Guestfs.create () in
11227 ";
11228
11229   let mkargs args =
11230     String.concat " " (
11231       List.map (
11232         function
11233         | CallString s -> "\"" ^ s ^ "\""
11234         | CallOptString None -> "None"
11235         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11236         | CallStringList xs ->
11237             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11238         | CallInt i when i >= 0 -> string_of_int i
11239         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11240         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11241         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11242         | CallBool b -> string_of_bool b
11243         | CallBuffer s -> sprintf "%S" s
11244       ) args
11245     )
11246   in
11247
11248   generate_lang_bindtests (
11249     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11250   );
11251
11252   pr "print_endline \"EOF\"\n"
11253
11254 and generate_perl_bindtests () =
11255   pr "#!/usr/bin/perl -w\n";
11256   generate_header HashStyle GPLv2plus;
11257
11258   pr "\
11259 use strict;
11260
11261 use Sys::Guestfs;
11262
11263 my $g = Sys::Guestfs->new ();
11264 ";
11265
11266   let mkargs args =
11267     String.concat ", " (
11268       List.map (
11269         function
11270         | CallString s -> "\"" ^ s ^ "\""
11271         | CallOptString None -> "undef"
11272         | CallOptString (Some s) -> sprintf "\"%s\"" s
11273         | CallStringList xs ->
11274             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11275         | CallInt i -> string_of_int i
11276         | CallInt64 i -> Int64.to_string i
11277         | CallBool b -> if b then "1" else "0"
11278         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11279       ) args
11280     )
11281   in
11282
11283   generate_lang_bindtests (
11284     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11285   );
11286
11287   pr "print \"EOF\\n\"\n"
11288
11289 and generate_python_bindtests () =
11290   generate_header HashStyle GPLv2plus;
11291
11292   pr "\
11293 import guestfs
11294
11295 g = guestfs.GuestFS ()
11296 ";
11297
11298   let mkargs args =
11299     String.concat ", " (
11300       List.map (
11301         function
11302         | CallString s -> "\"" ^ s ^ "\""
11303         | CallOptString None -> "None"
11304         | CallOptString (Some s) -> sprintf "\"%s\"" s
11305         | CallStringList xs ->
11306             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11307         | CallInt i -> string_of_int i
11308         | CallInt64 i -> Int64.to_string i
11309         | CallBool b -> if b then "1" else "0"
11310         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11311       ) args
11312     )
11313   in
11314
11315   generate_lang_bindtests (
11316     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11317   );
11318
11319   pr "print \"EOF\"\n"
11320
11321 and generate_ruby_bindtests () =
11322   generate_header HashStyle GPLv2plus;
11323
11324   pr "\
11325 require 'guestfs'
11326
11327 g = Guestfs::create()
11328 ";
11329
11330   let mkargs args =
11331     String.concat ", " (
11332       List.map (
11333         function
11334         | CallString s -> "\"" ^ s ^ "\""
11335         | CallOptString None -> "nil"
11336         | CallOptString (Some s) -> sprintf "\"%s\"" s
11337         | CallStringList xs ->
11338             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11339         | CallInt i -> string_of_int i
11340         | CallInt64 i -> Int64.to_string i
11341         | CallBool b -> string_of_bool b
11342         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11343       ) args
11344     )
11345   in
11346
11347   generate_lang_bindtests (
11348     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11349   );
11350
11351   pr "print \"EOF\\n\"\n"
11352
11353 and generate_java_bindtests () =
11354   generate_header CStyle GPLv2plus;
11355
11356   pr "\
11357 import com.redhat.et.libguestfs.*;
11358
11359 public class Bindtests {
11360     public static void main (String[] argv)
11361     {
11362         try {
11363             GuestFS g = new GuestFS ();
11364 ";
11365
11366   let mkargs args =
11367     String.concat ", " (
11368       List.map (
11369         function
11370         | CallString s -> "\"" ^ s ^ "\""
11371         | CallOptString None -> "null"
11372         | CallOptString (Some s) -> sprintf "\"%s\"" s
11373         | CallStringList xs ->
11374             "new String[]{" ^
11375               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11376         | CallInt i -> string_of_int i
11377         | CallInt64 i -> Int64.to_string i
11378         | CallBool b -> string_of_bool b
11379         | CallBuffer s ->
11380             "new byte[] { " ^ String.concat "," (
11381               map_chars (fun c -> string_of_int (Char.code c)) s
11382             ) ^ " }"
11383       ) args
11384     )
11385   in
11386
11387   generate_lang_bindtests (
11388     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11389   );
11390
11391   pr "
11392             System.out.println (\"EOF\");
11393         }
11394         catch (Exception exn) {
11395             System.err.println (exn);
11396             System.exit (1);
11397         }
11398     }
11399 }
11400 "
11401
11402 and generate_haskell_bindtests () =
11403   generate_header HaskellStyle GPLv2plus;
11404
11405   pr "\
11406 module Bindtests where
11407 import qualified Guestfs
11408
11409 main = do
11410   g <- Guestfs.create
11411 ";
11412
11413   let mkargs args =
11414     String.concat " " (
11415       List.map (
11416         function
11417         | CallString s -> "\"" ^ s ^ "\""
11418         | CallOptString None -> "Nothing"
11419         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11420         | CallStringList xs ->
11421             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11422         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11423         | CallInt i -> string_of_int i
11424         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11425         | CallInt64 i -> Int64.to_string i
11426         | CallBool true -> "True"
11427         | CallBool false -> "False"
11428         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11429       ) args
11430     )
11431   in
11432
11433   generate_lang_bindtests (
11434     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11435   );
11436
11437   pr "  putStrLn \"EOF\"\n"
11438
11439 (* Language-independent bindings tests - we do it this way to
11440  * ensure there is parity in testing bindings across all languages.
11441  *)
11442 and generate_lang_bindtests call =
11443   call "test0" [CallString "abc"; CallOptString (Some "def");
11444                 CallStringList []; CallBool false;
11445                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11446                 CallBuffer "abc\000abc"];
11447   call "test0" [CallString "abc"; CallOptString None;
11448                 CallStringList []; CallBool false;
11449                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11450                 CallBuffer "abc\000abc"];
11451   call "test0" [CallString ""; CallOptString (Some "def");
11452                 CallStringList []; CallBool false;
11453                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11454                 CallBuffer "abc\000abc"];
11455   call "test0" [CallString ""; CallOptString (Some "");
11456                 CallStringList []; CallBool false;
11457                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11458                 CallBuffer "abc\000abc"];
11459   call "test0" [CallString "abc"; CallOptString (Some "def");
11460                 CallStringList ["1"]; CallBool false;
11461                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11462                 CallBuffer "abc\000abc"];
11463   call "test0" [CallString "abc"; CallOptString (Some "def");
11464                 CallStringList ["1"; "2"]; CallBool false;
11465                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11466                 CallBuffer "abc\000abc"];
11467   call "test0" [CallString "abc"; CallOptString (Some "def");
11468                 CallStringList ["1"]; CallBool true;
11469                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11470                 CallBuffer "abc\000abc"];
11471   call "test0" [CallString "abc"; CallOptString (Some "def");
11472                 CallStringList ["1"]; CallBool false;
11473                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11474                 CallBuffer "abc\000abc"];
11475   call "test0" [CallString "abc"; CallOptString (Some "def");
11476                 CallStringList ["1"]; CallBool false;
11477                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11478                 CallBuffer "abc\000abc"];
11479   call "test0" [CallString "abc"; CallOptString (Some "def");
11480                 CallStringList ["1"]; CallBool false;
11481                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11482                 CallBuffer "abc\000abc"];
11483   call "test0" [CallString "abc"; CallOptString (Some "def");
11484                 CallStringList ["1"]; CallBool false;
11485                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11486                 CallBuffer "abc\000abc"];
11487   call "test0" [CallString "abc"; CallOptString (Some "def");
11488                 CallStringList ["1"]; CallBool false;
11489                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11490                 CallBuffer "abc\000abc"];
11491   call "test0" [CallString "abc"; CallOptString (Some "def");
11492                 CallStringList ["1"]; CallBool false;
11493                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11494                 CallBuffer "abc\000abc"]
11495
11496 (* XXX Add here tests of the return and error functions. *)
11497
11498 (* Code to generator bindings for virt-inspector.  Currently only
11499  * implemented for OCaml code (for virt-p2v 2.0).
11500  *)
11501 let rng_input = "inspector/virt-inspector.rng"
11502
11503 (* Read the input file and parse it into internal structures.  This is
11504  * by no means a complete RELAX NG parser, but is just enough to be
11505  * able to parse the specific input file.
11506  *)
11507 type rng =
11508   | Element of string * rng list        (* <element name=name/> *)
11509   | Attribute of string * rng list        (* <attribute name=name/> *)
11510   | Interleave of rng list                (* <interleave/> *)
11511   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11512   | OneOrMore of rng                        (* <oneOrMore/> *)
11513   | Optional of rng                        (* <optional/> *)
11514   | Choice of string list                (* <choice><value/>*</choice> *)
11515   | Value of string                        (* <value>str</value> *)
11516   | Text                                (* <text/> *)
11517
11518 let rec string_of_rng = function
11519   | Element (name, xs) ->
11520       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11521   | Attribute (name, xs) ->
11522       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11523   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11524   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11525   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11526   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11527   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11528   | Value value -> "Value \"" ^ value ^ "\""
11529   | Text -> "Text"
11530
11531 and string_of_rng_list xs =
11532   String.concat ", " (List.map string_of_rng xs)
11533
11534 let rec parse_rng ?defines context = function
11535   | [] -> []
11536   | Xml.Element ("element", ["name", name], children) :: rest ->
11537       Element (name, parse_rng ?defines context children)
11538       :: parse_rng ?defines context rest
11539   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11540       Attribute (name, parse_rng ?defines context children)
11541       :: parse_rng ?defines context rest
11542   | Xml.Element ("interleave", [], children) :: rest ->
11543       Interleave (parse_rng ?defines context children)
11544       :: parse_rng ?defines context rest
11545   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11546       let rng = parse_rng ?defines context [child] in
11547       (match rng with
11548        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11549        | _ ->
11550            failwithf "%s: <zeroOrMore> contains more than one child element"
11551              context
11552       )
11553   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11554       let rng = parse_rng ?defines context [child] in
11555       (match rng with
11556        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11557        | _ ->
11558            failwithf "%s: <oneOrMore> contains more than one child element"
11559              context
11560       )
11561   | Xml.Element ("optional", [], [child]) :: rest ->
11562       let rng = parse_rng ?defines context [child] in
11563       (match rng with
11564        | [child] -> Optional child :: parse_rng ?defines context rest
11565        | _ ->
11566            failwithf "%s: <optional> contains more than one child element"
11567              context
11568       )
11569   | Xml.Element ("choice", [], children) :: rest ->
11570       let values = List.map (
11571         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11572         | _ ->
11573             failwithf "%s: can't handle anything except <value> in <choice>"
11574               context
11575       ) children in
11576       Choice values
11577       :: parse_rng ?defines context rest
11578   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11579       Value value :: parse_rng ?defines context rest
11580   | Xml.Element ("text", [], []) :: rest ->
11581       Text :: parse_rng ?defines context rest
11582   | Xml.Element ("ref", ["name", name], []) :: rest ->
11583       (* Look up the reference.  Because of limitations in this parser,
11584        * we can't handle arbitrarily nested <ref> yet.  You can only
11585        * use <ref> from inside <start>.
11586        *)
11587       (match defines with
11588        | None ->
11589            failwithf "%s: contains <ref>, but no refs are defined yet" context
11590        | Some map ->
11591            let rng = StringMap.find name map in
11592            rng @ parse_rng ?defines context rest
11593       )
11594   | x :: _ ->
11595       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11596
11597 let grammar =
11598   let xml = Xml.parse_file rng_input in
11599   match xml with
11600   | Xml.Element ("grammar", _,
11601                  Xml.Element ("start", _, gram) :: defines) ->
11602       (* The <define/> elements are referenced in the <start> section,
11603        * so build a map of those first.
11604        *)
11605       let defines = List.fold_left (
11606         fun map ->
11607           function Xml.Element ("define", ["name", name], defn) ->
11608             StringMap.add name defn map
11609           | _ ->
11610               failwithf "%s: expected <define name=name/>" rng_input
11611       ) StringMap.empty defines in
11612       let defines = StringMap.mapi parse_rng defines in
11613
11614       (* Parse the <start> clause, passing the defines. *)
11615       parse_rng ~defines "<start>" gram
11616   | _ ->
11617       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11618         rng_input
11619
11620 let name_of_field = function
11621   | Element (name, _) | Attribute (name, _)
11622   | ZeroOrMore (Element (name, _))
11623   | OneOrMore (Element (name, _))
11624   | Optional (Element (name, _)) -> name
11625   | Optional (Attribute (name, _)) -> name
11626   | Text -> (* an unnamed field in an element *)
11627       "data"
11628   | rng ->
11629       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11630
11631 (* At the moment this function only generates OCaml types.  However we
11632  * should parameterize it later so it can generate types/structs in a
11633  * variety of languages.
11634  *)
11635 let generate_types xs =
11636   (* A simple type is one that can be printed out directly, eg.
11637    * "string option".  A complex type is one which has a name and has
11638    * to be defined via another toplevel definition, eg. a struct.
11639    *
11640    * generate_type generates code for either simple or complex types.
11641    * In the simple case, it returns the string ("string option").  In
11642    * the complex case, it returns the name ("mountpoint").  In the
11643    * complex case it has to print out the definition before returning,
11644    * so it should only be called when we are at the beginning of a
11645    * new line (BOL context).
11646    *)
11647   let rec generate_type = function
11648     | Text ->                                (* string *)
11649         "string", true
11650     | Choice values ->                        (* [`val1|`val2|...] *)
11651         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11652     | ZeroOrMore rng ->                        (* <rng> list *)
11653         let t, is_simple = generate_type rng in
11654         t ^ " list (* 0 or more *)", is_simple
11655     | OneOrMore rng ->                        (* <rng> list *)
11656         let t, is_simple = generate_type rng in
11657         t ^ " list (* 1 or more *)", is_simple
11658                                         (* virt-inspector hack: bool *)
11659     | Optional (Attribute (name, [Value "1"])) ->
11660         "bool", true
11661     | Optional rng ->                        (* <rng> list *)
11662         let t, is_simple = generate_type rng in
11663         t ^ " option", is_simple
11664                                         (* type name = { fields ... } *)
11665     | Element (name, fields) when is_attrs_interleave fields ->
11666         generate_type_struct name (get_attrs_interleave fields)
11667     | Element (name, [field])                (* type name = field *)
11668     | Attribute (name, [field]) ->
11669         let t, is_simple = generate_type field in
11670         if is_simple then (t, true)
11671         else (
11672           pr "type %s = %s\n" name t;
11673           name, false
11674         )
11675     | Element (name, fields) ->              (* type name = { fields ... } *)
11676         generate_type_struct name fields
11677     | rng ->
11678         failwithf "generate_type failed at: %s" (string_of_rng rng)
11679
11680   and is_attrs_interleave = function
11681     | [Interleave _] -> true
11682     | Attribute _ :: fields -> is_attrs_interleave fields
11683     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11684     | _ -> false
11685
11686   and get_attrs_interleave = function
11687     | [Interleave fields] -> fields
11688     | ((Attribute _) as field) :: fields
11689     | ((Optional (Attribute _)) as field) :: fields ->
11690         field :: get_attrs_interleave fields
11691     | _ -> assert false
11692
11693   and generate_types xs =
11694     List.iter (fun x -> ignore (generate_type x)) xs
11695
11696   and generate_type_struct name fields =
11697     (* Calculate the types of the fields first.  We have to do this
11698      * before printing anything so we are still in BOL context.
11699      *)
11700     let types = List.map fst (List.map generate_type fields) in
11701
11702     (* Special case of a struct containing just a string and another
11703      * field.  Turn it into an assoc list.
11704      *)
11705     match types with
11706     | ["string"; other] ->
11707         let fname1, fname2 =
11708           match fields with
11709           | [f1; f2] -> name_of_field f1, name_of_field f2
11710           | _ -> assert false in
11711         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11712         name, false
11713
11714     | types ->
11715         pr "type %s = {\n" name;
11716         List.iter (
11717           fun (field, ftype) ->
11718             let fname = name_of_field field in
11719             pr "  %s_%s : %s;\n" name fname ftype
11720         ) (List.combine fields types);
11721         pr "}\n";
11722         (* Return the name of this type, and
11723          * false because it's not a simple type.
11724          *)
11725         name, false
11726   in
11727
11728   generate_types xs
11729
11730 let generate_parsers xs =
11731   (* As for generate_type above, generate_parser makes a parser for
11732    * some type, and returns the name of the parser it has generated.
11733    * Because it (may) need to print something, it should always be
11734    * called in BOL context.
11735    *)
11736   let rec generate_parser = function
11737     | Text ->                                (* string *)
11738         "string_child_or_empty"
11739     | Choice values ->                        (* [`val1|`val2|...] *)
11740         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11741           (String.concat "|"
11742              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11743     | ZeroOrMore rng ->                        (* <rng> list *)
11744         let pa = generate_parser rng in
11745         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11746     | OneOrMore rng ->                        (* <rng> list *)
11747         let pa = generate_parser rng in
11748         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11749                                         (* virt-inspector hack: bool *)
11750     | Optional (Attribute (name, [Value "1"])) ->
11751         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11752     | Optional rng ->                        (* <rng> list *)
11753         let pa = generate_parser rng in
11754         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11755                                         (* type name = { fields ... } *)
11756     | Element (name, fields) when is_attrs_interleave fields ->
11757         generate_parser_struct name (get_attrs_interleave fields)
11758     | Element (name, [field]) ->        (* type name = field *)
11759         let pa = generate_parser field in
11760         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11761         pr "let %s =\n" parser_name;
11762         pr "  %s\n" pa;
11763         pr "let parse_%s = %s\n" name parser_name;
11764         parser_name
11765     | Attribute (name, [field]) ->
11766         let pa = generate_parser field in
11767         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11768         pr "let %s =\n" parser_name;
11769         pr "  %s\n" pa;
11770         pr "let parse_%s = %s\n" name parser_name;
11771         parser_name
11772     | Element (name, fields) ->              (* type name = { fields ... } *)
11773         generate_parser_struct name ([], fields)
11774     | rng ->
11775         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11776
11777   and is_attrs_interleave = function
11778     | [Interleave _] -> true
11779     | Attribute _ :: fields -> is_attrs_interleave fields
11780     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11781     | _ -> false
11782
11783   and get_attrs_interleave = function
11784     | [Interleave fields] -> [], fields
11785     | ((Attribute _) as field) :: fields
11786     | ((Optional (Attribute _)) as field) :: fields ->
11787         let attrs, interleaves = get_attrs_interleave fields in
11788         (field :: attrs), interleaves
11789     | _ -> assert false
11790
11791   and generate_parsers xs =
11792     List.iter (fun x -> ignore (generate_parser x)) xs
11793
11794   and generate_parser_struct name (attrs, interleaves) =
11795     (* Generate parsers for the fields first.  We have to do this
11796      * before printing anything so we are still in BOL context.
11797      *)
11798     let fields = attrs @ interleaves in
11799     let pas = List.map generate_parser fields in
11800
11801     (* Generate an intermediate tuple from all the fields first.
11802      * If the type is just a string + another field, then we will
11803      * return this directly, otherwise it is turned into a record.
11804      *
11805      * RELAX NG note: This code treats <interleave> and plain lists of
11806      * fields the same.  In other words, it doesn't bother enforcing
11807      * any ordering of fields in the XML.
11808      *)
11809     pr "let parse_%s x =\n" name;
11810     pr "  let t = (\n    ";
11811     let comma = ref false in
11812     List.iter (
11813       fun x ->
11814         if !comma then pr ",\n    ";
11815         comma := true;
11816         match x with
11817         | Optional (Attribute (fname, [field])), pa ->
11818             pr "%s x" pa
11819         | Optional (Element (fname, [field])), pa ->
11820             pr "%s (optional_child %S x)" pa fname
11821         | Attribute (fname, [Text]), _ ->
11822             pr "attribute %S x" fname
11823         | (ZeroOrMore _ | OneOrMore _), pa ->
11824             pr "%s x" pa
11825         | Text, pa ->
11826             pr "%s x" pa
11827         | (field, pa) ->
11828             let fname = name_of_field field in
11829             pr "%s (child %S x)" pa fname
11830     ) (List.combine fields pas);
11831     pr "\n  ) in\n";
11832
11833     (match fields with
11834      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11835          pr "  t\n"
11836
11837      | _ ->
11838          pr "  (Obj.magic t : %s)\n" name
11839 (*
11840          List.iter (
11841            function
11842            | (Optional (Attribute (fname, [field])), pa) ->
11843                pr "  %s_%s =\n" name fname;
11844                pr "    %s x;\n" pa
11845            | (Optional (Element (fname, [field])), pa) ->
11846                pr "  %s_%s =\n" name fname;
11847                pr "    (let x = optional_child %S x in\n" fname;
11848                pr "     %s x);\n" pa
11849            | (field, pa) ->
11850                let fname = name_of_field field in
11851                pr "  %s_%s =\n" name fname;
11852                pr "    (let x = child %S x in\n" fname;
11853                pr "     %s x);\n" pa
11854          ) (List.combine fields pas);
11855          pr "}\n"
11856 *)
11857     );
11858     sprintf "parse_%s" name
11859   in
11860
11861   generate_parsers xs
11862
11863 (* Generate ocaml/guestfs_inspector.mli. *)
11864 let generate_ocaml_inspector_mli () =
11865   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11866
11867   pr "\
11868 (** This is an OCaml language binding to the external [virt-inspector]
11869     program.
11870
11871     For more information, please read the man page [virt-inspector(1)].
11872 *)
11873
11874 ";
11875
11876   generate_types grammar;
11877   pr "(** The nested information returned from the {!inspect} function. *)\n";
11878   pr "\n";
11879
11880   pr "\
11881 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11882 (** To inspect a libvirt domain called [name], pass a singleton
11883     list: [inspect [name]].  When using libvirt only, you may
11884     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11885
11886     To inspect a disk image or images, pass a list of the filenames
11887     of the disk images: [inspect filenames]
11888
11889     This function inspects the given guest or disk images and
11890     returns a list of operating system(s) found and a large amount
11891     of information about them.  In the vast majority of cases,
11892     a virtual machine only contains a single operating system.
11893
11894     If the optional [~xml] parameter is given, then this function
11895     skips running the external virt-inspector program and just
11896     parses the given XML directly (which is expected to be XML
11897     produced from a previous run of virt-inspector).  The list of
11898     names and connect URI are ignored in this case.
11899
11900     This function can throw a wide variety of exceptions, for example
11901     if the external virt-inspector program cannot be found, or if
11902     it doesn't generate valid XML.
11903 *)
11904 "
11905
11906 (* Generate ocaml/guestfs_inspector.ml. *)
11907 let generate_ocaml_inspector_ml () =
11908   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11909
11910   pr "open Unix\n";
11911   pr "\n";
11912
11913   generate_types grammar;
11914   pr "\n";
11915
11916   pr "\
11917 (* Misc functions which are used by the parser code below. *)
11918 let first_child = function
11919   | Xml.Element (_, _, c::_) -> c
11920   | Xml.Element (name, _, []) ->
11921       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11922   | Xml.PCData str ->
11923       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11924
11925 let string_child_or_empty = function
11926   | Xml.Element (_, _, [Xml.PCData s]) -> s
11927   | Xml.Element (_, _, []) -> \"\"
11928   | Xml.Element (x, _, _) ->
11929       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11930                 x ^ \" instead\")
11931   | Xml.PCData str ->
11932       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11933
11934 let optional_child name xml =
11935   let children = Xml.children xml in
11936   try
11937     Some (List.find (function
11938                      | Xml.Element (n, _, _) when n = name -> true
11939                      | _ -> false) children)
11940   with
11941     Not_found -> None
11942
11943 let child name xml =
11944   match optional_child name xml with
11945   | Some c -> c
11946   | None ->
11947       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11948
11949 let attribute name xml =
11950   try Xml.attrib xml name
11951   with Xml.No_attribute _ ->
11952     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11953
11954 ";
11955
11956   generate_parsers grammar;
11957   pr "\n";
11958
11959   pr "\
11960 (* Run external virt-inspector, then use parser to parse the XML. *)
11961 let inspect ?connect ?xml names =
11962   let xml =
11963     match xml with
11964     | None ->
11965         if names = [] then invalid_arg \"inspect: no names given\";
11966         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11967           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11968           names in
11969         let cmd = List.map Filename.quote cmd in
11970         let cmd = String.concat \" \" cmd in
11971         let chan = open_process_in cmd in
11972         let xml = Xml.parse_in chan in
11973         (match close_process_in chan with
11974          | WEXITED 0 -> ()
11975          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11976          | WSIGNALED i | WSTOPPED i ->
11977              failwith (\"external virt-inspector command died or stopped on sig \" ^
11978                        string_of_int i)
11979         );
11980         xml
11981     | Some doc ->
11982         Xml.parse_string doc in
11983   parse_operatingsystems xml
11984 "
11985
11986 and generate_max_proc_nr () =
11987   pr "%d\n" max_proc_nr
11988
11989 let output_to filename k =
11990   let filename_new = filename ^ ".new" in
11991   chan := open_out filename_new;
11992   k ();
11993   close_out !chan;
11994   chan := Pervasives.stdout;
11995
11996   (* Is the new file different from the current file? *)
11997   if Sys.file_exists filename && files_equal filename filename_new then
11998     unlink filename_new                 (* same, so skip it *)
11999   else (
12000     (* different, overwrite old one *)
12001     (try chmod filename 0o644 with Unix_error _ -> ());
12002     rename filename_new filename;
12003     chmod filename 0o444;
12004     printf "written %s\n%!" filename;
12005   )
12006
12007 let perror msg = function
12008   | Unix_error (err, _, _) ->
12009       eprintf "%s: %s\n" msg (error_message err)
12010   | exn ->
12011       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12012
12013 (* Main program. *)
12014 let () =
12015   let lock_fd =
12016     try openfile "HACKING" [O_RDWR] 0
12017     with
12018     | Unix_error (ENOENT, _, _) ->
12019         eprintf "\
12020 You are probably running this from the wrong directory.
12021 Run it from the top source directory using the command
12022   src/generator.ml
12023 ";
12024         exit 1
12025     | exn ->
12026         perror "open: HACKING" exn;
12027         exit 1 in
12028
12029   (* Acquire a lock so parallel builds won't try to run the generator
12030    * twice at the same time.  Subsequent builds will wait for the first
12031    * one to finish.  Note the lock is released implicitly when the
12032    * program exits.
12033    *)
12034   (try lockf lock_fd F_LOCK 1
12035    with exn ->
12036      perror "lock: HACKING" exn;
12037      exit 1);
12038
12039   check_functions ();
12040
12041   output_to "src/guestfs_protocol.x" generate_xdr;
12042   output_to "src/guestfs-structs.h" generate_structs_h;
12043   output_to "src/guestfs-actions.h" generate_actions_h;
12044   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12045   output_to "src/guestfs-actions.c" generate_client_actions;
12046   output_to "src/guestfs-bindtests.c" generate_bindtests;
12047   output_to "src/guestfs-structs.pod" generate_structs_pod;
12048   output_to "src/guestfs-actions.pod" generate_actions_pod;
12049   output_to "src/guestfs-availability.pod" generate_availability_pod;
12050   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12051   output_to "src/libguestfs.syms" generate_linker_script;
12052   output_to "daemon/actions.h" generate_daemon_actions_h;
12053   output_to "daemon/stubs.c" generate_daemon_actions;
12054   output_to "daemon/names.c" generate_daemon_names;
12055   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12056   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12057   output_to "capitests/tests.c" generate_tests;
12058   output_to "fish/cmds.c" generate_fish_cmds;
12059   output_to "fish/completion.c" generate_fish_completion;
12060   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12061   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12062   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12063   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12064   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12065   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12066   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12067   output_to "perl/Guestfs.xs" generate_perl_xs;
12068   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12069   output_to "perl/bindtests.pl" generate_perl_bindtests;
12070   output_to "python/guestfs-py.c" generate_python_c;
12071   output_to "python/guestfs.py" generate_python_py;
12072   output_to "python/bindtests.py" generate_python_bindtests;
12073   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12074   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12075   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12076
12077   List.iter (
12078     fun (typ, jtyp) ->
12079       let cols = cols_of_struct typ in
12080       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12081       output_to filename (generate_java_struct jtyp cols);
12082   ) java_structs;
12083
12084   output_to "java/Makefile.inc" generate_java_makefile_inc;
12085   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12086   output_to "java/Bindtests.java" generate_java_bindtests;
12087   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12088   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12089   output_to "csharp/Libguestfs.cs" generate_csharp;
12090
12091   (* Always generate this file last, and unconditionally.  It's used
12092    * by the Makefile to know when we must re-run the generator.
12093    *)
12094   let chan = open_out "src/stamp-generator" in
12095   fprintf chan "1\n";
12096   close_out chan;
12097
12098   printf "generated %d lines of code\n" !lines