fish: Allow suffixes on number parameters (eg. 1M)
[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 ELF weak linking tricks to find out if
798 this symbol exists (if it doesn't, then it's an earlier version).
799
800 The call returns a structure with four elements.  The first
801 three (C<major>, C<minor> and C<release>) are numbers and
802 correspond to the usual version triplet.  The fourth element
803 (C<extra>) is a string and is normally empty, but may be
804 used for distro-specific information.
805
806 To construct the original version string:
807 C<$major.$minor.$release$extra>
808
809 I<Note:> Don't use this call to test for availability
810 of features.  Distro backports makes this unreliable.  Use
811 C<guestfs_available> instead.");
812
813   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
814    [InitNone, Always, TestOutputTrue (
815       [["set_selinux"; "true"];
816        ["get_selinux"]])],
817    "set SELinux enabled or disabled at appliance boot",
818    "\
819 This sets the selinux flag that is passed to the appliance
820 at boot time.  The default is C<selinux=0> (disabled).
821
822 Note that if SELinux is enabled, it is always in
823 Permissive mode (C<enforcing=0>).
824
825 For more information on the architecture of libguestfs,
826 see L<guestfs(3)>.");
827
828   ("get_selinux", (RBool "selinux", []), -1, [],
829    [],
830    "get SELinux enabled flag",
831    "\
832 This returns the current setting of the selinux flag which
833 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
834
835 For more information on the architecture of libguestfs,
836 see L<guestfs(3)>.");
837
838   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
839    [InitNone, Always, TestOutputFalse (
840       [["set_trace"; "false"];
841        ["get_trace"]])],
842    "enable or disable command traces",
843    "\
844 If the command trace flag is set to 1, then commands are
845 printed on stdout before they are executed in a format
846 which is very similar to the one used by guestfish.  In
847 other words, you can run a program with this enabled, and
848 you will get out a script which you can feed to guestfish
849 to perform the same set of actions.
850
851 If you want to trace C API calls into libguestfs (and
852 other libraries) then possibly a better way is to use
853 the external ltrace(1) command.
854
855 Command traces are disabled unless the environment variable
856 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
857
858   ("get_trace", (RBool "trace", []), -1, [],
859    [],
860    "get command trace enabled flag",
861    "\
862 Return the command trace flag.");
863
864   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
865    [InitNone, Always, TestOutputFalse (
866       [["set_direct"; "false"];
867        ["get_direct"]])],
868    "enable or disable direct appliance mode",
869    "\
870 If the direct appliance mode flag is enabled, then stdin and
871 stdout are passed directly through to the appliance once it
872 is launched.
873
874 One consequence of this is that log messages aren't caught
875 by the library and handled by C<guestfs_set_log_message_callback>,
876 but go straight to stdout.
877
878 You probably don't want to use this unless you know what you
879 are doing.
880
881 The default is disabled.");
882
883   ("get_direct", (RBool "direct", []), -1, [],
884    [],
885    "get direct appliance mode flag",
886    "\
887 Return the direct appliance mode flag.");
888
889   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
890    [InitNone, Always, TestOutputTrue (
891       [["set_recovery_proc"; "true"];
892        ["get_recovery_proc"]])],
893    "enable or disable the recovery process",
894    "\
895 If this is called with the parameter C<false> then
896 C<guestfs_launch> does not create a recovery process.  The
897 purpose of the recovery process is to stop runaway qemu
898 processes in the case where the main program aborts abruptly.
899
900 This only has any effect if called before C<guestfs_launch>,
901 and the default is true.
902
903 About the only time when you would want to disable this is
904 if the main process will fork itself into the background
905 (\"daemonize\" itself).  In this case the recovery process
906 thinks that the main program has disappeared and so kills
907 qemu, which is not very helpful.");
908
909   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
910    [],
911    "get recovery process enabled flag",
912    "\
913 Return the recovery process enabled flag.");
914
915   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
916    [],
917    "add a drive specifying the QEMU block emulation to use",
918    "\
919 This is the same as C<guestfs_add_drive> but it allows you
920 to specify the QEMU interface emulation to use at run time.");
921
922   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
923    [],
924    "add a drive read-only specifying the QEMU block emulation to use",
925    "\
926 This is the same as C<guestfs_add_drive_ro> but it allows you
927 to specify the QEMU interface emulation to use at run time.");
928
929 ]
930
931 (* daemon_functions are any functions which cause some action
932  * to take place in the daemon.
933  *)
934
935 let daemon_functions = [
936   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
937    [InitEmpty, Always, TestOutput (
938       [["part_disk"; "/dev/sda"; "mbr"];
939        ["mkfs"; "ext2"; "/dev/sda1"];
940        ["mount"; "/dev/sda1"; "/"];
941        ["write"; "/new"; "new file contents"];
942        ["cat"; "/new"]], "new file contents")],
943    "mount a guest disk at a position in the filesystem",
944    "\
945 Mount a guest disk at a position in the filesystem.  Block devices
946 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
947 the guest.  If those block devices contain partitions, they will have
948 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
949 names can be used.
950
951 The rules are the same as for L<mount(2)>:  A filesystem must
952 first be mounted on C</> before others can be mounted.  Other
953 filesystems can only be mounted on directories which already
954 exist.
955
956 The mounted filesystem is writable, if we have sufficient permissions
957 on the underlying device.
958
959 B<Important note:>
960 When you use this call, the filesystem options C<sync> and C<noatime>
961 are set implicitly.  This was originally done because we thought it
962 would improve reliability, but it turns out that I<-o sync> has a
963 very large negative performance impact and negligible effect on
964 reliability.  Therefore we recommend that you avoid using
965 C<guestfs_mount> in any code that needs performance, and instead
966 use C<guestfs_mount_options> (use an empty string for the first
967 parameter if you don't want any options).");
968
969   ("sync", (RErr, []), 2, [],
970    [ InitEmpty, Always, TestRun [["sync"]]],
971    "sync disks, writes are flushed through to the disk image",
972    "\
973 This syncs the disk, so that any writes are flushed through to the
974 underlying disk image.
975
976 You should always call this if you have modified a disk image, before
977 closing the handle.");
978
979   ("touch", (RErr, [Pathname "path"]), 3, [],
980    [InitBasicFS, Always, TestOutputTrue (
981       [["touch"; "/new"];
982        ["exists"; "/new"]])],
983    "update file timestamps or create a new file",
984    "\
985 Touch acts like the L<touch(1)> command.  It can be used to
986 update the timestamps on a file, or, if the file does not exist,
987 to create a new zero-length file.");
988
989   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
990    [InitISOFS, Always, TestOutput (
991       [["cat"; "/known-2"]], "abcdef\n")],
992    "list the contents of a file",
993    "\
994 Return the contents of the file named C<path>.
995
996 Note that this function cannot correctly handle binary files
997 (specifically, files containing C<\\0> character which is treated
998 as end of string).  For those you need to use the C<guestfs_read_file>
999 or C<guestfs_download> functions which have a more complex interface.");
1000
1001   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1002    [], (* XXX Tricky to test because it depends on the exact format
1003         * of the 'ls -l' command, which changes between F10 and F11.
1004         *)
1005    "list the files in a directory (long format)",
1006    "\
1007 List the files in C<directory> (relative to the root directory,
1008 there is no cwd) in the format of 'ls -la'.
1009
1010 This command is mostly useful for interactive sessions.  It
1011 is I<not> intended that you try to parse the output string.");
1012
1013   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1014    [InitBasicFS, Always, TestOutputList (
1015       [["touch"; "/new"];
1016        ["touch"; "/newer"];
1017        ["touch"; "/newest"];
1018        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1019    "list the files in a directory",
1020    "\
1021 List the files in C<directory> (relative to the root directory,
1022 there is no cwd).  The '.' and '..' entries are not returned, but
1023 hidden files are shown.
1024
1025 This command is mostly useful for interactive sessions.  Programs
1026 should probably use C<guestfs_readdir> instead.");
1027
1028   ("list_devices", (RStringList "devices", []), 7, [],
1029    [InitEmpty, Always, TestOutputListOfDevices (
1030       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1031    "list the block devices",
1032    "\
1033 List all the block devices.
1034
1035 The full block device names are returned, eg. C</dev/sda>");
1036
1037   ("list_partitions", (RStringList "partitions", []), 8, [],
1038    [InitBasicFS, Always, TestOutputListOfDevices (
1039       [["list_partitions"]], ["/dev/sda1"]);
1040     InitEmpty, Always, TestOutputListOfDevices (
1041       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1042        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1043    "list the partitions",
1044    "\
1045 List all the partitions detected on all block devices.
1046
1047 The full partition device names are returned, eg. C</dev/sda1>
1048
1049 This does not return logical volumes.  For that you will need to
1050 call C<guestfs_lvs>.");
1051
1052   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1053    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1054       [["pvs"]], ["/dev/sda1"]);
1055     InitEmpty, Always, TestOutputListOfDevices (
1056       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1057        ["pvcreate"; "/dev/sda1"];
1058        ["pvcreate"; "/dev/sda2"];
1059        ["pvcreate"; "/dev/sda3"];
1060        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1061    "list the LVM physical volumes (PVs)",
1062    "\
1063 List all the physical volumes detected.  This is the equivalent
1064 of the L<pvs(8)> command.
1065
1066 This returns a list of just the device names that contain
1067 PVs (eg. C</dev/sda2>).
1068
1069 See also C<guestfs_pvs_full>.");
1070
1071   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1072    [InitBasicFSonLVM, Always, TestOutputList (
1073       [["vgs"]], ["VG"]);
1074     InitEmpty, Always, TestOutputList (
1075       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1076        ["pvcreate"; "/dev/sda1"];
1077        ["pvcreate"; "/dev/sda2"];
1078        ["pvcreate"; "/dev/sda3"];
1079        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1080        ["vgcreate"; "VG2"; "/dev/sda3"];
1081        ["vgs"]], ["VG1"; "VG2"])],
1082    "list the LVM volume groups (VGs)",
1083    "\
1084 List all the volumes groups detected.  This is the equivalent
1085 of the L<vgs(8)> command.
1086
1087 This returns a list of just the volume group names that were
1088 detected (eg. C<VolGroup00>).
1089
1090 See also C<guestfs_vgs_full>.");
1091
1092   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1093    [InitBasicFSonLVM, Always, TestOutputList (
1094       [["lvs"]], ["/dev/VG/LV"]);
1095     InitEmpty, Always, TestOutputList (
1096       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1097        ["pvcreate"; "/dev/sda1"];
1098        ["pvcreate"; "/dev/sda2"];
1099        ["pvcreate"; "/dev/sda3"];
1100        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1101        ["vgcreate"; "VG2"; "/dev/sda3"];
1102        ["lvcreate"; "LV1"; "VG1"; "50"];
1103        ["lvcreate"; "LV2"; "VG1"; "50"];
1104        ["lvcreate"; "LV3"; "VG2"; "50"];
1105        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1106    "list the LVM logical volumes (LVs)",
1107    "\
1108 List all the logical volumes detected.  This is the equivalent
1109 of the L<lvs(8)> command.
1110
1111 This returns a list of the logical volume device names
1112 (eg. C</dev/VolGroup00/LogVol00>).
1113
1114 See also C<guestfs_lvs_full>.");
1115
1116   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1117    [], (* XXX how to test? *)
1118    "list the LVM physical volumes (PVs)",
1119    "\
1120 List all the physical volumes detected.  This is the equivalent
1121 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1122
1123   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1124    [], (* XXX how to test? *)
1125    "list the LVM volume groups (VGs)",
1126    "\
1127 List all the volumes groups detected.  This is the equivalent
1128 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1129
1130   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1131    [], (* XXX how to test? *)
1132    "list the LVM logical volumes (LVs)",
1133    "\
1134 List all the logical volumes detected.  This is the equivalent
1135 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1136
1137   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1138    [InitISOFS, Always, TestOutputList (
1139       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1140     InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/empty"]], [])],
1142    "read file as lines",
1143    "\
1144 Return the contents of the file named C<path>.
1145
1146 The file contents are returned as a list of lines.  Trailing
1147 C<LF> and C<CRLF> character sequences are I<not> returned.
1148
1149 Note that this function cannot correctly handle binary files
1150 (specifically, files containing C<\\0> character which is treated
1151 as end of line).  For those you need to use the C<guestfs_read_file>
1152 function which has a more complex interface.");
1153
1154   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1155    [], (* XXX Augeas code needs tests. *)
1156    "create a new Augeas handle",
1157    "\
1158 Create a new Augeas handle for editing configuration files.
1159 If there was any previous Augeas handle associated with this
1160 guestfs session, then it is closed.
1161
1162 You must call this before using any other C<guestfs_aug_*>
1163 commands.
1164
1165 C<root> is the filesystem root.  C<root> must not be NULL,
1166 use C</> instead.
1167
1168 The flags are the same as the flags defined in
1169 E<lt>augeas.hE<gt>, the logical I<or> of the following
1170 integers:
1171
1172 =over 4
1173
1174 =item C<AUG_SAVE_BACKUP> = 1
1175
1176 Keep the original file with a C<.augsave> extension.
1177
1178 =item C<AUG_SAVE_NEWFILE> = 2
1179
1180 Save changes into a file with extension C<.augnew>, and
1181 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1182
1183 =item C<AUG_TYPE_CHECK> = 4
1184
1185 Typecheck lenses (can be expensive).
1186
1187 =item C<AUG_NO_STDINC> = 8
1188
1189 Do not use standard load path for modules.
1190
1191 =item C<AUG_SAVE_NOOP> = 16
1192
1193 Make save a no-op, just record what would have been changed.
1194
1195 =item C<AUG_NO_LOAD> = 32
1196
1197 Do not load the tree in C<guestfs_aug_init>.
1198
1199 =back
1200
1201 To close the handle, you can call C<guestfs_aug_close>.
1202
1203 To find out more about Augeas, see L<http://augeas.net/>.");
1204
1205   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1206    [], (* XXX Augeas code needs tests. *)
1207    "close the current Augeas handle",
1208    "\
1209 Close the current Augeas handle and free up any resources
1210 used by it.  After calling this, you have to call
1211 C<guestfs_aug_init> again before you can use any other
1212 Augeas functions.");
1213
1214   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1215    [], (* XXX Augeas code needs tests. *)
1216    "define an Augeas variable",
1217    "\
1218 Defines an Augeas variable C<name> whose value is the result
1219 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1220 undefined.
1221
1222 On success this returns the number of nodes in C<expr>, or
1223 C<0> if C<expr> evaluates to something which is not a nodeset.");
1224
1225   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1226    [], (* XXX Augeas code needs tests. *)
1227    "define an Augeas node",
1228    "\
1229 Defines a variable C<name> whose value is the result of
1230 evaluating C<expr>.
1231
1232 If C<expr> evaluates to an empty nodeset, a node is created,
1233 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1234 C<name> will be the nodeset containing that single node.
1235
1236 On success this returns a pair containing the
1237 number of nodes in the nodeset, and a boolean flag
1238 if a node was created.");
1239
1240   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1241    [], (* XXX Augeas code needs tests. *)
1242    "look up the value of an Augeas path",
1243    "\
1244 Look up the value associated with C<path>.  If C<path>
1245 matches exactly one node, the C<value> is returned.");
1246
1247   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1248    [], (* XXX Augeas code needs tests. *)
1249    "set Augeas path to value",
1250    "\
1251 Set the value associated with C<path> to C<val>.
1252
1253 In the Augeas API, it is possible to clear a node by setting
1254 the value to NULL.  Due to an oversight in the libguestfs API
1255 you cannot do that with this call.  Instead you must use the
1256 C<guestfs_aug_clear> call.");
1257
1258   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1259    [], (* XXX Augeas code needs tests. *)
1260    "insert a sibling Augeas node",
1261    "\
1262 Create a new sibling C<label> for C<path>, inserting it into
1263 the tree before or after C<path> (depending on the boolean
1264 flag C<before>).
1265
1266 C<path> must match exactly one existing node in the tree, and
1267 C<label> must be a label, ie. not contain C</>, C<*> or end
1268 with a bracketed index C<[N]>.");
1269
1270   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "remove an Augeas path",
1273    "\
1274 Remove C<path> and all of its children.
1275
1276 On success this returns the number of entries which were removed.");
1277
1278   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "move Augeas node",
1281    "\
1282 Move the node C<src> to C<dest>.  C<src> must match exactly
1283 one node.  C<dest> is overwritten if it exists.");
1284
1285   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1286    [], (* XXX Augeas code needs tests. *)
1287    "return Augeas nodes which match augpath",
1288    "\
1289 Returns a list of paths which match the path expression C<path>.
1290 The returned paths are sufficiently qualified so that they match
1291 exactly one node in the current tree.");
1292
1293   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1294    [], (* XXX Augeas code needs tests. *)
1295    "write all pending Augeas changes to disk",
1296    "\
1297 This writes all pending changes to disk.
1298
1299 The flags which were passed to C<guestfs_aug_init> affect exactly
1300 how files are saved.");
1301
1302   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1303    [], (* XXX Augeas code needs tests. *)
1304    "load files into the tree",
1305    "\
1306 Load files into the tree.
1307
1308 See C<aug_load> in the Augeas documentation for the full gory
1309 details.");
1310
1311   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1312    [], (* XXX Augeas code needs tests. *)
1313    "list Augeas nodes under augpath",
1314    "\
1315 This is just a shortcut for listing C<guestfs_aug_match>
1316 C<path/*> and sorting the resulting nodes into alphabetical order.");
1317
1318   ("rm", (RErr, [Pathname "path"]), 29, [],
1319    [InitBasicFS, Always, TestRun
1320       [["touch"; "/new"];
1321        ["rm"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["mkdir"; "/new"];
1326        ["rm"; "/new"]]],
1327    "remove a file",
1328    "\
1329 Remove the single file C<path>.");
1330
1331   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1332    [InitBasicFS, Always, TestRun
1333       [["mkdir"; "/new"];
1334        ["rmdir"; "/new"]];
1335     InitBasicFS, Always, TestLastFail
1336       [["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["touch"; "/new"];
1339        ["rmdir"; "/new"]]],
1340    "remove a directory",
1341    "\
1342 Remove the single directory C<path>.");
1343
1344   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1345    [InitBasicFS, Always, TestOutputFalse
1346       [["mkdir"; "/new"];
1347        ["mkdir"; "/new/foo"];
1348        ["touch"; "/new/foo/bar"];
1349        ["rm_rf"; "/new"];
1350        ["exists"; "/new"]]],
1351    "remove a file or directory recursively",
1352    "\
1353 Remove the file or directory C<path>, recursively removing the
1354 contents if its a directory.  This is like the C<rm -rf> shell
1355 command.");
1356
1357   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1358    [InitBasicFS, Always, TestOutputTrue
1359       [["mkdir"; "/new"];
1360        ["is_dir"; "/new"]];
1361     InitBasicFS, Always, TestLastFail
1362       [["mkdir"; "/new/foo/bar"]]],
1363    "create a directory",
1364    "\
1365 Create a directory named C<path>.");
1366
1367   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1368    [InitBasicFS, Always, TestOutputTrue
1369       [["mkdir_p"; "/new/foo/bar"];
1370        ["is_dir"; "/new/foo/bar"]];
1371     InitBasicFS, Always, TestOutputTrue
1372       [["mkdir_p"; "/new/foo/bar"];
1373        ["is_dir"; "/new/foo"]];
1374     InitBasicFS, Always, TestOutputTrue
1375       [["mkdir_p"; "/new/foo/bar"];
1376        ["is_dir"; "/new"]];
1377     (* Regression tests for RHBZ#503133: *)
1378     InitBasicFS, Always, TestRun
1379       [["mkdir"; "/new"];
1380        ["mkdir_p"; "/new"]];
1381     InitBasicFS, Always, TestLastFail
1382       [["touch"; "/new"];
1383        ["mkdir_p"; "/new"]]],
1384    "create a directory and parents",
1385    "\
1386 Create a directory named C<path>, creating any parent directories
1387 as necessary.  This is like the C<mkdir -p> shell command.");
1388
1389   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1390    [], (* XXX Need stat command to test *)
1391    "change file mode",
1392    "\
1393 Change the mode (permissions) of C<path> to C<mode>.  Only
1394 numeric modes are supported.
1395
1396 I<Note>: When using this command from guestfish, C<mode>
1397 by default would be decimal, unless you prefix it with
1398 C<0> to get octal, ie. use C<0700> not C<700>.
1399
1400 The mode actually set is affected by the umask.");
1401
1402   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1403    [], (* XXX Need stat command to test *)
1404    "change file owner and group",
1405    "\
1406 Change the file owner to C<owner> and group to C<group>.
1407
1408 Only numeric uid and gid are supported.  If you want to use
1409 names, you will need to locate and parse the password file
1410 yourself (Augeas support makes this relatively easy).");
1411
1412   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1413    [InitISOFS, Always, TestOutputTrue (
1414       [["exists"; "/empty"]]);
1415     InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/directory"]])],
1417    "test if file or directory exists",
1418    "\
1419 This returns C<true> if and only if there is a file, directory
1420 (or anything) with the given C<path> name.
1421
1422 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1423
1424   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1425    [InitISOFS, Always, TestOutputTrue (
1426       [["is_file"; "/known-1"]]);
1427     InitISOFS, Always, TestOutputFalse (
1428       [["is_file"; "/directory"]])],
1429    "test if file exists",
1430    "\
1431 This returns C<true> if and only if there is a file
1432 with the given C<path> name.  Note that it returns false for
1433 other objects like directories.
1434
1435 See also C<guestfs_stat>.");
1436
1437   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1438    [InitISOFS, Always, TestOutputFalse (
1439       [["is_dir"; "/known-3"]]);
1440     InitISOFS, Always, TestOutputTrue (
1441       [["is_dir"; "/directory"]])],
1442    "test if file exists",
1443    "\
1444 This returns C<true> if and only if there is a directory
1445 with the given C<path> name.  Note that it returns false for
1446 other objects like files.
1447
1448 See also C<guestfs_stat>.");
1449
1450   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1451    [InitEmpty, Always, TestOutputListOfDevices (
1452       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1453        ["pvcreate"; "/dev/sda1"];
1454        ["pvcreate"; "/dev/sda2"];
1455        ["pvcreate"; "/dev/sda3"];
1456        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1457    "create an LVM physical volume",
1458    "\
1459 This creates an LVM physical volume on the named C<device>,
1460 where C<device> should usually be a partition name such
1461 as C</dev/sda1>.");
1462
1463   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1464    [InitEmpty, Always, TestOutputList (
1465       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1466        ["pvcreate"; "/dev/sda1"];
1467        ["pvcreate"; "/dev/sda2"];
1468        ["pvcreate"; "/dev/sda3"];
1469        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1470        ["vgcreate"; "VG2"; "/dev/sda3"];
1471        ["vgs"]], ["VG1"; "VG2"])],
1472    "create an LVM volume group",
1473    "\
1474 This creates an LVM volume group called C<volgroup>
1475 from the non-empty list of physical volumes C<physvols>.");
1476
1477   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1478    [InitEmpty, Always, TestOutputList (
1479       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1480        ["pvcreate"; "/dev/sda1"];
1481        ["pvcreate"; "/dev/sda2"];
1482        ["pvcreate"; "/dev/sda3"];
1483        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1484        ["vgcreate"; "VG2"; "/dev/sda3"];
1485        ["lvcreate"; "LV1"; "VG1"; "50"];
1486        ["lvcreate"; "LV2"; "VG1"; "50"];
1487        ["lvcreate"; "LV3"; "VG2"; "50"];
1488        ["lvcreate"; "LV4"; "VG2"; "50"];
1489        ["lvcreate"; "LV5"; "VG2"; "50"];
1490        ["lvs"]],
1491       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1492        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1493    "create an LVM logical volume",
1494    "\
1495 This creates an LVM logical volume called C<logvol>
1496 on the volume group C<volgroup>, with C<size> megabytes.");
1497
1498   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1499    [InitEmpty, Always, TestOutput (
1500       [["part_disk"; "/dev/sda"; "mbr"];
1501        ["mkfs"; "ext2"; "/dev/sda1"];
1502        ["mount_options"; ""; "/dev/sda1"; "/"];
1503        ["write"; "/new"; "new file contents"];
1504        ["cat"; "/new"]], "new file contents")],
1505    "make a filesystem",
1506    "\
1507 This creates a filesystem on C<device> (usually a partition
1508 or LVM logical volume).  The filesystem type is C<fstype>, for
1509 example C<ext3>.");
1510
1511   ("sfdisk", (RErr, [Device "device";
1512                      Int "cyls"; Int "heads"; Int "sectors";
1513                      StringList "lines"]), 43, [DangerWillRobinson],
1514    [],
1515    "create partitions on a block device",
1516    "\
1517 This is a direct interface to the L<sfdisk(8)> program for creating
1518 partitions on block devices.
1519
1520 C<device> should be a block device, for example C</dev/sda>.
1521
1522 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1523 and sectors on the device, which are passed directly to sfdisk as
1524 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1525 of these, then the corresponding parameter is omitted.  Usually for
1526 'large' disks, you can just pass C<0> for these, but for small
1527 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1528 out the right geometry and you will need to tell it.
1529
1530 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1531 information refer to the L<sfdisk(8)> manpage.
1532
1533 To create a single partition occupying the whole disk, you would
1534 pass C<lines> as a single element list, when the single element being
1535 the string C<,> (comma).
1536
1537 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1538 C<guestfs_part_init>");
1539
1540   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1541    [],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.");
1554
1555   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1556    [InitEmpty, Always, TestOutputListOfDevices (
1557       [["part_disk"; "/dev/sda"; "mbr"];
1558        ["mkfs"; "ext2"; "/dev/sda1"];
1559        ["mount_options"; ""; "/dev/sda1"; "/"];
1560        ["mounts"]], ["/dev/sda1"]);
1561     InitEmpty, Always, TestOutputList (
1562       [["part_disk"; "/dev/sda"; "mbr"];
1563        ["mkfs"; "ext2"; "/dev/sda1"];
1564        ["mount_options"; ""; "/dev/sda1"; "/"];
1565        ["umount"; "/"];
1566        ["mounts"]], [])],
1567    "unmount a filesystem",
1568    "\
1569 This unmounts the given filesystem.  The filesystem may be
1570 specified either by its mountpoint (path) or the device which
1571 contains the filesystem.");
1572
1573   ("mounts", (RStringList "devices", []), 46, [],
1574    [InitBasicFS, Always, TestOutputListOfDevices (
1575       [["mounts"]], ["/dev/sda1"])],
1576    "show mounted filesystems",
1577    "\
1578 This returns the list of currently mounted filesystems.  It returns
1579 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1580
1581 Some internal mounts are not shown.
1582
1583 See also: C<guestfs_mountpoints>");
1584
1585   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1586    [InitBasicFS, Always, TestOutputList (
1587       [["umount_all"];
1588        ["mounts"]], []);
1589     (* check that umount_all can unmount nested mounts correctly: *)
1590     InitEmpty, Always, TestOutputList (
1591       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1592        ["mkfs"; "ext2"; "/dev/sda1"];
1593        ["mkfs"; "ext2"; "/dev/sda2"];
1594        ["mkfs"; "ext2"; "/dev/sda3"];
1595        ["mount_options"; ""; "/dev/sda1"; "/"];
1596        ["mkdir"; "/mp1"];
1597        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1598        ["mkdir"; "/mp1/mp2"];
1599        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1600        ["mkdir"; "/mp1/mp2/mp3"];
1601        ["umount_all"];
1602        ["mounts"]], [])],
1603    "unmount all filesystems",
1604    "\
1605 This unmounts all mounted filesystems.
1606
1607 Some internal mounts are not unmounted by this call.");
1608
1609   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1610    [],
1611    "remove all LVM LVs, VGs and PVs",
1612    "\
1613 This command removes all LVM logical volumes, volume groups
1614 and physical volumes.");
1615
1616   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1617    [InitISOFS, Always, TestOutput (
1618       [["file"; "/empty"]], "empty");
1619     InitISOFS, Always, TestOutput (
1620       [["file"; "/known-1"]], "ASCII text");
1621     InitISOFS, Always, TestLastFail (
1622       [["file"; "/notexists"]])],
1623    "determine file type",
1624    "\
1625 This call uses the standard L<file(1)> command to determine
1626 the type or contents of the file.  This also works on devices,
1627 for example to find out whether a partition contains a filesystem.
1628
1629 This call will also transparently look inside various types
1630 of compressed file.
1631
1632 The exact command which runs is C<file -zbsL path>.  Note in
1633 particular that the filename is not prepended to the output
1634 (the C<-b> option).");
1635
1636   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1637    [InitBasicFS, Always, TestOutput (
1638       [["upload"; "test-command"; "/test-command"];
1639        ["chmod"; "0o755"; "/test-command"];
1640        ["command"; "/test-command 1"]], "Result1");
1641     InitBasicFS, Always, TestOutput (
1642       [["upload"; "test-command"; "/test-command"];
1643        ["chmod"; "0o755"; "/test-command"];
1644        ["command"; "/test-command 2"]], "Result2\n");
1645     InitBasicFS, Always, TestOutput (
1646       [["upload"; "test-command"; "/test-command"];
1647        ["chmod"; "0o755"; "/test-command"];
1648        ["command"; "/test-command 3"]], "\nResult3");
1649     InitBasicFS, Always, TestOutput (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command"; "/test-command 4"]], "\nResult4\n");
1653     InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 5"]], "\nResult5\n\n");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 7"]], "");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 8"]], "\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 9"]], "\n\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1681     InitBasicFS, Always, TestLastFail (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command"]])],
1685    "run a command from the guest filesystem",
1686    "\
1687 This call runs a command from the guest filesystem.  The
1688 filesystem must be mounted, and must contain a compatible
1689 operating system (ie. something Linux, with the same
1690 or compatible processor architecture).
1691
1692 The single parameter is an argv-style list of arguments.
1693 The first element is the name of the program to run.
1694 Subsequent elements are parameters.  The list must be
1695 non-empty (ie. must contain a program name).  Note that
1696 the command runs directly, and is I<not> invoked via
1697 the shell (see C<guestfs_sh>).
1698
1699 The return value is anything printed to I<stdout> by
1700 the command.
1701
1702 If the command returns a non-zero exit status, then
1703 this function returns an error message.  The error message
1704 string is the content of I<stderr> from the command.
1705
1706 The C<$PATH> environment variable will contain at least
1707 C</usr/bin> and C</bin>.  If you require a program from
1708 another location, you should provide the full path in the
1709 first parameter.
1710
1711 Shared libraries and data files required by the program
1712 must be available on filesystems which are mounted in the
1713 correct places.  It is the caller's responsibility to ensure
1714 all filesystems that are needed are mounted at the right
1715 locations.");
1716
1717   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1718    [InitBasicFS, Always, TestOutputList (
1719       [["upload"; "test-command"; "/test-command"];
1720        ["chmod"; "0o755"; "/test-command"];
1721        ["command_lines"; "/test-command 1"]], ["Result1"]);
1722     InitBasicFS, Always, TestOutputList (
1723       [["upload"; "test-command"; "/test-command"];
1724        ["chmod"; "0o755"; "/test-command"];
1725        ["command_lines"; "/test-command 2"]], ["Result2"]);
1726     InitBasicFS, Always, TestOutputList (
1727       [["upload"; "test-command"; "/test-command"];
1728        ["chmod"; "0o755"; "/test-command"];
1729        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1730     InitBasicFS, Always, TestOutputList (
1731       [["upload"; "test-command"; "/test-command"];
1732        ["chmod"; "0o755"; "/test-command"];
1733        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1734     InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 7"]], []);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 8"]], [""]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 9"]], ["";""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1762    "run a command, returning lines",
1763    "\
1764 This is the same as C<guestfs_command>, but splits the
1765 result into a list of lines.
1766
1767 See also: C<guestfs_sh_lines>");
1768
1769   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1770    [InitISOFS, Always, TestOutputStruct (
1771       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1772    "get file information",
1773    "\
1774 Returns file information for the given C<path>.
1775
1776 This is the same as the C<stat(2)> system call.");
1777
1778   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1779    [InitISOFS, Always, TestOutputStruct (
1780       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1781    "get file information for a symbolic link",
1782    "\
1783 Returns file information for the given C<path>.
1784
1785 This is the same as C<guestfs_stat> except that if C<path>
1786 is a symbolic link, then the link is stat-ed, not the file it
1787 refers to.
1788
1789 This is the same as the C<lstat(2)> system call.");
1790
1791   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1792    [InitISOFS, Always, TestOutputStruct (
1793       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1794    "get file system statistics",
1795    "\
1796 Returns file system statistics for any mounted file system.
1797 C<path> should be a file or directory in the mounted file system
1798 (typically it is the mount point itself, but it doesn't need to be).
1799
1800 This is the same as the C<statvfs(2)> system call.");
1801
1802   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1803    [], (* XXX test *)
1804    "get ext2/ext3/ext4 superblock details",
1805    "\
1806 This returns the contents of the ext2, ext3 or ext4 filesystem
1807 superblock on C<device>.
1808
1809 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1810 manpage for more details.  The list of fields returned isn't
1811 clearly defined, and depends on both the version of C<tune2fs>
1812 that libguestfs was built against, and the filesystem itself.");
1813
1814   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1815    [InitEmpty, Always, TestOutputTrue (
1816       [["blockdev_setro"; "/dev/sda"];
1817        ["blockdev_getro"; "/dev/sda"]])],
1818    "set block device to read-only",
1819    "\
1820 Sets the block device named C<device> to read-only.
1821
1822 This uses the L<blockdev(8)> command.");
1823
1824   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1825    [InitEmpty, Always, TestOutputFalse (
1826       [["blockdev_setrw"; "/dev/sda"];
1827        ["blockdev_getro"; "/dev/sda"]])],
1828    "set block device to read-write",
1829    "\
1830 Sets the block device named C<device> to read-write.
1831
1832 This uses the L<blockdev(8)> command.");
1833
1834   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1835    [InitEmpty, Always, TestOutputTrue (
1836       [["blockdev_setro"; "/dev/sda"];
1837        ["blockdev_getro"; "/dev/sda"]])],
1838    "is block device set to read-only",
1839    "\
1840 Returns a boolean indicating if the block device is read-only
1841 (true if read-only, false if not).
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1846    [InitEmpty, Always, TestOutputInt (
1847       [["blockdev_getss"; "/dev/sda"]], 512)],
1848    "get sectorsize of block device",
1849    "\
1850 This returns the size of sectors on a block device.
1851 Usually 512, but can be larger for modern devices.
1852
1853 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1854 for that).
1855
1856 This uses the L<blockdev(8)> command.");
1857
1858   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1859    [InitEmpty, Always, TestOutputInt (
1860       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1861    "get blocksize of block device",
1862    "\
1863 This returns the block size of a device.
1864
1865 (Note this is different from both I<size in blocks> and
1866 I<filesystem block size>).
1867
1868 This uses the L<blockdev(8)> command.");
1869
1870   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1871    [], (* XXX test *)
1872    "set blocksize of block device",
1873    "\
1874 This sets the block size of a device.
1875
1876 (Note this is different from both I<size in blocks> and
1877 I<filesystem block size>).
1878
1879 This uses the L<blockdev(8)> command.");
1880
1881   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1882    [InitEmpty, Always, TestOutputInt (
1883       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1884    "get total size of device in 512-byte sectors",
1885    "\
1886 This returns the size of the device in units of 512-byte sectors
1887 (even if the sectorsize isn't 512 bytes ... weird).
1888
1889 See also C<guestfs_blockdev_getss> for the real sector size of
1890 the device, and C<guestfs_blockdev_getsize64> for the more
1891 useful I<size in bytes>.
1892
1893 This uses the L<blockdev(8)> command.");
1894
1895   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1896    [InitEmpty, Always, TestOutputInt (
1897       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1898    "get total size of device in bytes",
1899    "\
1900 This returns the size of the device in bytes.
1901
1902 See also C<guestfs_blockdev_getsz>.
1903
1904 This uses the L<blockdev(8)> command.");
1905
1906   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1907    [InitEmpty, Always, TestRun
1908       [["blockdev_flushbufs"; "/dev/sda"]]],
1909    "flush device buffers",
1910    "\
1911 This tells the kernel to flush internal buffers associated
1912 with C<device>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1917    [InitEmpty, Always, TestRun
1918       [["blockdev_rereadpt"; "/dev/sda"]]],
1919    "reread partition table",
1920    "\
1921 Reread the partition table on C<device>.
1922
1923 This uses the L<blockdev(8)> command.");
1924
1925   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1926    [InitBasicFS, Always, TestOutput (
1927       (* Pick a file from cwd which isn't likely to change. *)
1928       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1929        ["checksum"; "md5"; "/COPYING.LIB"]],
1930       Digest.to_hex (Digest.file "COPYING.LIB"))],
1931    "upload a file from the local machine",
1932    "\
1933 Upload local file C<filename> to C<remotefilename> on the
1934 filesystem.
1935
1936 C<filename> can also be a named pipe.
1937
1938 See also C<guestfs_download>.");
1939
1940   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1941    [InitBasicFS, Always, TestOutput (
1942       (* Pick a file from cwd which isn't likely to change. *)
1943       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1944        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1945        ["upload"; "testdownload.tmp"; "/upload"];
1946        ["checksum"; "md5"; "/upload"]],
1947       Digest.to_hex (Digest.file "COPYING.LIB"))],
1948    "download a file to the local machine",
1949    "\
1950 Download file C<remotefilename> and save it as C<filename>
1951 on the local machine.
1952
1953 C<filename> can also be a named pipe.
1954
1955 See also C<guestfs_upload>, C<guestfs_cat>.");
1956
1957   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1958    [InitISOFS, Always, TestOutput (
1959       [["checksum"; "crc"; "/known-3"]], "2891671662");
1960     InitISOFS, Always, TestLastFail (
1961       [["checksum"; "crc"; "/notexists"]]);
1962     InitISOFS, Always, TestOutput (
1963       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1974     (* Test for RHBZ#579608, absolute symbolic links. *)
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1977    "compute MD5, SHAx or CRC checksum of file",
1978    "\
1979 This call computes the MD5, SHAx or CRC checksum of the
1980 file named C<path>.
1981
1982 The type of checksum to compute is given by the C<csumtype>
1983 parameter which must have one of the following values:
1984
1985 =over 4
1986
1987 =item C<crc>
1988
1989 Compute the cyclic redundancy check (CRC) specified by POSIX
1990 for the C<cksum> command.
1991
1992 =item C<md5>
1993
1994 Compute the MD5 hash (using the C<md5sum> program).
1995
1996 =item C<sha1>
1997
1998 Compute the SHA1 hash (using the C<sha1sum> program).
1999
2000 =item C<sha224>
2001
2002 Compute the SHA224 hash (using the C<sha224sum> program).
2003
2004 =item C<sha256>
2005
2006 Compute the SHA256 hash (using the C<sha256sum> program).
2007
2008 =item C<sha384>
2009
2010 Compute the SHA384 hash (using the C<sha384sum> program).
2011
2012 =item C<sha512>
2013
2014 Compute the SHA512 hash (using the C<sha512sum> program).
2015
2016 =back
2017
2018 The checksum is returned as a printable string.
2019
2020 To get the checksum for a device, use C<guestfs_checksum_device>.
2021
2022 To get the checksums for many files, use C<guestfs_checksums_out>.");
2023
2024   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2025    [InitBasicFS, Always, TestOutput (
2026       [["tar_in"; "../images/helloworld.tar"; "/"];
2027        ["cat"; "/hello"]], "hello\n")],
2028    "unpack tarfile to directory",
2029    "\
2030 This command uploads and unpacks local file C<tarfile> (an
2031 I<uncompressed> tar file) into C<directory>.
2032
2033 To upload a compressed tarball, use C<guestfs_tgz_in>
2034 or C<guestfs_txz_in>.");
2035
2036   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2037    [],
2038    "pack directory into tarfile",
2039    "\
2040 This command packs the contents of C<directory> and downloads
2041 it to local file C<tarfile>.
2042
2043 To download a compressed tarball, use C<guestfs_tgz_out>
2044 or C<guestfs_txz_out>.");
2045
2046   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2047    [InitBasicFS, Always, TestOutput (
2048       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2049        ["cat"; "/hello"]], "hello\n")],
2050    "unpack compressed tarball to directory",
2051    "\
2052 This command uploads and unpacks local file C<tarball> (a
2053 I<gzip compressed> tar file) into C<directory>.
2054
2055 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2056
2057   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2058    [],
2059    "pack directory into compressed tarball",
2060    "\
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarball>.
2063
2064 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2065
2066   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2067    [InitBasicFS, Always, TestLastFail (
2068       [["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["touch"; "/new"]]);
2071     InitBasicFS, Always, TestOutput (
2072       [["write"; "/new"; "data"];
2073        ["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["cat"; "/new"]], "data")],
2076    "mount a guest disk, read-only",
2077    "\
2078 This is the same as the C<guestfs_mount> command, but it
2079 mounts the filesystem with the read-only (I<-o ro>) flag.");
2080
2081   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2082    [],
2083    "mount a guest disk with mount options",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 allows you to set the mount options as for the
2087 L<mount(8)> I<-o> flag.
2088
2089 If the C<options> parameter is an empty string, then
2090 no options are passed (all options default to whatever
2091 the filesystem uses).");
2092
2093   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2094    [],
2095    "mount a guest disk with mount options and vfstype",
2096    "\
2097 This is the same as the C<guestfs_mount> command, but it
2098 allows you to set both the mount options and the vfstype
2099 as for the L<mount(8)> I<-o> and I<-t> flags.");
2100
2101   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2102    [],
2103    "debugging and internals",
2104    "\
2105 The C<guestfs_debug> command exposes some internals of
2106 C<guestfsd> (the guestfs daemon) that runs inside the
2107 qemu subprocess.
2108
2109 There is no comprehensive help for this command.  You have
2110 to look at the file C<daemon/debug.c> in the libguestfs source
2111 to find out what you can do.");
2112
2113   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2114    [InitEmpty, Always, TestOutputList (
2115       [["part_disk"; "/dev/sda"; "mbr"];
2116        ["pvcreate"; "/dev/sda1"];
2117        ["vgcreate"; "VG"; "/dev/sda1"];
2118        ["lvcreate"; "LV1"; "VG"; "50"];
2119        ["lvcreate"; "LV2"; "VG"; "50"];
2120        ["lvremove"; "/dev/VG/LV1"];
2121        ["lvs"]], ["/dev/VG/LV2"]);
2122     InitEmpty, Always, TestOutputList (
2123       [["part_disk"; "/dev/sda"; "mbr"];
2124        ["pvcreate"; "/dev/sda1"];
2125        ["vgcreate"; "VG"; "/dev/sda1"];
2126        ["lvcreate"; "LV1"; "VG"; "50"];
2127        ["lvcreate"; "LV2"; "VG"; "50"];
2128        ["lvremove"; "/dev/VG"];
2129        ["lvs"]], []);
2130     InitEmpty, Always, TestOutputList (
2131       [["part_disk"; "/dev/sda"; "mbr"];
2132        ["pvcreate"; "/dev/sda1"];
2133        ["vgcreate"; "VG"; "/dev/sda1"];
2134        ["lvcreate"; "LV1"; "VG"; "50"];
2135        ["lvcreate"; "LV2"; "VG"; "50"];
2136        ["lvremove"; "/dev/VG"];
2137        ["vgs"]], ["VG"])],
2138    "remove an LVM logical volume",
2139    "\
2140 Remove an LVM logical volume C<device>, where C<device> is
2141 the path to the LV, such as C</dev/VG/LV>.
2142
2143 You can also remove all LVs in a volume group by specifying
2144 the VG name, C</dev/VG>.");
2145
2146   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2147    [InitEmpty, Always, TestOutputList (
2148       [["part_disk"; "/dev/sda"; "mbr"];
2149        ["pvcreate"; "/dev/sda1"];
2150        ["vgcreate"; "VG"; "/dev/sda1"];
2151        ["lvcreate"; "LV1"; "VG"; "50"];
2152        ["lvcreate"; "LV2"; "VG"; "50"];
2153        ["vgremove"; "VG"];
2154        ["lvs"]], []);
2155     InitEmpty, Always, TestOutputList (
2156       [["part_disk"; "/dev/sda"; "mbr"];
2157        ["pvcreate"; "/dev/sda1"];
2158        ["vgcreate"; "VG"; "/dev/sda1"];
2159        ["lvcreate"; "LV1"; "VG"; "50"];
2160        ["lvcreate"; "LV2"; "VG"; "50"];
2161        ["vgremove"; "VG"];
2162        ["vgs"]], [])],
2163    "remove an LVM volume group",
2164    "\
2165 Remove an LVM volume group C<vgname>, (for example C<VG>).
2166
2167 This also forcibly removes all logical volumes in the volume
2168 group (if any).");
2169
2170   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2171    [InitEmpty, Always, TestOutputListOfDevices (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["pvremove"; "/dev/sda1"];
2179        ["lvs"]], []);
2180     InitEmpty, Always, TestOutputListOfDevices (
2181       [["part_disk"; "/dev/sda"; "mbr"];
2182        ["pvcreate"; "/dev/sda1"];
2183        ["vgcreate"; "VG"; "/dev/sda1"];
2184        ["lvcreate"; "LV1"; "VG"; "50"];
2185        ["lvcreate"; "LV2"; "VG"; "50"];
2186        ["vgremove"; "VG"];
2187        ["pvremove"; "/dev/sda1"];
2188        ["vgs"]], []);
2189     InitEmpty, Always, TestOutputListOfDevices (
2190       [["part_disk"; "/dev/sda"; "mbr"];
2191        ["pvcreate"; "/dev/sda1"];
2192        ["vgcreate"; "VG"; "/dev/sda1"];
2193        ["lvcreate"; "LV1"; "VG"; "50"];
2194        ["lvcreate"; "LV2"; "VG"; "50"];
2195        ["vgremove"; "VG"];
2196        ["pvremove"; "/dev/sda1"];
2197        ["pvs"]], [])],
2198    "remove an LVM physical volume",
2199    "\
2200 This wipes a physical volume C<device> so that LVM will no longer
2201 recognise it.
2202
2203 The implementation uses the C<pvremove> command which refuses to
2204 wipe physical volumes that contain any volume groups, so you have
2205 to remove those first.");
2206
2207   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2208    [InitBasicFS, Always, TestOutput (
2209       [["set_e2label"; "/dev/sda1"; "testlabel"];
2210        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2211    "set the ext2/3/4 filesystem label",
2212    "\
2213 This sets the ext2/3/4 filesystem label of the filesystem on
2214 C<device> to C<label>.  Filesystem labels are limited to
2215 16 characters.
2216
2217 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2218 to return the existing label on a filesystem.");
2219
2220   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2221    [],
2222    "get the ext2/3/4 filesystem label",
2223    "\
2224 This returns the ext2/3/4 filesystem label of the filesystem on
2225 C<device>.");
2226
2227   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2228    (let uuid = uuidgen () in
2229     [InitBasicFS, Always, TestOutput (
2230        [["set_e2uuid"; "/dev/sda1"; uuid];
2231         ["get_e2uuid"; "/dev/sda1"]], uuid);
2232      InitBasicFS, Always, TestOutput (
2233        [["set_e2uuid"; "/dev/sda1"; "clear"];
2234         ["get_e2uuid"; "/dev/sda1"]], "");
2235      (* We can't predict what UUIDs will be, so just check the commands run. *)
2236      InitBasicFS, Always, TestRun (
2237        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2238      InitBasicFS, Always, TestRun (
2239        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2240    "set the ext2/3/4 filesystem UUID",
2241    "\
2242 This sets the ext2/3/4 filesystem UUID of the filesystem on
2243 C<device> to C<uuid>.  The format of the UUID and alternatives
2244 such as C<clear>, C<random> and C<time> are described in the
2245 L<tune2fs(8)> manpage.
2246
2247 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2248 to return the existing UUID of a filesystem.");
2249
2250   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2251    [],
2252    "get the ext2/3/4 filesystem UUID",
2253    "\
2254 This returns the ext2/3/4 filesystem UUID of the filesystem on
2255 C<device>.");
2256
2257   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2258    [InitBasicFS, Always, TestOutputInt (
2259       [["umount"; "/dev/sda1"];
2260        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2261     InitBasicFS, Always, TestOutputInt (
2262       [["umount"; "/dev/sda1"];
2263        ["zero"; "/dev/sda1"];
2264        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2265    "run the filesystem checker",
2266    "\
2267 This runs the filesystem checker (fsck) on C<device> which
2268 should have filesystem type C<fstype>.
2269
2270 The returned integer is the status.  See L<fsck(8)> for the
2271 list of status codes from C<fsck>.
2272
2273 Notes:
2274
2275 =over 4
2276
2277 =item *
2278
2279 Multiple status codes can be summed together.
2280
2281 =item *
2282
2283 A non-zero return code can mean \"success\", for example if
2284 errors have been corrected on the filesystem.
2285
2286 =item *
2287
2288 Checking or repairing NTFS volumes is not supported
2289 (by linux-ntfs).
2290
2291 =back
2292
2293 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2294
2295   ("zero", (RErr, [Device "device"]), 85, [],
2296    [InitBasicFS, Always, TestOutput (
2297       [["umount"; "/dev/sda1"];
2298        ["zero"; "/dev/sda1"];
2299        ["file"; "/dev/sda1"]], "data")],
2300    "write zeroes to the device",
2301    "\
2302 This command writes zeroes over the first few blocks of C<device>.
2303
2304 How many blocks are zeroed isn't specified (but it's I<not> enough
2305 to securely wipe the device).  It should be sufficient to remove
2306 any partition tables, filesystem superblocks and so on.
2307
2308 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2309
2310   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2311    (* Test disabled because grub-install incompatible with virtio-blk driver.
2312     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2313     *)
2314    [InitBasicFS, Disabled, TestOutputTrue (
2315       [["grub_install"; "/"; "/dev/sda1"];
2316        ["is_dir"; "/boot"]])],
2317    "install GRUB",
2318    "\
2319 This command installs GRUB (the Grand Unified Bootloader) on
2320 C<device>, with the root directory being C<root>.");
2321
2322   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2323    [InitBasicFS, Always, TestOutput (
2324       [["write"; "/old"; "file content"];
2325        ["cp"; "/old"; "/new"];
2326        ["cat"; "/new"]], "file content");
2327     InitBasicFS, Always, TestOutputTrue (
2328       [["write"; "/old"; "file content"];
2329        ["cp"; "/old"; "/new"];
2330        ["is_file"; "/old"]]);
2331     InitBasicFS, Always, TestOutput (
2332       [["write"; "/old"; "file content"];
2333        ["mkdir"; "/dir"];
2334        ["cp"; "/old"; "/dir/new"];
2335        ["cat"; "/dir/new"]], "file content")],
2336    "copy a file",
2337    "\
2338 This copies a file from C<src> to C<dest> where C<dest> is
2339 either a destination filename or destination directory.");
2340
2341   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2342    [InitBasicFS, Always, TestOutput (
2343       [["mkdir"; "/olddir"];
2344        ["mkdir"; "/newdir"];
2345        ["write"; "/olddir/file"; "file content"];
2346        ["cp_a"; "/olddir"; "/newdir"];
2347        ["cat"; "/newdir/olddir/file"]], "file content")],
2348    "copy a file or directory recursively",
2349    "\
2350 This copies a file or directory from C<src> to C<dest>
2351 recursively using the C<cp -a> command.");
2352
2353   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2354    [InitBasicFS, Always, TestOutput (
2355       [["write"; "/old"; "file content"];
2356        ["mv"; "/old"; "/new"];
2357        ["cat"; "/new"]], "file content");
2358     InitBasicFS, Always, TestOutputFalse (
2359       [["write"; "/old"; "file content"];
2360        ["mv"; "/old"; "/new"];
2361        ["is_file"; "/old"]])],
2362    "move a file",
2363    "\
2364 This moves a file from C<src> to C<dest> where C<dest> is
2365 either a destination filename or destination directory.");
2366
2367   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2368    [InitEmpty, Always, TestRun (
2369       [["drop_caches"; "3"]])],
2370    "drop kernel page cache, dentries and inodes",
2371    "\
2372 This instructs the guest kernel to drop its page cache,
2373 and/or dentries and inode caches.  The parameter C<whattodrop>
2374 tells the kernel what precisely to drop, see
2375 L<http://linux-mm.org/Drop_Caches>
2376
2377 Setting C<whattodrop> to 3 should drop everything.
2378
2379 This automatically calls L<sync(2)> before the operation,
2380 so that the maximum guest memory is freed.");
2381
2382   ("dmesg", (RString "kmsgs", []), 91, [],
2383    [InitEmpty, Always, TestRun (
2384       [["dmesg"]])],
2385    "return kernel messages",
2386    "\
2387 This returns the kernel messages (C<dmesg> output) from
2388 the guest kernel.  This is sometimes useful for extended
2389 debugging of problems.
2390
2391 Another way to get the same information is to enable
2392 verbose messages with C<guestfs_set_verbose> or by setting
2393 the environment variable C<LIBGUESTFS_DEBUG=1> before
2394 running the program.");
2395
2396   ("ping_daemon", (RErr, []), 92, [],
2397    [InitEmpty, Always, TestRun (
2398       [["ping_daemon"]])],
2399    "ping the guest daemon",
2400    "\
2401 This is a test probe into the guestfs daemon running inside
2402 the qemu subprocess.  Calling this function checks that the
2403 daemon responds to the ping message, without affecting the daemon
2404 or attached block device(s) in any other way.");
2405
2406   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2407    [InitBasicFS, Always, TestOutputTrue (
2408       [["write"; "/file1"; "contents of a file"];
2409        ["cp"; "/file1"; "/file2"];
2410        ["equal"; "/file1"; "/file2"]]);
2411     InitBasicFS, Always, TestOutputFalse (
2412       [["write"; "/file1"; "contents of a file"];
2413        ["write"; "/file2"; "contents of another file"];
2414        ["equal"; "/file1"; "/file2"]]);
2415     InitBasicFS, Always, TestLastFail (
2416       [["equal"; "/file1"; "/file2"]])],
2417    "test if two files have equal contents",
2418    "\
2419 This compares the two files C<file1> and C<file2> and returns
2420 true if their content is exactly equal, or false otherwise.
2421
2422 The external L<cmp(1)> program is used for the comparison.");
2423
2424   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2425    [InitISOFS, Always, TestOutputList (
2426       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2427     InitISOFS, Always, TestOutputList (
2428       [["strings"; "/empty"]], []);
2429     (* Test for RHBZ#579608, absolute symbolic links. *)
2430     InitISOFS, Always, TestRun (
2431       [["strings"; "/abssymlink"]])],
2432    "print the printable strings in a file",
2433    "\
2434 This runs the L<strings(1)> command on a file and returns
2435 the list of printable strings found.");
2436
2437   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2438    [InitISOFS, Always, TestOutputList (
2439       [["strings_e"; "b"; "/known-5"]], []);
2440     InitBasicFS, Always, TestOutputList (
2441       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2442        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2443    "print the printable strings in a file",
2444    "\
2445 This is like the C<guestfs_strings> command, but allows you to
2446 specify the encoding of strings that are looked for in
2447 the source file C<path>.
2448
2449 Allowed encodings are:
2450
2451 =over 4
2452
2453 =item s
2454
2455 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2456 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2457
2458 =item S
2459
2460 Single 8-bit-byte characters.
2461
2462 =item b
2463
2464 16-bit big endian strings such as those encoded in
2465 UTF-16BE or UCS-2BE.
2466
2467 =item l (lower case letter L)
2468
2469 16-bit little endian such as UTF-16LE and UCS-2LE.
2470 This is useful for examining binaries in Windows guests.
2471
2472 =item B
2473
2474 32-bit big endian such as UCS-4BE.
2475
2476 =item L
2477
2478 32-bit little endian such as UCS-4LE.
2479
2480 =back
2481
2482 The returned strings are transcoded to UTF-8.");
2483
2484   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2485    [InitISOFS, Always, TestOutput (
2486       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2487     (* Test for RHBZ#501888c2 regression which caused large hexdump
2488      * commands to segfault.
2489      *)
2490     InitISOFS, Always, TestRun (
2491       [["hexdump"; "/100krandom"]]);
2492     (* Test for RHBZ#579608, absolute symbolic links. *)
2493     InitISOFS, Always, TestRun (
2494       [["hexdump"; "/abssymlink"]])],
2495    "dump a file in hexadecimal",
2496    "\
2497 This runs C<hexdump -C> on the given C<path>.  The result is
2498 the human-readable, canonical hex dump of the file.");
2499
2500   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2501    [InitNone, Always, TestOutput (
2502       [["part_disk"; "/dev/sda"; "mbr"];
2503        ["mkfs"; "ext3"; "/dev/sda1"];
2504        ["mount_options"; ""; "/dev/sda1"; "/"];
2505        ["write"; "/new"; "test file"];
2506        ["umount"; "/dev/sda1"];
2507        ["zerofree"; "/dev/sda1"];
2508        ["mount_options"; ""; "/dev/sda1"; "/"];
2509        ["cat"; "/new"]], "test file")],
2510    "zero unused inodes and disk blocks on ext2/3 filesystem",
2511    "\
2512 This runs the I<zerofree> program on C<device>.  This program
2513 claims to zero unused inodes and disk blocks on an ext2/3
2514 filesystem, thus making it possible to compress the filesystem
2515 more effectively.
2516
2517 You should B<not> run this program if the filesystem is
2518 mounted.
2519
2520 It is possible that using this program can damage the filesystem
2521 or data on the filesystem.");
2522
2523   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2524    [],
2525    "resize an LVM physical volume",
2526    "\
2527 This resizes (expands or shrinks) an existing LVM physical
2528 volume to match the new size of the underlying device.");
2529
2530   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2531                        Int "cyls"; Int "heads"; Int "sectors";
2532                        String "line"]), 99, [DangerWillRobinson],
2533    [],
2534    "modify a single partition on a block device",
2535    "\
2536 This runs L<sfdisk(8)> option to modify just the single
2537 partition C<n> (note: C<n> counts from 1).
2538
2539 For other parameters, see C<guestfs_sfdisk>.  You should usually
2540 pass C<0> for the cyls/heads/sectors parameters.
2541
2542 See also: C<guestfs_part_add>");
2543
2544   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2545    [],
2546    "display the partition table",
2547    "\
2548 This displays the partition table on C<device>, in the
2549 human-readable output of the L<sfdisk(8)> command.  It is
2550 not intended to be parsed.
2551
2552 See also: C<guestfs_part_list>");
2553
2554   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2555    [],
2556    "display the kernel geometry",
2557    "\
2558 This displays the kernel's idea of the geometry of C<device>.
2559
2560 The result is in human-readable format, and not designed to
2561 be parsed.");
2562
2563   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2564    [],
2565    "display the disk geometry from the partition table",
2566    "\
2567 This displays the disk geometry of C<device> read from the
2568 partition table.  Especially in the case where the underlying
2569 block device has been resized, this can be different from the
2570 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2571
2572 The result is in human-readable format, and not designed to
2573 be parsed.");
2574
2575   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2576    [],
2577    "activate or deactivate all volume groups",
2578    "\
2579 This command activates or (if C<activate> is false) deactivates
2580 all logical volumes in all volume groups.
2581 If activated, then they are made known to the
2582 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2583 then those devices disappear.
2584
2585 This command is the same as running C<vgchange -a y|n>");
2586
2587   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2588    [],
2589    "activate or deactivate some volume groups",
2590    "\
2591 This command activates or (if C<activate> is false) deactivates
2592 all logical volumes in the listed volume groups C<volgroups>.
2593 If activated, then they are made known to the
2594 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2595 then those devices disappear.
2596
2597 This command is the same as running C<vgchange -a y|n volgroups...>
2598
2599 Note that if C<volgroups> is an empty list then B<all> volume groups
2600 are activated or deactivated.");
2601
2602   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2603    [InitNone, Always, TestOutput (
2604       [["part_disk"; "/dev/sda"; "mbr"];
2605        ["pvcreate"; "/dev/sda1"];
2606        ["vgcreate"; "VG"; "/dev/sda1"];
2607        ["lvcreate"; "LV"; "VG"; "10"];
2608        ["mkfs"; "ext2"; "/dev/VG/LV"];
2609        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2610        ["write"; "/new"; "test content"];
2611        ["umount"; "/"];
2612        ["lvresize"; "/dev/VG/LV"; "20"];
2613        ["e2fsck_f"; "/dev/VG/LV"];
2614        ["resize2fs"; "/dev/VG/LV"];
2615        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2616        ["cat"; "/new"]], "test content");
2617     InitNone, Always, TestRun (
2618       (* Make an LV smaller to test RHBZ#587484. *)
2619       [["part_disk"; "/dev/sda"; "mbr"];
2620        ["pvcreate"; "/dev/sda1"];
2621        ["vgcreate"; "VG"; "/dev/sda1"];
2622        ["lvcreate"; "LV"; "VG"; "20"];
2623        ["lvresize"; "/dev/VG/LV"; "10"]])],
2624    "resize an LVM logical volume",
2625    "\
2626 This resizes (expands or shrinks) an existing LVM logical
2627 volume to C<mbytes>.  When reducing, data in the reduced part
2628 is lost.");
2629
2630   ("resize2fs", (RErr, [Device "device"]), 106, [],
2631    [], (* lvresize tests this *)
2632    "resize an ext2/ext3 filesystem",
2633    "\
2634 This resizes an ext2 or ext3 filesystem to match the size of
2635 the underlying device.
2636
2637 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2638 on the C<device> before calling this command.  For unknown reasons
2639 C<resize2fs> sometimes gives an error about this and sometimes not.
2640 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2641 calling this function.");
2642
2643   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2644    [InitBasicFS, Always, TestOutputList (
2645       [["find"; "/"]], ["lost+found"]);
2646     InitBasicFS, Always, TestOutputList (
2647       [["touch"; "/a"];
2648        ["mkdir"; "/b"];
2649        ["touch"; "/b/c"];
2650        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2651     InitBasicFS, Always, TestOutputList (
2652       [["mkdir_p"; "/a/b/c"];
2653        ["touch"; "/a/b/c/d"];
2654        ["find"; "/a/b/"]], ["c"; "c/d"])],
2655    "find all files and directories",
2656    "\
2657 This command lists out all files and directories, recursively,
2658 starting at C<directory>.  It is essentially equivalent to
2659 running the shell command C<find directory -print> but some
2660 post-processing happens on the output, described below.
2661
2662 This returns a list of strings I<without any prefix>.  Thus
2663 if the directory structure was:
2664
2665  /tmp/a
2666  /tmp/b
2667  /tmp/c/d
2668
2669 then the returned list from C<guestfs_find> C</tmp> would be
2670 4 elements:
2671
2672  a
2673  b
2674  c
2675  c/d
2676
2677 If C<directory> is not a directory, then this command returns
2678 an error.
2679
2680 The returned list is sorted.
2681
2682 See also C<guestfs_find0>.");
2683
2684   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2685    [], (* lvresize tests this *)
2686    "check an ext2/ext3 filesystem",
2687    "\
2688 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2689 filesystem checker on C<device>, noninteractively (C<-p>),
2690 even if the filesystem appears to be clean (C<-f>).
2691
2692 This command is only needed because of C<guestfs_resize2fs>
2693 (q.v.).  Normally you should use C<guestfs_fsck>.");
2694
2695   ("sleep", (RErr, [Int "secs"]), 109, [],
2696    [InitNone, Always, TestRun (
2697       [["sleep"; "1"]])],
2698    "sleep for some seconds",
2699    "\
2700 Sleep for C<secs> seconds.");
2701
2702   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2703    [InitNone, Always, TestOutputInt (
2704       [["part_disk"; "/dev/sda"; "mbr"];
2705        ["mkfs"; "ntfs"; "/dev/sda1"];
2706        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2707     InitNone, Always, TestOutputInt (
2708       [["part_disk"; "/dev/sda"; "mbr"];
2709        ["mkfs"; "ext2"; "/dev/sda1"];
2710        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2711    "probe NTFS volume",
2712    "\
2713 This command runs the L<ntfs-3g.probe(8)> command which probes
2714 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2715 be mounted read-write, and some cannot be mounted at all).
2716
2717 C<rw> is a boolean flag.  Set it to true if you want to test
2718 if the volume can be mounted read-write.  Set it to false if
2719 you want to test if the volume can be mounted read-only.
2720
2721 The return value is an integer which C<0> if the operation
2722 would succeed, or some non-zero value documented in the
2723 L<ntfs-3g.probe(8)> manual page.");
2724
2725   ("sh", (RString "output", [String "command"]), 111, [],
2726    [], (* XXX needs tests *)
2727    "run a command via the shell",
2728    "\
2729 This call runs a command from the guest filesystem via the
2730 guest's C</bin/sh>.
2731
2732 This is like C<guestfs_command>, but passes the command to:
2733
2734  /bin/sh -c \"command\"
2735
2736 Depending on the guest's shell, this usually results in
2737 wildcards being expanded, shell expressions being interpolated
2738 and so on.
2739
2740 All the provisos about C<guestfs_command> apply to this call.");
2741
2742   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2743    [], (* XXX needs tests *)
2744    "run a command via the shell returning lines",
2745    "\
2746 This is the same as C<guestfs_sh>, but splits the result
2747 into a list of lines.
2748
2749 See also: C<guestfs_command_lines>");
2750
2751   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2752    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2753     * code in stubs.c, since all valid glob patterns must start with "/".
2754     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2755     *)
2756    [InitBasicFS, Always, TestOutputList (
2757       [["mkdir_p"; "/a/b/c"];
2758        ["touch"; "/a/b/c/d"];
2759        ["touch"; "/a/b/c/e"];
2760        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
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/*/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/*/x/*"]], [])],
2771    "expand a wildcard path",
2772    "\
2773 This command searches for all the pathnames matching
2774 C<pattern> according to the wildcard expansion rules
2775 used by the shell.
2776
2777 If no paths match, then this returns an empty list
2778 (note: not an error).
2779
2780 It is just a wrapper around the C L<glob(3)> function
2781 with flags C<GLOB_MARK|GLOB_BRACE>.
2782 See that manual page for more details.");
2783
2784   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2785    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2786       [["scrub_device"; "/dev/sdc"]])],
2787    "scrub (securely wipe) a device",
2788    "\
2789 This command writes patterns over C<device> to make data retrieval
2790 more difficult.
2791
2792 It is an interface to the L<scrub(1)> program.  See that
2793 manual page for more details.");
2794
2795   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2796    [InitBasicFS, Always, TestRun (
2797       [["write"; "/file"; "content"];
2798        ["scrub_file"; "/file"]])],
2799    "scrub (securely wipe) a file",
2800    "\
2801 This command writes patterns over a file to make data retrieval
2802 more difficult.
2803
2804 The file is I<removed> after scrubbing.
2805
2806 It is an interface to the L<scrub(1)> program.  See that
2807 manual page for more details.");
2808
2809   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2810    [], (* XXX needs testing *)
2811    "scrub (securely wipe) free space",
2812    "\
2813 This command creates the directory C<dir> and then fills it
2814 with files until the filesystem is full, and scrubs the files
2815 as for C<guestfs_scrub_file>, and deletes them.
2816 The intention is to scrub any free space on the partition
2817 containing C<dir>.
2818
2819 It is an interface to the L<scrub(1)> program.  See that
2820 manual page for more details.");
2821
2822   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2823    [InitBasicFS, Always, TestRun (
2824       [["mkdir"; "/tmp"];
2825        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2826    "create a temporary directory",
2827    "\
2828 This command creates a temporary directory.  The
2829 C<template> parameter should be a full pathname for the
2830 temporary directory name with the final six characters being
2831 \"XXXXXX\".
2832
2833 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2834 the second one being suitable for Windows filesystems.
2835
2836 The name of the temporary directory that was created
2837 is returned.
2838
2839 The temporary directory is created with mode 0700
2840 and is owned by root.
2841
2842 The caller is responsible for deleting the temporary
2843 directory and its contents after use.
2844
2845 See also: L<mkdtemp(3)>");
2846
2847   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2848    [InitISOFS, Always, TestOutputInt (
2849       [["wc_l"; "/10klines"]], 10000);
2850     (* Test for RHBZ#579608, absolute symbolic links. *)
2851     InitISOFS, Always, TestOutputInt (
2852       [["wc_l"; "/abssymlink"]], 10000)],
2853    "count lines in a file",
2854    "\
2855 This command counts the lines in a file, using the
2856 C<wc -l> external command.");
2857
2858   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2859    [InitISOFS, Always, TestOutputInt (
2860       [["wc_w"; "/10klines"]], 10000)],
2861    "count words in a file",
2862    "\
2863 This command counts the words in a file, using the
2864 C<wc -w> external command.");
2865
2866   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2867    [InitISOFS, Always, TestOutputInt (
2868       [["wc_c"; "/100kallspaces"]], 102400)],
2869    "count characters in a file",
2870    "\
2871 This command counts the characters in a file, using the
2872 C<wc -c> external command.");
2873
2874   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2875    [InitISOFS, Always, TestOutputList (
2876       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2877     (* Test for RHBZ#579608, absolute symbolic links. *)
2878     InitISOFS, Always, TestOutputList (
2879       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2880    "return first 10 lines of a file",
2881    "\
2882 This command returns up to the first 10 lines of a file as
2883 a list of strings.");
2884
2885   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2886    [InitISOFS, Always, TestOutputList (
2887       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2888     InitISOFS, Always, TestOutputList (
2889       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2890     InitISOFS, Always, TestOutputList (
2891       [["head_n"; "0"; "/10klines"]], [])],
2892    "return first N lines of a file",
2893    "\
2894 If the parameter C<nrlines> is a positive number, this returns the first
2895 C<nrlines> lines of the file C<path>.
2896
2897 If the parameter C<nrlines> is a negative number, this returns lines
2898 from the file C<path>, excluding the last C<nrlines> lines.
2899
2900 If the parameter C<nrlines> is zero, this returns an empty list.");
2901
2902   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2903    [InitISOFS, Always, TestOutputList (
2904       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2905    "return last 10 lines of a file",
2906    "\
2907 This command returns up to the last 10 lines of a file as
2908 a list of strings.");
2909
2910   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2911    [InitISOFS, Always, TestOutputList (
2912       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2913     InitISOFS, Always, TestOutputList (
2914       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2915     InitISOFS, Always, TestOutputList (
2916       [["tail_n"; "0"; "/10klines"]], [])],
2917    "return last N lines of a file",
2918    "\
2919 If the parameter C<nrlines> is a positive number, this returns the last
2920 C<nrlines> lines of the file C<path>.
2921
2922 If the parameter C<nrlines> is a negative number, this returns lines
2923 from the file C<path>, starting with the C<-nrlines>th line.
2924
2925 If the parameter C<nrlines> is zero, this returns an empty list.");
2926
2927   ("df", (RString "output", []), 125, [],
2928    [], (* XXX Tricky to test because it depends on the exact format
2929         * of the 'df' command and other imponderables.
2930         *)
2931    "report file system disk space usage",
2932    "\
2933 This command runs the C<df> command to report disk space used.
2934
2935 This command is mostly useful for interactive sessions.  It
2936 is I<not> intended that you try to parse the output string.
2937 Use C<statvfs> from programs.");
2938
2939   ("df_h", (RString "output", []), 126, [],
2940    [], (* XXX Tricky to test because it depends on the exact format
2941         * of the 'df' command and other imponderables.
2942         *)
2943    "report file system disk space usage (human readable)",
2944    "\
2945 This command runs the C<df -h> command to report disk space used
2946 in human-readable format.
2947
2948 This command is mostly useful for interactive sessions.  It
2949 is I<not> intended that you try to parse the output string.
2950 Use C<statvfs> from programs.");
2951
2952   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2953    [InitISOFS, Always, TestOutputInt (
2954       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2955    "estimate file space usage",
2956    "\
2957 This command runs the C<du -s> command to estimate file space
2958 usage for C<path>.
2959
2960 C<path> can be a file or a directory.  If C<path> is a directory
2961 then the estimate includes the contents of the directory and all
2962 subdirectories (recursively).
2963
2964 The result is the estimated size in I<kilobytes>
2965 (ie. units of 1024 bytes).");
2966
2967   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2968    [InitISOFS, Always, TestOutputList (
2969       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2970    "list files in an initrd",
2971    "\
2972 This command lists out files contained in an initrd.
2973
2974 The files are listed without any initial C</> character.  The
2975 files are listed in the order they appear (not necessarily
2976 alphabetical).  Directory names are listed as separate items.
2977
2978 Old Linux kernels (2.4 and earlier) used a compressed ext2
2979 filesystem as initrd.  We I<only> support the newer initramfs
2980 format (compressed cpio files).");
2981
2982   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2983    [],
2984    "mount a file using the loop device",
2985    "\
2986 This command lets you mount C<file> (a filesystem image
2987 in a file) on a mount point.  It is entirely equivalent to
2988 the command C<mount -o loop file mountpoint>.");
2989
2990   ("mkswap", (RErr, [Device "device"]), 130, [],
2991    [InitEmpty, Always, TestRun (
2992       [["part_disk"; "/dev/sda"; "mbr"];
2993        ["mkswap"; "/dev/sda1"]])],
2994    "create a swap partition",
2995    "\
2996 Create a swap partition on C<device>.");
2997
2998   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2999    [InitEmpty, Always, TestRun (
3000       [["part_disk"; "/dev/sda"; "mbr"];
3001        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3002    "create a swap partition with a label",
3003    "\
3004 Create a swap partition on C<device> with label C<label>.
3005
3006 Note that you cannot attach a swap label to a block device
3007 (eg. C</dev/sda>), just to a partition.  This appears to be
3008 a limitation of the kernel or swap tools.");
3009
3010   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3011    (let uuid = uuidgen () in
3012     [InitEmpty, Always, TestRun (
3013        [["part_disk"; "/dev/sda"; "mbr"];
3014         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3015    "create a swap partition with an explicit UUID",
3016    "\
3017 Create a swap partition on C<device> with UUID C<uuid>.");
3018
3019   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3020    [InitBasicFS, Always, TestOutputStruct (
3021       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3022        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3023        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3024     InitBasicFS, Always, TestOutputStruct (
3025       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3026        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3027    "make block, character or FIFO devices",
3028    "\
3029 This call creates block or character special devices, or
3030 named pipes (FIFOs).
3031
3032 The C<mode> parameter should be the mode, using the standard
3033 constants.  C<devmajor> and C<devminor> are the
3034 device major and minor numbers, only used when creating block
3035 and character special devices.
3036
3037 Note that, just like L<mknod(2)>, the mode must be bitwise
3038 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3039 just creates a regular file).  These constants are
3040 available in the standard Linux header files, or you can use
3041 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3042 which are wrappers around this command which bitwise OR
3043 in the appropriate constant for you.
3044
3045 The mode actually set is affected by the umask.");
3046
3047   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3048    [InitBasicFS, Always, TestOutputStruct (
3049       [["mkfifo"; "0o777"; "/node"];
3050        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3051    "make FIFO (named pipe)",
3052    "\
3053 This call creates a FIFO (named pipe) called C<path> with
3054 mode C<mode>.  It is just a convenient wrapper around
3055 C<guestfs_mknod>.
3056
3057 The mode actually set is affected by the umask.");
3058
3059   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3060    [InitBasicFS, Always, TestOutputStruct (
3061       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3062        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3063    "make block device node",
3064    "\
3065 This call creates a block device node called C<path> with
3066 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3067 It is just a convenient wrapper around C<guestfs_mknod>.
3068
3069 The mode actually set is affected by the umask.");
3070
3071   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3072    [InitBasicFS, Always, TestOutputStruct (
3073       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3074        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3075    "make char device node",
3076    "\
3077 This call creates a char device node called C<path> with
3078 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3079 It is just a convenient wrapper around C<guestfs_mknod>.
3080
3081 The mode actually set is affected by the umask.");
3082
3083   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3084    [InitEmpty, Always, TestOutputInt (
3085       [["umask"; "0o22"]], 0o22)],
3086    "set file mode creation mask (umask)",
3087    "\
3088 This function sets the mask used for creating new files and
3089 device nodes to C<mask & 0777>.
3090
3091 Typical umask values would be C<022> which creates new files
3092 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3093 C<002> which creates new files with permissions like
3094 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3095
3096 The default umask is C<022>.  This is important because it
3097 means that directories and device nodes will be created with
3098 C<0644> or C<0755> mode even if you specify C<0777>.
3099
3100 See also C<guestfs_get_umask>,
3101 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3102
3103 This call returns the previous umask.");
3104
3105   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3106    [],
3107    "read directories entries",
3108    "\
3109 This returns the list of directory entries in directory C<dir>.
3110
3111 All entries in the directory are returned, including C<.> and
3112 C<..>.  The entries are I<not> sorted, but returned in the same
3113 order as the underlying filesystem.
3114
3115 Also this call returns basic file type information about each
3116 file.  The C<ftyp> field will contain one of the following characters:
3117
3118 =over 4
3119
3120 =item 'b'
3121
3122 Block special
3123
3124 =item 'c'
3125
3126 Char special
3127
3128 =item 'd'
3129
3130 Directory
3131
3132 =item 'f'
3133
3134 FIFO (named pipe)
3135
3136 =item 'l'
3137
3138 Symbolic link
3139
3140 =item 'r'
3141
3142 Regular file
3143
3144 =item 's'
3145
3146 Socket
3147
3148 =item 'u'
3149
3150 Unknown file type
3151
3152 =item '?'
3153
3154 The L<readdir(3)> returned a C<d_type> field with an
3155 unexpected value
3156
3157 =back
3158
3159 This function is primarily intended for use by programs.  To
3160 get a simple list of names, use C<guestfs_ls>.  To get a printable
3161 directory for human consumption, use C<guestfs_ll>.");
3162
3163   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3164    [],
3165    "create partitions on a block device",
3166    "\
3167 This is a simplified interface to the C<guestfs_sfdisk>
3168 command, where partition sizes are specified in megabytes
3169 only (rounded to the nearest cylinder) and you don't need
3170 to specify the cyls, heads and sectors parameters which
3171 were rarely if ever used anyway.
3172
3173 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3174 and C<guestfs_part_disk>");
3175
3176   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3177    [],
3178    "determine file type inside a compressed file",
3179    "\
3180 This command runs C<file> after first decompressing C<path>
3181 using C<method>.
3182
3183 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3184
3185 Since 1.0.63, use C<guestfs_file> instead which can now
3186 process compressed files.");
3187
3188   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3189    [],
3190    "list extended attributes of a file or directory",
3191    "\
3192 This call lists the extended attributes of the file or directory
3193 C<path>.
3194
3195 At the system call level, this is a combination of the
3196 L<listxattr(2)> and L<getxattr(2)> calls.
3197
3198 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3199
3200   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3201    [],
3202    "list extended attributes of a file or directory",
3203    "\
3204 This is the same as C<guestfs_getxattrs>, but if C<path>
3205 is a symbolic link, then it returns the extended attributes
3206 of the link itself.");
3207
3208   ("setxattr", (RErr, [String "xattr";
3209                        String "val"; Int "vallen"; (* will be BufferIn *)
3210                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3211    [],
3212    "set extended attribute of a file or directory",
3213    "\
3214 This call sets the extended attribute named C<xattr>
3215 of the file C<path> to the value C<val> (of length C<vallen>).
3216 The value is arbitrary 8 bit data.
3217
3218 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3219
3220   ("lsetxattr", (RErr, [String "xattr";
3221                         String "val"; Int "vallen"; (* will be BufferIn *)
3222                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3223    [],
3224    "set extended attribute of a file or directory",
3225    "\
3226 This is the same as C<guestfs_setxattr>, but if C<path>
3227 is a symbolic link, then it sets an extended attribute
3228 of the link itself.");
3229
3230   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3231    [],
3232    "remove extended attribute of a file or directory",
3233    "\
3234 This call removes the extended attribute named C<xattr>
3235 of the file C<path>.
3236
3237 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3238
3239   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3240    [],
3241    "remove extended attribute of a file or directory",
3242    "\
3243 This is the same as C<guestfs_removexattr>, but if C<path>
3244 is a symbolic link, then it removes an extended attribute
3245 of the link itself.");
3246
3247   ("mountpoints", (RHashtable "mps", []), 147, [],
3248    [],
3249    "show mountpoints",
3250    "\
3251 This call is similar to C<guestfs_mounts>.  That call returns
3252 a list of devices.  This one returns a hash table (map) of
3253 device name to directory where the device is mounted.");
3254
3255   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3256    (* This is a special case: while you would expect a parameter
3257     * of type "Pathname", that doesn't work, because it implies
3258     * NEED_ROOT in the generated calling code in stubs.c, and
3259     * this function cannot use NEED_ROOT.
3260     *)
3261    [],
3262    "create a mountpoint",
3263    "\
3264 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3265 specialized calls that can be used to create extra mountpoints
3266 before mounting the first filesystem.
3267
3268 These calls are I<only> necessary in some very limited circumstances,
3269 mainly the case where you want to mount a mix of unrelated and/or
3270 read-only filesystems together.
3271
3272 For example, live CDs often contain a \"Russian doll\" nest of
3273 filesystems, an ISO outer layer, with a squashfs image inside, with
3274 an ext2/3 image inside that.  You can unpack this as follows
3275 in guestfish:
3276
3277  add-ro Fedora-11-i686-Live.iso
3278  run
3279  mkmountpoint /cd
3280  mkmountpoint /squash
3281  mkmountpoint /ext3
3282  mount /dev/sda /cd
3283  mount-loop /cd/LiveOS/squashfs.img /squash
3284  mount-loop /squash/LiveOS/ext3fs.img /ext3
3285
3286 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3287
3288   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3289    [],
3290    "remove a mountpoint",
3291    "\
3292 This calls removes a mountpoint that was previously created
3293 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3294 for full details.");
3295
3296   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3297    [InitISOFS, Always, TestOutputBuffer (
3298       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3299     (* Test various near large, large and too large files (RHBZ#589039). *)
3300     InitBasicFS, Always, TestLastFail (
3301       [["touch"; "/a"];
3302        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3303        ["read_file"; "/a"]]);
3304     InitBasicFS, Always, TestLastFail (
3305       [["touch"; "/a"];
3306        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3307        ["read_file"; "/a"]]);
3308     InitBasicFS, Always, TestLastFail (
3309       [["touch"; "/a"];
3310        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3311        ["read_file"; "/a"]])],
3312    "read a file",
3313    "\
3314 This calls returns the contents of the file C<path> as a
3315 buffer.
3316
3317 Unlike C<guestfs_cat>, this function can correctly
3318 handle files that contain embedded ASCII NUL characters.
3319 However unlike C<guestfs_download>, this function is limited
3320 in the total size of file that can be handled.");
3321
3322   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3323    [InitISOFS, Always, TestOutputList (
3324       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3325     InitISOFS, Always, TestOutputList (
3326       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3327     (* Test for RHBZ#579608, absolute symbolic links. *)
3328     InitISOFS, Always, TestOutputList (
3329       [["grep"; "nomatch"; "/abssymlink"]], [])],
3330    "return lines matching a pattern",
3331    "\
3332 This calls the external C<grep> program and returns the
3333 matching lines.");
3334
3335   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3336    [InitISOFS, Always, TestOutputList (
3337       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3338    "return lines matching a pattern",
3339    "\
3340 This calls the external C<egrep> program and returns the
3341 matching lines.");
3342
3343   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3344    [InitISOFS, Always, TestOutputList (
3345       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3346    "return lines matching a pattern",
3347    "\
3348 This calls the external C<fgrep> program and returns the
3349 matching lines.");
3350
3351   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3352    [InitISOFS, Always, TestOutputList (
3353       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3354    "return lines matching a pattern",
3355    "\
3356 This calls the external C<grep -i> program and returns the
3357 matching lines.");
3358
3359   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3360    [InitISOFS, Always, TestOutputList (
3361       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3362    "return lines matching a pattern",
3363    "\
3364 This calls the external C<egrep -i> program and returns the
3365 matching lines.");
3366
3367   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3368    [InitISOFS, Always, TestOutputList (
3369       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3370    "return lines matching a pattern",
3371    "\
3372 This calls the external C<fgrep -i> program and returns the
3373 matching lines.");
3374
3375   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3376    [InitISOFS, Always, TestOutputList (
3377       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3378    "return lines matching a pattern",
3379    "\
3380 This calls the external C<zgrep> program and returns the
3381 matching lines.");
3382
3383   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3384    [InitISOFS, Always, TestOutputList (
3385       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3386    "return lines matching a pattern",
3387    "\
3388 This calls the external C<zegrep> program and returns the
3389 matching lines.");
3390
3391   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3392    [InitISOFS, Always, TestOutputList (
3393       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3394    "return lines matching a pattern",
3395    "\
3396 This calls the external C<zfgrep> program and returns the
3397 matching lines.");
3398
3399   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3400    [InitISOFS, Always, TestOutputList (
3401       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3402    "return lines matching a pattern",
3403    "\
3404 This calls the external C<zgrep -i> program and returns the
3405 matching lines.");
3406
3407   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3408    [InitISOFS, Always, TestOutputList (
3409       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3410    "return lines matching a pattern",
3411    "\
3412 This calls the external C<zegrep -i> program and returns the
3413 matching lines.");
3414
3415   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3416    [InitISOFS, Always, TestOutputList (
3417       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3418    "return lines matching a pattern",
3419    "\
3420 This calls the external C<zfgrep -i> program and returns the
3421 matching lines.");
3422
3423   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3424    [InitISOFS, Always, TestOutput (
3425       [["realpath"; "/../directory"]], "/directory")],
3426    "canonicalized absolute pathname",
3427    "\
3428 Return the canonicalized absolute pathname of C<path>.  The
3429 returned path has no C<.>, C<..> or symbolic link path elements.");
3430
3431   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3432    [InitBasicFS, Always, TestOutputStruct (
3433       [["touch"; "/a"];
3434        ["ln"; "/a"; "/b"];
3435        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3436    "create a hard link",
3437    "\
3438 This command creates a hard link using the C<ln> command.");
3439
3440   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3441    [InitBasicFS, Always, TestOutputStruct (
3442       [["touch"; "/a"];
3443        ["touch"; "/b"];
3444        ["ln_f"; "/a"; "/b"];
3445        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3446    "create a hard link",
3447    "\
3448 This command creates a hard link using the C<ln -f> command.
3449 The C<-f> option removes the link (C<linkname>) if it exists already.");
3450
3451   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3452    [InitBasicFS, Always, TestOutputStruct (
3453       [["touch"; "/a"];
3454        ["ln_s"; "a"; "/b"];
3455        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3456    "create a symbolic link",
3457    "\
3458 This command creates a symbolic link using the C<ln -s> command.");
3459
3460   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3461    [InitBasicFS, Always, TestOutput (
3462       [["mkdir_p"; "/a/b"];
3463        ["touch"; "/a/b/c"];
3464        ["ln_sf"; "../d"; "/a/b/c"];
3465        ["readlink"; "/a/b/c"]], "../d")],
3466    "create a symbolic link",
3467    "\
3468 This command creates a symbolic link using the C<ln -sf> command,
3469 The C<-f> option removes the link (C<linkname>) if it exists already.");
3470
3471   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3472    [] (* XXX tested above *),
3473    "read the target of a symbolic link",
3474    "\
3475 This command reads the target of a symbolic link.");
3476
3477   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3478    [InitBasicFS, Always, TestOutputStruct (
3479       [["fallocate"; "/a"; "1000000"];
3480        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3481    "preallocate a file in the guest filesystem",
3482    "\
3483 This command preallocates a file (containing zero bytes) named
3484 C<path> of size C<len> bytes.  If the file exists already, it
3485 is overwritten.
3486
3487 Do not confuse this with the guestfish-specific
3488 C<alloc> command which allocates a file in the host and
3489 attaches it as a device.");
3490
3491   ("swapon_device", (RErr, [Device "device"]), 170, [],
3492    [InitPartition, Always, TestRun (
3493       [["mkswap"; "/dev/sda1"];
3494        ["swapon_device"; "/dev/sda1"];
3495        ["swapoff_device"; "/dev/sda1"]])],
3496    "enable swap on device",
3497    "\
3498 This command enables the libguestfs appliance to use the
3499 swap device or partition named C<device>.  The increased
3500 memory is made available for all commands, for example
3501 those run using C<guestfs_command> or C<guestfs_sh>.
3502
3503 Note that you should not swap to existing guest swap
3504 partitions unless you know what you are doing.  They may
3505 contain hibernation information, or other information that
3506 the guest doesn't want you to trash.  You also risk leaking
3507 information about the host to the guest this way.  Instead,
3508 attach a new host device to the guest and swap on that.");
3509
3510   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3511    [], (* XXX tested by swapon_device *)
3512    "disable swap on device",
3513    "\
3514 This command disables the libguestfs appliance swap
3515 device or partition named C<device>.
3516 See C<guestfs_swapon_device>.");
3517
3518   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3519    [InitBasicFS, Always, TestRun (
3520       [["fallocate"; "/swap"; "8388608"];
3521        ["mkswap_file"; "/swap"];
3522        ["swapon_file"; "/swap"];
3523        ["swapoff_file"; "/swap"]])],
3524    "enable swap on file",
3525    "\
3526 This command enables swap to a file.
3527 See C<guestfs_swapon_device> for other notes.");
3528
3529   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3530    [], (* XXX tested by swapon_file *)
3531    "disable swap on file",
3532    "\
3533 This command disables the libguestfs appliance swap on file.");
3534
3535   ("swapon_label", (RErr, [String "label"]), 174, [],
3536    [InitEmpty, Always, TestRun (
3537       [["part_disk"; "/dev/sdb"; "mbr"];
3538        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3539        ["swapon_label"; "swapit"];
3540        ["swapoff_label"; "swapit"];
3541        ["zero"; "/dev/sdb"];
3542        ["blockdev_rereadpt"; "/dev/sdb"]])],
3543    "enable swap on labeled swap partition",
3544    "\
3545 This command enables swap to a labeled swap partition.
3546 See C<guestfs_swapon_device> for other notes.");
3547
3548   ("swapoff_label", (RErr, [String "label"]), 175, [],
3549    [], (* XXX tested by swapon_label *)
3550    "disable swap on labeled swap partition",
3551    "\
3552 This command disables the libguestfs appliance swap on
3553 labeled swap partition.");
3554
3555   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3556    (let uuid = uuidgen () in
3557     [InitEmpty, Always, TestRun (
3558        [["mkswap_U"; uuid; "/dev/sdb"];
3559         ["swapon_uuid"; uuid];
3560         ["swapoff_uuid"; uuid]])]),
3561    "enable swap on swap partition by UUID",
3562    "\
3563 This command enables swap to a swap partition with the given UUID.
3564 See C<guestfs_swapon_device> for other notes.");
3565
3566   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3567    [], (* XXX tested by swapon_uuid *)
3568    "disable swap on swap partition by UUID",
3569    "\
3570 This command disables the libguestfs appliance swap partition
3571 with the given UUID.");
3572
3573   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3574    [InitBasicFS, Always, TestRun (
3575       [["fallocate"; "/swap"; "8388608"];
3576        ["mkswap_file"; "/swap"]])],
3577    "create a swap file",
3578    "\
3579 Create a swap file.
3580
3581 This command just writes a swap file signature to an existing
3582 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3583
3584   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3585    [InitISOFS, Always, TestRun (
3586       [["inotify_init"; "0"]])],
3587    "create an inotify handle",
3588    "\
3589 This command creates a new inotify handle.
3590 The inotify subsystem can be used to notify events which happen to
3591 objects in the guest filesystem.
3592
3593 C<maxevents> is the maximum number of events which will be
3594 queued up between calls to C<guestfs_inotify_read> or
3595 C<guestfs_inotify_files>.
3596 If this is passed as C<0>, then the kernel (or previously set)
3597 default is used.  For Linux 2.6.29 the default was 16384 events.
3598 Beyond this limit, the kernel throws away events, but records
3599 the fact that it threw them away by setting a flag
3600 C<IN_Q_OVERFLOW> in the returned structure list (see
3601 C<guestfs_inotify_read>).
3602
3603 Before any events are generated, you have to add some
3604 watches to the internal watch list.  See:
3605 C<guestfs_inotify_add_watch>,
3606 C<guestfs_inotify_rm_watch> and
3607 C<guestfs_inotify_watch_all>.
3608
3609 Queued up events should be read periodically by calling
3610 C<guestfs_inotify_read>
3611 (or C<guestfs_inotify_files> which is just a helpful
3612 wrapper around C<guestfs_inotify_read>).  If you don't
3613 read the events out often enough then you risk the internal
3614 queue overflowing.
3615
3616 The handle should be closed after use by calling
3617 C<guestfs_inotify_close>.  This also removes any
3618 watches automatically.
3619
3620 See also L<inotify(7)> for an overview of the inotify interface
3621 as exposed by the Linux kernel, which is roughly what we expose
3622 via libguestfs.  Note that there is one global inotify handle
3623 per libguestfs instance.");
3624
3625   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3626    [InitBasicFS, Always, TestOutputList (
3627       [["inotify_init"; "0"];
3628        ["inotify_add_watch"; "/"; "1073741823"];
3629        ["touch"; "/a"];
3630        ["touch"; "/b"];
3631        ["inotify_files"]], ["a"; "b"])],
3632    "add an inotify watch",
3633    "\
3634 Watch C<path> for the events listed in C<mask>.
3635
3636 Note that if C<path> is a directory then events within that
3637 directory are watched, but this does I<not> happen recursively
3638 (in subdirectories).
3639
3640 Note for non-C or non-Linux callers: the inotify events are
3641 defined by the Linux kernel ABI and are listed in
3642 C</usr/include/sys/inotify.h>.");
3643
3644   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3645    [],
3646    "remove an inotify watch",
3647    "\
3648 Remove a previously defined inotify watch.
3649 See C<guestfs_inotify_add_watch>.");
3650
3651   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3652    [],
3653    "return list of inotify events",
3654    "\
3655 Return the complete queue of events that have happened
3656 since the previous read call.
3657
3658 If no events have happened, this returns an empty list.
3659
3660 I<Note>: In order to make sure that all events have been
3661 read, you must call this function repeatedly until it
3662 returns an empty list.  The reason is that the call will
3663 read events up to the maximum appliance-to-host message
3664 size and leave remaining events in the queue.");
3665
3666   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3667    [],
3668    "return list of watched files that had events",
3669    "\
3670 This function is a helpful wrapper around C<guestfs_inotify_read>
3671 which just returns a list of pathnames of objects that were
3672 touched.  The returned pathnames are sorted and deduplicated.");
3673
3674   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3675    [],
3676    "close the inotify handle",
3677    "\
3678 This closes the inotify handle which was previously
3679 opened by inotify_init.  It removes all watches, throws
3680 away any pending events, and deallocates all resources.");
3681
3682   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3683    [],
3684    "set SELinux security context",
3685    "\
3686 This sets the SELinux security context of the daemon
3687 to the string C<context>.
3688
3689 See the documentation about SELINUX in L<guestfs(3)>.");
3690
3691   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3692    [],
3693    "get SELinux security context",
3694    "\
3695 This gets the SELinux security context of the daemon.
3696
3697 See the documentation about SELINUX in L<guestfs(3)>,
3698 and C<guestfs_setcon>");
3699
3700   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3701    [InitEmpty, Always, TestOutput (
3702       [["part_disk"; "/dev/sda"; "mbr"];
3703        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3704        ["mount_options"; ""; "/dev/sda1"; "/"];
3705        ["write"; "/new"; "new file contents"];
3706        ["cat"; "/new"]], "new file contents")],
3707    "make a filesystem with block size",
3708    "\
3709 This call is similar to C<guestfs_mkfs>, but it allows you to
3710 control the block size of the resulting filesystem.  Supported
3711 block sizes depend on the filesystem type, but typically they
3712 are C<1024>, C<2048> or C<4096> only.");
3713
3714   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3715    [InitEmpty, Always, TestOutput (
3716       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3717        ["mke2journal"; "4096"; "/dev/sda1"];
3718        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3719        ["mount_options"; ""; "/dev/sda2"; "/"];
3720        ["write"; "/new"; "new file contents"];
3721        ["cat"; "/new"]], "new file contents")],
3722    "make ext2/3/4 external journal",
3723    "\
3724 This creates an ext2 external journal on C<device>.  It is equivalent
3725 to the command:
3726
3727  mke2fs -O journal_dev -b blocksize device");
3728
3729   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3730    [InitEmpty, Always, TestOutput (
3731       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3732        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3733        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3734        ["mount_options"; ""; "/dev/sda2"; "/"];
3735        ["write"; "/new"; "new file contents"];
3736        ["cat"; "/new"]], "new file contents")],
3737    "make ext2/3/4 external journal with label",
3738    "\
3739 This creates an ext2 external journal on C<device> with label C<label>.");
3740
3741   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3742    (let uuid = uuidgen () in
3743     [InitEmpty, Always, TestOutput (
3744        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3745         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3746         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3747         ["mount_options"; ""; "/dev/sda2"; "/"];
3748         ["write"; "/new"; "new file contents"];
3749         ["cat"; "/new"]], "new file contents")]),
3750    "make ext2/3/4 external journal with UUID",
3751    "\
3752 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3753
3754   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3755    [],
3756    "make ext2/3/4 filesystem with external journal",
3757    "\
3758 This creates an ext2/3/4 filesystem on C<device> with
3759 an external journal on C<journal>.  It is equivalent
3760 to the command:
3761
3762  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3763
3764 See also C<guestfs_mke2journal>.");
3765
3766   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3767    [],
3768    "make ext2/3/4 filesystem with external journal",
3769    "\
3770 This creates an ext2/3/4 filesystem on C<device> with
3771 an external journal on the journal labeled C<label>.
3772
3773 See also C<guestfs_mke2journal_L>.");
3774
3775   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3776    [],
3777    "make ext2/3/4 filesystem with external journal",
3778    "\
3779 This creates an ext2/3/4 filesystem on C<device> with
3780 an external journal on the journal with UUID C<uuid>.
3781
3782 See also C<guestfs_mke2journal_U>.");
3783
3784   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3785    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3786    "load a kernel module",
3787    "\
3788 This loads a kernel module in the appliance.
3789
3790 The kernel module must have been whitelisted when libguestfs
3791 was built (see C<appliance/kmod.whitelist.in> in the source).");
3792
3793   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3794    [InitNone, Always, TestOutput (
3795       [["echo_daemon"; "This is a test"]], "This is a test"
3796     )],
3797    "echo arguments back to the client",
3798    "\
3799 This command concatenate the list of C<words> passed with single spaces between
3800 them and returns the resulting string.
3801
3802 You can use this command to test the connection through to the daemon.
3803
3804 See also C<guestfs_ping_daemon>.");
3805
3806   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3807    [], (* There is a regression test for this. *)
3808    "find all files and directories, returning NUL-separated list",
3809    "\
3810 This command lists out all files and directories, recursively,
3811 starting at C<directory>, placing the resulting list in the
3812 external file called C<files>.
3813
3814 This command works the same way as C<guestfs_find> with the
3815 following exceptions:
3816
3817 =over 4
3818
3819 =item *
3820
3821 The resulting list is written to an external file.
3822
3823 =item *
3824
3825 Items (filenames) in the result are separated
3826 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3827
3828 =item *
3829
3830 This command is not limited in the number of names that it
3831 can return.
3832
3833 =item *
3834
3835 The result list is not sorted.
3836
3837 =back");
3838
3839   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3840    [InitISOFS, Always, TestOutput (
3841       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3842     InitISOFS, Always, TestOutput (
3843       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3844     InitISOFS, Always, TestOutput (
3845       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3846     InitISOFS, Always, TestLastFail (
3847       [["case_sensitive_path"; "/Known-1/"]]);
3848     InitBasicFS, Always, TestOutput (
3849       [["mkdir"; "/a"];
3850        ["mkdir"; "/a/bbb"];
3851        ["touch"; "/a/bbb/c"];
3852        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
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, TestLastFail (
3859       [["mkdir"; "/a"];
3860        ["mkdir"; "/a/bbb"];
3861        ["touch"; "/a/bbb/c"];
3862        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3863    "return true path on case-insensitive filesystem",
3864    "\
3865 This can be used to resolve case insensitive paths on
3866 a filesystem which is case sensitive.  The use case is
3867 to resolve paths which you have read from Windows configuration
3868 files or the Windows Registry, to the true path.
3869
3870 The command handles a peculiarity of the Linux ntfs-3g
3871 filesystem driver (and probably others), which is that although
3872 the underlying filesystem is case-insensitive, the driver
3873 exports the filesystem to Linux as case-sensitive.
3874
3875 One consequence of this is that special directories such
3876 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3877 (or other things) depending on the precise details of how
3878 they were created.  In Windows itself this would not be
3879 a problem.
3880
3881 Bug or feature?  You decide:
3882 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3883
3884 This function resolves the true case of each element in the
3885 path and returns the case-sensitive path.
3886
3887 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3888 might return C<\"/WINDOWS/system32\"> (the exact return value
3889 would depend on details of how the directories were originally
3890 created under Windows).
3891
3892 I<Note>:
3893 This function does not handle drive names, backslashes etc.
3894
3895 See also C<guestfs_realpath>.");
3896
3897   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3898    [InitBasicFS, Always, TestOutput (
3899       [["vfs_type"; "/dev/sda1"]], "ext2")],
3900    "get the Linux VFS type corresponding to a mounted device",
3901    "\
3902 This command gets the block device type corresponding to
3903 a mounted device called C<device>.
3904
3905 Usually the result is the name of the Linux VFS module that
3906 is used to mount this device (probably determined automatically
3907 if you used the C<guestfs_mount> call).");
3908
3909   ("truncate", (RErr, [Pathname "path"]), 199, [],
3910    [InitBasicFS, Always, TestOutputStruct (
3911       [["write"; "/test"; "some stuff so size is not zero"];
3912        ["truncate"; "/test"];
3913        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3914    "truncate a file to zero size",
3915    "\
3916 This command truncates C<path> to a zero-length file.  The
3917 file must exist already.");
3918
3919   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3920    [InitBasicFS, Always, TestOutputStruct (
3921       [["touch"; "/test"];
3922        ["truncate_size"; "/test"; "1000"];
3923        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3924    "truncate a file to a particular size",
3925    "\
3926 This command truncates C<path> to size C<size> bytes.  The file
3927 must exist already.  If the file is smaller than C<size> then
3928 the file is extended to the required size with null bytes.");
3929
3930   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3931    [InitBasicFS, Always, TestOutputStruct (
3932       [["touch"; "/test"];
3933        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3934        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3935    "set timestamp of a file with nanosecond precision",
3936    "\
3937 This command sets the timestamps of a file with nanosecond
3938 precision.
3939
3940 C<atsecs, atnsecs> are the last access time (atime) in secs and
3941 nanoseconds from the epoch.
3942
3943 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3944 secs and nanoseconds from the epoch.
3945
3946 If the C<*nsecs> field contains the special value C<-1> then
3947 the corresponding timestamp is set to the current time.  (The
3948 C<*secs> field is ignored in this case).
3949
3950 If the C<*nsecs> field contains the special value C<-2> then
3951 the corresponding timestamp is left unchanged.  (The
3952 C<*secs> field is ignored in this case).");
3953
3954   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3955    [InitBasicFS, Always, TestOutputStruct (
3956       [["mkdir_mode"; "/test"; "0o111"];
3957        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3958    "create a directory with a particular mode",
3959    "\
3960 This command creates a directory, setting the initial permissions
3961 of the directory to C<mode>.
3962
3963 For common Linux filesystems, the actual mode which is set will
3964 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3965 interpret the mode in other ways.
3966
3967 See also C<guestfs_mkdir>, C<guestfs_umask>");
3968
3969   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3970    [], (* XXX *)
3971    "change file owner and group",
3972    "\
3973 Change the file owner to C<owner> and group to C<group>.
3974 This is like C<guestfs_chown> but if C<path> is a symlink then
3975 the link itself is changed, not the target.
3976
3977 Only numeric uid and gid are supported.  If you want to use
3978 names, you will need to locate and parse the password file
3979 yourself (Augeas support makes this relatively easy).");
3980
3981   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3982    [], (* XXX *)
3983    "lstat on multiple files",
3984    "\
3985 This call allows you to perform the C<guestfs_lstat> operation
3986 on multiple files, where all files are in the directory C<path>.
3987 C<names> is the list of files from this directory.
3988
3989 On return you get a list of stat structs, with a one-to-one
3990 correspondence to the C<names> list.  If any name did not exist
3991 or could not be lstat'd, then the C<ino> field of that structure
3992 is set to C<-1>.
3993
3994 This call is intended for programs that want to efficiently
3995 list a directory contents without making many round-trips.
3996 See also C<guestfs_lxattrlist> for a similarly efficient call
3997 for getting extended attributes.  Very long directory listings
3998 might cause the protocol message size to be exceeded, causing
3999 this call to fail.  The caller must split up such requests
4000 into smaller groups of names.");
4001
4002   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4003    [], (* XXX *)
4004    "lgetxattr on multiple files",
4005    "\
4006 This call allows you to get the extended attributes
4007 of multiple files, where all files are in the directory C<path>.
4008 C<names> is the list of files from this directory.
4009
4010 On return you get a flat list of xattr structs which must be
4011 interpreted sequentially.  The first xattr struct always has a zero-length
4012 C<attrname>.  C<attrval> in this struct is zero-length
4013 to indicate there was an error doing C<lgetxattr> for this
4014 file, I<or> is a C string which is a decimal number
4015 (the number of following attributes for this file, which could
4016 be C<\"0\">).  Then after the first xattr struct are the
4017 zero or more attributes for the first named file.
4018 This repeats for the second and subsequent files.
4019
4020 This call is intended for programs that want to efficiently
4021 list a directory contents without making many round-trips.
4022 See also C<guestfs_lstatlist> for a similarly efficient call
4023 for getting standard stats.  Very long directory listings
4024 might cause the protocol message size to be exceeded, causing
4025 this call to fail.  The caller must split up such requests
4026 into smaller groups of names.");
4027
4028   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4029    [], (* XXX *)
4030    "readlink on multiple files",
4031    "\
4032 This call allows you to do a C<readlink> operation
4033 on multiple files, where all files are in the directory C<path>.
4034 C<names> is the list of files from this directory.
4035
4036 On return you get a list of strings, with a one-to-one
4037 correspondence to the C<names> list.  Each string is the
4038 value of the symbol link.
4039
4040 If the C<readlink(2)> operation fails on any name, then
4041 the corresponding result string is the empty string C<\"\">.
4042 However the whole operation is completed even if there
4043 were C<readlink(2)> errors, and so you can call this
4044 function with names where you don't know if they are
4045 symbolic links already (albeit slightly less efficient).
4046
4047 This call is intended for programs that want to efficiently
4048 list a directory contents without making many round-trips.
4049 Very long directory listings might cause the protocol
4050 message size to be exceeded, causing
4051 this call to fail.  The caller must split up such requests
4052 into smaller groups of names.");
4053
4054   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4055    [InitISOFS, Always, TestOutputBuffer (
4056       [["pread"; "/known-4"; "1"; "3"]], "\n");
4057     InitISOFS, Always, TestOutputBuffer (
4058       [["pread"; "/empty"; "0"; "100"]], "")],
4059    "read part of a file",
4060    "\
4061 This command lets you read part of a file.  It reads C<count>
4062 bytes of the file, starting at C<offset>, from file C<path>.
4063
4064 This may read fewer bytes than requested.  For further details
4065 see the L<pread(2)> system call.
4066
4067 See also C<guestfs_pwrite>.");
4068
4069   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4070    [InitEmpty, Always, TestRun (
4071       [["part_init"; "/dev/sda"; "gpt"]])],
4072    "create an empty partition table",
4073    "\
4074 This creates an empty partition table on C<device> of one of the
4075 partition types listed below.  Usually C<parttype> should be
4076 either C<msdos> or C<gpt> (for large disks).
4077
4078 Initially there are no partitions.  Following this, you should
4079 call C<guestfs_part_add> for each partition required.
4080
4081 Possible values for C<parttype> are:
4082
4083 =over 4
4084
4085 =item B<efi> | B<gpt>
4086
4087 Intel EFI / GPT partition table.
4088
4089 This is recommended for >= 2 TB partitions that will be accessed
4090 from Linux and Intel-based Mac OS X.  It also has limited backwards
4091 compatibility with the C<mbr> format.
4092
4093 =item B<mbr> | B<msdos>
4094
4095 The standard PC \"Master Boot Record\" (MBR) format used
4096 by MS-DOS and Windows.  This partition type will B<only> work
4097 for device sizes up to 2 TB.  For large disks we recommend
4098 using C<gpt>.
4099
4100 =back
4101
4102 Other partition table types that may work but are not
4103 supported include:
4104
4105 =over 4
4106
4107 =item B<aix>
4108
4109 AIX disk labels.
4110
4111 =item B<amiga> | B<rdb>
4112
4113 Amiga \"Rigid Disk Block\" format.
4114
4115 =item B<bsd>
4116
4117 BSD disk labels.
4118
4119 =item B<dasd>
4120
4121 DASD, used on IBM mainframes.
4122
4123 =item B<dvh>
4124
4125 MIPS/SGI volumes.
4126
4127 =item B<mac>
4128
4129 Old Mac partition format.  Modern Macs use C<gpt>.
4130
4131 =item B<pc98>
4132
4133 NEC PC-98 format, common in Japan apparently.
4134
4135 =item B<sun>
4136
4137 Sun disk labels.
4138
4139 =back");
4140
4141   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4142    [InitEmpty, Always, TestRun (
4143       [["part_init"; "/dev/sda"; "mbr"];
4144        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4145     InitEmpty, Always, TestRun (
4146       [["part_init"; "/dev/sda"; "gpt"];
4147        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4148        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4149     InitEmpty, Always, TestRun (
4150       [["part_init"; "/dev/sda"; "mbr"];
4151        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4152        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4153        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4154        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4155    "add a partition to the device",
4156    "\
4157 This command adds a partition to C<device>.  If there is no partition
4158 table on the device, call C<guestfs_part_init> first.
4159
4160 The C<prlogex> parameter is the type of partition.  Normally you
4161 should pass C<p> or C<primary> here, but MBR partition tables also
4162 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4163 types.
4164
4165 C<startsect> and C<endsect> are the start and end of the partition
4166 in I<sectors>.  C<endsect> may be negative, which means it counts
4167 backwards from the end of the disk (C<-1> is the last sector).
4168
4169 Creating a partition which covers the whole disk is not so easy.
4170 Use C<guestfs_part_disk> to do that.");
4171
4172   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4173    [InitEmpty, Always, TestRun (
4174       [["part_disk"; "/dev/sda"; "mbr"]]);
4175     InitEmpty, Always, TestRun (
4176       [["part_disk"; "/dev/sda"; "gpt"]])],
4177    "partition whole disk with a single primary partition",
4178    "\
4179 This command is simply a combination of C<guestfs_part_init>
4180 followed by C<guestfs_part_add> to create a single primary partition
4181 covering the whole disk.
4182
4183 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4184 but other possible values are described in C<guestfs_part_init>.");
4185
4186   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4187    [InitEmpty, Always, TestRun (
4188       [["part_disk"; "/dev/sda"; "mbr"];
4189        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4190    "make a partition bootable",
4191    "\
4192 This sets the bootable flag on partition numbered C<partnum> on
4193 device C<device>.  Note that partitions are numbered from 1.
4194
4195 The bootable flag is used by some operating systems (notably
4196 Windows) to determine which partition to boot from.  It is by
4197 no means universally recognized.");
4198
4199   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4200    [InitEmpty, Always, TestRun (
4201       [["part_disk"; "/dev/sda"; "gpt"];
4202        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4203    "set partition name",
4204    "\
4205 This sets the partition name on partition numbered C<partnum> on
4206 device C<device>.  Note that partitions are numbered from 1.
4207
4208 The partition name can only be set on certain types of partition
4209 table.  This works on C<gpt> but not on C<mbr> partitions.");
4210
4211   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4212    [], (* XXX Add a regression test for this. *)
4213    "list partitions on a device",
4214    "\
4215 This command parses the partition table on C<device> and
4216 returns the list of partitions found.
4217
4218 The fields in the returned structure are:
4219
4220 =over 4
4221
4222 =item B<part_num>
4223
4224 Partition number, counting from 1.
4225
4226 =item B<part_start>
4227
4228 Start of the partition I<in bytes>.  To get sectors you have to
4229 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4230
4231 =item B<part_end>
4232
4233 End of the partition in bytes.
4234
4235 =item B<part_size>
4236
4237 Size of the partition in bytes.
4238
4239 =back");
4240
4241   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4242    [InitEmpty, Always, TestOutput (
4243       [["part_disk"; "/dev/sda"; "gpt"];
4244        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4245    "get the partition table type",
4246    "\
4247 This command examines the partition table on C<device> and
4248 returns the partition table type (format) being used.
4249
4250 Common return values include: C<msdos> (a DOS/Windows style MBR
4251 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4252 values are possible, although unusual.  See C<guestfs_part_init>
4253 for a full list.");
4254
4255   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4256    [InitBasicFS, Always, TestOutputBuffer (
4257       [["fill"; "0x63"; "10"; "/test"];
4258        ["read_file"; "/test"]], "cccccccccc")],
4259    "fill a file with octets",
4260    "\
4261 This command creates a new file called C<path>.  The initial
4262 content of the file is C<len> octets of C<c>, where C<c>
4263 must be a number in the range C<[0..255]>.
4264
4265 To fill a file with zero bytes (sparsely), it is
4266 much more efficient to use C<guestfs_truncate_size>.
4267 To create a file with a pattern of repeating bytes
4268 use C<guestfs_fill_pattern>.");
4269
4270   ("available", (RErr, [StringList "groups"]), 216, [],
4271    [InitNone, Always, TestRun [["available"; ""]]],
4272    "test availability of some parts of the API",
4273    "\
4274 This command is used to check the availability of some
4275 groups of functionality in the appliance, which not all builds of
4276 the libguestfs appliance will be able to provide.
4277
4278 The libguestfs groups, and the functions that those
4279 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4280
4281 The argument C<groups> is a list of group names, eg:
4282 C<[\"inotify\", \"augeas\"]> would check for the availability of
4283 the Linux inotify functions and Augeas (configuration file
4284 editing) functions.
4285
4286 The command returns no error if I<all> requested groups are available.
4287
4288 It fails with an error if one or more of the requested
4289 groups is unavailable in the appliance.
4290
4291 If an unknown group name is included in the
4292 list of groups then an error is always returned.
4293
4294 I<Notes:>
4295
4296 =over 4
4297
4298 =item *
4299
4300 You must call C<guestfs_launch> before calling this function.
4301
4302 The reason is because we don't know what groups are
4303 supported by the appliance/daemon until it is running and can
4304 be queried.
4305
4306 =item *
4307
4308 If a group of functions is available, this does not necessarily
4309 mean that they will work.  You still have to check for errors
4310 when calling individual API functions even if they are
4311 available.
4312
4313 =item *
4314
4315 It is usually the job of distro packagers to build
4316 complete functionality into the libguestfs appliance.
4317 Upstream libguestfs, if built from source with all
4318 requirements satisfied, will support everything.
4319
4320 =item *
4321
4322 This call was added in version C<1.0.80>.  In previous
4323 versions of libguestfs all you could do would be to speculatively
4324 execute a command to find out if the daemon implemented it.
4325 See also C<guestfs_version>.
4326
4327 =back");
4328
4329   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4330    [InitBasicFS, Always, TestOutputBuffer (
4331       [["write"; "/src"; "hello, world"];
4332        ["dd"; "/src"; "/dest"];
4333        ["read_file"; "/dest"]], "hello, world")],
4334    "copy from source to destination using dd",
4335    "\
4336 This command copies from one source device or file C<src>
4337 to another destination device or file C<dest>.  Normally you
4338 would use this to copy to or from a device or partition, for
4339 example to duplicate a filesystem.
4340
4341 If the destination is a device, it must be as large or larger
4342 than the source file or device, otherwise the copy will fail.
4343 This command cannot do partial copies (see C<guestfs_copy_size>).");
4344
4345   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4346    [InitBasicFS, Always, TestOutputInt (
4347       [["write"; "/file"; "hello, world"];
4348        ["filesize"; "/file"]], 12)],
4349    "return the size of the file in bytes",
4350    "\
4351 This command returns the size of C<file> in bytes.
4352
4353 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4354 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4355 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4356
4357   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4358    [InitBasicFSonLVM, Always, TestOutputList (
4359       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4360        ["lvs"]], ["/dev/VG/LV2"])],
4361    "rename an LVM logical volume",
4362    "\
4363 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4364
4365   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4366    [InitBasicFSonLVM, Always, TestOutputList (
4367       [["umount"; "/"];
4368        ["vg_activate"; "false"; "VG"];
4369        ["vgrename"; "VG"; "VG2"];
4370        ["vg_activate"; "true"; "VG2"];
4371        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4372        ["vgs"]], ["VG2"])],
4373    "rename an LVM volume group",
4374    "\
4375 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4376
4377   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4378    [InitISOFS, Always, TestOutputBuffer (
4379       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4380    "list the contents of a single file in an initrd",
4381    "\
4382 This command unpacks the file C<filename> from the initrd file
4383 called C<initrdpath>.  The filename must be given I<without> the
4384 initial C</> character.
4385
4386 For example, in guestfish you could use the following command
4387 to examine the boot script (usually called C</init>)
4388 contained in a Linux initrd or initramfs image:
4389
4390  initrd-cat /boot/initrd-<version>.img init
4391
4392 See also C<guestfs_initrd_list>.");
4393
4394   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4395    [],
4396    "get the UUID of a physical volume",
4397    "\
4398 This command returns the UUID of the LVM PV C<device>.");
4399
4400   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4401    [],
4402    "get the UUID of a volume group",
4403    "\
4404 This command returns the UUID of the LVM VG named C<vgname>.");
4405
4406   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4407    [],
4408    "get the UUID of a logical volume",
4409    "\
4410 This command returns the UUID of the LVM LV C<device>.");
4411
4412   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4413    [],
4414    "get the PV UUIDs containing the volume group",
4415    "\
4416 Given a VG called C<vgname>, this returns the UUIDs of all
4417 the physical volumes that this volume group resides on.
4418
4419 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4420 calls to associate physical volumes and volume groups.
4421
4422 See also C<guestfs_vglvuuids>.");
4423
4424   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4425    [],
4426    "get the LV UUIDs of all LVs in the volume group",
4427    "\
4428 Given a VG called C<vgname>, this returns the UUIDs of all
4429 the logical volumes created in this volume group.
4430
4431 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4432 calls to associate logical volumes and volume groups.
4433
4434 See also C<guestfs_vgpvuuids>.");
4435
4436   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4437    [InitBasicFS, Always, TestOutputBuffer (
4438       [["write"; "/src"; "hello, world"];
4439        ["copy_size"; "/src"; "/dest"; "5"];
4440        ["read_file"; "/dest"]], "hello")],
4441    "copy size bytes from source to destination using dd",
4442    "\
4443 This command copies exactly C<size> bytes from one source device
4444 or file C<src> to another destination device or file C<dest>.
4445
4446 Note this will fail if the source is too short or if the destination
4447 is not large enough.");
4448
4449   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4450    [InitBasicFSonLVM, Always, TestRun (
4451       [["zero_device"; "/dev/VG/LV"]])],
4452    "write zeroes to an entire device",
4453    "\
4454 This command writes zeroes over the entire C<device>.  Compare
4455 with C<guestfs_zero> which just zeroes the first few blocks of
4456 a device.");
4457
4458   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4459    [InitBasicFS, Always, TestOutput (
4460       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4461        ["cat"; "/hello"]], "hello\n")],
4462    "unpack compressed tarball to directory",
4463    "\
4464 This command uploads and unpacks local file C<tarball> (an
4465 I<xz compressed> tar file) into C<directory>.");
4466
4467   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4468    [],
4469    "pack directory into compressed tarball",
4470    "\
4471 This command packs the contents of C<directory> and downloads
4472 it to local file C<tarball> (as an xz compressed tar archive).");
4473
4474   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4475    [],
4476    "resize an NTFS filesystem",
4477    "\
4478 This command resizes an NTFS filesystem, expanding or
4479 shrinking it to the size of the underlying device.
4480 See also L<ntfsresize(8)>.");
4481
4482   ("vgscan", (RErr, []), 232, [],
4483    [InitEmpty, Always, TestRun (
4484       [["vgscan"]])],
4485    "rescan for LVM physical volumes, volume groups and logical volumes",
4486    "\
4487 This rescans all block devices and rebuilds the list of LVM
4488 physical volumes, volume groups and logical volumes.");
4489
4490   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4491    [InitEmpty, Always, TestRun (
4492       [["part_init"; "/dev/sda"; "mbr"];
4493        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4494        ["part_del"; "/dev/sda"; "1"]])],
4495    "delete a partition",
4496    "\
4497 This command deletes the partition numbered C<partnum> on C<device>.
4498
4499 Note that in the case of MBR partitioning, deleting an
4500 extended partition also deletes any logical partitions
4501 it contains.");
4502
4503   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4504    [InitEmpty, Always, TestOutputTrue (
4505       [["part_init"; "/dev/sda"; "mbr"];
4506        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4507        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4508        ["part_get_bootable"; "/dev/sda"; "1"]])],
4509    "return true if a partition is bootable",
4510    "\
4511 This command returns true if the partition C<partnum> on
4512 C<device> has the bootable flag set.
4513
4514 See also C<guestfs_part_set_bootable>.");
4515
4516   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4517    [InitEmpty, Always, TestOutputInt (
4518       [["part_init"; "/dev/sda"; "mbr"];
4519        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4520        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4521        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4522    "get the MBR type byte (ID byte) from a partition",
4523    "\
4524 Returns the MBR type byte (also known as the ID byte) from
4525 the numbered partition C<partnum>.
4526
4527 Note that only MBR (old DOS-style) partitions have type bytes.
4528 You will get undefined results for other partition table
4529 types (see C<guestfs_part_get_parttype>).");
4530
4531   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4532    [], (* tested by part_get_mbr_id *)
4533    "set the MBR type byte (ID byte) of a partition",
4534    "\
4535 Sets the MBR type byte (also known as the ID byte) of
4536 the numbered partition C<partnum> to C<idbyte>.  Note
4537 that the type bytes quoted in most documentation are
4538 in fact hexadecimal numbers, but usually documented
4539 without any leading \"0x\" which might be confusing.
4540
4541 Note that only MBR (old DOS-style) partitions have type bytes.
4542 You will get undefined results for other partition table
4543 types (see C<guestfs_part_get_parttype>).");
4544
4545   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4546    [InitISOFS, Always, TestOutput (
4547       [["checksum_device"; "md5"; "/dev/sdd"]],
4548       (Digest.to_hex (Digest.file "images/test.iso")))],
4549    "compute MD5, SHAx or CRC checksum of the contents of a device",
4550    "\
4551 This call computes the MD5, SHAx or CRC checksum of the
4552 contents of the device named C<device>.  For the types of
4553 checksums supported see the C<guestfs_checksum> command.");
4554
4555   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4556    [InitNone, Always, TestRun (
4557       [["part_disk"; "/dev/sda"; "mbr"];
4558        ["pvcreate"; "/dev/sda1"];
4559        ["vgcreate"; "VG"; "/dev/sda1"];
4560        ["lvcreate"; "LV"; "VG"; "10"];
4561        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4562    "expand an LV to fill free space",
4563    "\
4564 This expands an existing logical volume C<lv> so that it fills
4565 C<pc>% of the remaining free space in the volume group.  Commonly
4566 you would call this with pc = 100 which expands the logical volume
4567 as much as possible, using all remaining free space in the volume
4568 group.");
4569
4570   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4571    [], (* XXX Augeas code needs tests. *)
4572    "clear Augeas path",
4573    "\
4574 Set the value associated with C<path> to C<NULL>.  This
4575 is the same as the L<augtool(1)> C<clear> command.");
4576
4577   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4578    [InitEmpty, Always, TestOutputInt (
4579       [["get_umask"]], 0o22)],
4580    "get the current umask",
4581    "\
4582 Return the current umask.  By default the umask is C<022>
4583 unless it has been set by calling C<guestfs_umask>.");
4584
4585   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4586    [],
4587    "upload a file to the appliance (internal use only)",
4588    "\
4589 The C<guestfs_debug_upload> command uploads a file to
4590 the libguestfs appliance.
4591
4592 There is no comprehensive help for this command.  You have
4593 to look at the file C<daemon/debug.c> in the libguestfs source
4594 to find out what it is for.");
4595
4596   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4597    [InitBasicFS, Always, TestOutput (
4598       [["base64_in"; "../images/hello.b64"; "/hello"];
4599        ["cat"; "/hello"]], "hello\n")],
4600    "upload base64-encoded data to file",
4601    "\
4602 This command uploads base64-encoded data from C<base64file>
4603 to C<filename>.");
4604
4605   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4606    [],
4607    "download file and encode as base64",
4608    "\
4609 This command downloads the contents of C<filename>, writing
4610 it out to local file C<base64file> encoded as base64.");
4611
4612   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4613    [],
4614    "compute MD5, SHAx or CRC checksum of files in a directory",
4615    "\
4616 This command computes the checksums of all regular files in
4617 C<directory> and then emits a list of those checksums to
4618 the local output file C<sumsfile>.
4619
4620 This can be used for verifying the integrity of a virtual
4621 machine.  However to be properly secure you should pay
4622 attention to the output of the checksum command (it uses
4623 the ones from GNU coreutils).  In particular when the
4624 filename is not printable, coreutils uses a special
4625 backslash syntax.  For more information, see the GNU
4626 coreutils info file.");
4627
4628   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4629    [InitBasicFS, Always, TestOutputBuffer (
4630       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4631        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4632    "fill a file with a repeating pattern of bytes",
4633    "\
4634 This function is like C<guestfs_fill> except that it creates
4635 a new file of length C<len> containing the repeating pattern
4636 of bytes in C<pattern>.  The pattern is truncated if necessary
4637 to ensure the length of the file is exactly C<len> bytes.");
4638
4639   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4640    [InitBasicFS, Always, TestOutput (
4641       [["write"; "/new"; "new file contents"];
4642        ["cat"; "/new"]], "new file contents");
4643     InitBasicFS, Always, TestOutput (
4644       [["write"; "/new"; "\nnew file contents\n"];
4645        ["cat"; "/new"]], "\nnew file contents\n");
4646     InitBasicFS, Always, TestOutput (
4647       [["write"; "/new"; "\n\n"];
4648        ["cat"; "/new"]], "\n\n");
4649     InitBasicFS, Always, TestOutput (
4650       [["write"; "/new"; ""];
4651        ["cat"; "/new"]], "");
4652     InitBasicFS, Always, TestOutput (
4653       [["write"; "/new"; "\n\n\n"];
4654        ["cat"; "/new"]], "\n\n\n");
4655     InitBasicFS, Always, TestOutput (
4656       [["write"; "/new"; "\n"];
4657        ["cat"; "/new"]], "\n")],
4658    "create a new file",
4659    "\
4660 This call creates a file called C<path>.  The content of the
4661 file is the string C<content> (which can contain any 8 bit data).");
4662
4663   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4664    [InitBasicFS, Always, TestOutput (
4665       [["write"; "/new"; "new file contents"];
4666        ["pwrite"; "/new"; "data"; "4"];
4667        ["cat"; "/new"]], "new data contents");
4668     InitBasicFS, Always, TestOutput (
4669       [["write"; "/new"; "new file contents"];
4670        ["pwrite"; "/new"; "is extended"; "9"];
4671        ["cat"; "/new"]], "new file is extended");
4672     InitBasicFS, Always, TestOutput (
4673       [["write"; "/new"; "new file contents"];
4674        ["pwrite"; "/new"; ""; "4"];
4675        ["cat"; "/new"]], "new file contents")],
4676    "write to part of a file",
4677    "\
4678 This command writes to part of a file.  It writes the data
4679 buffer C<content> to the file C<path> starting at offset C<offset>.
4680
4681 This command implements the L<pwrite(2)> system call, and like
4682 that system call it may not write the full data requested.  The
4683 return value is the number of bytes that were actually written
4684 to the file.  This could even be 0, although short writes are
4685 unlikely for regular files in ordinary circumstances.
4686
4687 See also C<guestfs_pread>.");
4688
4689 ]
4690
4691 let all_functions = non_daemon_functions @ daemon_functions
4692
4693 (* In some places we want the functions to be displayed sorted
4694  * alphabetically, so this is useful:
4695  *)
4696 let all_functions_sorted =
4697   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4698                compare n1 n2) all_functions
4699
4700 (* This is used to generate the src/MAX_PROC_NR file which
4701  * contains the maximum procedure number, a surrogate for the
4702  * ABI version number.  See src/Makefile.am for the details.
4703  *)
4704 let max_proc_nr =
4705   let proc_nrs = List.map (
4706     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4707   ) daemon_functions in
4708   List.fold_left max 0 proc_nrs
4709
4710 (* Field types for structures. *)
4711 type field =
4712   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4713   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4714   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4715   | FUInt32
4716   | FInt32
4717   | FUInt64
4718   | FInt64
4719   | FBytes                      (* Any int measure that counts bytes. *)
4720   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4721   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4722
4723 (* Because we generate extra parsing code for LVM command line tools,
4724  * we have to pull out the LVM columns separately here.
4725  *)
4726 let lvm_pv_cols = [
4727   "pv_name", FString;
4728   "pv_uuid", FUUID;
4729   "pv_fmt", FString;
4730   "pv_size", FBytes;
4731   "dev_size", FBytes;
4732   "pv_free", FBytes;
4733   "pv_used", FBytes;
4734   "pv_attr", FString (* XXX *);
4735   "pv_pe_count", FInt64;
4736   "pv_pe_alloc_count", FInt64;
4737   "pv_tags", FString;
4738   "pe_start", FBytes;
4739   "pv_mda_count", FInt64;
4740   "pv_mda_free", FBytes;
4741   (* Not in Fedora 10:
4742      "pv_mda_size", FBytes;
4743   *)
4744 ]
4745 let lvm_vg_cols = [
4746   "vg_name", FString;
4747   "vg_uuid", FUUID;
4748   "vg_fmt", FString;
4749   "vg_attr", FString (* XXX *);
4750   "vg_size", FBytes;
4751   "vg_free", FBytes;
4752   "vg_sysid", FString;
4753   "vg_extent_size", FBytes;
4754   "vg_extent_count", FInt64;
4755   "vg_free_count", FInt64;
4756   "max_lv", FInt64;
4757   "max_pv", FInt64;
4758   "pv_count", FInt64;
4759   "lv_count", FInt64;
4760   "snap_count", FInt64;
4761   "vg_seqno", FInt64;
4762   "vg_tags", FString;
4763   "vg_mda_count", FInt64;
4764   "vg_mda_free", FBytes;
4765   (* Not in Fedora 10:
4766      "vg_mda_size", FBytes;
4767   *)
4768 ]
4769 let lvm_lv_cols = [
4770   "lv_name", FString;
4771   "lv_uuid", FUUID;
4772   "lv_attr", FString (* XXX *);
4773   "lv_major", FInt64;
4774   "lv_minor", FInt64;
4775   "lv_kernel_major", FInt64;
4776   "lv_kernel_minor", FInt64;
4777   "lv_size", FBytes;
4778   "seg_count", FInt64;
4779   "origin", FString;
4780   "snap_percent", FOptPercent;
4781   "copy_percent", FOptPercent;
4782   "move_pv", FString;
4783   "lv_tags", FString;
4784   "mirror_log", FString;
4785   "modules", FString;
4786 ]
4787
4788 (* Names and fields in all structures (in RStruct and RStructList)
4789  * that we support.
4790  *)
4791 let structs = [
4792   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4793    * not use this struct in any new code.
4794    *)
4795   "int_bool", [
4796     "i", FInt32;                (* for historical compatibility *)
4797     "b", FInt32;                (* for historical compatibility *)
4798   ];
4799
4800   (* LVM PVs, VGs, LVs. *)
4801   "lvm_pv", lvm_pv_cols;
4802   "lvm_vg", lvm_vg_cols;
4803   "lvm_lv", lvm_lv_cols;
4804
4805   (* Column names and types from stat structures.
4806    * NB. Can't use things like 'st_atime' because glibc header files
4807    * define some of these as macros.  Ugh.
4808    *)
4809   "stat", [
4810     "dev", FInt64;
4811     "ino", FInt64;
4812     "mode", FInt64;
4813     "nlink", FInt64;
4814     "uid", FInt64;
4815     "gid", FInt64;
4816     "rdev", FInt64;
4817     "size", FInt64;
4818     "blksize", FInt64;
4819     "blocks", FInt64;
4820     "atime", FInt64;
4821     "mtime", FInt64;
4822     "ctime", FInt64;
4823   ];
4824   "statvfs", [
4825     "bsize", FInt64;
4826     "frsize", FInt64;
4827     "blocks", FInt64;
4828     "bfree", FInt64;
4829     "bavail", FInt64;
4830     "files", FInt64;
4831     "ffree", FInt64;
4832     "favail", FInt64;
4833     "fsid", FInt64;
4834     "flag", FInt64;
4835     "namemax", FInt64;
4836   ];
4837
4838   (* Column names in dirent structure. *)
4839   "dirent", [
4840     "ino", FInt64;
4841     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4842     "ftyp", FChar;
4843     "name", FString;
4844   ];
4845
4846   (* Version numbers. *)
4847   "version", [
4848     "major", FInt64;
4849     "minor", FInt64;
4850     "release", FInt64;
4851     "extra", FString;
4852   ];
4853
4854   (* Extended attribute. *)
4855   "xattr", [
4856     "attrname", FString;
4857     "attrval", FBuffer;
4858   ];
4859
4860   (* Inotify events. *)
4861   "inotify_event", [
4862     "in_wd", FInt64;
4863     "in_mask", FUInt32;
4864     "in_cookie", FUInt32;
4865     "in_name", FString;
4866   ];
4867
4868   (* Partition table entry. *)
4869   "partition", [
4870     "part_num", FInt32;
4871     "part_start", FBytes;
4872     "part_end", FBytes;
4873     "part_size", FBytes;
4874   ];
4875 ] (* end of structs *)
4876
4877 (* Ugh, Java has to be different ..
4878  * These names are also used by the Haskell bindings.
4879  *)
4880 let java_structs = [
4881   "int_bool", "IntBool";
4882   "lvm_pv", "PV";
4883   "lvm_vg", "VG";
4884   "lvm_lv", "LV";
4885   "stat", "Stat";
4886   "statvfs", "StatVFS";
4887   "dirent", "Dirent";
4888   "version", "Version";
4889   "xattr", "XAttr";
4890   "inotify_event", "INotifyEvent";
4891   "partition", "Partition";
4892 ]
4893
4894 (* What structs are actually returned. *)
4895 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4896
4897 (* Returns a list of RStruct/RStructList structs that are returned
4898  * by any function.  Each element of returned list is a pair:
4899  *
4900  * (structname, RStructOnly)
4901  *    == there exists function which returns RStruct (_, structname)
4902  * (structname, RStructListOnly)
4903  *    == there exists function which returns RStructList (_, structname)
4904  * (structname, RStructAndList)
4905  *    == there are functions returning both RStruct (_, structname)
4906  *                                      and RStructList (_, structname)
4907  *)
4908 let rstructs_used_by functions =
4909   (* ||| is a "logical OR" for rstructs_used_t *)
4910   let (|||) a b =
4911     match a, b with
4912     | RStructAndList, _
4913     | _, RStructAndList -> RStructAndList
4914     | RStructOnly, RStructListOnly
4915     | RStructListOnly, RStructOnly -> RStructAndList
4916     | RStructOnly, RStructOnly -> RStructOnly
4917     | RStructListOnly, RStructListOnly -> RStructListOnly
4918   in
4919
4920   let h = Hashtbl.create 13 in
4921
4922   (* if elem->oldv exists, update entry using ||| operator,
4923    * else just add elem->newv to the hash
4924    *)
4925   let update elem newv =
4926     try  let oldv = Hashtbl.find h elem in
4927          Hashtbl.replace h elem (newv ||| oldv)
4928     with Not_found -> Hashtbl.add h elem newv
4929   in
4930
4931   List.iter (
4932     fun (_, style, _, _, _, _, _) ->
4933       match fst style with
4934       | RStruct (_, structname) -> update structname RStructOnly
4935       | RStructList (_, structname) -> update structname RStructListOnly
4936       | _ -> ()
4937   ) functions;
4938
4939   (* return key->values as a list of (key,value) *)
4940   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4941
4942 (* Used for testing language bindings. *)
4943 type callt =
4944   | CallString of string
4945   | CallOptString of string option
4946   | CallStringList of string list
4947   | CallInt of int
4948   | CallInt64 of int64
4949   | CallBool of bool
4950   | CallBuffer of string
4951
4952 (* Used to memoize the result of pod2text. *)
4953 let pod2text_memo_filename = "src/.pod2text.data"
4954 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4955   try
4956     let chan = open_in pod2text_memo_filename in
4957     let v = input_value chan in
4958     close_in chan;
4959     v
4960   with
4961     _ -> Hashtbl.create 13
4962 let pod2text_memo_updated () =
4963   let chan = open_out pod2text_memo_filename in
4964   output_value chan pod2text_memo;
4965   close_out chan
4966
4967 (* Useful functions.
4968  * Note we don't want to use any external OCaml libraries which
4969  * makes this a bit harder than it should be.
4970  *)
4971 module StringMap = Map.Make (String)
4972
4973 let failwithf fs = ksprintf failwith fs
4974
4975 let unique = let i = ref 0 in fun () -> incr i; !i
4976
4977 let replace_char s c1 c2 =
4978   let s2 = String.copy s in
4979   let r = ref false in
4980   for i = 0 to String.length s2 - 1 do
4981     if String.unsafe_get s2 i = c1 then (
4982       String.unsafe_set s2 i c2;
4983       r := true
4984     )
4985   done;
4986   if not !r then s else s2
4987
4988 let isspace c =
4989   c = ' '
4990   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4991
4992 let triml ?(test = isspace) str =
4993   let i = ref 0 in
4994   let n = ref (String.length str) in
4995   while !n > 0 && test str.[!i]; do
4996     decr n;
4997     incr i
4998   done;
4999   if !i = 0 then str
5000   else String.sub str !i !n
5001
5002 let trimr ?(test = isspace) str =
5003   let n = ref (String.length str) in
5004   while !n > 0 && test str.[!n-1]; do
5005     decr n
5006   done;
5007   if !n = String.length str then str
5008   else String.sub str 0 !n
5009
5010 let trim ?(test = isspace) str =
5011   trimr ~test (triml ~test str)
5012
5013 let rec find s sub =
5014   let len = String.length s in
5015   let sublen = String.length sub in
5016   let rec loop i =
5017     if i <= len-sublen then (
5018       let rec loop2 j =
5019         if j < sublen then (
5020           if s.[i+j] = sub.[j] then loop2 (j+1)
5021           else -1
5022         ) else
5023           i (* found *)
5024       in
5025       let r = loop2 0 in
5026       if r = -1 then loop (i+1) else r
5027     ) else
5028       -1 (* not found *)
5029   in
5030   loop 0
5031
5032 let rec replace_str s s1 s2 =
5033   let len = String.length s in
5034   let sublen = String.length s1 in
5035   let i = find s s1 in
5036   if i = -1 then s
5037   else (
5038     let s' = String.sub s 0 i in
5039     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5040     s' ^ s2 ^ replace_str s'' s1 s2
5041   )
5042
5043 let rec string_split sep str =
5044   let len = String.length str in
5045   let seplen = String.length sep in
5046   let i = find str sep in
5047   if i = -1 then [str]
5048   else (
5049     let s' = String.sub str 0 i in
5050     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5051     s' :: string_split sep s''
5052   )
5053
5054 let files_equal n1 n2 =
5055   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5056   match Sys.command cmd with
5057   | 0 -> true
5058   | 1 -> false
5059   | i -> failwithf "%s: failed with error code %d" cmd i
5060
5061 let rec filter_map f = function
5062   | [] -> []
5063   | x :: xs ->
5064       match f x with
5065       | Some y -> y :: filter_map f xs
5066       | None -> filter_map f xs
5067
5068 let rec find_map f = function
5069   | [] -> raise Not_found
5070   | x :: xs ->
5071       match f x with
5072       | Some y -> y
5073       | None -> find_map f xs
5074
5075 let iteri f xs =
5076   let rec loop i = function
5077     | [] -> ()
5078     | x :: xs -> f i x; loop (i+1) xs
5079   in
5080   loop 0 xs
5081
5082 let mapi f xs =
5083   let rec loop i = function
5084     | [] -> []
5085     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5086   in
5087   loop 0 xs
5088
5089 let count_chars c str =
5090   let count = ref 0 in
5091   for i = 0 to String.length str - 1 do
5092     if c = String.unsafe_get str i then incr count
5093   done;
5094   !count
5095
5096 let explode str =
5097   let r = ref [] in
5098   for i = 0 to String.length str - 1 do
5099     let c = String.unsafe_get str i in
5100     r := c :: !r;
5101   done;
5102   List.rev !r
5103
5104 let map_chars f str =
5105   List.map f (explode str)
5106
5107 let name_of_argt = function
5108   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5109   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5110   | FileIn n | FileOut n | BufferIn n -> n
5111
5112 let java_name_of_struct typ =
5113   try List.assoc typ java_structs
5114   with Not_found ->
5115     failwithf
5116       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5117
5118 let cols_of_struct typ =
5119   try List.assoc typ structs
5120   with Not_found ->
5121     failwithf "cols_of_struct: unknown struct %s" typ
5122
5123 let seq_of_test = function
5124   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5125   | TestOutputListOfDevices (s, _)
5126   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5127   | TestOutputTrue s | TestOutputFalse s
5128   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5129   | TestOutputStruct (s, _)
5130   | TestLastFail s -> s
5131
5132 (* Handling for function flags. *)
5133 let protocol_limit_warning =
5134   "Because of the message protocol, there is a transfer limit
5135 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5136
5137 let danger_will_robinson =
5138   "B<This command is dangerous.  Without careful use you
5139 can easily destroy all your data>."
5140
5141 let deprecation_notice flags =
5142   try
5143     let alt =
5144       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5145     let txt =
5146       sprintf "This function is deprecated.
5147 In new code, use the C<%s> call instead.
5148
5149 Deprecated functions will not be removed from the API, but the
5150 fact that they are deprecated indicates that there are problems
5151 with correct use of these functions." alt in
5152     Some txt
5153   with
5154     Not_found -> None
5155
5156 (* Create list of optional groups. *)
5157 let optgroups =
5158   let h = Hashtbl.create 13 in
5159   List.iter (
5160     fun (name, _, _, flags, _, _, _) ->
5161       List.iter (
5162         function
5163         | Optional group ->
5164             let names = try Hashtbl.find h group with Not_found -> [] in
5165             Hashtbl.replace h group (name :: names)
5166         | _ -> ()
5167       ) flags
5168   ) daemon_functions;
5169   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5170   let groups =
5171     List.map (
5172       fun group -> group, List.sort compare (Hashtbl.find h group)
5173     ) groups in
5174   List.sort (fun x y -> compare (fst x) (fst y)) groups
5175
5176 (* Check function names etc. for consistency. *)
5177 let check_functions () =
5178   let contains_uppercase str =
5179     let len = String.length str in
5180     let rec loop i =
5181       if i >= len then false
5182       else (
5183         let c = str.[i] in
5184         if c >= 'A' && c <= 'Z' then true
5185         else loop (i+1)
5186       )
5187     in
5188     loop 0
5189   in
5190
5191   (* Check function names. *)
5192   List.iter (
5193     fun (name, _, _, _, _, _, _) ->
5194       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5195         failwithf "function name %s does not need 'guestfs' prefix" name;
5196       if name = "" then
5197         failwithf "function name is empty";
5198       if name.[0] < 'a' || name.[0] > 'z' then
5199         failwithf "function name %s must start with lowercase a-z" name;
5200       if String.contains name '-' then
5201         failwithf "function name %s should not contain '-', use '_' instead."
5202           name
5203   ) all_functions;
5204
5205   (* Check function parameter/return names. *)
5206   List.iter (
5207     fun (name, style, _, _, _, _, _) ->
5208       let check_arg_ret_name n =
5209         if contains_uppercase n then
5210           failwithf "%s param/ret %s should not contain uppercase chars"
5211             name n;
5212         if String.contains n '-' || String.contains n '_' then
5213           failwithf "%s param/ret %s should not contain '-' or '_'"
5214             name n;
5215         if n = "value" then
5216           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;
5217         if n = "int" || n = "char" || n = "short" || n = "long" then
5218           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5219         if n = "i" || n = "n" then
5220           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5221         if n = "argv" || n = "args" then
5222           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5223
5224         (* List Haskell, OCaml and C keywords here.
5225          * http://www.haskell.org/haskellwiki/Keywords
5226          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5227          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5228          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5229          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5230          * Omitting _-containing words, since they're handled above.
5231          * Omitting the OCaml reserved word, "val", is ok,
5232          * and saves us from renaming several parameters.
5233          *)
5234         let reserved = [
5235           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5236           "char"; "class"; "const"; "constraint"; "continue"; "data";
5237           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5238           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5239           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5240           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5241           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5242           "interface";
5243           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5244           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5245           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5246           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5247           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5248           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5249           "volatile"; "when"; "where"; "while";
5250           ] in
5251         if List.mem n reserved then
5252           failwithf "%s has param/ret using reserved word %s" name n;
5253       in
5254
5255       (match fst style with
5256        | RErr -> ()
5257        | RInt n | RInt64 n | RBool n
5258        | RConstString n | RConstOptString n | RString n
5259        | RStringList n | RStruct (n, _) | RStructList (n, _)
5260        | RHashtable n | RBufferOut n ->
5261            check_arg_ret_name n
5262       );
5263       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5264   ) all_functions;
5265
5266   (* Check short descriptions. *)
5267   List.iter (
5268     fun (name, _, _, _, _, shortdesc, _) ->
5269       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5270         failwithf "short description of %s should begin with lowercase." name;
5271       let c = shortdesc.[String.length shortdesc-1] in
5272       if c = '\n' || c = '.' then
5273         failwithf "short description of %s should not end with . or \\n." name
5274   ) all_functions;
5275
5276   (* Check long descriptions. *)
5277   List.iter (
5278     fun (name, _, _, _, _, _, longdesc) ->
5279       if longdesc.[String.length longdesc-1] = '\n' then
5280         failwithf "long description of %s should not end with \\n." name
5281   ) all_functions;
5282
5283   (* Check proc_nrs. *)
5284   List.iter (
5285     fun (name, _, proc_nr, _, _, _, _) ->
5286       if proc_nr <= 0 then
5287         failwithf "daemon function %s should have proc_nr > 0" name
5288   ) daemon_functions;
5289
5290   List.iter (
5291     fun (name, _, proc_nr, _, _, _, _) ->
5292       if proc_nr <> -1 then
5293         failwithf "non-daemon function %s should have proc_nr -1" name
5294   ) non_daemon_functions;
5295
5296   let proc_nrs =
5297     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5298       daemon_functions in
5299   let proc_nrs =
5300     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5301   let rec loop = function
5302     | [] -> ()
5303     | [_] -> ()
5304     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5305         loop rest
5306     | (name1,nr1) :: (name2,nr2) :: _ ->
5307         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5308           name1 name2 nr1 nr2
5309   in
5310   loop proc_nrs;
5311
5312   (* Check tests. *)
5313   List.iter (
5314     function
5315       (* Ignore functions that have no tests.  We generate a
5316        * warning when the user does 'make check' instead.
5317        *)
5318     | name, _, _, _, [], _, _ -> ()
5319     | name, _, _, _, tests, _, _ ->
5320         let funcs =
5321           List.map (
5322             fun (_, _, test) ->
5323               match seq_of_test test with
5324               | [] ->
5325                   failwithf "%s has a test containing an empty sequence" name
5326               | cmds -> List.map List.hd cmds
5327           ) tests in
5328         let funcs = List.flatten funcs in
5329
5330         let tested = List.mem name funcs in
5331
5332         if not tested then
5333           failwithf "function %s has tests but does not test itself" name
5334   ) all_functions
5335
5336 (* 'pr' prints to the current output file. *)
5337 let chan = ref Pervasives.stdout
5338 let lines = ref 0
5339 let pr fs =
5340   ksprintf
5341     (fun str ->
5342        let i = count_chars '\n' str in
5343        lines := !lines + i;
5344        output_string !chan str
5345     ) fs
5346
5347 let copyright_years =
5348   let this_year = 1900 + (localtime (time ())).tm_year in
5349   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5350
5351 (* Generate a header block in a number of standard styles. *)
5352 type comment_style =
5353     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5354 type license = GPLv2plus | LGPLv2plus
5355
5356 let generate_header ?(extra_inputs = []) comment license =
5357   let inputs = "src/generator.ml" :: extra_inputs in
5358   let c = match comment with
5359     | CStyle ->         pr "/* "; " *"
5360     | CPlusPlusStyle -> pr "// "; "//"
5361     | HashStyle ->      pr "# ";  "#"
5362     | OCamlStyle ->     pr "(* "; " *"
5363     | HaskellStyle ->   pr "{- "; "  " in
5364   pr "libguestfs generated file\n";
5365   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5366   List.iter (pr "%s   %s\n" c) inputs;
5367   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5368   pr "%s\n" c;
5369   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5370   pr "%s\n" c;
5371   (match license with
5372    | GPLv2plus ->
5373        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5374        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5375        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5376        pr "%s (at your option) any later version.\n" c;
5377        pr "%s\n" c;
5378        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5379        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5380        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5381        pr "%s GNU General Public License for more details.\n" c;
5382        pr "%s\n" c;
5383        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5384        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5385        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5386
5387    | LGPLv2plus ->
5388        pr "%s This library is free software; you can redistribute it and/or\n" c;
5389        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5390        pr "%s License as published by the Free Software Foundation; either\n" c;
5391        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5392        pr "%s\n" c;
5393        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5394        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5395        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5396        pr "%s Lesser General Public License for more details.\n" c;
5397        pr "%s\n" c;
5398        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5399        pr "%s License along with this library; if not, write to the Free Software\n" c;
5400        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5401   );
5402   (match comment with
5403    | CStyle -> pr " */\n"
5404    | CPlusPlusStyle
5405    | HashStyle -> ()
5406    | OCamlStyle -> pr " *)\n"
5407    | HaskellStyle -> pr "-}\n"
5408   );
5409   pr "\n"
5410
5411 (* Start of main code generation functions below this line. *)
5412
5413 (* Generate the pod documentation for the C API. *)
5414 let rec generate_actions_pod () =
5415   List.iter (
5416     fun (shortname, style, _, flags, _, _, longdesc) ->
5417       if not (List.mem NotInDocs flags) then (
5418         let name = "guestfs_" ^ shortname in
5419         pr "=head2 %s\n\n" name;
5420         pr " ";
5421         generate_prototype ~extern:false ~handle:"g" name style;
5422         pr "\n\n";
5423         pr "%s\n\n" longdesc;
5424         (match fst style with
5425          | RErr ->
5426              pr "This function returns 0 on success or -1 on error.\n\n"
5427          | RInt _ ->
5428              pr "On error this function returns -1.\n\n"
5429          | RInt64 _ ->
5430              pr "On error this function returns -1.\n\n"
5431          | RBool _ ->
5432              pr "This function returns a C truth value on success or -1 on error.\n\n"
5433          | RConstString _ ->
5434              pr "This function returns a string, or NULL on error.
5435 The string is owned by the guest handle and must I<not> be freed.\n\n"
5436          | RConstOptString _ ->
5437              pr "This function returns a string which may be NULL.
5438 There is way to return an error from this function.
5439 The string is owned by the guest handle and must I<not> be freed.\n\n"
5440          | RString _ ->
5441              pr "This function returns a string, or NULL on error.
5442 I<The caller must free the returned string after use>.\n\n"
5443          | RStringList _ ->
5444              pr "This function returns a NULL-terminated array of strings
5445 (like L<environ(3)>), or NULL if there was an error.
5446 I<The caller must free the strings and the array after use>.\n\n"
5447          | RStruct (_, typ) ->
5448              pr "This function returns a C<struct guestfs_%s *>,
5449 or NULL if there was an error.
5450 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5451          | RStructList (_, typ) ->
5452              pr "This function returns a C<struct guestfs_%s_list *>
5453 (see E<lt>guestfs-structs.hE<gt>),
5454 or NULL if there was an error.
5455 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5456          | RHashtable _ ->
5457              pr "This function returns a NULL-terminated array of
5458 strings, or NULL if there was an error.
5459 The array of strings will always have length C<2n+1>, where
5460 C<n> keys and values alternate, followed by the trailing NULL entry.
5461 I<The caller must free the strings and the array after use>.\n\n"
5462          | RBufferOut _ ->
5463              pr "This function returns a buffer, or NULL on error.
5464 The size of the returned buffer is written to C<*size_r>.
5465 I<The caller must free the returned buffer after use>.\n\n"
5466         );
5467         if List.mem ProtocolLimitWarning flags then
5468           pr "%s\n\n" protocol_limit_warning;
5469         if List.mem DangerWillRobinson flags then
5470           pr "%s\n\n" danger_will_robinson;
5471         match deprecation_notice flags with
5472         | None -> ()
5473         | Some txt -> pr "%s\n\n" txt
5474       )
5475   ) all_functions_sorted
5476
5477 and generate_structs_pod () =
5478   (* Structs documentation. *)
5479   List.iter (
5480     fun (typ, cols) ->
5481       pr "=head2 guestfs_%s\n" typ;
5482       pr "\n";
5483       pr " struct guestfs_%s {\n" typ;
5484       List.iter (
5485         function
5486         | name, FChar -> pr "   char %s;\n" name
5487         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5488         | name, FInt32 -> pr "   int32_t %s;\n" name
5489         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5490         | name, FInt64 -> pr "   int64_t %s;\n" name
5491         | name, FString -> pr "   char *%s;\n" name
5492         | name, FBuffer ->
5493             pr "   /* The next two fields describe a byte array. */\n";
5494             pr "   uint32_t %s_len;\n" name;
5495             pr "   char *%s;\n" name
5496         | name, FUUID ->
5497             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5498             pr "   char %s[32];\n" name
5499         | name, FOptPercent ->
5500             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5501             pr "   float %s;\n" name
5502       ) cols;
5503       pr " };\n";
5504       pr " \n";
5505       pr " struct guestfs_%s_list {\n" typ;
5506       pr "   uint32_t len; /* Number of elements in list. */\n";
5507       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5508       pr " };\n";
5509       pr " \n";
5510       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5511       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5512         typ typ;
5513       pr "\n"
5514   ) structs
5515
5516 and generate_availability_pod () =
5517   (* Availability documentation. *)
5518   pr "=over 4\n";
5519   pr "\n";
5520   List.iter (
5521     fun (group, functions) ->
5522       pr "=item B<%s>\n" group;
5523       pr "\n";
5524       pr "The following functions:\n";
5525       List.iter (pr "L</guestfs_%s>\n") functions;
5526       pr "\n"
5527   ) optgroups;
5528   pr "=back\n";
5529   pr "\n"
5530
5531 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5532  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5533  *
5534  * We have to use an underscore instead of a dash because otherwise
5535  * rpcgen generates incorrect code.
5536  *
5537  * This header is NOT exported to clients, but see also generate_structs_h.
5538  *)
5539 and generate_xdr () =
5540   generate_header CStyle LGPLv2plus;
5541
5542   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5543   pr "typedef string str<>;\n";
5544   pr "\n";
5545
5546   (* Internal structures. *)
5547   List.iter (
5548     function
5549     | typ, cols ->
5550         pr "struct guestfs_int_%s {\n" typ;
5551         List.iter (function
5552                    | name, FChar -> pr "  char %s;\n" name
5553                    | name, FString -> pr "  string %s<>;\n" name
5554                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5555                    | name, FUUID -> pr "  opaque %s[32];\n" name
5556                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5557                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5558                    | name, FOptPercent -> pr "  float %s;\n" name
5559                   ) cols;
5560         pr "};\n";
5561         pr "\n";
5562         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5563         pr "\n";
5564   ) structs;
5565
5566   List.iter (
5567     fun (shortname, style, _, _, _, _, _) ->
5568       let name = "guestfs_" ^ shortname in
5569
5570       (match snd style with
5571        | [] -> ()
5572        | args ->
5573            pr "struct %s_args {\n" name;
5574            List.iter (
5575              function
5576              | Pathname n | Device n | Dev_or_Path n | String n ->
5577                  pr "  string %s<>;\n" n
5578              | OptString n -> pr "  str *%s;\n" n
5579              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5580              | Bool n -> pr "  bool %s;\n" n
5581              | Int n -> pr "  int %s;\n" n
5582              | Int64 n -> pr "  hyper %s;\n" n
5583              | BufferIn n ->
5584                  pr "  opaque %s<>;\n" n
5585              | FileIn _ | FileOut _ -> ()
5586            ) args;
5587            pr "};\n\n"
5588       );
5589       (match fst style with
5590        | RErr -> ()
5591        | RInt n ->
5592            pr "struct %s_ret {\n" name;
5593            pr "  int %s;\n" n;
5594            pr "};\n\n"
5595        | RInt64 n ->
5596            pr "struct %s_ret {\n" name;
5597            pr "  hyper %s;\n" n;
5598            pr "};\n\n"
5599        | RBool n ->
5600            pr "struct %s_ret {\n" name;
5601            pr "  bool %s;\n" n;
5602            pr "};\n\n"
5603        | RConstString _ | RConstOptString _ ->
5604            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5605        | RString n ->
5606            pr "struct %s_ret {\n" name;
5607            pr "  string %s<>;\n" n;
5608            pr "};\n\n"
5609        | RStringList n ->
5610            pr "struct %s_ret {\n" name;
5611            pr "  str %s<>;\n" n;
5612            pr "};\n\n"
5613        | RStruct (n, typ) ->
5614            pr "struct %s_ret {\n" name;
5615            pr "  guestfs_int_%s %s;\n" typ n;
5616            pr "};\n\n"
5617        | RStructList (n, typ) ->
5618            pr "struct %s_ret {\n" name;
5619            pr "  guestfs_int_%s_list %s;\n" typ n;
5620            pr "};\n\n"
5621        | RHashtable n ->
5622            pr "struct %s_ret {\n" name;
5623            pr "  str %s<>;\n" n;
5624            pr "};\n\n"
5625        | RBufferOut n ->
5626            pr "struct %s_ret {\n" name;
5627            pr "  opaque %s<>;\n" n;
5628            pr "};\n\n"
5629       );
5630   ) daemon_functions;
5631
5632   (* Table of procedure numbers. *)
5633   pr "enum guestfs_procedure {\n";
5634   List.iter (
5635     fun (shortname, _, proc_nr, _, _, _, _) ->
5636       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5637   ) daemon_functions;
5638   pr "  GUESTFS_PROC_NR_PROCS\n";
5639   pr "};\n";
5640   pr "\n";
5641
5642   (* Having to choose a maximum message size is annoying for several
5643    * reasons (it limits what we can do in the API), but it (a) makes
5644    * the protocol a lot simpler, and (b) provides a bound on the size
5645    * of the daemon which operates in limited memory space.
5646    *)
5647   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5648   pr "\n";
5649
5650   (* Message header, etc. *)
5651   pr "\
5652 /* The communication protocol is now documented in the guestfs(3)
5653  * manpage.
5654  */
5655
5656 const GUESTFS_PROGRAM = 0x2000F5F5;
5657 const GUESTFS_PROTOCOL_VERSION = 1;
5658
5659 /* These constants must be larger than any possible message length. */
5660 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5661 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5662
5663 enum guestfs_message_direction {
5664   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5665   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5666 };
5667
5668 enum guestfs_message_status {
5669   GUESTFS_STATUS_OK = 0,
5670   GUESTFS_STATUS_ERROR = 1
5671 };
5672
5673 const GUESTFS_ERROR_LEN = 256;
5674
5675 struct guestfs_message_error {
5676   string error_message<GUESTFS_ERROR_LEN>;
5677 };
5678
5679 struct guestfs_message_header {
5680   unsigned prog;                     /* GUESTFS_PROGRAM */
5681   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5682   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5683   guestfs_message_direction direction;
5684   unsigned serial;                   /* message serial number */
5685   guestfs_message_status status;
5686 };
5687
5688 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5689
5690 struct guestfs_chunk {
5691   int cancel;                        /* if non-zero, transfer is cancelled */
5692   /* data size is 0 bytes if the transfer has finished successfully */
5693   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5694 };
5695 "
5696
5697 (* Generate the guestfs-structs.h file. *)
5698 and generate_structs_h () =
5699   generate_header CStyle LGPLv2plus;
5700
5701   (* This is a public exported header file containing various
5702    * structures.  The structures are carefully written to have
5703    * exactly the same in-memory format as the XDR structures that
5704    * we use on the wire to the daemon.  The reason for creating
5705    * copies of these structures here is just so we don't have to
5706    * export the whole of guestfs_protocol.h (which includes much
5707    * unrelated and XDR-dependent stuff that we don't want to be
5708    * public, or required by clients).
5709    *
5710    * To reiterate, we will pass these structures to and from the
5711    * client with a simple assignment or memcpy, so the format
5712    * must be identical to what rpcgen / the RFC defines.
5713    *)
5714
5715   (* Public structures. *)
5716   List.iter (
5717     fun (typ, cols) ->
5718       pr "struct guestfs_%s {\n" typ;
5719       List.iter (
5720         function
5721         | name, FChar -> pr "  char %s;\n" name
5722         | name, FString -> pr "  char *%s;\n" name
5723         | name, FBuffer ->
5724             pr "  uint32_t %s_len;\n" name;
5725             pr "  char *%s;\n" name
5726         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5727         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5728         | name, FInt32 -> pr "  int32_t %s;\n" name
5729         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5730         | name, FInt64 -> pr "  int64_t %s;\n" name
5731         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5732       ) cols;
5733       pr "};\n";
5734       pr "\n";
5735       pr "struct guestfs_%s_list {\n" typ;
5736       pr "  uint32_t len;\n";
5737       pr "  struct guestfs_%s *val;\n" typ;
5738       pr "};\n";
5739       pr "\n";
5740       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5741       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5742       pr "\n"
5743   ) structs
5744
5745 (* Generate the guestfs-actions.h file. *)
5746 and generate_actions_h () =
5747   generate_header CStyle LGPLv2plus;
5748   List.iter (
5749     fun (shortname, style, _, _, _, _, _) ->
5750       let name = "guestfs_" ^ shortname in
5751       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5752         name style
5753   ) all_functions
5754
5755 (* Generate the guestfs-internal-actions.h file. *)
5756 and generate_internal_actions_h () =
5757   generate_header CStyle LGPLv2plus;
5758   List.iter (
5759     fun (shortname, style, _, _, _, _, _) ->
5760       let name = "guestfs__" ^ shortname in
5761       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5762         name style
5763   ) non_daemon_functions
5764
5765 (* Generate the client-side dispatch stubs. *)
5766 and generate_client_actions () =
5767   generate_header CStyle LGPLv2plus;
5768
5769   pr "\
5770 #include <stdio.h>
5771 #include <stdlib.h>
5772 #include <stdint.h>
5773 #include <string.h>
5774 #include <inttypes.h>
5775
5776 #include \"guestfs.h\"
5777 #include \"guestfs-internal.h\"
5778 #include \"guestfs-internal-actions.h\"
5779 #include \"guestfs_protocol.h\"
5780
5781 #define error guestfs_error
5782 //#define perrorf guestfs_perrorf
5783 #define safe_malloc guestfs_safe_malloc
5784 #define safe_realloc guestfs_safe_realloc
5785 //#define safe_strdup guestfs_safe_strdup
5786 #define safe_memdup guestfs_safe_memdup
5787
5788 /* Check the return message from a call for validity. */
5789 static int
5790 check_reply_header (guestfs_h *g,
5791                     const struct guestfs_message_header *hdr,
5792                     unsigned int proc_nr, unsigned int serial)
5793 {
5794   if (hdr->prog != GUESTFS_PROGRAM) {
5795     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5796     return -1;
5797   }
5798   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5799     error (g, \"wrong protocol version (%%d/%%d)\",
5800            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5801     return -1;
5802   }
5803   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5804     error (g, \"unexpected message direction (%%d/%%d)\",
5805            hdr->direction, GUESTFS_DIRECTION_REPLY);
5806     return -1;
5807   }
5808   if (hdr->proc != proc_nr) {
5809     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5810     return -1;
5811   }
5812   if (hdr->serial != serial) {
5813     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5814     return -1;
5815   }
5816
5817   return 0;
5818 }
5819
5820 /* Check we are in the right state to run a high-level action. */
5821 static int
5822 check_state (guestfs_h *g, const char *caller)
5823 {
5824   if (!guestfs__is_ready (g)) {
5825     if (guestfs__is_config (g) || guestfs__is_launching (g))
5826       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5827         caller);
5828     else
5829       error (g, \"%%s called from the wrong state, %%d != READY\",
5830         caller, guestfs__get_state (g));
5831     return -1;
5832   }
5833   return 0;
5834 }
5835
5836 ";
5837
5838   let error_code_of = function
5839     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5840     | RConstString _ | RConstOptString _
5841     | RString _ | RStringList _
5842     | RStruct _ | RStructList _
5843     | RHashtable _ | RBufferOut _ -> "NULL"
5844   in
5845
5846   (* Generate code to check String-like parameters are not passed in
5847    * as NULL (returning an error if they are).
5848    *)
5849   let check_null_strings shortname style =
5850     let pr_newline = ref false in
5851     List.iter (
5852       function
5853       (* parameters which should not be NULL *)
5854       | String n
5855       | Device n
5856       | Pathname n
5857       | Dev_or_Path n
5858       | FileIn n
5859       | FileOut n
5860       | BufferIn n
5861       | StringList n
5862       | DeviceList n ->
5863           pr "  if (%s == NULL) {\n" n;
5864           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5865           pr "           \"%s\", \"%s\");\n" shortname n;
5866           pr "    return %s;\n" (error_code_of (fst style));
5867           pr "  }\n";
5868           pr_newline := true
5869
5870       (* can be NULL *)
5871       | OptString _
5872
5873       (* not applicable *)
5874       | Bool _
5875       | Int _
5876       | Int64 _ -> ()
5877     ) (snd style);
5878
5879     if !pr_newline then pr "\n";
5880   in
5881
5882   (* Generate code to generate guestfish call traces. *)
5883   let trace_call shortname style =
5884     pr "  if (guestfs__get_trace (g)) {\n";
5885
5886     let needs_i =
5887       List.exists (function
5888                    | StringList _ | DeviceList _ -> true
5889                    | _ -> false) (snd style) in
5890     if needs_i then (
5891       pr "    int i;\n";
5892       pr "\n"
5893     );
5894
5895     pr "    printf (\"%s\");\n" shortname;
5896     List.iter (
5897       function
5898       | String n                        (* strings *)
5899       | Device n
5900       | Pathname n
5901       | Dev_or_Path n
5902       | FileIn n
5903       | FileOut n
5904       | BufferIn n ->
5905           (* guestfish doesn't support string escaping, so neither do we *)
5906           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5907       | OptString n ->                  (* string option *)
5908           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5909           pr "    else printf (\" null\");\n"
5910       | StringList n
5911       | DeviceList n ->                 (* string list *)
5912           pr "    putchar (' ');\n";
5913           pr "    putchar ('\"');\n";
5914           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5915           pr "      if (i > 0) putchar (' ');\n";
5916           pr "      fputs (%s[i], stdout);\n" n;
5917           pr "    }\n";
5918           pr "    putchar ('\"');\n";
5919       | Bool n ->                       (* boolean *)
5920           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5921       | Int n ->                        (* int *)
5922           pr "    printf (\" %%d\", %s);\n" n
5923       | Int64 n ->
5924           pr "    printf (\" %%\" PRIi64, %s);\n" n
5925     ) (snd style);
5926     pr "    putchar ('\\n');\n";
5927     pr "  }\n";
5928     pr "\n";
5929   in
5930
5931   (* For non-daemon functions, generate a wrapper around each function. *)
5932   List.iter (
5933     fun (shortname, style, _, _, _, _, _) ->
5934       let name = "guestfs_" ^ shortname in
5935
5936       generate_prototype ~extern:false ~semicolon:false ~newline:true
5937         ~handle:"g" name style;
5938       pr "{\n";
5939       check_null_strings shortname style;
5940       trace_call shortname style;
5941       pr "  return guestfs__%s " shortname;
5942       generate_c_call_args ~handle:"g" style;
5943       pr ";\n";
5944       pr "}\n";
5945       pr "\n"
5946   ) non_daemon_functions;
5947
5948   (* Client-side stubs for each function. *)
5949   List.iter (
5950     fun (shortname, style, _, _, _, _, _) ->
5951       let name = "guestfs_" ^ shortname in
5952       let error_code = error_code_of (fst style) in
5953
5954       (* Generate the action stub. *)
5955       generate_prototype ~extern:false ~semicolon:false ~newline:true
5956         ~handle:"g" name style;
5957
5958       pr "{\n";
5959
5960       (match snd style with
5961        | [] -> ()
5962        | _ -> pr "  struct %s_args args;\n" name
5963       );
5964
5965       pr "  guestfs_message_header hdr;\n";
5966       pr "  guestfs_message_error err;\n";
5967       let has_ret =
5968         match fst style with
5969         | RErr -> false
5970         | RConstString _ | RConstOptString _ ->
5971             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5972         | RInt _ | RInt64 _
5973         | RBool _ | RString _ | RStringList _
5974         | RStruct _ | RStructList _
5975         | RHashtable _ | RBufferOut _ ->
5976             pr "  struct %s_ret ret;\n" name;
5977             true in
5978
5979       pr "  int serial;\n";
5980       pr "  int r;\n";
5981       pr "\n";
5982       check_null_strings shortname style;
5983       trace_call shortname style;
5984       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5985         shortname error_code;
5986       pr "  guestfs___set_busy (g);\n";
5987       pr "\n";
5988
5989       (* Send the main header and arguments. *)
5990       (match snd style with
5991        | [] ->
5992            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5993              (String.uppercase shortname)
5994        | args ->
5995            List.iter (
5996              function
5997              | Pathname n | Device n | Dev_or_Path n | String n ->
5998                  pr "  args.%s = (char *) %s;\n" n n
5999              | OptString n ->
6000                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6001              | StringList n | DeviceList n ->
6002                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6003                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6004              | Bool n ->
6005                  pr "  args.%s = %s;\n" n n
6006              | Int n ->
6007                  pr "  args.%s = %s;\n" n n
6008              | Int64 n ->
6009                  pr "  args.%s = %s;\n" n n
6010              | FileIn _ | FileOut _ -> ()
6011              | BufferIn n ->
6012                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6013                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6014                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6015                    shortname;
6016                  pr "    guestfs___end_busy (g);\n";
6017                  pr "    return %s;\n" error_code;
6018                  pr "  }\n";
6019                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6020                  pr "  args.%s.%s_len = %s_size;\n" n n n
6021            ) args;
6022            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6023              (String.uppercase shortname);
6024            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6025              name;
6026       );
6027       pr "  if (serial == -1) {\n";
6028       pr "    guestfs___end_busy (g);\n";
6029       pr "    return %s;\n" error_code;
6030       pr "  }\n";
6031       pr "\n";
6032
6033       (* Send any additional files (FileIn) requested. *)
6034       let need_read_reply_label = ref false in
6035       List.iter (
6036         function
6037         | FileIn n ->
6038             pr "  r = guestfs___send_file (g, %s);\n" n;
6039             pr "  if (r == -1) {\n";
6040             pr "    guestfs___end_busy (g);\n";
6041             pr "    return %s;\n" error_code;
6042             pr "  }\n";
6043             pr "  if (r == -2) /* daemon cancelled */\n";
6044             pr "    goto read_reply;\n";
6045             need_read_reply_label := true;
6046             pr "\n";
6047         | _ -> ()
6048       ) (snd style);
6049
6050       (* Wait for the reply from the remote end. *)
6051       if !need_read_reply_label then pr " read_reply:\n";
6052       pr "  memset (&hdr, 0, sizeof hdr);\n";
6053       pr "  memset (&err, 0, sizeof err);\n";
6054       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6055       pr "\n";
6056       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6057       if not has_ret then
6058         pr "NULL, NULL"
6059       else
6060         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6061       pr ");\n";
6062
6063       pr "  if (r == -1) {\n";
6064       pr "    guestfs___end_busy (g);\n";
6065       pr "    return %s;\n" error_code;
6066       pr "  }\n";
6067       pr "\n";
6068
6069       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6070         (String.uppercase shortname);
6071       pr "    guestfs___end_busy (g);\n";
6072       pr "    return %s;\n" error_code;
6073       pr "  }\n";
6074       pr "\n";
6075
6076       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6077       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6078       pr "    free (err.error_message);\n";
6079       pr "    guestfs___end_busy (g);\n";
6080       pr "    return %s;\n" error_code;
6081       pr "  }\n";
6082       pr "\n";
6083
6084       (* Expecting to receive further files (FileOut)? *)
6085       List.iter (
6086         function
6087         | FileOut n ->
6088             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6089             pr "    guestfs___end_busy (g);\n";
6090             pr "    return %s;\n" error_code;
6091             pr "  }\n";
6092             pr "\n";
6093         | _ -> ()
6094       ) (snd style);
6095
6096       pr "  guestfs___end_busy (g);\n";
6097
6098       (match fst style with
6099        | RErr -> pr "  return 0;\n"
6100        | RInt n | RInt64 n | RBool n ->
6101            pr "  return ret.%s;\n" n
6102        | RConstString _ | RConstOptString _ ->
6103            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6104        | RString n ->
6105            pr "  return ret.%s; /* caller will free */\n" n
6106        | RStringList n | RHashtable n ->
6107            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6108            pr "  ret.%s.%s_val =\n" n n;
6109            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6110            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6111              n n;
6112            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6113            pr "  return ret.%s.%s_val;\n" n n
6114        | RStruct (n, _) ->
6115            pr "  /* caller will free this */\n";
6116            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6117        | RStructList (n, _) ->
6118            pr "  /* caller will free this */\n";
6119            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6120        | RBufferOut n ->
6121            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6122            pr "   * _val might be NULL here.  To make the API saner for\n";
6123            pr "   * callers, we turn this case into a unique pointer (using\n";
6124            pr "   * malloc(1)).\n";
6125            pr "   */\n";
6126            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6127            pr "    *size_r = ret.%s.%s_len;\n" n n;
6128            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6129            pr "  } else {\n";
6130            pr "    free (ret.%s.%s_val);\n" n n;
6131            pr "    char *p = safe_malloc (g, 1);\n";
6132            pr "    *size_r = ret.%s.%s_len;\n" n n;
6133            pr "    return p;\n";
6134            pr "  }\n";
6135       );
6136
6137       pr "}\n\n"
6138   ) daemon_functions;
6139
6140   (* Functions to free structures. *)
6141   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6142   pr " * structure format is identical to the XDR format.  See note in\n";
6143   pr " * generator.ml.\n";
6144   pr " */\n";
6145   pr "\n";
6146
6147   List.iter (
6148     fun (typ, _) ->
6149       pr "void\n";
6150       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6151       pr "{\n";
6152       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6153       pr "  free (x);\n";
6154       pr "}\n";
6155       pr "\n";
6156
6157       pr "void\n";
6158       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6159       pr "{\n";
6160       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6161       pr "  free (x);\n";
6162       pr "}\n";
6163       pr "\n";
6164
6165   ) structs;
6166
6167 (* Generate daemon/actions.h. *)
6168 and generate_daemon_actions_h () =
6169   generate_header CStyle GPLv2plus;
6170
6171   pr "#include \"../src/guestfs_protocol.h\"\n";
6172   pr "\n";
6173
6174   List.iter (
6175     fun (name, style, _, _, _, _, _) ->
6176       generate_prototype
6177         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6178         name style;
6179   ) daemon_functions
6180
6181 (* Generate the linker script which controls the visibility of
6182  * symbols in the public ABI and ensures no other symbols get
6183  * exported accidentally.
6184  *)
6185 and generate_linker_script () =
6186   generate_header HashStyle GPLv2plus;
6187
6188   let globals = [
6189     "guestfs_create";
6190     "guestfs_close";
6191     "guestfs_get_error_handler";
6192     "guestfs_get_out_of_memory_handler";
6193     "guestfs_last_error";
6194     "guestfs_set_error_handler";
6195     "guestfs_set_launch_done_callback";
6196     "guestfs_set_log_message_callback";
6197     "guestfs_set_out_of_memory_handler";
6198     "guestfs_set_subprocess_quit_callback";
6199
6200     (* Unofficial parts of the API: the bindings code use these
6201      * functions, so it is useful to export them.
6202      *)
6203     "guestfs_safe_calloc";
6204     "guestfs_safe_malloc";
6205   ] in
6206   let functions =
6207     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6208       all_functions in
6209   let structs =
6210     List.concat (
6211       List.map (fun (typ, _) ->
6212                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6213         structs
6214     ) in
6215   let globals = List.sort compare (globals @ functions @ structs) in
6216
6217   pr "{\n";
6218   pr "    global:\n";
6219   List.iter (pr "        %s;\n") globals;
6220   pr "\n";
6221
6222   pr "    local:\n";
6223   pr "        *;\n";
6224   pr "};\n"
6225
6226 (* Generate the server-side stubs. *)
6227 and generate_daemon_actions () =
6228   generate_header CStyle GPLv2plus;
6229
6230   pr "#include <config.h>\n";
6231   pr "\n";
6232   pr "#include <stdio.h>\n";
6233   pr "#include <stdlib.h>\n";
6234   pr "#include <string.h>\n";
6235   pr "#include <inttypes.h>\n";
6236   pr "#include <rpc/types.h>\n";
6237   pr "#include <rpc/xdr.h>\n";
6238   pr "\n";
6239   pr "#include \"daemon.h\"\n";
6240   pr "#include \"c-ctype.h\"\n";
6241   pr "#include \"../src/guestfs_protocol.h\"\n";
6242   pr "#include \"actions.h\"\n";
6243   pr "\n";
6244
6245   List.iter (
6246     fun (name, style, _, _, _, _, _) ->
6247       (* Generate server-side stubs. *)
6248       pr "static void %s_stub (XDR *xdr_in)\n" name;
6249       pr "{\n";
6250       let error_code =
6251         match fst style with
6252         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6253         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6254         | RBool _ -> pr "  int r;\n"; "-1"
6255         | RConstString _ | RConstOptString _ ->
6256             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6257         | RString _ -> pr "  char *r;\n"; "NULL"
6258         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6259         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6260         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6261         | RBufferOut _ ->
6262             pr "  size_t size = 1;\n";
6263             pr "  char *r;\n";
6264             "NULL" in
6265
6266       (match snd style with
6267        | [] -> ()
6268        | args ->
6269            pr "  struct guestfs_%s_args args;\n" name;
6270            List.iter (
6271              function
6272              | Device n | Dev_or_Path n
6273              | Pathname n
6274              | String n -> ()
6275              | OptString n -> pr "  char *%s;\n" n
6276              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6277              | Bool n -> pr "  int %s;\n" n
6278              | Int n -> pr "  int %s;\n" n
6279              | Int64 n -> pr "  int64_t %s;\n" n
6280              | FileIn _ | FileOut _ -> ()
6281              | BufferIn n ->
6282                  pr "  const char *%s;\n" n;
6283                  pr "  size_t %s_size;\n" n
6284            ) args
6285       );
6286       pr "\n";
6287
6288       let is_filein =
6289         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6290
6291       (match snd style with
6292        | [] -> ()
6293        | args ->
6294            pr "  memset (&args, 0, sizeof args);\n";
6295            pr "\n";
6296            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6297            if is_filein then
6298              pr "    if (cancel_receive () != -2)\n";
6299            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6300            pr "    goto done;\n";
6301            pr "  }\n";
6302            let pr_args n =
6303              pr "  char *%s = args.%s;\n" n n
6304            in
6305            let pr_list_handling_code n =
6306              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6307              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6308              pr "  if (%s == NULL) {\n" n;
6309              if is_filein then
6310                pr "    if (cancel_receive () != -2)\n";
6311              pr "      reply_with_perror (\"realloc\");\n";
6312              pr "    goto done;\n";
6313              pr "  }\n";
6314              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6315              pr "  args.%s.%s_val = %s;\n" n n n;
6316            in
6317            List.iter (
6318              function
6319              | Pathname n ->
6320                  pr_args n;
6321                  pr "  ABS_PATH (%s, %s, goto done);\n"
6322                    n (if is_filein then "cancel_receive ()" else "0");
6323              | Device n ->
6324                  pr_args n;
6325                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6326                    n (if is_filein then "cancel_receive ()" else "0");
6327              | Dev_or_Path n ->
6328                  pr_args n;
6329                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6330                    n (if is_filein then "cancel_receive ()" else "0");
6331              | String n -> pr_args n
6332              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6333              | StringList n ->
6334                  pr_list_handling_code n;
6335              | DeviceList n ->
6336                  pr_list_handling_code n;
6337                  pr "  /* Ensure that each is a device,\n";
6338                  pr "   * and perform device name translation. */\n";
6339                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6340                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6341                    (if is_filein then "cancel_receive ()" else "0");
6342                  pr "  }\n";
6343              | Bool n -> pr "  %s = args.%s;\n" n n
6344              | Int n -> pr "  %s = args.%s;\n" n n
6345              | Int64 n -> pr "  %s = args.%s;\n" n n
6346              | FileIn _ | FileOut _ -> ()
6347              | BufferIn n ->
6348                  pr "  %s = args.%s.%s_val;\n" n n n;
6349                  pr "  %s_size = args.%s.%s_len;\n" n n n
6350            ) args;
6351            pr "\n"
6352       );
6353
6354       (* this is used at least for do_equal *)
6355       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6356         (* Emit NEED_ROOT just once, even when there are two or
6357            more Pathname args *)
6358         pr "  NEED_ROOT (%s, goto done);\n"
6359           (if is_filein then "cancel_receive ()" else "0");
6360       );
6361
6362       (* Don't want to call the impl with any FileIn or FileOut
6363        * parameters, since these go "outside" the RPC protocol.
6364        *)
6365       let args' =
6366         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6367           (snd style) in
6368       pr "  r = do_%s " name;
6369       generate_c_call_args (fst style, args');
6370       pr ";\n";
6371
6372       (match fst style with
6373        | RErr | RInt _ | RInt64 _ | RBool _
6374        | RConstString _ | RConstOptString _
6375        | RString _ | RStringList _ | RHashtable _
6376        | RStruct (_, _) | RStructList (_, _) ->
6377            pr "  if (r == %s)\n" error_code;
6378            pr "    /* do_%s has already called reply_with_error */\n" name;
6379            pr "    goto done;\n";
6380            pr "\n"
6381        | RBufferOut _ ->
6382            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6383            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6384            pr "   */\n";
6385            pr "  if (size == 1 && r == %s)\n" error_code;
6386            pr "    /* do_%s has already called reply_with_error */\n" name;
6387            pr "    goto done;\n";
6388            pr "\n"
6389       );
6390
6391       (* If there are any FileOut parameters, then the impl must
6392        * send its own reply.
6393        *)
6394       let no_reply =
6395         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6396       if no_reply then
6397         pr "  /* do_%s has already sent a reply */\n" name
6398       else (
6399         match fst style with
6400         | RErr -> pr "  reply (NULL, NULL);\n"
6401         | RInt n | RInt64 n | RBool n ->
6402             pr "  struct guestfs_%s_ret ret;\n" name;
6403             pr "  ret.%s = r;\n" n;
6404             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6405               name
6406         | RConstString _ | RConstOptString _ ->
6407             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6408         | RString n ->
6409             pr "  struct guestfs_%s_ret ret;\n" name;
6410             pr "  ret.%s = r;\n" n;
6411             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6412               name;
6413             pr "  free (r);\n"
6414         | RStringList n | RHashtable n ->
6415             pr "  struct guestfs_%s_ret ret;\n" name;
6416             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6417             pr "  ret.%s.%s_val = r;\n" n n;
6418             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6419               name;
6420             pr "  free_strings (r);\n"
6421         | RStruct (n, _) ->
6422             pr "  struct guestfs_%s_ret ret;\n" name;
6423             pr "  ret.%s = *r;\n" n;
6424             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6425               name;
6426             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6427               name
6428         | RStructList (n, _) ->
6429             pr "  struct guestfs_%s_ret ret;\n" name;
6430             pr "  ret.%s = *r;\n" n;
6431             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6432               name;
6433             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6434               name
6435         | RBufferOut n ->
6436             pr "  struct guestfs_%s_ret ret;\n" name;
6437             pr "  ret.%s.%s_val = r;\n" n n;
6438             pr "  ret.%s.%s_len = size;\n" n n;
6439             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6440               name;
6441             pr "  free (r);\n"
6442       );
6443
6444       (* Free the args. *)
6445       pr "done:\n";
6446       (match snd style with
6447        | [] -> ()
6448        | _ ->
6449            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6450              name
6451       );
6452       pr "  return;\n";
6453       pr "}\n\n";
6454   ) daemon_functions;
6455
6456   (* Dispatch function. *)
6457   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6458   pr "{\n";
6459   pr "  switch (proc_nr) {\n";
6460
6461   List.iter (
6462     fun (name, style, _, _, _, _, _) ->
6463       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6464       pr "      %s_stub (xdr_in);\n" name;
6465       pr "      break;\n"
6466   ) daemon_functions;
6467
6468   pr "    default:\n";
6469   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";
6470   pr "  }\n";
6471   pr "}\n";
6472   pr "\n";
6473
6474   (* LVM columns and tokenization functions. *)
6475   (* XXX This generates crap code.  We should rethink how we
6476    * do this parsing.
6477    *)
6478   List.iter (
6479     function
6480     | typ, cols ->
6481         pr "static const char *lvm_%s_cols = \"%s\";\n"
6482           typ (String.concat "," (List.map fst cols));
6483         pr "\n";
6484
6485         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6486         pr "{\n";
6487         pr "  char *tok, *p, *next;\n";
6488         pr "  int i, j;\n";
6489         pr "\n";
6490         (*
6491           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6492           pr "\n";
6493         *)
6494         pr "  if (!str) {\n";
6495         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6496         pr "    return -1;\n";
6497         pr "  }\n";
6498         pr "  if (!*str || c_isspace (*str)) {\n";
6499         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6500         pr "    return -1;\n";
6501         pr "  }\n";
6502         pr "  tok = str;\n";
6503         List.iter (
6504           fun (name, coltype) ->
6505             pr "  if (!tok) {\n";
6506             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6507             pr "    return -1;\n";
6508             pr "  }\n";
6509             pr "  p = strchrnul (tok, ',');\n";
6510             pr "  if (*p) next = p+1; else next = NULL;\n";
6511             pr "  *p = '\\0';\n";
6512             (match coltype with
6513              | FString ->
6514                  pr "  r->%s = strdup (tok);\n" name;
6515                  pr "  if (r->%s == NULL) {\n" name;
6516                  pr "    perror (\"strdup\");\n";
6517                  pr "    return -1;\n";
6518                  pr "  }\n"
6519              | FUUID ->
6520                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6521                  pr "    if (tok[j] == '\\0') {\n";
6522                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6523                  pr "      return -1;\n";
6524                  pr "    } else if (tok[j] != '-')\n";
6525                  pr "      r->%s[i++] = tok[j];\n" name;
6526                  pr "  }\n";
6527              | FBytes ->
6528                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6529                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6530                  pr "    return -1;\n";
6531                  pr "  }\n";
6532              | FInt64 ->
6533                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6534                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6535                  pr "    return -1;\n";
6536                  pr "  }\n";
6537              | FOptPercent ->
6538                  pr "  if (tok[0] == '\\0')\n";
6539                  pr "    r->%s = -1;\n" name;
6540                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6541                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6542                  pr "    return -1;\n";
6543                  pr "  }\n";
6544              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6545                  assert false (* can never be an LVM column *)
6546             );
6547             pr "  tok = next;\n";
6548         ) cols;
6549
6550         pr "  if (tok != NULL) {\n";
6551         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6552         pr "    return -1;\n";
6553         pr "  }\n";
6554         pr "  return 0;\n";
6555         pr "}\n";
6556         pr "\n";
6557
6558         pr "guestfs_int_lvm_%s_list *\n" typ;
6559         pr "parse_command_line_%ss (void)\n" typ;
6560         pr "{\n";
6561         pr "  char *out, *err;\n";
6562         pr "  char *p, *pend;\n";
6563         pr "  int r, i;\n";
6564         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6565         pr "  void *newp;\n";
6566         pr "\n";
6567         pr "  ret = malloc (sizeof *ret);\n";
6568         pr "  if (!ret) {\n";
6569         pr "    reply_with_perror (\"malloc\");\n";
6570         pr "    return NULL;\n";
6571         pr "  }\n";
6572         pr "\n";
6573         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6574         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6575         pr "\n";
6576         pr "  r = command (&out, &err,\n";
6577         pr "           \"lvm\", \"%ss\",\n" typ;
6578         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6579         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6580         pr "  if (r == -1) {\n";
6581         pr "    reply_with_error (\"%%s\", err);\n";
6582         pr "    free (out);\n";
6583         pr "    free (err);\n";
6584         pr "    free (ret);\n";
6585         pr "    return NULL;\n";
6586         pr "  }\n";
6587         pr "\n";
6588         pr "  free (err);\n";
6589         pr "\n";
6590         pr "  /* Tokenize each line of the output. */\n";
6591         pr "  p = out;\n";
6592         pr "  i = 0;\n";
6593         pr "  while (p) {\n";
6594         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6595         pr "    if (pend) {\n";
6596         pr "      *pend = '\\0';\n";
6597         pr "      pend++;\n";
6598         pr "    }\n";
6599         pr "\n";
6600         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6601         pr "      p++;\n";
6602         pr "\n";
6603         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6604         pr "      p = pend;\n";
6605         pr "      continue;\n";
6606         pr "    }\n";
6607         pr "\n";
6608         pr "    /* Allocate some space to store this next entry. */\n";
6609         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6610         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6611         pr "    if (newp == NULL) {\n";
6612         pr "      reply_with_perror (\"realloc\");\n";
6613         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6614         pr "      free (ret);\n";
6615         pr "      free (out);\n";
6616         pr "      return NULL;\n";
6617         pr "    }\n";
6618         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6619         pr "\n";
6620         pr "    /* Tokenize the next entry. */\n";
6621         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6622         pr "    if (r == -1) {\n";
6623         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6624         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6625         pr "      free (ret);\n";
6626         pr "      free (out);\n";
6627         pr "      return NULL;\n";
6628         pr "    }\n";
6629         pr "\n";
6630         pr "    ++i;\n";
6631         pr "    p = pend;\n";
6632         pr "  }\n";
6633         pr "\n";
6634         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6635         pr "\n";
6636         pr "  free (out);\n";
6637         pr "  return ret;\n";
6638         pr "}\n"
6639
6640   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6641
6642 (* Generate a list of function names, for debugging in the daemon.. *)
6643 and generate_daemon_names () =
6644   generate_header CStyle GPLv2plus;
6645
6646   pr "#include <config.h>\n";
6647   pr "\n";
6648   pr "#include \"daemon.h\"\n";
6649   pr "\n";
6650
6651   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6652   pr "const char *function_names[] = {\n";
6653   List.iter (
6654     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6655   ) daemon_functions;
6656   pr "};\n";
6657
6658 (* Generate the optional groups for the daemon to implement
6659  * guestfs_available.
6660  *)
6661 and generate_daemon_optgroups_c () =
6662   generate_header CStyle GPLv2plus;
6663
6664   pr "#include <config.h>\n";
6665   pr "\n";
6666   pr "#include \"daemon.h\"\n";
6667   pr "#include \"optgroups.h\"\n";
6668   pr "\n";
6669
6670   pr "struct optgroup optgroups[] = {\n";
6671   List.iter (
6672     fun (group, _) ->
6673       pr "  { \"%s\", optgroup_%s_available },\n" group group
6674   ) optgroups;
6675   pr "  { NULL, NULL }\n";
6676   pr "};\n"
6677
6678 and generate_daemon_optgroups_h () =
6679   generate_header CStyle GPLv2plus;
6680
6681   List.iter (
6682     fun (group, _) ->
6683       pr "extern int optgroup_%s_available (void);\n" group
6684   ) optgroups
6685
6686 (* Generate the tests. *)
6687 and generate_tests () =
6688   generate_header CStyle GPLv2plus;
6689
6690   pr "\
6691 #include <stdio.h>
6692 #include <stdlib.h>
6693 #include <string.h>
6694 #include <unistd.h>
6695 #include <sys/types.h>
6696 #include <fcntl.h>
6697
6698 #include \"guestfs.h\"
6699 #include \"guestfs-internal.h\"
6700
6701 static guestfs_h *g;
6702 static int suppress_error = 0;
6703
6704 static void print_error (guestfs_h *g, void *data, const char *msg)
6705 {
6706   if (!suppress_error)
6707     fprintf (stderr, \"%%s\\n\", msg);
6708 }
6709
6710 /* FIXME: nearly identical code appears in fish.c */
6711 static void print_strings (char *const *argv)
6712 {
6713   int argc;
6714
6715   for (argc = 0; argv[argc] != NULL; ++argc)
6716     printf (\"\\t%%s\\n\", argv[argc]);
6717 }
6718
6719 /*
6720 static void print_table (char const *const *argv)
6721 {
6722   int i;
6723
6724   for (i = 0; argv[i] != NULL; i += 2)
6725     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6726 }
6727 */
6728
6729 ";
6730
6731   (* Generate a list of commands which are not tested anywhere. *)
6732   pr "static void no_test_warnings (void)\n";
6733   pr "{\n";
6734
6735   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6736   List.iter (
6737     fun (_, _, _, _, tests, _, _) ->
6738       let tests = filter_map (
6739         function
6740         | (_, (Always|If _|Unless _), test) -> Some test
6741         | (_, Disabled, _) -> None
6742       ) tests in
6743       let seq = List.concat (List.map seq_of_test tests) in
6744       let cmds_tested = List.map List.hd seq in
6745       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6746   ) all_functions;
6747
6748   List.iter (
6749     fun (name, _, _, _, _, _, _) ->
6750       if not (Hashtbl.mem hash name) then
6751         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6752   ) all_functions;
6753
6754   pr "}\n";
6755   pr "\n";
6756
6757   (* Generate the actual tests.  Note that we generate the tests
6758    * in reverse order, deliberately, so that (in general) the
6759    * newest tests run first.  This makes it quicker and easier to
6760    * debug them.
6761    *)
6762   let test_names =
6763     List.map (
6764       fun (name, _, _, flags, tests, _, _) ->
6765         mapi (generate_one_test name flags) tests
6766     ) (List.rev all_functions) in
6767   let test_names = List.concat test_names in
6768   let nr_tests = List.length test_names in
6769
6770   pr "\
6771 int main (int argc, char *argv[])
6772 {
6773   char c = 0;
6774   unsigned long int n_failed = 0;
6775   const char *filename;
6776   int fd;
6777   int nr_tests, test_num = 0;
6778
6779   setbuf (stdout, NULL);
6780
6781   no_test_warnings ();
6782
6783   g = guestfs_create ();
6784   if (g == NULL) {
6785     printf (\"guestfs_create FAILED\\n\");
6786     exit (EXIT_FAILURE);
6787   }
6788
6789   guestfs_set_error_handler (g, print_error, NULL);
6790
6791   guestfs_set_path (g, \"../appliance\");
6792
6793   filename = \"test1.img\";
6794   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6795   if (fd == -1) {
6796     perror (filename);
6797     exit (EXIT_FAILURE);
6798   }
6799   if (lseek (fd, %d, SEEK_SET) == -1) {
6800     perror (\"lseek\");
6801     close (fd);
6802     unlink (filename);
6803     exit (EXIT_FAILURE);
6804   }
6805   if (write (fd, &c, 1) == -1) {
6806     perror (\"write\");
6807     close (fd);
6808     unlink (filename);
6809     exit (EXIT_FAILURE);
6810   }
6811   if (close (fd) == -1) {
6812     perror (filename);
6813     unlink (filename);
6814     exit (EXIT_FAILURE);
6815   }
6816   if (guestfs_add_drive (g, filename) == -1) {
6817     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6818     exit (EXIT_FAILURE);
6819   }
6820
6821   filename = \"test2.img\";
6822   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6823   if (fd == -1) {
6824     perror (filename);
6825     exit (EXIT_FAILURE);
6826   }
6827   if (lseek (fd, %d, SEEK_SET) == -1) {
6828     perror (\"lseek\");
6829     close (fd);
6830     unlink (filename);
6831     exit (EXIT_FAILURE);
6832   }
6833   if (write (fd, &c, 1) == -1) {
6834     perror (\"write\");
6835     close (fd);
6836     unlink (filename);
6837     exit (EXIT_FAILURE);
6838   }
6839   if (close (fd) == -1) {
6840     perror (filename);
6841     unlink (filename);
6842     exit (EXIT_FAILURE);
6843   }
6844   if (guestfs_add_drive (g, filename) == -1) {
6845     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6846     exit (EXIT_FAILURE);
6847   }
6848
6849   filename = \"test3.img\";
6850   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6851   if (fd == -1) {
6852     perror (filename);
6853     exit (EXIT_FAILURE);
6854   }
6855   if (lseek (fd, %d, SEEK_SET) == -1) {
6856     perror (\"lseek\");
6857     close (fd);
6858     unlink (filename);
6859     exit (EXIT_FAILURE);
6860   }
6861   if (write (fd, &c, 1) == -1) {
6862     perror (\"write\");
6863     close (fd);
6864     unlink (filename);
6865     exit (EXIT_FAILURE);
6866   }
6867   if (close (fd) == -1) {
6868     perror (filename);
6869     unlink (filename);
6870     exit (EXIT_FAILURE);
6871   }
6872   if (guestfs_add_drive (g, filename) == -1) {
6873     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6874     exit (EXIT_FAILURE);
6875   }
6876
6877   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6878     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6879     exit (EXIT_FAILURE);
6880   }
6881
6882   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6883   alarm (600);
6884
6885   if (guestfs_launch (g) == -1) {
6886     printf (\"guestfs_launch FAILED\\n\");
6887     exit (EXIT_FAILURE);
6888   }
6889
6890   /* Cancel previous alarm. */
6891   alarm (0);
6892
6893   nr_tests = %d;
6894
6895 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6896
6897   iteri (
6898     fun i test_name ->
6899       pr "  test_num++;\n";
6900       pr "  if (guestfs_get_verbose (g))\n";
6901       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6902       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6903       pr "  if (%s () == -1) {\n" test_name;
6904       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6905       pr "    n_failed++;\n";
6906       pr "  }\n";
6907   ) test_names;
6908   pr "\n";
6909
6910   pr "  guestfs_close (g);\n";
6911   pr "  unlink (\"test1.img\");\n";
6912   pr "  unlink (\"test2.img\");\n";
6913   pr "  unlink (\"test3.img\");\n";
6914   pr "\n";
6915
6916   pr "  if (n_failed > 0) {\n";
6917   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6918   pr "    exit (EXIT_FAILURE);\n";
6919   pr "  }\n";
6920   pr "\n";
6921
6922   pr "  exit (EXIT_SUCCESS);\n";
6923   pr "}\n"
6924
6925 and generate_one_test name flags i (init, prereq, test) =
6926   let test_name = sprintf "test_%s_%d" name i in
6927
6928   pr "\
6929 static int %s_skip (void)
6930 {
6931   const char *str;
6932
6933   str = getenv (\"TEST_ONLY\");
6934   if (str)
6935     return strstr (str, \"%s\") == NULL;
6936   str = getenv (\"SKIP_%s\");
6937   if (str && STREQ (str, \"1\")) return 1;
6938   str = getenv (\"SKIP_TEST_%s\");
6939   if (str && STREQ (str, \"1\")) return 1;
6940   return 0;
6941 }
6942
6943 " test_name name (String.uppercase test_name) (String.uppercase name);
6944
6945   (match prereq with
6946    | Disabled | Always -> ()
6947    | If code | Unless code ->
6948        pr "static int %s_prereq (void)\n" test_name;
6949        pr "{\n";
6950        pr "  %s\n" code;
6951        pr "}\n";
6952        pr "\n";
6953   );
6954
6955   pr "\
6956 static int %s (void)
6957 {
6958   if (%s_skip ()) {
6959     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6960     return 0;
6961   }
6962
6963 " test_name test_name test_name;
6964
6965   (* Optional functions should only be tested if the relevant
6966    * support is available in the daemon.
6967    *)
6968   List.iter (
6969     function
6970     | Optional group ->
6971         pr "  {\n";
6972         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6973         pr "    int r;\n";
6974         pr "    suppress_error = 1;\n";
6975         pr "    r = guestfs_available (g, (char **) groups);\n";
6976         pr "    suppress_error = 0;\n";
6977         pr "    if (r == -1) {\n";
6978         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6979         pr "      return 0;\n";
6980         pr "    }\n";
6981         pr "  }\n";
6982     | _ -> ()
6983   ) flags;
6984
6985   (match prereq with
6986    | Disabled ->
6987        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6988    | If _ ->
6989        pr "  if (! %s_prereq ()) {\n" test_name;
6990        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6991        pr "    return 0;\n";
6992        pr "  }\n";
6993        pr "\n";
6994        generate_one_test_body name i test_name init test;
6995    | Unless _ ->
6996        pr "  if (%s_prereq ()) {\n" test_name;
6997        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6998        pr "    return 0;\n";
6999        pr "  }\n";
7000        pr "\n";
7001        generate_one_test_body name i test_name init test;
7002    | Always ->
7003        generate_one_test_body name i test_name init test
7004   );
7005
7006   pr "  return 0;\n";
7007   pr "}\n";
7008   pr "\n";
7009   test_name
7010
7011 and generate_one_test_body name i test_name init test =
7012   (match init with
7013    | InitNone (* XXX at some point, InitNone and InitEmpty became
7014                * folded together as the same thing.  Really we should
7015                * make InitNone do nothing at all, but the tests may
7016                * need to be checked to make sure this is OK.
7017                *)
7018    | InitEmpty ->
7019        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7020        List.iter (generate_test_command_call test_name)
7021          [["blockdev_setrw"; "/dev/sda"];
7022           ["umount_all"];
7023           ["lvm_remove_all"]]
7024    | InitPartition ->
7025        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7026        List.iter (generate_test_command_call test_name)
7027          [["blockdev_setrw"; "/dev/sda"];
7028           ["umount_all"];
7029           ["lvm_remove_all"];
7030           ["part_disk"; "/dev/sda"; "mbr"]]
7031    | InitBasicFS ->
7032        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7033        List.iter (generate_test_command_call test_name)
7034          [["blockdev_setrw"; "/dev/sda"];
7035           ["umount_all"];
7036           ["lvm_remove_all"];
7037           ["part_disk"; "/dev/sda"; "mbr"];
7038           ["mkfs"; "ext2"; "/dev/sda1"];
7039           ["mount_options"; ""; "/dev/sda1"; "/"]]
7040    | InitBasicFSonLVM ->
7041        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7042          test_name;
7043        List.iter (generate_test_command_call test_name)
7044          [["blockdev_setrw"; "/dev/sda"];
7045           ["umount_all"];
7046           ["lvm_remove_all"];
7047           ["part_disk"; "/dev/sda"; "mbr"];
7048           ["pvcreate"; "/dev/sda1"];
7049           ["vgcreate"; "VG"; "/dev/sda1"];
7050           ["lvcreate"; "LV"; "VG"; "8"];
7051           ["mkfs"; "ext2"; "/dev/VG/LV"];
7052           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7053    | InitISOFS ->
7054        pr "  /* InitISOFS for %s */\n" test_name;
7055        List.iter (generate_test_command_call test_name)
7056          [["blockdev_setrw"; "/dev/sda"];
7057           ["umount_all"];
7058           ["lvm_remove_all"];
7059           ["mount_ro"; "/dev/sdd"; "/"]]
7060   );
7061
7062   let get_seq_last = function
7063     | [] ->
7064         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7065           test_name
7066     | seq ->
7067         let seq = List.rev seq in
7068         List.rev (List.tl seq), List.hd seq
7069   in
7070
7071   match test with
7072   | TestRun seq ->
7073       pr "  /* TestRun for %s (%d) */\n" name i;
7074       List.iter (generate_test_command_call test_name) seq
7075   | TestOutput (seq, expected) ->
7076       pr "  /* TestOutput for %s (%d) */\n" name i;
7077       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7078       let seq, last = get_seq_last seq in
7079       let test () =
7080         pr "    if (STRNEQ (r, expected)) {\n";
7081         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7082         pr "      return -1;\n";
7083         pr "    }\n"
7084       in
7085       List.iter (generate_test_command_call test_name) seq;
7086       generate_test_command_call ~test test_name last
7087   | TestOutputList (seq, expected) ->
7088       pr "  /* TestOutputList for %s (%d) */\n" name i;
7089       let seq, last = get_seq_last seq in
7090       let test () =
7091         iteri (
7092           fun i str ->
7093             pr "    if (!r[%d]) {\n" i;
7094             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7095             pr "      print_strings (r);\n";
7096             pr "      return -1;\n";
7097             pr "    }\n";
7098             pr "    {\n";
7099             pr "      const char *expected = \"%s\";\n" (c_quote str);
7100             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7101             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7102             pr "        return -1;\n";
7103             pr "      }\n";
7104             pr "    }\n"
7105         ) expected;
7106         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7107         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7108           test_name;
7109         pr "      print_strings (r);\n";
7110         pr "      return -1;\n";
7111         pr "    }\n"
7112       in
7113       List.iter (generate_test_command_call test_name) seq;
7114       generate_test_command_call ~test test_name last
7115   | TestOutputListOfDevices (seq, expected) ->
7116       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7117       let seq, last = get_seq_last seq in
7118       let test () =
7119         iteri (
7120           fun i str ->
7121             pr "    if (!r[%d]) {\n" i;
7122             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7123             pr "      print_strings (r);\n";
7124             pr "      return -1;\n";
7125             pr "    }\n";
7126             pr "    {\n";
7127             pr "      const char *expected = \"%s\";\n" (c_quote str);
7128             pr "      r[%d][5] = 's';\n" i;
7129             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7130             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7131             pr "        return -1;\n";
7132             pr "      }\n";
7133             pr "    }\n"
7134         ) expected;
7135         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7136         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7137           test_name;
7138         pr "      print_strings (r);\n";
7139         pr "      return -1;\n";
7140         pr "    }\n"
7141       in
7142       List.iter (generate_test_command_call test_name) seq;
7143       generate_test_command_call ~test test_name last
7144   | TestOutputInt (seq, expected) ->
7145       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7146       let seq, last = get_seq_last seq in
7147       let test () =
7148         pr "    if (r != %d) {\n" expected;
7149         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7150           test_name expected;
7151         pr "               (int) r);\n";
7152         pr "      return -1;\n";
7153         pr "    }\n"
7154       in
7155       List.iter (generate_test_command_call test_name) seq;
7156       generate_test_command_call ~test test_name last
7157   | TestOutputIntOp (seq, op, expected) ->
7158       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7159       let seq, last = get_seq_last seq in
7160       let test () =
7161         pr "    if (! (r %s %d)) {\n" op expected;
7162         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7163           test_name op expected;
7164         pr "               (int) r);\n";
7165         pr "      return -1;\n";
7166         pr "    }\n"
7167       in
7168       List.iter (generate_test_command_call test_name) seq;
7169       generate_test_command_call ~test test_name last
7170   | TestOutputTrue seq ->
7171       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7172       let seq, last = get_seq_last seq in
7173       let test () =
7174         pr "    if (!r) {\n";
7175         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7176           test_name;
7177         pr "      return -1;\n";
7178         pr "    }\n"
7179       in
7180       List.iter (generate_test_command_call test_name) seq;
7181       generate_test_command_call ~test test_name last
7182   | TestOutputFalse seq ->
7183       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7184       let seq, last = get_seq_last seq in
7185       let test () =
7186         pr "    if (r) {\n";
7187         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7188           test_name;
7189         pr "      return -1;\n";
7190         pr "    }\n"
7191       in
7192       List.iter (generate_test_command_call test_name) seq;
7193       generate_test_command_call ~test test_name last
7194   | TestOutputLength (seq, expected) ->
7195       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7196       let seq, last = get_seq_last seq in
7197       let test () =
7198         pr "    int j;\n";
7199         pr "    for (j = 0; j < %d; ++j)\n" expected;
7200         pr "      if (r[j] == NULL) {\n";
7201         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7202           test_name;
7203         pr "        print_strings (r);\n";
7204         pr "        return -1;\n";
7205         pr "      }\n";
7206         pr "    if (r[j] != NULL) {\n";
7207         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7208           test_name;
7209         pr "      print_strings (r);\n";
7210         pr "      return -1;\n";
7211         pr "    }\n"
7212       in
7213       List.iter (generate_test_command_call test_name) seq;
7214       generate_test_command_call ~test test_name last
7215   | TestOutputBuffer (seq, expected) ->
7216       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7217       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7218       let seq, last = get_seq_last seq in
7219       let len = String.length expected in
7220       let test () =
7221         pr "    if (size != %d) {\n" len;
7222         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7223         pr "      return -1;\n";
7224         pr "    }\n";
7225         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7226         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7227         pr "      return -1;\n";
7228         pr "    }\n"
7229       in
7230       List.iter (generate_test_command_call test_name) seq;
7231       generate_test_command_call ~test test_name last
7232   | TestOutputStruct (seq, checks) ->
7233       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7234       let seq, last = get_seq_last seq in
7235       let test () =
7236         List.iter (
7237           function
7238           | CompareWithInt (field, expected) ->
7239               pr "    if (r->%s != %d) {\n" field expected;
7240               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7241                 test_name field expected;
7242               pr "               (int) r->%s);\n" field;
7243               pr "      return -1;\n";
7244               pr "    }\n"
7245           | CompareWithIntOp (field, op, expected) ->
7246               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7247               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7248                 test_name field op expected;
7249               pr "               (int) r->%s);\n" field;
7250               pr "      return -1;\n";
7251               pr "    }\n"
7252           | CompareWithString (field, expected) ->
7253               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7254               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7255                 test_name field expected;
7256               pr "               r->%s);\n" field;
7257               pr "      return -1;\n";
7258               pr "    }\n"
7259           | CompareFieldsIntEq (field1, field2) ->
7260               pr "    if (r->%s != r->%s) {\n" field1 field2;
7261               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7262                 test_name field1 field2;
7263               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7264               pr "      return -1;\n";
7265               pr "    }\n"
7266           | CompareFieldsStrEq (field1, field2) ->
7267               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7268               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7269                 test_name field1 field2;
7270               pr "               r->%s, r->%s);\n" field1 field2;
7271               pr "      return -1;\n";
7272               pr "    }\n"
7273         ) checks
7274       in
7275       List.iter (generate_test_command_call test_name) seq;
7276       generate_test_command_call ~test test_name last
7277   | TestLastFail seq ->
7278       pr "  /* TestLastFail for %s (%d) */\n" name i;
7279       let seq, last = get_seq_last seq in
7280       List.iter (generate_test_command_call test_name) seq;
7281       generate_test_command_call test_name ~expect_error:true last
7282
7283 (* Generate the code to run a command, leaving the result in 'r'.
7284  * If you expect to get an error then you should set expect_error:true.
7285  *)
7286 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7287   match cmd with
7288   | [] -> assert false
7289   | name :: args ->
7290       (* Look up the command to find out what args/ret it has. *)
7291       let style =
7292         try
7293           let _, style, _, _, _, _, _ =
7294             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7295           style
7296         with Not_found ->
7297           failwithf "%s: in test, command %s was not found" test_name name in
7298
7299       if List.length (snd style) <> List.length args then
7300         failwithf "%s: in test, wrong number of args given to %s"
7301           test_name name;
7302
7303       pr "  {\n";
7304
7305       List.iter (
7306         function
7307         | OptString n, "NULL" -> ()
7308         | Pathname n, arg
7309         | Device n, arg
7310         | Dev_or_Path n, arg
7311         | String n, arg
7312         | OptString n, arg ->
7313             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7314         | BufferIn n, arg ->
7315             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7316             pr "    size_t %s_size = %d;\n" n (String.length arg)
7317         | Int _, _
7318         | Int64 _, _
7319         | Bool _, _
7320         | FileIn _, _ | FileOut _, _ -> ()
7321         | StringList n, "" | DeviceList n, "" ->
7322             pr "    const char *const %s[1] = { NULL };\n" n
7323         | StringList n, arg | DeviceList n, arg ->
7324             let strs = string_split " " arg in
7325             iteri (
7326               fun i str ->
7327                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7328             ) strs;
7329             pr "    const char *const %s[] = {\n" n;
7330             iteri (
7331               fun i _ -> pr "      %s_%d,\n" n i
7332             ) strs;
7333             pr "      NULL\n";
7334             pr "    };\n";
7335       ) (List.combine (snd style) args);
7336
7337       let error_code =
7338         match fst style with
7339         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7340         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7341         | RConstString _ | RConstOptString _ ->
7342             pr "    const char *r;\n"; "NULL"
7343         | RString _ -> pr "    char *r;\n"; "NULL"
7344         | RStringList _ | RHashtable _ ->
7345             pr "    char **r;\n";
7346             pr "    int i;\n";
7347             "NULL"
7348         | RStruct (_, typ) ->
7349             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7350         | RStructList (_, typ) ->
7351             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7352         | RBufferOut _ ->
7353             pr "    char *r;\n";
7354             pr "    size_t size;\n";
7355             "NULL" in
7356
7357       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7358       pr "    r = guestfs_%s (g" name;
7359
7360       (* Generate the parameters. *)
7361       List.iter (
7362         function
7363         | OptString _, "NULL" -> pr ", NULL"
7364         | Pathname n, _
7365         | Device n, _ | Dev_or_Path n, _
7366         | String n, _
7367         | OptString n, _ ->
7368             pr ", %s" n
7369         | BufferIn n, _ ->
7370             pr ", %s, %s_size" n n
7371         | FileIn _, arg | FileOut _, arg ->
7372             pr ", \"%s\"" (c_quote arg)
7373         | StringList n, _ | DeviceList n, _ ->
7374             pr ", (char **) %s" n
7375         | Int _, arg ->
7376             let i =
7377               try int_of_string arg
7378               with Failure "int_of_string" ->
7379                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7380             pr ", %d" i
7381         | Int64 _, arg ->
7382             let i =
7383               try Int64.of_string arg
7384               with Failure "int_of_string" ->
7385                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7386             pr ", %Ld" i
7387         | Bool _, arg ->
7388             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7389       ) (List.combine (snd style) args);
7390
7391       (match fst style with
7392        | RBufferOut _ -> pr ", &size"
7393        | _ -> ()
7394       );
7395
7396       pr ");\n";
7397
7398       if not expect_error then
7399         pr "    if (r == %s)\n" error_code
7400       else
7401         pr "    if (r != %s)\n" error_code;
7402       pr "      return -1;\n";
7403
7404       (* Insert the test code. *)
7405       (match test with
7406        | None -> ()
7407        | Some f -> f ()
7408       );
7409
7410       (match fst style with
7411        | RErr | RInt _ | RInt64 _ | RBool _
7412        | RConstString _ | RConstOptString _ -> ()
7413        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7414        | RStringList _ | RHashtable _ ->
7415            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7416            pr "      free (r[i]);\n";
7417            pr "    free (r);\n"
7418        | RStruct (_, typ) ->
7419            pr "    guestfs_free_%s (r);\n" typ
7420        | RStructList (_, typ) ->
7421            pr "    guestfs_free_%s_list (r);\n" typ
7422       );
7423
7424       pr "  }\n"
7425
7426 and c_quote str =
7427   let str = replace_str str "\r" "\\r" in
7428   let str = replace_str str "\n" "\\n" in
7429   let str = replace_str str "\t" "\\t" in
7430   let str = replace_str str "\000" "\\0" in
7431   str
7432
7433 (* Generate a lot of different functions for guestfish. *)
7434 and generate_fish_cmds () =
7435   generate_header CStyle GPLv2plus;
7436
7437   let all_functions =
7438     List.filter (
7439       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7440     ) all_functions in
7441   let all_functions_sorted =
7442     List.filter (
7443       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7444     ) all_functions_sorted in
7445
7446   pr "#include <config.h>\n";
7447   pr "\n";
7448   pr "#include <stdio.h>\n";
7449   pr "#include <stdlib.h>\n";
7450   pr "#include <string.h>\n";
7451   pr "#include <inttypes.h>\n";
7452   pr "\n";
7453   pr "#include <guestfs.h>\n";
7454   pr "#include \"c-ctype.h\"\n";
7455   pr "#include \"full-write.h\"\n";
7456   pr "#include \"xstrtol.h\"\n";
7457   pr "#include \"fish.h\"\n";
7458   pr "\n";
7459   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7460   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7461   pr "\n";
7462
7463   (* list_commands function, which implements guestfish -h *)
7464   pr "void list_commands (void)\n";
7465   pr "{\n";
7466   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7467   pr "  list_builtin_commands ();\n";
7468   List.iter (
7469     fun (name, _, _, flags, _, shortdesc, _) ->
7470       let name = replace_char name '_' '-' in
7471       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7472         name shortdesc
7473   ) all_functions_sorted;
7474   pr "  printf (\"    %%s\\n\",";
7475   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7476   pr "}\n";
7477   pr "\n";
7478
7479   (* display_command function, which implements guestfish -h cmd *)
7480   pr "void display_command (const char *cmd)\n";
7481   pr "{\n";
7482   List.iter (
7483     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7484       let name2 = replace_char name '_' '-' in
7485       let alias =
7486         try find_map (function FishAlias n -> Some n | _ -> None) flags
7487         with Not_found -> name in
7488       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7489       let synopsis =
7490         match snd style with
7491         | [] -> name2
7492         | args ->
7493             sprintf "%s %s"
7494               name2 (String.concat " " (List.map name_of_argt args)) in
7495
7496       let warnings =
7497         if List.mem ProtocolLimitWarning flags then
7498           ("\n\n" ^ protocol_limit_warning)
7499         else "" in
7500
7501       (* For DangerWillRobinson commands, we should probably have
7502        * guestfish prompt before allowing you to use them (especially
7503        * in interactive mode). XXX
7504        *)
7505       let warnings =
7506         warnings ^
7507           if List.mem DangerWillRobinson flags then
7508             ("\n\n" ^ danger_will_robinson)
7509           else "" in
7510
7511       let warnings =
7512         warnings ^
7513           match deprecation_notice flags with
7514           | None -> ""
7515           | Some txt -> "\n\n" ^ txt in
7516
7517       let describe_alias =
7518         if name <> alias then
7519           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7520         else "" in
7521
7522       pr "  if (";
7523       pr "STRCASEEQ (cmd, \"%s\")" name;
7524       if name <> name2 then
7525         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7526       if name <> alias then
7527         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7528       pr ")\n";
7529       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7530         name2 shortdesc
7531         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7532          "=head1 DESCRIPTION\n\n" ^
7533          longdesc ^ warnings ^ describe_alias);
7534       pr "  else\n"
7535   ) all_functions;
7536   pr "    display_builtin_command (cmd);\n";
7537   pr "}\n";
7538   pr "\n";
7539
7540   let emit_print_list_function typ =
7541     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7542       typ typ typ;
7543     pr "{\n";
7544     pr "  unsigned int i;\n";
7545     pr "\n";
7546     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7547     pr "    printf (\"[%%d] = {\\n\", i);\n";
7548     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7549     pr "    printf (\"}\\n\");\n";
7550     pr "  }\n";
7551     pr "}\n";
7552     pr "\n";
7553   in
7554
7555   (* print_* functions *)
7556   List.iter (
7557     fun (typ, cols) ->
7558       let needs_i =
7559         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7560
7561       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7562       pr "{\n";
7563       if needs_i then (
7564         pr "  unsigned int i;\n";
7565         pr "\n"
7566       );
7567       List.iter (
7568         function
7569         | name, FString ->
7570             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7571         | name, FUUID ->
7572             pr "  printf (\"%%s%s: \", indent);\n" name;
7573             pr "  for (i = 0; i < 32; ++i)\n";
7574             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7575             pr "  printf (\"\\n\");\n"
7576         | name, FBuffer ->
7577             pr "  printf (\"%%s%s: \", indent);\n" name;
7578             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7579             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7580             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7581             pr "    else\n";
7582             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7583             pr "  printf (\"\\n\");\n"
7584         | name, (FUInt64|FBytes) ->
7585             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7586               name typ name
7587         | name, FInt64 ->
7588             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7589               name typ name
7590         | name, FUInt32 ->
7591             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7592               name typ name
7593         | name, FInt32 ->
7594             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7595               name typ name
7596         | name, FChar ->
7597             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7598               name typ name
7599         | name, FOptPercent ->
7600             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7601               typ name name typ name;
7602             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7603       ) cols;
7604       pr "}\n";
7605       pr "\n";
7606   ) structs;
7607
7608   (* Emit a print_TYPE_list function definition only if that function is used. *)
7609   List.iter (
7610     function
7611     | typ, (RStructListOnly | RStructAndList) ->
7612         (* generate the function for typ *)
7613         emit_print_list_function typ
7614     | typ, _ -> () (* empty *)
7615   ) (rstructs_used_by all_functions);
7616
7617   (* Emit a print_TYPE function definition only if that function is used. *)
7618   List.iter (
7619     function
7620     | typ, (RStructOnly | RStructAndList) ->
7621         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7622         pr "{\n";
7623         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7624         pr "}\n";
7625         pr "\n";
7626     | typ, _ -> () (* empty *)
7627   ) (rstructs_used_by all_functions);
7628
7629   (* run_<action> actions *)
7630   List.iter (
7631     fun (name, style, _, flags, _, _, _) ->
7632       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7633       pr "{\n";
7634       (match fst style with
7635        | RErr
7636        | RInt _
7637        | RBool _ -> pr "  int r;\n"
7638        | RInt64 _ -> pr "  int64_t r;\n"
7639        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7640        | RString _ -> pr "  char *r;\n"
7641        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7642        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7643        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7644        | RBufferOut _ ->
7645            pr "  char *r;\n";
7646            pr "  size_t size;\n";
7647       );
7648       List.iter (
7649         function
7650         | Device n
7651         | String n
7652         | OptString n -> pr "  const char *%s;\n" n
7653         | Pathname n
7654         | Dev_or_Path n
7655         | FileIn n
7656         | FileOut n -> pr "  char *%s;\n" n
7657         | BufferIn n ->
7658             pr "  const char *%s;\n" n;
7659             pr "  size_t %s_size;\n" n
7660         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7661         | Bool n -> pr "  int %s;\n" n
7662         | Int n -> pr "  int %s;\n" n
7663         | Int64 n -> pr "  int64_t %s;\n" n
7664       ) (snd style);
7665
7666       (* Check and convert parameters. *)
7667       let argc_expected = List.length (snd style) in
7668       pr "  if (argc != %d) {\n" argc_expected;
7669       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7670         argc_expected;
7671       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7672       pr "    return -1;\n";
7673       pr "  }\n";
7674
7675       let parse_integer fn fntyp rtyp range name i =
7676         pr "  {\n";
7677         pr "    strtol_error xerr;\n";
7678         pr "    %s r;\n" fntyp;
7679         pr "\n";
7680         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7681         pr "    if (xerr != LONGINT_OK) {\n";
7682         pr "      fprintf (stderr,\n";
7683         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7684         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7685         pr "      return -1;\n";
7686         pr "    }\n";
7687         (match range with
7688          | None -> ()
7689          | Some (min, max, comment) ->
7690              pr "    /* %s */\n" comment;
7691              pr "    if (r < %s || r > %s) {\n" min max;
7692              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7693                name;
7694              pr "      return -1;\n";
7695              pr "    }\n";
7696              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7697         );
7698         pr "    %s = r;\n" name;
7699         pr "  }\n";
7700       in
7701
7702       iteri (
7703         fun i ->
7704           function
7705           | Device name
7706           | String name ->
7707               pr "  %s = argv[%d];\n" name i
7708           | Pathname name
7709           | Dev_or_Path name ->
7710               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7711               pr "  if (%s == NULL) return -1;\n" name
7712           | OptString name ->
7713               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7714                 name i i
7715           | BufferIn name ->
7716               pr "  %s = argv[%d];\n" name i;
7717               pr "  %s_size = strlen (argv[%d]);\n" name i
7718           | FileIn name ->
7719               pr "  %s = file_in (argv[%d]);\n" name i;
7720               pr "  if (%s == NULL) return -1;\n" name
7721           | FileOut name ->
7722               pr "  %s = file_out (argv[%d]);\n" name i;
7723               pr "  if (%s == NULL) return -1;\n" name
7724           | StringList name | DeviceList name ->
7725               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7726               pr "  if (%s == NULL) return -1;\n" name;
7727           | Bool name ->
7728               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7729           | Int name ->
7730               let range =
7731                 let min = "(-(2LL<<30))"
7732                 and max = "((2LL<<30)-1)"
7733                 and comment =
7734                   "The Int type in the generator is a signed 31 bit int." in
7735                 Some (min, max, comment) in
7736               parse_integer "xstrtoll" "long long" "int" range name i
7737           | Int64 name ->
7738               parse_integer "xstrtoll" "long long" "int64_t" None name i
7739       ) (snd style);
7740
7741       (* Call C API function. *)
7742       pr "  r = guestfs_%s " name;
7743       generate_c_call_args ~handle:"g" style;
7744       pr ";\n";
7745
7746       List.iter (
7747         function
7748         | Device name | String name
7749         | OptString name | Bool name
7750         | Int name | Int64 name
7751         | BufferIn name -> ()
7752         | Pathname name | Dev_or_Path name | FileOut name ->
7753             pr "  free (%s);\n" name
7754         | FileIn name ->
7755             pr "  free_file_in (%s);\n" name
7756         | StringList name | DeviceList name ->
7757             pr "  free_strings (%s);\n" name
7758       ) (snd style);
7759
7760       (* Any output flags? *)
7761       let fish_output =
7762         let flags = filter_map (
7763           function FishOutput flag -> Some flag | _ -> None
7764         ) flags in
7765         match flags with
7766         | [] -> None
7767         | [f] -> Some f
7768         | _ ->
7769             failwithf "%s: more than one FishOutput flag is not allowed" name in
7770
7771       (* Check return value for errors and display command results. *)
7772       (match fst style with
7773        | RErr -> pr "  return r;\n"
7774        | RInt _ ->
7775            pr "  if (r == -1) return -1;\n";
7776            (match fish_output with
7777             | None ->
7778                 pr "  printf (\"%%d\\n\", r);\n";
7779             | Some FishOutputOctal ->
7780                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7781             | Some FishOutputHexadecimal ->
7782                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7783            pr "  return 0;\n"
7784        | RInt64 _ ->
7785            pr "  if (r == -1) return -1;\n";
7786            (match fish_output with
7787             | None ->
7788                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7789             | Some FishOutputOctal ->
7790                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7791             | Some FishOutputHexadecimal ->
7792                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7793            pr "  return 0;\n"
7794        | RBool _ ->
7795            pr "  if (r == -1) return -1;\n";
7796            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7797            pr "  return 0;\n"
7798        | RConstString _ ->
7799            pr "  if (r == NULL) return -1;\n";
7800            pr "  printf (\"%%s\\n\", r);\n";
7801            pr "  return 0;\n"
7802        | RConstOptString _ ->
7803            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7804            pr "  return 0;\n"
7805        | RString _ ->
7806            pr "  if (r == NULL) return -1;\n";
7807            pr "  printf (\"%%s\\n\", r);\n";
7808            pr "  free (r);\n";
7809            pr "  return 0;\n"
7810        | RStringList _ ->
7811            pr "  if (r == NULL) return -1;\n";
7812            pr "  print_strings (r);\n";
7813            pr "  free_strings (r);\n";
7814            pr "  return 0;\n"
7815        | RStruct (_, typ) ->
7816            pr "  if (r == NULL) return -1;\n";
7817            pr "  print_%s (r);\n" typ;
7818            pr "  guestfs_free_%s (r);\n" typ;
7819            pr "  return 0;\n"
7820        | RStructList (_, typ) ->
7821            pr "  if (r == NULL) return -1;\n";
7822            pr "  print_%s_list (r);\n" typ;
7823            pr "  guestfs_free_%s_list (r);\n" typ;
7824            pr "  return 0;\n"
7825        | RHashtable _ ->
7826            pr "  if (r == NULL) return -1;\n";
7827            pr "  print_table (r);\n";
7828            pr "  free_strings (r);\n";
7829            pr "  return 0;\n"
7830        | RBufferOut _ ->
7831            pr "  if (r == NULL) return -1;\n";
7832            pr "  if (full_write (1, r, size) != size) {\n";
7833            pr "    perror (\"write\");\n";
7834            pr "    free (r);\n";
7835            pr "    return -1;\n";
7836            pr "  }\n";
7837            pr "  free (r);\n";
7838            pr "  return 0;\n"
7839       );
7840       pr "}\n";
7841       pr "\n"
7842   ) all_functions;
7843
7844   (* run_action function *)
7845   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7846   pr "{\n";
7847   List.iter (
7848     fun (name, _, _, flags, _, _, _) ->
7849       let name2 = replace_char name '_' '-' in
7850       let alias =
7851         try find_map (function FishAlias n -> Some n | _ -> None) flags
7852         with Not_found -> name in
7853       pr "  if (";
7854       pr "STRCASEEQ (cmd, \"%s\")" name;
7855       if name <> name2 then
7856         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7857       if name <> alias then
7858         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7859       pr ")\n";
7860       pr "    return run_%s (cmd, argc, argv);\n" name;
7861       pr "  else\n";
7862   ) all_functions;
7863   pr "    {\n";
7864   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7865   pr "      if (command_num == 1)\n";
7866   pr "        extended_help_message ();\n";
7867   pr "      return -1;\n";
7868   pr "    }\n";
7869   pr "  return 0;\n";
7870   pr "}\n";
7871   pr "\n"
7872
7873 (* Readline completion for guestfish. *)
7874 and generate_fish_completion () =
7875   generate_header CStyle GPLv2plus;
7876
7877   let all_functions =
7878     List.filter (
7879       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7880     ) all_functions in
7881
7882   pr "\
7883 #include <config.h>
7884
7885 #include <stdio.h>
7886 #include <stdlib.h>
7887 #include <string.h>
7888
7889 #ifdef HAVE_LIBREADLINE
7890 #include <readline/readline.h>
7891 #endif
7892
7893 #include \"fish.h\"
7894
7895 #ifdef HAVE_LIBREADLINE
7896
7897 static const char *const commands[] = {
7898   BUILTIN_COMMANDS_FOR_COMPLETION,
7899 ";
7900
7901   (* Get the commands, including the aliases.  They don't need to be
7902    * sorted - the generator() function just does a dumb linear search.
7903    *)
7904   let commands =
7905     List.map (
7906       fun (name, _, _, flags, _, _, _) ->
7907         let name2 = replace_char name '_' '-' in
7908         let alias =
7909           try find_map (function FishAlias n -> Some n | _ -> None) flags
7910           with Not_found -> name in
7911
7912         if name <> alias then [name2; alias] else [name2]
7913     ) all_functions in
7914   let commands = List.flatten commands in
7915
7916   List.iter (pr "  \"%s\",\n") commands;
7917
7918   pr "  NULL
7919 };
7920
7921 static char *
7922 generator (const char *text, int state)
7923 {
7924   static int index, len;
7925   const char *name;
7926
7927   if (!state) {
7928     index = 0;
7929     len = strlen (text);
7930   }
7931
7932   rl_attempted_completion_over = 1;
7933
7934   while ((name = commands[index]) != NULL) {
7935     index++;
7936     if (STRCASEEQLEN (name, text, len))
7937       return strdup (name);
7938   }
7939
7940   return NULL;
7941 }
7942
7943 #endif /* HAVE_LIBREADLINE */
7944
7945 #ifdef HAVE_RL_COMPLETION_MATCHES
7946 #define RL_COMPLETION_MATCHES rl_completion_matches
7947 #else
7948 #ifdef HAVE_COMPLETION_MATCHES
7949 #define RL_COMPLETION_MATCHES completion_matches
7950 #endif
7951 #endif /* else just fail if we don't have either symbol */
7952
7953 char **
7954 do_completion (const char *text, int start, int end)
7955 {
7956   char **matches = NULL;
7957
7958 #ifdef HAVE_LIBREADLINE
7959   rl_completion_append_character = ' ';
7960
7961   if (start == 0)
7962     matches = RL_COMPLETION_MATCHES (text, generator);
7963   else if (complete_dest_paths)
7964     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7965 #endif
7966
7967   return matches;
7968 }
7969 ";
7970
7971 (* Generate the POD documentation for guestfish. *)
7972 and generate_fish_actions_pod () =
7973   let all_functions_sorted =
7974     List.filter (
7975       fun (_, _, _, flags, _, _, _) ->
7976         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7977     ) all_functions_sorted in
7978
7979   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7980
7981   List.iter (
7982     fun (name, style, _, flags, _, _, longdesc) ->
7983       let longdesc =
7984         Str.global_substitute rex (
7985           fun s ->
7986             let sub =
7987               try Str.matched_group 1 s
7988               with Not_found ->
7989                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7990             "C<" ^ replace_char sub '_' '-' ^ ">"
7991         ) longdesc in
7992       let name = replace_char name '_' '-' in
7993       let alias =
7994         try find_map (function FishAlias n -> Some n | _ -> None) flags
7995         with Not_found -> name in
7996
7997       pr "=head2 %s" name;
7998       if name <> alias then
7999         pr " | %s" alias;
8000       pr "\n";
8001       pr "\n";
8002       pr " %s" name;
8003       List.iter (
8004         function
8005         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8006         | OptString n -> pr " %s" n
8007         | StringList n | DeviceList n -> pr " '%s ...'" n
8008         | Bool _ -> pr " true|false"
8009         | Int n -> pr " %s" n
8010         | Int64 n -> pr " %s" n
8011         | FileIn n | FileOut n -> pr " (%s|-)" n
8012         | BufferIn n -> pr " %s" n
8013       ) (snd style);
8014       pr "\n";
8015       pr "\n";
8016       pr "%s\n\n" longdesc;
8017
8018       if List.exists (function FileIn _ | FileOut _ -> true
8019                       | _ -> false) (snd style) then
8020         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8021
8022       if List.mem ProtocolLimitWarning flags then
8023         pr "%s\n\n" protocol_limit_warning;
8024
8025       if List.mem DangerWillRobinson flags then
8026         pr "%s\n\n" danger_will_robinson;
8027
8028       match deprecation_notice flags with
8029       | None -> ()
8030       | Some txt -> pr "%s\n\n" txt
8031   ) all_functions_sorted
8032
8033 (* Generate a C function prototype. *)
8034 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8035     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8036     ?(prefix = "")
8037     ?handle name style =
8038   if extern then pr "extern ";
8039   if static then pr "static ";
8040   (match fst style with
8041    | RErr -> pr "int "
8042    | RInt _ -> pr "int "
8043    | RInt64 _ -> pr "int64_t "
8044    | RBool _ -> pr "int "
8045    | RConstString _ | RConstOptString _ -> pr "const char *"
8046    | RString _ | RBufferOut _ -> pr "char *"
8047    | RStringList _ | RHashtable _ -> pr "char **"
8048    | RStruct (_, typ) ->
8049        if not in_daemon then pr "struct guestfs_%s *" typ
8050        else pr "guestfs_int_%s *" typ
8051    | RStructList (_, typ) ->
8052        if not in_daemon then pr "struct guestfs_%s_list *" typ
8053        else pr "guestfs_int_%s_list *" typ
8054   );
8055   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8056   pr "%s%s (" prefix name;
8057   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8058     pr "void"
8059   else (
8060     let comma = ref false in
8061     (match handle with
8062      | None -> ()
8063      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8064     );
8065     let next () =
8066       if !comma then (
8067         if single_line then pr ", " else pr ",\n\t\t"
8068       );
8069       comma := true
8070     in
8071     List.iter (
8072       function
8073       | Pathname n
8074       | Device n | Dev_or_Path n
8075       | String n
8076       | OptString n ->
8077           next ();
8078           pr "const char *%s" n
8079       | StringList n | DeviceList n ->
8080           next ();
8081           pr "char *const *%s" n
8082       | Bool n -> next (); pr "int %s" n
8083       | Int n -> next (); pr "int %s" n
8084       | Int64 n -> next (); pr "int64_t %s" n
8085       | FileIn n
8086       | FileOut n ->
8087           if not in_daemon then (next (); pr "const char *%s" n)
8088       | BufferIn n ->
8089           next ();
8090           pr "const char *%s" n;
8091           next ();
8092           pr "size_t %s_size" n
8093     ) (snd style);
8094     if is_RBufferOut then (next (); pr "size_t *size_r");
8095   );
8096   pr ")";
8097   if semicolon then pr ";";
8098   if newline then pr "\n"
8099
8100 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8101 and generate_c_call_args ?handle ?(decl = false) style =
8102   pr "(";
8103   let comma = ref false in
8104   let next () =
8105     if !comma then pr ", ";
8106     comma := true
8107   in
8108   (match handle with
8109    | None -> ()
8110    | Some handle -> pr "%s" handle; comma := true
8111   );
8112   List.iter (
8113     function
8114     | BufferIn n ->
8115         next ();
8116         pr "%s, %s_size" n n
8117     | arg ->
8118         next ();
8119         pr "%s" (name_of_argt arg)
8120   ) (snd style);
8121   (* For RBufferOut calls, add implicit &size parameter. *)
8122   if not decl then (
8123     match fst style with
8124     | RBufferOut _ ->
8125         next ();
8126         pr "&size"
8127     | _ -> ()
8128   );
8129   pr ")"
8130
8131 (* Generate the OCaml bindings interface. *)
8132 and generate_ocaml_mli () =
8133   generate_header OCamlStyle LGPLv2plus;
8134
8135   pr "\
8136 (** For API documentation you should refer to the C API
8137     in the guestfs(3) manual page.  The OCaml API uses almost
8138     exactly the same calls. *)
8139
8140 type t
8141 (** A [guestfs_h] handle. *)
8142
8143 exception Error of string
8144 (** This exception is raised when there is an error. *)
8145
8146 exception Handle_closed of string
8147 (** This exception is raised if you use a {!Guestfs.t} handle
8148     after calling {!close} on it.  The string is the name of
8149     the function. *)
8150
8151 val create : unit -> t
8152 (** Create a {!Guestfs.t} handle. *)
8153
8154 val close : t -> unit
8155 (** Close the {!Guestfs.t} handle and free up all resources used
8156     by it immediately.
8157
8158     Handles are closed by the garbage collector when they become
8159     unreferenced, but callers can call this in order to provide
8160     predictable cleanup. *)
8161
8162 ";
8163   generate_ocaml_structure_decls ();
8164
8165   (* The actions. *)
8166   List.iter (
8167     fun (name, style, _, _, _, shortdesc, _) ->
8168       generate_ocaml_prototype name style;
8169       pr "(** %s *)\n" shortdesc;
8170       pr "\n"
8171   ) all_functions_sorted
8172
8173 (* Generate the OCaml bindings implementation. *)
8174 and generate_ocaml_ml () =
8175   generate_header OCamlStyle LGPLv2plus;
8176
8177   pr "\
8178 type t
8179
8180 exception Error of string
8181 exception Handle_closed of string
8182
8183 external create : unit -> t = \"ocaml_guestfs_create\"
8184 external close : t -> unit = \"ocaml_guestfs_close\"
8185
8186 (* Give the exceptions names, so they can be raised from the C code. *)
8187 let () =
8188   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8189   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8190
8191 ";
8192
8193   generate_ocaml_structure_decls ();
8194
8195   (* The actions. *)
8196   List.iter (
8197     fun (name, style, _, _, _, shortdesc, _) ->
8198       generate_ocaml_prototype ~is_external:true name style;
8199   ) all_functions_sorted
8200
8201 (* Generate the OCaml bindings C implementation. *)
8202 and generate_ocaml_c () =
8203   generate_header CStyle LGPLv2plus;
8204
8205   pr "\
8206 #include <stdio.h>
8207 #include <stdlib.h>
8208 #include <string.h>
8209
8210 #include <caml/config.h>
8211 #include <caml/alloc.h>
8212 #include <caml/callback.h>
8213 #include <caml/fail.h>
8214 #include <caml/memory.h>
8215 #include <caml/mlvalues.h>
8216 #include <caml/signals.h>
8217
8218 #include <guestfs.h>
8219
8220 #include \"guestfs_c.h\"
8221
8222 /* Copy a hashtable of string pairs into an assoc-list.  We return
8223  * the list in reverse order, but hashtables aren't supposed to be
8224  * ordered anyway.
8225  */
8226 static CAMLprim value
8227 copy_table (char * const * argv)
8228 {
8229   CAMLparam0 ();
8230   CAMLlocal5 (rv, pairv, kv, vv, cons);
8231   int i;
8232
8233   rv = Val_int (0);
8234   for (i = 0; argv[i] != NULL; i += 2) {
8235     kv = caml_copy_string (argv[i]);
8236     vv = caml_copy_string (argv[i+1]);
8237     pairv = caml_alloc (2, 0);
8238     Store_field (pairv, 0, kv);
8239     Store_field (pairv, 1, vv);
8240     cons = caml_alloc (2, 0);
8241     Store_field (cons, 1, rv);
8242     rv = cons;
8243     Store_field (cons, 0, pairv);
8244   }
8245
8246   CAMLreturn (rv);
8247 }
8248
8249 ";
8250
8251   (* Struct copy functions. *)
8252
8253   let emit_ocaml_copy_list_function typ =
8254     pr "static CAMLprim value\n";
8255     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8256     pr "{\n";
8257     pr "  CAMLparam0 ();\n";
8258     pr "  CAMLlocal2 (rv, v);\n";
8259     pr "  unsigned int i;\n";
8260     pr "\n";
8261     pr "  if (%ss->len == 0)\n" typ;
8262     pr "    CAMLreturn (Atom (0));\n";
8263     pr "  else {\n";
8264     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8265     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8266     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8267     pr "      caml_modify (&Field (rv, i), v);\n";
8268     pr "    }\n";
8269     pr "    CAMLreturn (rv);\n";
8270     pr "  }\n";
8271     pr "}\n";
8272     pr "\n";
8273   in
8274
8275   List.iter (
8276     fun (typ, cols) ->
8277       let has_optpercent_col =
8278         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8279
8280       pr "static CAMLprim value\n";
8281       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8282       pr "{\n";
8283       pr "  CAMLparam0 ();\n";
8284       if has_optpercent_col then
8285         pr "  CAMLlocal3 (rv, v, v2);\n"
8286       else
8287         pr "  CAMLlocal2 (rv, v);\n";
8288       pr "\n";
8289       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8290       iteri (
8291         fun i col ->
8292           (match col with
8293            | name, FString ->
8294                pr "  v = caml_copy_string (%s->%s);\n" typ name
8295            | name, FBuffer ->
8296                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8297                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8298                  typ name typ name
8299            | name, FUUID ->
8300                pr "  v = caml_alloc_string (32);\n";
8301                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8302            | name, (FBytes|FInt64|FUInt64) ->
8303                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8304            | name, (FInt32|FUInt32) ->
8305                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8306            | name, FOptPercent ->
8307                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8308                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8309                pr "    v = caml_alloc (1, 0);\n";
8310                pr "    Store_field (v, 0, v2);\n";
8311                pr "  } else /* None */\n";
8312                pr "    v = Val_int (0);\n";
8313            | name, FChar ->
8314                pr "  v = Val_int (%s->%s);\n" typ name
8315           );
8316           pr "  Store_field (rv, %d, v);\n" i
8317       ) cols;
8318       pr "  CAMLreturn (rv);\n";
8319       pr "}\n";
8320       pr "\n";
8321   ) structs;
8322
8323   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8324   List.iter (
8325     function
8326     | typ, (RStructListOnly | RStructAndList) ->
8327         (* generate the function for typ *)
8328         emit_ocaml_copy_list_function typ
8329     | typ, _ -> () (* empty *)
8330   ) (rstructs_used_by all_functions);
8331
8332   (* The wrappers. *)
8333   List.iter (
8334     fun (name, style, _, _, _, _, _) ->
8335       pr "/* Automatically generated wrapper for function\n";
8336       pr " * ";
8337       generate_ocaml_prototype name style;
8338       pr " */\n";
8339       pr "\n";
8340
8341       let params =
8342         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8343
8344       let needs_extra_vs =
8345         match fst style with RConstOptString _ -> true | _ -> false in
8346
8347       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8348       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8349       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8350       pr "\n";
8351
8352       pr "CAMLprim value\n";
8353       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8354       List.iter (pr ", value %s") (List.tl params);
8355       pr ")\n";
8356       pr "{\n";
8357
8358       (match params with
8359        | [p1; p2; p3; p4; p5] ->
8360            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8361        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8362            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8363            pr "  CAMLxparam%d (%s);\n"
8364              (List.length rest) (String.concat ", " rest)
8365        | ps ->
8366            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8367       );
8368       if not needs_extra_vs then
8369         pr "  CAMLlocal1 (rv);\n"
8370       else
8371         pr "  CAMLlocal3 (rv, v, v2);\n";
8372       pr "\n";
8373
8374       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8375       pr "  if (g == NULL)\n";
8376       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8377       pr "\n";
8378
8379       List.iter (
8380         function
8381         | Pathname n
8382         | Device n | Dev_or_Path n
8383         | String n
8384         | FileIn n
8385         | FileOut n ->
8386             pr "  const char *%s = String_val (%sv);\n" n n
8387         | OptString n ->
8388             pr "  const char *%s =\n" n;
8389             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8390               n n
8391         | BufferIn n ->
8392             pr "  const char *%s = String_val (%sv);\n" n n;
8393             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8394         | StringList n | DeviceList n ->
8395             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8396         | Bool n ->
8397             pr "  int %s = Bool_val (%sv);\n" n n
8398         | Int n ->
8399             pr "  int %s = Int_val (%sv);\n" n n
8400         | Int64 n ->
8401             pr "  int64_t %s = Int64_val (%sv);\n" n n
8402       ) (snd style);
8403       let error_code =
8404         match fst style with
8405         | RErr -> pr "  int r;\n"; "-1"
8406         | RInt _ -> pr "  int r;\n"; "-1"
8407         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8408         | RBool _ -> pr "  int r;\n"; "-1"
8409         | RConstString _ | RConstOptString _ ->
8410             pr "  const char *r;\n"; "NULL"
8411         | RString _ -> pr "  char *r;\n"; "NULL"
8412         | RStringList _ ->
8413             pr "  int i;\n";
8414             pr "  char **r;\n";
8415             "NULL"
8416         | RStruct (_, typ) ->
8417             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8418         | RStructList (_, typ) ->
8419             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8420         | RHashtable _ ->
8421             pr "  int i;\n";
8422             pr "  char **r;\n";
8423             "NULL"
8424         | RBufferOut _ ->
8425             pr "  char *r;\n";
8426             pr "  size_t size;\n";
8427             "NULL" in
8428       pr "\n";
8429
8430       pr "  caml_enter_blocking_section ();\n";
8431       pr "  r = guestfs_%s " name;
8432       generate_c_call_args ~handle:"g" style;
8433       pr ";\n";
8434       pr "  caml_leave_blocking_section ();\n";
8435
8436       List.iter (
8437         function
8438         | StringList n | DeviceList n ->
8439             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8440         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8441         | Bool _ | Int _ | Int64 _
8442         | FileIn _ | FileOut _ | BufferIn _ -> ()
8443       ) (snd style);
8444
8445       pr "  if (r == %s)\n" error_code;
8446       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8447       pr "\n";
8448
8449       (match fst style with
8450        | RErr -> pr "  rv = Val_unit;\n"
8451        | RInt _ -> pr "  rv = Val_int (r);\n"
8452        | RInt64 _ ->
8453            pr "  rv = caml_copy_int64 (r);\n"
8454        | RBool _ -> pr "  rv = Val_bool (r);\n"
8455        | RConstString _ ->
8456            pr "  rv = caml_copy_string (r);\n"
8457        | RConstOptString _ ->
8458            pr "  if (r) { /* Some string */\n";
8459            pr "    v = caml_alloc (1, 0);\n";
8460            pr "    v2 = caml_copy_string (r);\n";
8461            pr "    Store_field (v, 0, v2);\n";
8462            pr "  } else /* None */\n";
8463            pr "    v = Val_int (0);\n";
8464        | RString _ ->
8465            pr "  rv = caml_copy_string (r);\n";
8466            pr "  free (r);\n"
8467        | RStringList _ ->
8468            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8469            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8470            pr "  free (r);\n"
8471        | RStruct (_, typ) ->
8472            pr "  rv = copy_%s (r);\n" typ;
8473            pr "  guestfs_free_%s (r);\n" typ;
8474        | RStructList (_, typ) ->
8475            pr "  rv = copy_%s_list (r);\n" typ;
8476            pr "  guestfs_free_%s_list (r);\n" typ;
8477        | RHashtable _ ->
8478            pr "  rv = copy_table (r);\n";
8479            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8480            pr "  free (r);\n";
8481        | RBufferOut _ ->
8482            pr "  rv = caml_alloc_string (size);\n";
8483            pr "  memcpy (String_val (rv), r, size);\n";
8484       );
8485
8486       pr "  CAMLreturn (rv);\n";
8487       pr "}\n";
8488       pr "\n";
8489
8490       if List.length params > 5 then (
8491         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8492         pr "CAMLprim value ";
8493         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8494         pr "CAMLprim value\n";
8495         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8496         pr "{\n";
8497         pr "  return ocaml_guestfs_%s (argv[0]" name;
8498         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8499         pr ");\n";
8500         pr "}\n";
8501         pr "\n"
8502       )
8503   ) all_functions_sorted
8504
8505 and generate_ocaml_structure_decls () =
8506   List.iter (
8507     fun (typ, cols) ->
8508       pr "type %s = {\n" typ;
8509       List.iter (
8510         function
8511         | name, FString -> pr "  %s : string;\n" name
8512         | name, FBuffer -> pr "  %s : string;\n" name
8513         | name, FUUID -> pr "  %s : string;\n" name
8514         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8515         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8516         | name, FChar -> pr "  %s : char;\n" name
8517         | name, FOptPercent -> pr "  %s : float option;\n" name
8518       ) cols;
8519       pr "}\n";
8520       pr "\n"
8521   ) structs
8522
8523 and generate_ocaml_prototype ?(is_external = false) name style =
8524   if is_external then pr "external " else pr "val ";
8525   pr "%s : t -> " name;
8526   List.iter (
8527     function
8528     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8529     | BufferIn _ -> pr "string -> "
8530     | OptString _ -> pr "string option -> "
8531     | StringList _ | DeviceList _ -> pr "string array -> "
8532     | Bool _ -> pr "bool -> "
8533     | Int _ -> pr "int -> "
8534     | Int64 _ -> pr "int64 -> "
8535   ) (snd style);
8536   (match fst style with
8537    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8538    | RInt _ -> pr "int"
8539    | RInt64 _ -> pr "int64"
8540    | RBool _ -> pr "bool"
8541    | RConstString _ -> pr "string"
8542    | RConstOptString _ -> pr "string option"
8543    | RString _ | RBufferOut _ -> pr "string"
8544    | RStringList _ -> pr "string array"
8545    | RStruct (_, typ) -> pr "%s" typ
8546    | RStructList (_, typ) -> pr "%s array" typ
8547    | RHashtable _ -> pr "(string * string) list"
8548   );
8549   if is_external then (
8550     pr " = ";
8551     if List.length (snd style) + 1 > 5 then
8552       pr "\"ocaml_guestfs_%s_byte\" " name;
8553     pr "\"ocaml_guestfs_%s\"" name
8554   );
8555   pr "\n"
8556
8557 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8558 and generate_perl_xs () =
8559   generate_header CStyle LGPLv2plus;
8560
8561   pr "\
8562 #include \"EXTERN.h\"
8563 #include \"perl.h\"
8564 #include \"XSUB.h\"
8565
8566 #include <guestfs.h>
8567
8568 #ifndef PRId64
8569 #define PRId64 \"lld\"
8570 #endif
8571
8572 static SV *
8573 my_newSVll(long long val) {
8574 #ifdef USE_64_BIT_ALL
8575   return newSViv(val);
8576 #else
8577   char buf[100];
8578   int len;
8579   len = snprintf(buf, 100, \"%%\" PRId64, val);
8580   return newSVpv(buf, len);
8581 #endif
8582 }
8583
8584 #ifndef PRIu64
8585 #define PRIu64 \"llu\"
8586 #endif
8587
8588 static SV *
8589 my_newSVull(unsigned long long val) {
8590 #ifdef USE_64_BIT_ALL
8591   return newSVuv(val);
8592 #else
8593   char buf[100];
8594   int len;
8595   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8596   return newSVpv(buf, len);
8597 #endif
8598 }
8599
8600 /* http://www.perlmonks.org/?node_id=680842 */
8601 static char **
8602 XS_unpack_charPtrPtr (SV *arg) {
8603   char **ret;
8604   AV *av;
8605   I32 i;
8606
8607   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8608     croak (\"array reference expected\");
8609
8610   av = (AV *)SvRV (arg);
8611   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8612   if (!ret)
8613     croak (\"malloc failed\");
8614
8615   for (i = 0; i <= av_len (av); i++) {
8616     SV **elem = av_fetch (av, i, 0);
8617
8618     if (!elem || !*elem)
8619       croak (\"missing element in list\");
8620
8621     ret[i] = SvPV_nolen (*elem);
8622   }
8623
8624   ret[i] = NULL;
8625
8626   return ret;
8627 }
8628
8629 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8630
8631 PROTOTYPES: ENABLE
8632
8633 guestfs_h *
8634 _create ()
8635    CODE:
8636       RETVAL = guestfs_create ();
8637       if (!RETVAL)
8638         croak (\"could not create guestfs handle\");
8639       guestfs_set_error_handler (RETVAL, NULL, NULL);
8640  OUTPUT:
8641       RETVAL
8642
8643 void
8644 DESTROY (g)
8645       guestfs_h *g;
8646  PPCODE:
8647       guestfs_close (g);
8648
8649 ";
8650
8651   List.iter (
8652     fun (name, style, _, _, _, _, _) ->
8653       (match fst style with
8654        | RErr -> pr "void\n"
8655        | RInt _ -> pr "SV *\n"
8656        | RInt64 _ -> pr "SV *\n"
8657        | RBool _ -> pr "SV *\n"
8658        | RConstString _ -> pr "SV *\n"
8659        | RConstOptString _ -> pr "SV *\n"
8660        | RString _ -> pr "SV *\n"
8661        | RBufferOut _ -> pr "SV *\n"
8662        | RStringList _
8663        | RStruct _ | RStructList _
8664        | RHashtable _ ->
8665            pr "void\n" (* all lists returned implictly on the stack *)
8666       );
8667       (* Call and arguments. *)
8668       pr "%s (g" name;
8669       List.iter (
8670         fun arg -> pr ", %s" (name_of_argt arg)
8671       ) (snd style);
8672       pr ")\n";
8673       pr "      guestfs_h *g;\n";
8674       iteri (
8675         fun i ->
8676           function
8677           | Pathname n | Device n | Dev_or_Path n | String n
8678           | FileIn n | FileOut n ->
8679               pr "      char *%s;\n" n
8680           | BufferIn n ->
8681               pr "      char *%s;\n" n;
8682               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8683           | OptString n ->
8684               (* http://www.perlmonks.org/?node_id=554277
8685                * Note that the implicit handle argument means we have
8686                * to add 1 to the ST(x) operator.
8687                *)
8688               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8689           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8690           | Bool n -> pr "      int %s;\n" n
8691           | Int n -> pr "      int %s;\n" n
8692           | Int64 n -> pr "      int64_t %s;\n" n
8693       ) (snd style);
8694
8695       let do_cleanups () =
8696         List.iter (
8697           function
8698           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8699           | Bool _ | Int _ | Int64 _
8700           | FileIn _ | FileOut _
8701           | BufferIn _ -> ()
8702           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8703         ) (snd style)
8704       in
8705
8706       (* Code. *)
8707       (match fst style with
8708        | RErr ->
8709            pr "PREINIT:\n";
8710            pr "      int r;\n";
8711            pr " PPCODE:\n";
8712            pr "      r = guestfs_%s " name;
8713            generate_c_call_args ~handle:"g" style;
8714            pr ";\n";
8715            do_cleanups ();
8716            pr "      if (r == -1)\n";
8717            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8718        | RInt n
8719        | RBool n ->
8720            pr "PREINIT:\n";
8721            pr "      int %s;\n" n;
8722            pr "   CODE:\n";
8723            pr "      %s = guestfs_%s " n name;
8724            generate_c_call_args ~handle:"g" style;
8725            pr ";\n";
8726            do_cleanups ();
8727            pr "      if (%s == -1)\n" n;
8728            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8729            pr "      RETVAL = newSViv (%s);\n" n;
8730            pr " OUTPUT:\n";
8731            pr "      RETVAL\n"
8732        | RInt64 n ->
8733            pr "PREINIT:\n";
8734            pr "      int64_t %s;\n" n;
8735            pr "   CODE:\n";
8736            pr "      %s = guestfs_%s " n name;
8737            generate_c_call_args ~handle:"g" style;
8738            pr ";\n";
8739            do_cleanups ();
8740            pr "      if (%s == -1)\n" n;
8741            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8742            pr "      RETVAL = my_newSVll (%s);\n" n;
8743            pr " OUTPUT:\n";
8744            pr "      RETVAL\n"
8745        | RConstString n ->
8746            pr "PREINIT:\n";
8747            pr "      const char *%s;\n" n;
8748            pr "   CODE:\n";
8749            pr "      %s = guestfs_%s " n name;
8750            generate_c_call_args ~handle:"g" style;
8751            pr ";\n";
8752            do_cleanups ();
8753            pr "      if (%s == NULL)\n" n;
8754            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8755            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8756            pr " OUTPUT:\n";
8757            pr "      RETVAL\n"
8758        | RConstOptString n ->
8759            pr "PREINIT:\n";
8760            pr "      const char *%s;\n" n;
8761            pr "   CODE:\n";
8762            pr "      %s = guestfs_%s " n name;
8763            generate_c_call_args ~handle:"g" style;
8764            pr ";\n";
8765            do_cleanups ();
8766            pr "      if (%s == NULL)\n" n;
8767            pr "        RETVAL = &PL_sv_undef;\n";
8768            pr "      else\n";
8769            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8770            pr " OUTPUT:\n";
8771            pr "      RETVAL\n"
8772        | RString n ->
8773            pr "PREINIT:\n";
8774            pr "      char *%s;\n" n;
8775            pr "   CODE:\n";
8776            pr "      %s = guestfs_%s " n name;
8777            generate_c_call_args ~handle:"g" style;
8778            pr ";\n";
8779            do_cleanups ();
8780            pr "      if (%s == NULL)\n" n;
8781            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8782            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8783            pr "      free (%s);\n" n;
8784            pr " OUTPUT:\n";
8785            pr "      RETVAL\n"
8786        | RStringList n | RHashtable n ->
8787            pr "PREINIT:\n";
8788            pr "      char **%s;\n" n;
8789            pr "      int i, n;\n";
8790            pr " PPCODE:\n";
8791            pr "      %s = guestfs_%s " n name;
8792            generate_c_call_args ~handle:"g" style;
8793            pr ";\n";
8794            do_cleanups ();
8795            pr "      if (%s == NULL)\n" n;
8796            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8797            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8798            pr "      EXTEND (SP, n);\n";
8799            pr "      for (i = 0; i < n; ++i) {\n";
8800            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8801            pr "        free (%s[i]);\n" n;
8802            pr "      }\n";
8803            pr "      free (%s);\n" n;
8804        | RStruct (n, typ) ->
8805            let cols = cols_of_struct typ in
8806            generate_perl_struct_code typ cols name style n do_cleanups
8807        | RStructList (n, typ) ->
8808            let cols = cols_of_struct typ in
8809            generate_perl_struct_list_code typ cols name style n do_cleanups
8810        | RBufferOut n ->
8811            pr "PREINIT:\n";
8812            pr "      char *%s;\n" n;
8813            pr "      size_t size;\n";
8814            pr "   CODE:\n";
8815            pr "      %s = guestfs_%s " n name;
8816            generate_c_call_args ~handle:"g" style;
8817            pr ";\n";
8818            do_cleanups ();
8819            pr "      if (%s == NULL)\n" n;
8820            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8821            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8822            pr "      free (%s);\n" n;
8823            pr " OUTPUT:\n";
8824            pr "      RETVAL\n"
8825       );
8826
8827       pr "\n"
8828   ) all_functions
8829
8830 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8831   pr "PREINIT:\n";
8832   pr "      struct guestfs_%s_list *%s;\n" typ n;
8833   pr "      int i;\n";
8834   pr "      HV *hv;\n";
8835   pr " PPCODE:\n";
8836   pr "      %s = guestfs_%s " n name;
8837   generate_c_call_args ~handle:"g" style;
8838   pr ";\n";
8839   do_cleanups ();
8840   pr "      if (%s == NULL)\n" n;
8841   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8842   pr "      EXTEND (SP, %s->len);\n" n;
8843   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8844   pr "        hv = newHV ();\n";
8845   List.iter (
8846     function
8847     | name, FString ->
8848         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8849           name (String.length name) n name
8850     | name, FUUID ->
8851         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8852           name (String.length name) n name
8853     | name, FBuffer ->
8854         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8855           name (String.length name) n name n name
8856     | name, (FBytes|FUInt64) ->
8857         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8858           name (String.length name) n name
8859     | name, FInt64 ->
8860         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8861           name (String.length name) n name
8862     | name, (FInt32|FUInt32) ->
8863         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8864           name (String.length name) n name
8865     | name, FChar ->
8866         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8867           name (String.length name) n name
8868     | name, FOptPercent ->
8869         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8870           name (String.length name) n name
8871   ) cols;
8872   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8873   pr "      }\n";
8874   pr "      guestfs_free_%s_list (%s);\n" typ n
8875
8876 and generate_perl_struct_code typ cols name style n do_cleanups =
8877   pr "PREINIT:\n";
8878   pr "      struct guestfs_%s *%s;\n" typ n;
8879   pr " PPCODE:\n";
8880   pr "      %s = guestfs_%s " n name;
8881   generate_c_call_args ~handle:"g" style;
8882   pr ";\n";
8883   do_cleanups ();
8884   pr "      if (%s == NULL)\n" n;
8885   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8886   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8887   List.iter (
8888     fun ((name, _) as col) ->
8889       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8890
8891       match col with
8892       | name, FString ->
8893           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8894             n name
8895       | name, FBuffer ->
8896           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8897             n name n name
8898       | name, FUUID ->
8899           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8900             n name
8901       | name, (FBytes|FUInt64) ->
8902           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8903             n name
8904       | name, FInt64 ->
8905           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8906             n name
8907       | name, (FInt32|FUInt32) ->
8908           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8909             n name
8910       | name, FChar ->
8911           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8912             n name
8913       | name, FOptPercent ->
8914           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8915             n name
8916   ) cols;
8917   pr "      free (%s);\n" n
8918
8919 (* Generate Sys/Guestfs.pm. *)
8920 and generate_perl_pm () =
8921   generate_header HashStyle LGPLv2plus;
8922
8923   pr "\
8924 =pod
8925
8926 =head1 NAME
8927
8928 Sys::Guestfs - Perl bindings for libguestfs
8929
8930 =head1 SYNOPSIS
8931
8932  use Sys::Guestfs;
8933
8934  my $h = Sys::Guestfs->new ();
8935  $h->add_drive ('guest.img');
8936  $h->launch ();
8937  $h->mount ('/dev/sda1', '/');
8938  $h->touch ('/hello');
8939  $h->sync ();
8940
8941 =head1 DESCRIPTION
8942
8943 The C<Sys::Guestfs> module provides a Perl XS binding to the
8944 libguestfs API for examining and modifying virtual machine
8945 disk images.
8946
8947 Amongst the things this is good for: making batch configuration
8948 changes to guests, getting disk used/free statistics (see also:
8949 virt-df), migrating between virtualization systems (see also:
8950 virt-p2v), performing partial backups, performing partial guest
8951 clones, cloning guests and changing registry/UUID/hostname info, and
8952 much else besides.
8953
8954 Libguestfs uses Linux kernel and qemu code, and can access any type of
8955 guest filesystem that Linux and qemu can, including but not limited
8956 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8957 schemes, qcow, qcow2, vmdk.
8958
8959 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8960 LVs, what filesystem is in each LV, etc.).  It can also run commands
8961 in the context of the guest.  Also you can access filesystems over
8962 FUSE.
8963
8964 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8965 functions for using libguestfs from Perl, including integration
8966 with libvirt.
8967
8968 =head1 ERRORS
8969
8970 All errors turn into calls to C<croak> (see L<Carp(3)>).
8971
8972 =head1 METHODS
8973
8974 =over 4
8975
8976 =cut
8977
8978 package Sys::Guestfs;
8979
8980 use strict;
8981 use warnings;
8982
8983 # This version number changes whenever a new function
8984 # is added to the libguestfs API.  It is not directly
8985 # related to the libguestfs version number.
8986 use vars qw($VERSION);
8987 $VERSION = '0.%d';
8988
8989 require XSLoader;
8990 XSLoader::load ('Sys::Guestfs');
8991
8992 =item $h = Sys::Guestfs->new ();
8993
8994 Create a new guestfs handle.
8995
8996 =cut
8997
8998 sub new {
8999   my $proto = shift;
9000   my $class = ref ($proto) || $proto;
9001
9002   my $self = Sys::Guestfs::_create ();
9003   bless $self, $class;
9004   return $self;
9005 }
9006
9007 " max_proc_nr;
9008
9009   (* Actions.  We only need to print documentation for these as
9010    * they are pulled in from the XS code automatically.
9011    *)
9012   List.iter (
9013     fun (name, style, _, flags, _, _, longdesc) ->
9014       if not (List.mem NotInDocs flags) then (
9015         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9016         pr "=item ";
9017         generate_perl_prototype name style;
9018         pr "\n\n";
9019         pr "%s\n\n" longdesc;
9020         if List.mem ProtocolLimitWarning flags then
9021           pr "%s\n\n" protocol_limit_warning;
9022         if List.mem DangerWillRobinson flags then
9023           pr "%s\n\n" danger_will_robinson;
9024         match deprecation_notice flags with
9025         | None -> ()
9026         | Some txt -> pr "%s\n\n" txt
9027       )
9028   ) all_functions_sorted;
9029
9030   (* End of file. *)
9031   pr "\
9032 =cut
9033
9034 1;
9035
9036 =back
9037
9038 =head1 COPYRIGHT
9039
9040 Copyright (C) %s Red Hat Inc.
9041
9042 =head1 LICENSE
9043
9044 Please see the file COPYING.LIB for the full license.
9045
9046 =head1 SEE ALSO
9047
9048 L<guestfs(3)>,
9049 L<guestfish(1)>,
9050 L<http://libguestfs.org>,
9051 L<Sys::Guestfs::Lib(3)>.
9052
9053 =cut
9054 " copyright_years
9055
9056 and generate_perl_prototype name style =
9057   (match fst style with
9058    | RErr -> ()
9059    | RBool n
9060    | RInt n
9061    | RInt64 n
9062    | RConstString n
9063    | RConstOptString n
9064    | RString n
9065    | RBufferOut n -> pr "$%s = " n
9066    | RStruct (n,_)
9067    | RHashtable n -> pr "%%%s = " n
9068    | RStringList n
9069    | RStructList (n,_) -> pr "@%s = " n
9070   );
9071   pr "$h->%s (" name;
9072   let comma = ref false in
9073   List.iter (
9074     fun arg ->
9075       if !comma then pr ", ";
9076       comma := true;
9077       match arg with
9078       | Pathname n | Device n | Dev_or_Path n | String n
9079       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9080       | BufferIn n ->
9081           pr "$%s" n
9082       | StringList n | DeviceList n ->
9083           pr "\\@%s" n
9084   ) (snd style);
9085   pr ");"
9086
9087 (* Generate Python C module. *)
9088 and generate_python_c () =
9089   generate_header CStyle LGPLv2plus;
9090
9091   pr "\
9092 #define PY_SSIZE_T_CLEAN 1
9093 #include <Python.h>
9094
9095 #include <stdio.h>
9096 #include <stdlib.h>
9097 #include <assert.h>
9098
9099 #include \"guestfs.h\"
9100
9101 typedef struct {
9102   PyObject_HEAD
9103   guestfs_h *g;
9104 } Pyguestfs_Object;
9105
9106 static guestfs_h *
9107 get_handle (PyObject *obj)
9108 {
9109   assert (obj);
9110   assert (obj != Py_None);
9111   return ((Pyguestfs_Object *) obj)->g;
9112 }
9113
9114 static PyObject *
9115 put_handle (guestfs_h *g)
9116 {
9117   assert (g);
9118   return
9119     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9120 }
9121
9122 /* This list should be freed (but not the strings) after use. */
9123 static char **
9124 get_string_list (PyObject *obj)
9125 {
9126   int i, len;
9127   char **r;
9128
9129   assert (obj);
9130
9131   if (!PyList_Check (obj)) {
9132     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9133     return NULL;
9134   }
9135
9136   len = PyList_Size (obj);
9137   r = malloc (sizeof (char *) * (len+1));
9138   if (r == NULL) {
9139     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9140     return NULL;
9141   }
9142
9143   for (i = 0; i < len; ++i)
9144     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9145   r[len] = NULL;
9146
9147   return r;
9148 }
9149
9150 static PyObject *
9151 put_string_list (char * const * const argv)
9152 {
9153   PyObject *list;
9154   int argc, i;
9155
9156   for (argc = 0; argv[argc] != NULL; ++argc)
9157     ;
9158
9159   list = PyList_New (argc);
9160   for (i = 0; i < argc; ++i)
9161     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9162
9163   return list;
9164 }
9165
9166 static PyObject *
9167 put_table (char * const * const argv)
9168 {
9169   PyObject *list, *item;
9170   int argc, i;
9171
9172   for (argc = 0; argv[argc] != NULL; ++argc)
9173     ;
9174
9175   list = PyList_New (argc >> 1);
9176   for (i = 0; i < argc; i += 2) {
9177     item = PyTuple_New (2);
9178     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9179     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9180     PyList_SetItem (list, i >> 1, item);
9181   }
9182
9183   return list;
9184 }
9185
9186 static void
9187 free_strings (char **argv)
9188 {
9189   int argc;
9190
9191   for (argc = 0; argv[argc] != NULL; ++argc)
9192     free (argv[argc]);
9193   free (argv);
9194 }
9195
9196 static PyObject *
9197 py_guestfs_create (PyObject *self, PyObject *args)
9198 {
9199   guestfs_h *g;
9200
9201   g = guestfs_create ();
9202   if (g == NULL) {
9203     PyErr_SetString (PyExc_RuntimeError,
9204                      \"guestfs.create: failed to allocate handle\");
9205     return NULL;
9206   }
9207   guestfs_set_error_handler (g, NULL, NULL);
9208   return put_handle (g);
9209 }
9210
9211 static PyObject *
9212 py_guestfs_close (PyObject *self, PyObject *args)
9213 {
9214   PyObject *py_g;
9215   guestfs_h *g;
9216
9217   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9218     return NULL;
9219   g = get_handle (py_g);
9220
9221   guestfs_close (g);
9222
9223   Py_INCREF (Py_None);
9224   return Py_None;
9225 }
9226
9227 ";
9228
9229   let emit_put_list_function typ =
9230     pr "static PyObject *\n";
9231     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9232     pr "{\n";
9233     pr "  PyObject *list;\n";
9234     pr "  int i;\n";
9235     pr "\n";
9236     pr "  list = PyList_New (%ss->len);\n" typ;
9237     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9238     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9239     pr "  return list;\n";
9240     pr "};\n";
9241     pr "\n"
9242   in
9243
9244   (* Structures, turned into Python dictionaries. *)
9245   List.iter (
9246     fun (typ, cols) ->
9247       pr "static PyObject *\n";
9248       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9249       pr "{\n";
9250       pr "  PyObject *dict;\n";
9251       pr "\n";
9252       pr "  dict = PyDict_New ();\n";
9253       List.iter (
9254         function
9255         | name, FString ->
9256             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9257             pr "                        PyString_FromString (%s->%s));\n"
9258               typ name
9259         | name, FBuffer ->
9260             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9261             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9262               typ name typ name
9263         | name, FUUID ->
9264             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9265             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9266               typ name
9267         | name, (FBytes|FUInt64) ->
9268             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9269             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9270               typ name
9271         | name, FInt64 ->
9272             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9273             pr "                        PyLong_FromLongLong (%s->%s));\n"
9274               typ name
9275         | name, FUInt32 ->
9276             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9277             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9278               typ name
9279         | name, FInt32 ->
9280             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9281             pr "                        PyLong_FromLong (%s->%s));\n"
9282               typ name
9283         | name, FOptPercent ->
9284             pr "  if (%s->%s >= 0)\n" typ name;
9285             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9286             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9287               typ name;
9288             pr "  else {\n";
9289             pr "    Py_INCREF (Py_None);\n";
9290             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9291             pr "  }\n"
9292         | name, FChar ->
9293             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9294             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9295       ) cols;
9296       pr "  return dict;\n";
9297       pr "};\n";
9298       pr "\n";
9299
9300   ) structs;
9301
9302   (* Emit a put_TYPE_list function definition only if that function is used. *)
9303   List.iter (
9304     function
9305     | typ, (RStructListOnly | RStructAndList) ->
9306         (* generate the function for typ *)
9307         emit_put_list_function typ
9308     | typ, _ -> () (* empty *)
9309   ) (rstructs_used_by all_functions);
9310
9311   (* Python wrapper functions. *)
9312   List.iter (
9313     fun (name, style, _, _, _, _, _) ->
9314       pr "static PyObject *\n";
9315       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9316       pr "{\n";
9317
9318       pr "  PyObject *py_g;\n";
9319       pr "  guestfs_h *g;\n";
9320       pr "  PyObject *py_r;\n";
9321
9322       let error_code =
9323         match fst style with
9324         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9325         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9326         | RConstString _ | RConstOptString _ ->
9327             pr "  const char *r;\n"; "NULL"
9328         | RString _ -> pr "  char *r;\n"; "NULL"
9329         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9330         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9331         | RStructList (_, typ) ->
9332             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9333         | RBufferOut _ ->
9334             pr "  char *r;\n";
9335             pr "  size_t size;\n";
9336             "NULL" in
9337
9338       List.iter (
9339         function
9340         | Pathname n | Device n | Dev_or_Path n | String n
9341         | FileIn n | FileOut n ->
9342             pr "  const char *%s;\n" n
9343         | OptString n -> pr "  const char *%s;\n" n
9344         | BufferIn n ->
9345             pr "  const char *%s;\n" n;
9346             pr "  Py_ssize_t %s_size;\n" n
9347         | StringList n | DeviceList n ->
9348             pr "  PyObject *py_%s;\n" n;
9349             pr "  char **%s;\n" n
9350         | Bool n -> pr "  int %s;\n" n
9351         | Int n -> pr "  int %s;\n" n
9352         | Int64 n -> pr "  long long %s;\n" n
9353       ) (snd style);
9354
9355       pr "\n";
9356
9357       (* Convert the parameters. *)
9358       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9359       List.iter (
9360         function
9361         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9362         | OptString _ -> pr "z"
9363         | StringList _ | DeviceList _ -> pr "O"
9364         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9365         | Int _ -> pr "i"
9366         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9367                              * emulate C's int/long/long long in Python?
9368                              *)
9369         | BufferIn _ -> pr "s#"
9370       ) (snd style);
9371       pr ":guestfs_%s\",\n" name;
9372       pr "                         &py_g";
9373       List.iter (
9374         function
9375         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9376         | OptString n -> pr ", &%s" n
9377         | StringList n | DeviceList n -> pr ", &py_%s" n
9378         | Bool n -> pr ", &%s" n
9379         | Int n -> pr ", &%s" n
9380         | Int64 n -> pr ", &%s" n
9381         | BufferIn n -> pr ", &%s, &%s_size" n n
9382       ) (snd style);
9383
9384       pr "))\n";
9385       pr "    return NULL;\n";
9386
9387       pr "  g = get_handle (py_g);\n";
9388       List.iter (
9389         function
9390         | Pathname _ | Device _ | Dev_or_Path _ | String _
9391         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9392         | BufferIn _ -> ()
9393         | StringList n | DeviceList n ->
9394             pr "  %s = get_string_list (py_%s);\n" n n;
9395             pr "  if (!%s) return NULL;\n" n
9396       ) (snd style);
9397
9398       pr "\n";
9399
9400       pr "  r = guestfs_%s " name;
9401       generate_c_call_args ~handle:"g" style;
9402       pr ";\n";
9403
9404       List.iter (
9405         function
9406         | Pathname _ | Device _ | Dev_or_Path _ | String _
9407         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9408         | BufferIn _ -> ()
9409         | StringList n | DeviceList n ->
9410             pr "  free (%s);\n" n
9411       ) (snd style);
9412
9413       pr "  if (r == %s) {\n" error_code;
9414       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9415       pr "    return NULL;\n";
9416       pr "  }\n";
9417       pr "\n";
9418
9419       (match fst style with
9420        | RErr ->
9421            pr "  Py_INCREF (Py_None);\n";
9422            pr "  py_r = Py_None;\n"
9423        | RInt _
9424        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9425        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9426        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9427        | RConstOptString _ ->
9428            pr "  if (r)\n";
9429            pr "    py_r = PyString_FromString (r);\n";
9430            pr "  else {\n";
9431            pr "    Py_INCREF (Py_None);\n";
9432            pr "    py_r = Py_None;\n";
9433            pr "  }\n"
9434        | RString _ ->
9435            pr "  py_r = PyString_FromString (r);\n";
9436            pr "  free (r);\n"
9437        | RStringList _ ->
9438            pr "  py_r = put_string_list (r);\n";
9439            pr "  free_strings (r);\n"
9440        | RStruct (_, typ) ->
9441            pr "  py_r = put_%s (r);\n" typ;
9442            pr "  guestfs_free_%s (r);\n" typ
9443        | RStructList (_, typ) ->
9444            pr "  py_r = put_%s_list (r);\n" typ;
9445            pr "  guestfs_free_%s_list (r);\n" typ
9446        | RHashtable n ->
9447            pr "  py_r = put_table (r);\n";
9448            pr "  free_strings (r);\n"
9449        | RBufferOut _ ->
9450            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9451            pr "  free (r);\n"
9452       );
9453
9454       pr "  return py_r;\n";
9455       pr "}\n";
9456       pr "\n"
9457   ) all_functions;
9458
9459   (* Table of functions. *)
9460   pr "static PyMethodDef methods[] = {\n";
9461   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9462   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9463   List.iter (
9464     fun (name, _, _, _, _, _, _) ->
9465       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9466         name name
9467   ) all_functions;
9468   pr "  { NULL, NULL, 0, NULL }\n";
9469   pr "};\n";
9470   pr "\n";
9471
9472   (* Init function. *)
9473   pr "\
9474 void
9475 initlibguestfsmod (void)
9476 {
9477   static int initialized = 0;
9478
9479   if (initialized) return;
9480   Py_InitModule ((char *) \"libguestfsmod\", methods);
9481   initialized = 1;
9482 }
9483 "
9484
9485 (* Generate Python module. *)
9486 and generate_python_py () =
9487   generate_header HashStyle LGPLv2plus;
9488
9489   pr "\
9490 u\"\"\"Python bindings for libguestfs
9491
9492 import guestfs
9493 g = guestfs.GuestFS ()
9494 g.add_drive (\"guest.img\")
9495 g.launch ()
9496 parts = g.list_partitions ()
9497
9498 The guestfs module provides a Python binding to the libguestfs API
9499 for examining and modifying virtual machine disk images.
9500
9501 Amongst the things this is good for: making batch configuration
9502 changes to guests, getting disk used/free statistics (see also:
9503 virt-df), migrating between virtualization systems (see also:
9504 virt-p2v), performing partial backups, performing partial guest
9505 clones, cloning guests and changing registry/UUID/hostname info, and
9506 much else besides.
9507
9508 Libguestfs uses Linux kernel and qemu code, and can access any type of
9509 guest filesystem that Linux and qemu can, including but not limited
9510 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9511 schemes, qcow, qcow2, vmdk.
9512
9513 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9514 LVs, what filesystem is in each LV, etc.).  It can also run commands
9515 in the context of the guest.  Also you can access filesystems over
9516 FUSE.
9517
9518 Errors which happen while using the API are turned into Python
9519 RuntimeError exceptions.
9520
9521 To create a guestfs handle you usually have to perform the following
9522 sequence of calls:
9523
9524 # Create the handle, call add_drive at least once, and possibly
9525 # several times if the guest has multiple block devices:
9526 g = guestfs.GuestFS ()
9527 g.add_drive (\"guest.img\")
9528
9529 # Launch the qemu subprocess and wait for it to become ready:
9530 g.launch ()
9531
9532 # Now you can issue commands, for example:
9533 logvols = g.lvs ()
9534
9535 \"\"\"
9536
9537 import libguestfsmod
9538
9539 class GuestFS:
9540     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9541
9542     def __init__ (self):
9543         \"\"\"Create a new libguestfs handle.\"\"\"
9544         self._o = libguestfsmod.create ()
9545
9546     def __del__ (self):
9547         libguestfsmod.close (self._o)
9548
9549 ";
9550
9551   List.iter (
9552     fun (name, style, _, flags, _, _, longdesc) ->
9553       pr "    def %s " name;
9554       generate_py_call_args ~handle:"self" (snd style);
9555       pr ":\n";
9556
9557       if not (List.mem NotInDocs flags) then (
9558         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9559         let doc =
9560           match fst style with
9561           | RErr | RInt _ | RInt64 _ | RBool _
9562           | RConstOptString _ | RConstString _
9563           | RString _ | RBufferOut _ -> doc
9564           | RStringList _ ->
9565               doc ^ "\n\nThis function returns a list of strings."
9566           | RStruct (_, typ) ->
9567               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9568           | RStructList (_, typ) ->
9569               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9570           | RHashtable _ ->
9571               doc ^ "\n\nThis function returns a dictionary." in
9572         let doc =
9573           if List.mem ProtocolLimitWarning flags then
9574             doc ^ "\n\n" ^ protocol_limit_warning
9575           else doc in
9576         let doc =
9577           if List.mem DangerWillRobinson flags then
9578             doc ^ "\n\n" ^ danger_will_robinson
9579           else doc in
9580         let doc =
9581           match deprecation_notice flags with
9582           | None -> doc
9583           | Some txt -> doc ^ "\n\n" ^ txt in
9584         let doc = pod2text ~width:60 name doc in
9585         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9586         let doc = String.concat "\n        " doc in
9587         pr "        u\"\"\"%s\"\"\"\n" doc;
9588       );
9589       pr "        return libguestfsmod.%s " name;
9590       generate_py_call_args ~handle:"self._o" (snd style);
9591       pr "\n";
9592       pr "\n";
9593   ) all_functions
9594
9595 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9596 and generate_py_call_args ~handle args =
9597   pr "(%s" handle;
9598   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9599   pr ")"
9600
9601 (* Useful if you need the longdesc POD text as plain text.  Returns a
9602  * list of lines.
9603  *
9604  * Because this is very slow (the slowest part of autogeneration),
9605  * we memoize the results.
9606  *)
9607 and pod2text ~width name longdesc =
9608   let key = width, name, longdesc in
9609   try Hashtbl.find pod2text_memo key
9610   with Not_found ->
9611     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9612     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9613     close_out chan;
9614     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9615     let chan = open_process_in cmd in
9616     let lines = ref [] in
9617     let rec loop i =
9618       let line = input_line chan in
9619       if i = 1 then             (* discard the first line of output *)
9620         loop (i+1)
9621       else (
9622         let line = triml line in
9623         lines := line :: !lines;
9624         loop (i+1)
9625       ) in
9626     let lines = try loop 1 with End_of_file -> List.rev !lines in
9627     unlink filename;
9628     (match close_process_in chan with
9629      | WEXITED 0 -> ()
9630      | WEXITED i ->
9631          failwithf "pod2text: process exited with non-zero status (%d)" i
9632      | WSIGNALED i | WSTOPPED i ->
9633          failwithf "pod2text: process signalled or stopped by signal %d" i
9634     );
9635     Hashtbl.add pod2text_memo key lines;
9636     pod2text_memo_updated ();
9637     lines
9638
9639 (* Generate ruby bindings. *)
9640 and generate_ruby_c () =
9641   generate_header CStyle LGPLv2plus;
9642
9643   pr "\
9644 #include <stdio.h>
9645 #include <stdlib.h>
9646
9647 #include <ruby.h>
9648
9649 #include \"guestfs.h\"
9650
9651 #include \"extconf.h\"
9652
9653 /* For Ruby < 1.9 */
9654 #ifndef RARRAY_LEN
9655 #define RARRAY_LEN(r) (RARRAY((r))->len)
9656 #endif
9657
9658 static VALUE m_guestfs;                 /* guestfs module */
9659 static VALUE c_guestfs;                 /* guestfs_h handle */
9660 static VALUE e_Error;                   /* used for all errors */
9661
9662 static void ruby_guestfs_free (void *p)
9663 {
9664   if (!p) return;
9665   guestfs_close ((guestfs_h *) p);
9666 }
9667
9668 static VALUE ruby_guestfs_create (VALUE m)
9669 {
9670   guestfs_h *g;
9671
9672   g = guestfs_create ();
9673   if (!g)
9674     rb_raise (e_Error, \"failed to create guestfs handle\");
9675
9676   /* Don't print error messages to stderr by default. */
9677   guestfs_set_error_handler (g, NULL, NULL);
9678
9679   /* Wrap it, and make sure the close function is called when the
9680    * handle goes away.
9681    */
9682   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9683 }
9684
9685 static VALUE ruby_guestfs_close (VALUE gv)
9686 {
9687   guestfs_h *g;
9688   Data_Get_Struct (gv, guestfs_h, g);
9689
9690   ruby_guestfs_free (g);
9691   DATA_PTR (gv) = NULL;
9692
9693   return Qnil;
9694 }
9695
9696 ";
9697
9698   List.iter (
9699     fun (name, style, _, _, _, _, _) ->
9700       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9701       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9702       pr ")\n";
9703       pr "{\n";
9704       pr "  guestfs_h *g;\n";
9705       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9706       pr "  if (!g)\n";
9707       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9708         name;
9709       pr "\n";
9710
9711       List.iter (
9712         function
9713         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9714             pr "  Check_Type (%sv, T_STRING);\n" n;
9715             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9716             pr "  if (!%s)\n" n;
9717             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9718             pr "              \"%s\", \"%s\");\n" n name
9719         | BufferIn n ->
9720             pr "  Check_Type (%sv, T_STRING);\n" n;
9721             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9722             pr "  if (!%s)\n" n;
9723             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9724             pr "              \"%s\", \"%s\");\n" n name;
9725             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9726         | OptString n ->
9727             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9728         | StringList n | DeviceList n ->
9729             pr "  char **%s;\n" n;
9730             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9731             pr "  {\n";
9732             pr "    int i, len;\n";
9733             pr "    len = RARRAY_LEN (%sv);\n" n;
9734             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9735               n;
9736             pr "    for (i = 0; i < len; ++i) {\n";
9737             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9738             pr "      %s[i] = StringValueCStr (v);\n" n;
9739             pr "    }\n";
9740             pr "    %s[len] = NULL;\n" n;
9741             pr "  }\n";
9742         | Bool n ->
9743             pr "  int %s = RTEST (%sv);\n" n n
9744         | Int n ->
9745             pr "  int %s = NUM2INT (%sv);\n" n n
9746         | Int64 n ->
9747             pr "  long long %s = NUM2LL (%sv);\n" n n
9748       ) (snd style);
9749       pr "\n";
9750
9751       let error_code =
9752         match fst style with
9753         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9754         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9755         | RConstString _ | RConstOptString _ ->
9756             pr "  const char *r;\n"; "NULL"
9757         | RString _ -> pr "  char *r;\n"; "NULL"
9758         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9759         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9760         | RStructList (_, typ) ->
9761             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9762         | RBufferOut _ ->
9763             pr "  char *r;\n";
9764             pr "  size_t size;\n";
9765             "NULL" in
9766       pr "\n";
9767
9768       pr "  r = guestfs_%s " name;
9769       generate_c_call_args ~handle:"g" style;
9770       pr ";\n";
9771
9772       List.iter (
9773         function
9774         | Pathname _ | Device _ | Dev_or_Path _ | String _
9775         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9776         | BufferIn _ -> ()
9777         | StringList n | DeviceList n ->
9778             pr "  free (%s);\n" n
9779       ) (snd style);
9780
9781       pr "  if (r == %s)\n" error_code;
9782       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9783       pr "\n";
9784
9785       (match fst style with
9786        | RErr ->
9787            pr "  return Qnil;\n"
9788        | RInt _ | RBool _ ->
9789            pr "  return INT2NUM (r);\n"
9790        | RInt64 _ ->
9791            pr "  return ULL2NUM (r);\n"
9792        | RConstString _ ->
9793            pr "  return rb_str_new2 (r);\n";
9794        | RConstOptString _ ->
9795            pr "  if (r)\n";
9796            pr "    return rb_str_new2 (r);\n";
9797            pr "  else\n";
9798            pr "    return Qnil;\n";
9799        | RString _ ->
9800            pr "  VALUE rv = rb_str_new2 (r);\n";
9801            pr "  free (r);\n";
9802            pr "  return rv;\n";
9803        | RStringList _ ->
9804            pr "  int i, len = 0;\n";
9805            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9806            pr "  VALUE rv = rb_ary_new2 (len);\n";
9807            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9808            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9809            pr "    free (r[i]);\n";
9810            pr "  }\n";
9811            pr "  free (r);\n";
9812            pr "  return rv;\n"
9813        | RStruct (_, typ) ->
9814            let cols = cols_of_struct typ in
9815            generate_ruby_struct_code typ cols
9816        | RStructList (_, typ) ->
9817            let cols = cols_of_struct typ in
9818            generate_ruby_struct_list_code typ cols
9819        | RHashtable _ ->
9820            pr "  VALUE rv = rb_hash_new ();\n";
9821            pr "  int i;\n";
9822            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9823            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9824            pr "    free (r[i]);\n";
9825            pr "    free (r[i+1]);\n";
9826            pr "  }\n";
9827            pr "  free (r);\n";
9828            pr "  return rv;\n"
9829        | RBufferOut _ ->
9830            pr "  VALUE rv = rb_str_new (r, size);\n";
9831            pr "  free (r);\n";
9832            pr "  return rv;\n";
9833       );
9834
9835       pr "}\n";
9836       pr "\n"
9837   ) all_functions;
9838
9839   pr "\
9840 /* Initialize the module. */
9841 void Init__guestfs ()
9842 {
9843   m_guestfs = rb_define_module (\"Guestfs\");
9844   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9845   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9846
9847   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9848   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9849
9850 ";
9851   (* Define the rest of the methods. *)
9852   List.iter (
9853     fun (name, style, _, _, _, _, _) ->
9854       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9855       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9856   ) all_functions;
9857
9858   pr "}\n"
9859
9860 (* Ruby code to return a struct. *)
9861 and generate_ruby_struct_code typ cols =
9862   pr "  VALUE rv = rb_hash_new ();\n";
9863   List.iter (
9864     function
9865     | name, FString ->
9866         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9867     | name, FBuffer ->
9868         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9869     | name, FUUID ->
9870         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9871     | name, (FBytes|FUInt64) ->
9872         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9873     | name, FInt64 ->
9874         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9875     | name, FUInt32 ->
9876         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9877     | name, FInt32 ->
9878         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9879     | name, FOptPercent ->
9880         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9881     | name, FChar -> (* XXX wrong? *)
9882         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9883   ) cols;
9884   pr "  guestfs_free_%s (r);\n" typ;
9885   pr "  return rv;\n"
9886
9887 (* Ruby code to return a struct list. *)
9888 and generate_ruby_struct_list_code typ cols =
9889   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9890   pr "  int i;\n";
9891   pr "  for (i = 0; i < r->len; ++i) {\n";
9892   pr "    VALUE hv = rb_hash_new ();\n";
9893   List.iter (
9894     function
9895     | name, FString ->
9896         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9897     | name, FBuffer ->
9898         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
9899     | name, FUUID ->
9900         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9901     | name, (FBytes|FUInt64) ->
9902         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9903     | name, FInt64 ->
9904         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9905     | name, FUInt32 ->
9906         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9907     | name, FInt32 ->
9908         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9909     | name, FOptPercent ->
9910         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9911     | name, FChar -> (* XXX wrong? *)
9912         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9913   ) cols;
9914   pr "    rb_ary_push (rv, hv);\n";
9915   pr "  }\n";
9916   pr "  guestfs_free_%s_list (r);\n" typ;
9917   pr "  return rv;\n"
9918
9919 (* Generate Java bindings GuestFS.java file. *)
9920 and generate_java_java () =
9921   generate_header CStyle LGPLv2plus;
9922
9923   pr "\
9924 package com.redhat.et.libguestfs;
9925
9926 import java.util.HashMap;
9927 import com.redhat.et.libguestfs.LibGuestFSException;
9928 import com.redhat.et.libguestfs.PV;
9929 import com.redhat.et.libguestfs.VG;
9930 import com.redhat.et.libguestfs.LV;
9931 import com.redhat.et.libguestfs.Stat;
9932 import com.redhat.et.libguestfs.StatVFS;
9933 import com.redhat.et.libguestfs.IntBool;
9934 import com.redhat.et.libguestfs.Dirent;
9935
9936 /**
9937  * The GuestFS object is a libguestfs handle.
9938  *
9939  * @author rjones
9940  */
9941 public class GuestFS {
9942   // Load the native code.
9943   static {
9944     System.loadLibrary (\"guestfs_jni\");
9945   }
9946
9947   /**
9948    * The native guestfs_h pointer.
9949    */
9950   long g;
9951
9952   /**
9953    * Create a libguestfs handle.
9954    *
9955    * @throws LibGuestFSException
9956    */
9957   public GuestFS () throws LibGuestFSException
9958   {
9959     g = _create ();
9960   }
9961   private native long _create () throws LibGuestFSException;
9962
9963   /**
9964    * Close a libguestfs handle.
9965    *
9966    * You can also leave handles to be collected by the garbage
9967    * collector, but this method ensures that the resources used
9968    * by the handle are freed up immediately.  If you call any
9969    * other methods after closing the handle, you will get an
9970    * exception.
9971    *
9972    * @throws LibGuestFSException
9973    */
9974   public void close () throws LibGuestFSException
9975   {
9976     if (g != 0)
9977       _close (g);
9978     g = 0;
9979   }
9980   private native void _close (long g) throws LibGuestFSException;
9981
9982   public void finalize () throws LibGuestFSException
9983   {
9984     close ();
9985   }
9986
9987 ";
9988
9989   List.iter (
9990     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9991       if not (List.mem NotInDocs flags); then (
9992         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9993         let doc =
9994           if List.mem ProtocolLimitWarning flags then
9995             doc ^ "\n\n" ^ protocol_limit_warning
9996           else doc in
9997         let doc =
9998           if List.mem DangerWillRobinson flags then
9999             doc ^ "\n\n" ^ danger_will_robinson
10000           else doc in
10001         let doc =
10002           match deprecation_notice flags with
10003           | None -> doc
10004           | Some txt -> doc ^ "\n\n" ^ txt in
10005         let doc = pod2text ~width:60 name doc in
10006         let doc = List.map (            (* RHBZ#501883 *)
10007           function
10008           | "" -> "<p>"
10009           | nonempty -> nonempty
10010         ) doc in
10011         let doc = String.concat "\n   * " doc in
10012
10013         pr "  /**\n";
10014         pr "   * %s\n" shortdesc;
10015         pr "   * <p>\n";
10016         pr "   * %s\n" doc;
10017         pr "   * @throws LibGuestFSException\n";
10018         pr "   */\n";
10019         pr "  ";
10020       );
10021       generate_java_prototype ~public:true ~semicolon:false name style;
10022       pr "\n";
10023       pr "  {\n";
10024       pr "    if (g == 0)\n";
10025       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10026         name;
10027       pr "    ";
10028       if fst style <> RErr then pr "return ";
10029       pr "_%s " name;
10030       generate_java_call_args ~handle:"g" (snd style);
10031       pr ";\n";
10032       pr "  }\n";
10033       pr "  ";
10034       generate_java_prototype ~privat:true ~native:true name style;
10035       pr "\n";
10036       pr "\n";
10037   ) all_functions;
10038
10039   pr "}\n"
10040
10041 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10042 and generate_java_call_args ~handle args =
10043   pr "(%s" handle;
10044   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10045   pr ")"
10046
10047 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10048     ?(semicolon=true) name style =
10049   if privat then pr "private ";
10050   if public then pr "public ";
10051   if native then pr "native ";
10052
10053   (* return type *)
10054   (match fst style with
10055    | RErr -> pr "void ";
10056    | RInt _ -> pr "int ";
10057    | RInt64 _ -> pr "long ";
10058    | RBool _ -> pr "boolean ";
10059    | RConstString _ | RConstOptString _ | RString _
10060    | RBufferOut _ -> pr "String ";
10061    | RStringList _ -> pr "String[] ";
10062    | RStruct (_, typ) ->
10063        let name = java_name_of_struct typ in
10064        pr "%s " name;
10065    | RStructList (_, typ) ->
10066        let name = java_name_of_struct typ in
10067        pr "%s[] " name;
10068    | RHashtable _ -> pr "HashMap<String,String> ";
10069   );
10070
10071   if native then pr "_%s " name else pr "%s " name;
10072   pr "(";
10073   let needs_comma = ref false in
10074   if native then (
10075     pr "long g";
10076     needs_comma := true
10077   );
10078
10079   (* args *)
10080   List.iter (
10081     fun arg ->
10082       if !needs_comma then pr ", ";
10083       needs_comma := true;
10084
10085       match arg with
10086       | Pathname n
10087       | Device n | Dev_or_Path n
10088       | String n
10089       | OptString n
10090       | FileIn n
10091       | FileOut n ->
10092           pr "String %s" n
10093       | BufferIn n ->
10094           pr "byte[] %s" n
10095       | StringList n | DeviceList n ->
10096           pr "String[] %s" n
10097       | Bool n ->
10098           pr "boolean %s" n
10099       | Int n ->
10100           pr "int %s" n
10101       | Int64 n ->
10102           pr "long %s" n
10103   ) (snd style);
10104
10105   pr ")\n";
10106   pr "    throws LibGuestFSException";
10107   if semicolon then pr ";"
10108
10109 and generate_java_struct jtyp cols () =
10110   generate_header CStyle LGPLv2plus;
10111
10112   pr "\
10113 package com.redhat.et.libguestfs;
10114
10115 /**
10116  * Libguestfs %s structure.
10117  *
10118  * @author rjones
10119  * @see GuestFS
10120  */
10121 public class %s {
10122 " jtyp jtyp;
10123
10124   List.iter (
10125     function
10126     | name, FString
10127     | name, FUUID
10128     | name, FBuffer -> pr "  public String %s;\n" name
10129     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10130     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10131     | name, FChar -> pr "  public char %s;\n" name
10132     | name, FOptPercent ->
10133         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10134         pr "  public float %s;\n" name
10135   ) cols;
10136
10137   pr "}\n"
10138
10139 and generate_java_c () =
10140   generate_header CStyle LGPLv2plus;
10141
10142   pr "\
10143 #include <stdio.h>
10144 #include <stdlib.h>
10145 #include <string.h>
10146
10147 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10148 #include \"guestfs.h\"
10149
10150 /* Note that this function returns.  The exception is not thrown
10151  * until after the wrapper function returns.
10152  */
10153 static void
10154 throw_exception (JNIEnv *env, const char *msg)
10155 {
10156   jclass cl;
10157   cl = (*env)->FindClass (env,
10158                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10159   (*env)->ThrowNew (env, cl, msg);
10160 }
10161
10162 JNIEXPORT jlong JNICALL
10163 Java_com_redhat_et_libguestfs_GuestFS__1create
10164   (JNIEnv *env, jobject obj)
10165 {
10166   guestfs_h *g;
10167
10168   g = guestfs_create ();
10169   if (g == NULL) {
10170     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10171     return 0;
10172   }
10173   guestfs_set_error_handler (g, NULL, NULL);
10174   return (jlong) (long) g;
10175 }
10176
10177 JNIEXPORT void JNICALL
10178 Java_com_redhat_et_libguestfs_GuestFS__1close
10179   (JNIEnv *env, jobject obj, jlong jg)
10180 {
10181   guestfs_h *g = (guestfs_h *) (long) jg;
10182   guestfs_close (g);
10183 }
10184
10185 ";
10186
10187   List.iter (
10188     fun (name, style, _, _, _, _, _) ->
10189       pr "JNIEXPORT ";
10190       (match fst style with
10191        | RErr -> pr "void ";
10192        | RInt _ -> pr "jint ";
10193        | RInt64 _ -> pr "jlong ";
10194        | RBool _ -> pr "jboolean ";
10195        | RConstString _ | RConstOptString _ | RString _
10196        | RBufferOut _ -> pr "jstring ";
10197        | RStruct _ | RHashtable _ ->
10198            pr "jobject ";
10199        | RStringList _ | RStructList _ ->
10200            pr "jobjectArray ";
10201       );
10202       pr "JNICALL\n";
10203       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10204       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10205       pr "\n";
10206       pr "  (JNIEnv *env, jobject obj, jlong jg";
10207       List.iter (
10208         function
10209         | Pathname n
10210         | Device n | Dev_or_Path n
10211         | String n
10212         | OptString n
10213         | FileIn n
10214         | FileOut n ->
10215             pr ", jstring j%s" n
10216         | BufferIn n ->
10217             pr ", jbyteArray j%s" n
10218         | StringList n | DeviceList n ->
10219             pr ", jobjectArray j%s" n
10220         | Bool n ->
10221             pr ", jboolean j%s" n
10222         | Int n ->
10223             pr ", jint j%s" n
10224         | Int64 n ->
10225             pr ", jlong j%s" n
10226       ) (snd style);
10227       pr ")\n";
10228       pr "{\n";
10229       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10230       let error_code, no_ret =
10231         match fst style with
10232         | RErr -> pr "  int r;\n"; "-1", ""
10233         | RBool _
10234         | RInt _ -> pr "  int r;\n"; "-1", "0"
10235         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10236         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10237         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10238         | RString _ ->
10239             pr "  jstring jr;\n";
10240             pr "  char *r;\n"; "NULL", "NULL"
10241         | RStringList _ ->
10242             pr "  jobjectArray jr;\n";
10243             pr "  int r_len;\n";
10244             pr "  jclass cl;\n";
10245             pr "  jstring jstr;\n";
10246             pr "  char **r;\n"; "NULL", "NULL"
10247         | RStruct (_, typ) ->
10248             pr "  jobject jr;\n";
10249             pr "  jclass cl;\n";
10250             pr "  jfieldID fl;\n";
10251             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10252         | RStructList (_, typ) ->
10253             pr "  jobjectArray jr;\n";
10254             pr "  jclass cl;\n";
10255             pr "  jfieldID fl;\n";
10256             pr "  jobject jfl;\n";
10257             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10258         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10259         | RBufferOut _ ->
10260             pr "  jstring jr;\n";
10261             pr "  char *r;\n";
10262             pr "  size_t size;\n";
10263             "NULL", "NULL" in
10264       List.iter (
10265         function
10266         | Pathname n
10267         | Device n | Dev_or_Path n
10268         | String n
10269         | OptString n
10270         | FileIn n
10271         | FileOut n ->
10272             pr "  const char *%s;\n" n
10273         | BufferIn n ->
10274             pr "  jbyte *%s;\n" n;
10275             pr "  size_t %s_size;\n" n
10276         | StringList n | DeviceList n ->
10277             pr "  int %s_len;\n" n;
10278             pr "  const char **%s;\n" n
10279         | Bool n
10280         | Int n ->
10281             pr "  int %s;\n" n
10282         | Int64 n ->
10283             pr "  int64_t %s;\n" n
10284       ) (snd style);
10285
10286       let needs_i =
10287         (match fst style with
10288          | RStringList _ | RStructList _ -> true
10289          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10290          | RConstOptString _
10291          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10292           List.exists (function
10293                        | StringList _ -> true
10294                        | DeviceList _ -> true
10295                        | _ -> false) (snd style) in
10296       if needs_i then
10297         pr "  int i;\n";
10298
10299       pr "\n";
10300
10301       (* Get the parameters. *)
10302       List.iter (
10303         function
10304         | Pathname n
10305         | Device n | Dev_or_Path n
10306         | String n
10307         | FileIn n
10308         | FileOut n ->
10309             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10310         | OptString n ->
10311             (* This is completely undocumented, but Java null becomes
10312              * a NULL parameter.
10313              *)
10314             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10315         | BufferIn n ->
10316             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10317             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10318         | StringList n | DeviceList n ->
10319             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10320             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10321             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10322             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10323               n;
10324             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10325             pr "  }\n";
10326             pr "  %s[%s_len] = NULL;\n" n n;
10327         | Bool n
10328         | Int n
10329         | Int64 n ->
10330             pr "  %s = j%s;\n" n n
10331       ) (snd style);
10332
10333       (* Make the call. *)
10334       pr "  r = guestfs_%s " name;
10335       generate_c_call_args ~handle:"g" style;
10336       pr ";\n";
10337
10338       (* Release the parameters. *)
10339       List.iter (
10340         function
10341         | Pathname n
10342         | Device n | Dev_or_Path n
10343         | String n
10344         | FileIn n
10345         | FileOut n ->
10346             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10347         | OptString n ->
10348             pr "  if (j%s)\n" n;
10349             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10350         | BufferIn n ->
10351             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10352         | StringList n | DeviceList n ->
10353             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10354             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10355               n;
10356             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10357             pr "  }\n";
10358             pr "  free (%s);\n" n
10359         | Bool n
10360         | Int n
10361         | Int64 n -> ()
10362       ) (snd style);
10363
10364       (* Check for errors. *)
10365       pr "  if (r == %s) {\n" error_code;
10366       pr "    throw_exception (env, guestfs_last_error (g));\n";
10367       pr "    return %s;\n" no_ret;
10368       pr "  }\n";
10369
10370       (* Return value. *)
10371       (match fst style with
10372        | RErr -> ()
10373        | RInt _ -> pr "  return (jint) r;\n"
10374        | RBool _ -> pr "  return (jboolean) r;\n"
10375        | RInt64 _ -> pr "  return (jlong) r;\n"
10376        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10377        | RConstOptString _ ->
10378            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10379        | RString _ ->
10380            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10381            pr "  free (r);\n";
10382            pr "  return jr;\n"
10383        | RStringList _ ->
10384            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10385            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10386            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10387            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10388            pr "  for (i = 0; i < r_len; ++i) {\n";
10389            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10390            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10391            pr "    free (r[i]);\n";
10392            pr "  }\n";
10393            pr "  free (r);\n";
10394            pr "  return jr;\n"
10395        | RStruct (_, typ) ->
10396            let jtyp = java_name_of_struct typ in
10397            let cols = cols_of_struct typ in
10398            generate_java_struct_return typ jtyp cols
10399        | RStructList (_, typ) ->
10400            let jtyp = java_name_of_struct typ in
10401            let cols = cols_of_struct typ in
10402            generate_java_struct_list_return typ jtyp cols
10403        | RHashtable _ ->
10404            (* XXX *)
10405            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10406            pr "  return NULL;\n"
10407        | RBufferOut _ ->
10408            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10409            pr "  free (r);\n";
10410            pr "  return jr;\n"
10411       );
10412
10413       pr "}\n";
10414       pr "\n"
10415   ) all_functions
10416
10417 and generate_java_struct_return typ jtyp cols =
10418   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10419   pr "  jr = (*env)->AllocObject (env, cl);\n";
10420   List.iter (
10421     function
10422     | name, FString ->
10423         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10424         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10425     | name, FUUID ->
10426         pr "  {\n";
10427         pr "    char s[33];\n";
10428         pr "    memcpy (s, r->%s, 32);\n" name;
10429         pr "    s[32] = 0;\n";
10430         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10431         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10432         pr "  }\n";
10433     | name, FBuffer ->
10434         pr "  {\n";
10435         pr "    int len = r->%s_len;\n" name;
10436         pr "    char s[len+1];\n";
10437         pr "    memcpy (s, r->%s, len);\n" name;
10438         pr "    s[len] = 0;\n";
10439         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10440         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10441         pr "  }\n";
10442     | name, (FBytes|FUInt64|FInt64) ->
10443         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10444         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10445     | name, (FUInt32|FInt32) ->
10446         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10447         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10448     | name, FOptPercent ->
10449         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10450         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10451     | name, FChar ->
10452         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10453         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10454   ) cols;
10455   pr "  free (r);\n";
10456   pr "  return jr;\n"
10457
10458 and generate_java_struct_list_return typ jtyp cols =
10459   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10460   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10461   pr "  for (i = 0; i < r->len; ++i) {\n";
10462   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10463   List.iter (
10464     function
10465     | name, FString ->
10466         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10467         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10468     | name, FUUID ->
10469         pr "    {\n";
10470         pr "      char s[33];\n";
10471         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10472         pr "      s[32] = 0;\n";
10473         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10474         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10475         pr "    }\n";
10476     | name, FBuffer ->
10477         pr "    {\n";
10478         pr "      int len = r->val[i].%s_len;\n" name;
10479         pr "      char s[len+1];\n";
10480         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10481         pr "      s[len] = 0;\n";
10482         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10483         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10484         pr "    }\n";
10485     | name, (FBytes|FUInt64|FInt64) ->
10486         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10487         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10488     | name, (FUInt32|FInt32) ->
10489         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10490         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10491     | name, FOptPercent ->
10492         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10493         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10494     | name, FChar ->
10495         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10496         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10497   ) cols;
10498   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10499   pr "  }\n";
10500   pr "  guestfs_free_%s_list (r);\n" typ;
10501   pr "  return jr;\n"
10502
10503 and generate_java_makefile_inc () =
10504   generate_header HashStyle GPLv2plus;
10505
10506   pr "java_built_sources = \\\n";
10507   List.iter (
10508     fun (typ, jtyp) ->
10509         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10510   ) java_structs;
10511   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10512
10513 and generate_haskell_hs () =
10514   generate_header HaskellStyle LGPLv2plus;
10515
10516   (* XXX We only know how to generate partial FFI for Haskell
10517    * at the moment.  Please help out!
10518    *)
10519   let can_generate style =
10520     match style with
10521     | RErr, _
10522     | RInt _, _
10523     | RInt64 _, _ -> true
10524     | RBool _, _
10525     | RConstString _, _
10526     | RConstOptString _, _
10527     | RString _, _
10528     | RStringList _, _
10529     | RStruct _, _
10530     | RStructList _, _
10531     | RHashtable _, _
10532     | RBufferOut _, _ -> false in
10533
10534   pr "\
10535 {-# INCLUDE <guestfs.h> #-}
10536 {-# LANGUAGE ForeignFunctionInterface #-}
10537
10538 module Guestfs (
10539   create";
10540
10541   (* List out the names of the actions we want to export. *)
10542   List.iter (
10543     fun (name, style, _, _, _, _, _) ->
10544       if can_generate style then pr ",\n  %s" name
10545   ) all_functions;
10546
10547   pr "
10548   ) where
10549
10550 -- Unfortunately some symbols duplicate ones already present
10551 -- in Prelude.  We don't know which, so we hard-code a list
10552 -- here.
10553 import Prelude hiding (truncate)
10554
10555 import Foreign
10556 import Foreign.C
10557 import Foreign.C.Types
10558 import IO
10559 import Control.Exception
10560 import Data.Typeable
10561
10562 data GuestfsS = GuestfsS            -- represents the opaque C struct
10563 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10564 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10565
10566 -- XXX define properly later XXX
10567 data PV = PV
10568 data VG = VG
10569 data LV = LV
10570 data IntBool = IntBool
10571 data Stat = Stat
10572 data StatVFS = StatVFS
10573 data Hashtable = Hashtable
10574
10575 foreign import ccall unsafe \"guestfs_create\" c_create
10576   :: IO GuestfsP
10577 foreign import ccall unsafe \"&guestfs_close\" c_close
10578   :: FunPtr (GuestfsP -> IO ())
10579 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10580   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10581
10582 create :: IO GuestfsH
10583 create = do
10584   p <- c_create
10585   c_set_error_handler p nullPtr nullPtr
10586   h <- newForeignPtr c_close p
10587   return h
10588
10589 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10590   :: GuestfsP -> IO CString
10591
10592 -- last_error :: GuestfsH -> IO (Maybe String)
10593 -- last_error h = do
10594 --   str <- withForeignPtr h (\\p -> c_last_error p)
10595 --   maybePeek peekCString str
10596
10597 last_error :: GuestfsH -> IO (String)
10598 last_error h = do
10599   str <- withForeignPtr h (\\p -> c_last_error p)
10600   if (str == nullPtr)
10601     then return \"no error\"
10602     else peekCString str
10603
10604 ";
10605
10606   (* Generate wrappers for each foreign function. *)
10607   List.iter (
10608     fun (name, style, _, _, _, _, _) ->
10609       if can_generate style then (
10610         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10611         pr "  :: ";
10612         generate_haskell_prototype ~handle:"GuestfsP" style;
10613         pr "\n";
10614         pr "\n";
10615         pr "%s :: " name;
10616         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10617         pr "\n";
10618         pr "%s %s = do\n" name
10619           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10620         pr "  r <- ";
10621         (* Convert pointer arguments using with* functions. *)
10622         List.iter (
10623           function
10624           | FileIn n
10625           | FileOut n
10626           | Pathname n | Device n | Dev_or_Path n | String n ->
10627               pr "withCString %s $ \\%s -> " n n
10628           | BufferIn n ->
10629               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10630           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10631           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10632           | Bool _ | Int _ | Int64 _ -> ()
10633         ) (snd style);
10634         (* Convert integer arguments. *)
10635         let args =
10636           List.map (
10637             function
10638             | Bool n -> sprintf "(fromBool %s)" n
10639             | Int n -> sprintf "(fromIntegral %s)" n
10640             | Int64 n -> sprintf "(fromIntegral %s)" n
10641             | FileIn n | FileOut n
10642             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10643             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10644           ) (snd style) in
10645         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10646           (String.concat " " ("p" :: args));
10647         (match fst style with
10648          | RErr | RInt _ | RInt64 _ | RBool _ ->
10649              pr "  if (r == -1)\n";
10650              pr "    then do\n";
10651              pr "      err <- last_error h\n";
10652              pr "      fail err\n";
10653          | RConstString _ | RConstOptString _ | RString _
10654          | RStringList _ | RStruct _
10655          | RStructList _ | RHashtable _ | RBufferOut _ ->
10656              pr "  if (r == nullPtr)\n";
10657              pr "    then do\n";
10658              pr "      err <- last_error h\n";
10659              pr "      fail err\n";
10660         );
10661         (match fst style with
10662          | RErr ->
10663              pr "    else return ()\n"
10664          | RInt _ ->
10665              pr "    else return (fromIntegral r)\n"
10666          | RInt64 _ ->
10667              pr "    else return (fromIntegral r)\n"
10668          | RBool _ ->
10669              pr "    else return (toBool r)\n"
10670          | RConstString _
10671          | RConstOptString _
10672          | RString _
10673          | RStringList _
10674          | RStruct _
10675          | RStructList _
10676          | RHashtable _
10677          | RBufferOut _ ->
10678              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10679         );
10680         pr "\n";
10681       )
10682   ) all_functions
10683
10684 and generate_haskell_prototype ~handle ?(hs = false) style =
10685   pr "%s -> " handle;
10686   let string = if hs then "String" else "CString" in
10687   let int = if hs then "Int" else "CInt" in
10688   let bool = if hs then "Bool" else "CInt" in
10689   let int64 = if hs then "Integer" else "Int64" in
10690   List.iter (
10691     fun arg ->
10692       (match arg with
10693        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10694        | BufferIn _ ->
10695            if hs then pr "String"
10696            else pr "CString -> CInt"
10697        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10698        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10699        | Bool _ -> pr "%s" bool
10700        | Int _ -> pr "%s" int
10701        | Int64 _ -> pr "%s" int
10702        | FileIn _ -> pr "%s" string
10703        | FileOut _ -> pr "%s" string
10704       );
10705       pr " -> ";
10706   ) (snd style);
10707   pr "IO (";
10708   (match fst style with
10709    | RErr -> if not hs then pr "CInt"
10710    | RInt _ -> pr "%s" int
10711    | RInt64 _ -> pr "%s" int64
10712    | RBool _ -> pr "%s" bool
10713    | RConstString _ -> pr "%s" string
10714    | RConstOptString _ -> pr "Maybe %s" string
10715    | RString _ -> pr "%s" string
10716    | RStringList _ -> pr "[%s]" string
10717    | RStruct (_, typ) ->
10718        let name = java_name_of_struct typ in
10719        pr "%s" name
10720    | RStructList (_, typ) ->
10721        let name = java_name_of_struct typ in
10722        pr "[%s]" name
10723    | RHashtable _ -> pr "Hashtable"
10724    | RBufferOut _ -> pr "%s" string
10725   );
10726   pr ")"
10727
10728 and generate_csharp () =
10729   generate_header CPlusPlusStyle LGPLv2plus;
10730
10731   (* XXX Make this configurable by the C# assembly users. *)
10732   let library = "libguestfs.so.0" in
10733
10734   pr "\
10735 // These C# bindings are highly experimental at present.
10736 //
10737 // Firstly they only work on Linux (ie. Mono).  In order to get them
10738 // to work on Windows (ie. .Net) you would need to port the library
10739 // itself to Windows first.
10740 //
10741 // The second issue is that some calls are known to be incorrect and
10742 // can cause Mono to segfault.  Particularly: calls which pass or
10743 // return string[], or return any structure value.  This is because
10744 // we haven't worked out the correct way to do this from C#.
10745 //
10746 // The third issue is that when compiling you get a lot of warnings.
10747 // We are not sure whether the warnings are important or not.
10748 //
10749 // Fourthly we do not routinely build or test these bindings as part
10750 // of the make && make check cycle, which means that regressions might
10751 // go unnoticed.
10752 //
10753 // Suggestions and patches are welcome.
10754
10755 // To compile:
10756 //
10757 // gmcs Libguestfs.cs
10758 // mono Libguestfs.exe
10759 //
10760 // (You'll probably want to add a Test class / static main function
10761 // otherwise this won't do anything useful).
10762
10763 using System;
10764 using System.IO;
10765 using System.Runtime.InteropServices;
10766 using System.Runtime.Serialization;
10767 using System.Collections;
10768
10769 namespace Guestfs
10770 {
10771   class Error : System.ApplicationException
10772   {
10773     public Error (string message) : base (message) {}
10774     protected Error (SerializationInfo info, StreamingContext context) {}
10775   }
10776
10777   class Guestfs
10778   {
10779     IntPtr _handle;
10780
10781     [DllImport (\"%s\")]
10782     static extern IntPtr guestfs_create ();
10783
10784     public Guestfs ()
10785     {
10786       _handle = guestfs_create ();
10787       if (_handle == IntPtr.Zero)
10788         throw new Error (\"could not create guestfs handle\");
10789     }
10790
10791     [DllImport (\"%s\")]
10792     static extern void guestfs_close (IntPtr h);
10793
10794     ~Guestfs ()
10795     {
10796       guestfs_close (_handle);
10797     }
10798
10799     [DllImport (\"%s\")]
10800     static extern string guestfs_last_error (IntPtr h);
10801
10802 " library library library;
10803
10804   (* Generate C# structure bindings.  We prefix struct names with
10805    * underscore because C# cannot have conflicting struct names and
10806    * method names (eg. "class stat" and "stat").
10807    *)
10808   List.iter (
10809     fun (typ, cols) ->
10810       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10811       pr "    public class _%s {\n" typ;
10812       List.iter (
10813         function
10814         | name, FChar -> pr "      char %s;\n" name
10815         | name, FString -> pr "      string %s;\n" name
10816         | name, FBuffer ->
10817             pr "      uint %s_len;\n" name;
10818             pr "      string %s;\n" name
10819         | name, FUUID ->
10820             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10821             pr "      string %s;\n" name
10822         | name, FUInt32 -> pr "      uint %s;\n" name
10823         | name, FInt32 -> pr "      int %s;\n" name
10824         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10825         | name, FInt64 -> pr "      long %s;\n" name
10826         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10827       ) cols;
10828       pr "    }\n";
10829       pr "\n"
10830   ) structs;
10831
10832   (* Generate C# function bindings. *)
10833   List.iter (
10834     fun (name, style, _, _, _, shortdesc, _) ->
10835       let rec csharp_return_type () =
10836         match fst style with
10837         | RErr -> "void"
10838         | RBool n -> "bool"
10839         | RInt n -> "int"
10840         | RInt64 n -> "long"
10841         | RConstString n
10842         | RConstOptString n
10843         | RString n
10844         | RBufferOut n -> "string"
10845         | RStruct (_,n) -> "_" ^ n
10846         | RHashtable n -> "Hashtable"
10847         | RStringList n -> "string[]"
10848         | RStructList (_,n) -> sprintf "_%s[]" n
10849
10850       and c_return_type () =
10851         match fst style with
10852         | RErr
10853         | RBool _
10854         | RInt _ -> "int"
10855         | RInt64 _ -> "long"
10856         | RConstString _
10857         | RConstOptString _
10858         | RString _
10859         | RBufferOut _ -> "string"
10860         | RStruct (_,n) -> "_" ^ n
10861         | RHashtable _
10862         | RStringList _ -> "string[]"
10863         | RStructList (_,n) -> sprintf "_%s[]" n
10864
10865       and c_error_comparison () =
10866         match fst style with
10867         | RErr
10868         | RBool _
10869         | RInt _
10870         | RInt64 _ -> "== -1"
10871         | RConstString _
10872         | RConstOptString _
10873         | RString _
10874         | RBufferOut _
10875         | RStruct (_,_)
10876         | RHashtable _
10877         | RStringList _
10878         | RStructList (_,_) -> "== null"
10879
10880       and generate_extern_prototype () =
10881         pr "    static extern %s guestfs_%s (IntPtr h"
10882           (c_return_type ()) name;
10883         List.iter (
10884           function
10885           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10886           | FileIn n | FileOut n
10887           | BufferIn n ->
10888               pr ", [In] string %s" n
10889           | StringList n | DeviceList n ->
10890               pr ", [In] string[] %s" n
10891           | Bool n ->
10892               pr ", bool %s" n
10893           | Int n ->
10894               pr ", int %s" n
10895           | Int64 n ->
10896               pr ", long %s" n
10897         ) (snd style);
10898         pr ");\n"
10899
10900       and generate_public_prototype () =
10901         pr "    public %s %s (" (csharp_return_type ()) name;
10902         let comma = ref false in
10903         let next () =
10904           if !comma then pr ", ";
10905           comma := true
10906         in
10907         List.iter (
10908           function
10909           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10910           | FileIn n | FileOut n
10911           | BufferIn n ->
10912               next (); pr "string %s" n
10913           | StringList n | DeviceList n ->
10914               next (); pr "string[] %s" n
10915           | Bool n ->
10916               next (); pr "bool %s" n
10917           | Int n ->
10918               next (); pr "int %s" n
10919           | Int64 n ->
10920               next (); pr "long %s" n
10921         ) (snd style);
10922         pr ")\n"
10923
10924       and generate_call () =
10925         pr "guestfs_%s (_handle" name;
10926         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10927         pr ");\n";
10928       in
10929
10930       pr "    [DllImport (\"%s\")]\n" library;
10931       generate_extern_prototype ();
10932       pr "\n";
10933       pr "    /// <summary>\n";
10934       pr "    /// %s\n" shortdesc;
10935       pr "    /// </summary>\n";
10936       generate_public_prototype ();
10937       pr "    {\n";
10938       pr "      %s r;\n" (c_return_type ());
10939       pr "      r = ";
10940       generate_call ();
10941       pr "      if (r %s)\n" (c_error_comparison ());
10942       pr "        throw new Error (guestfs_last_error (_handle));\n";
10943       (match fst style with
10944        | RErr -> ()
10945        | RBool _ ->
10946            pr "      return r != 0 ? true : false;\n"
10947        | RHashtable _ ->
10948            pr "      Hashtable rr = new Hashtable ();\n";
10949            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10950            pr "        rr.Add (r[i], r[i+1]);\n";
10951            pr "      return rr;\n"
10952        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10953        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10954        | RStructList _ ->
10955            pr "      return r;\n"
10956       );
10957       pr "    }\n";
10958       pr "\n";
10959   ) all_functions_sorted;
10960
10961   pr "  }
10962 }
10963 "
10964
10965 and generate_bindtests () =
10966   generate_header CStyle LGPLv2plus;
10967
10968   pr "\
10969 #include <stdio.h>
10970 #include <stdlib.h>
10971 #include <inttypes.h>
10972 #include <string.h>
10973
10974 #include \"guestfs.h\"
10975 #include \"guestfs-internal.h\"
10976 #include \"guestfs-internal-actions.h\"
10977 #include \"guestfs_protocol.h\"
10978
10979 #define error guestfs_error
10980 #define safe_calloc guestfs_safe_calloc
10981 #define safe_malloc guestfs_safe_malloc
10982
10983 static void
10984 print_strings (char *const *argv)
10985 {
10986   int argc;
10987
10988   printf (\"[\");
10989   for (argc = 0; argv[argc] != NULL; ++argc) {
10990     if (argc > 0) printf (\", \");
10991     printf (\"\\\"%%s\\\"\", argv[argc]);
10992   }
10993   printf (\"]\\n\");
10994 }
10995
10996 /* The test0 function prints its parameters to stdout. */
10997 ";
10998
10999   let test0, tests =
11000     match test_functions with
11001     | [] -> assert false
11002     | test0 :: tests -> test0, tests in
11003
11004   let () =
11005     let (name, style, _, _, _, _, _) = test0 in
11006     generate_prototype ~extern:false ~semicolon:false ~newline:true
11007       ~handle:"g" ~prefix:"guestfs__" name style;
11008     pr "{\n";
11009     List.iter (
11010       function
11011       | Pathname n
11012       | Device n | Dev_or_Path n
11013       | String n
11014       | FileIn n
11015       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11016       | BufferIn n ->
11017           pr "  for (size_t i = 0; i < %s_size; ++i)\n" n;
11018           pr "    printf (\"<%%02x>\", %s[i]);\n" n;
11019           pr "  printf (\"\\n\");\n"
11020       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11021       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11022       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11023       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11024       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11025     ) (snd style);
11026     pr "  /* Java changes stdout line buffering so we need this: */\n";
11027     pr "  fflush (stdout);\n";
11028     pr "  return 0;\n";
11029     pr "}\n";
11030     pr "\n" in
11031
11032   List.iter (
11033     fun (name, style, _, _, _, _, _) ->
11034       if String.sub name (String.length name - 3) 3 <> "err" then (
11035         pr "/* Test normal return. */\n";
11036         generate_prototype ~extern:false ~semicolon:false ~newline:true
11037           ~handle:"g" ~prefix:"guestfs__" name style;
11038         pr "{\n";
11039         (match fst style with
11040          | RErr ->
11041              pr "  return 0;\n"
11042          | RInt _ ->
11043              pr "  int r;\n";
11044              pr "  sscanf (val, \"%%d\", &r);\n";
11045              pr "  return r;\n"
11046          | RInt64 _ ->
11047              pr "  int64_t r;\n";
11048              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11049              pr "  return r;\n"
11050          | RBool _ ->
11051              pr "  return STREQ (val, \"true\");\n"
11052          | RConstString _
11053          | RConstOptString _ ->
11054              (* Can't return the input string here.  Return a static
11055               * string so we ensure we get a segfault if the caller
11056               * tries to free it.
11057               *)
11058              pr "  return \"static string\";\n"
11059          | RString _ ->
11060              pr "  return strdup (val);\n"
11061          | RStringList _ ->
11062              pr "  char **strs;\n";
11063              pr "  int n, i;\n";
11064              pr "  sscanf (val, \"%%d\", &n);\n";
11065              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11066              pr "  for (i = 0; i < n; ++i) {\n";
11067              pr "    strs[i] = safe_malloc (g, 16);\n";
11068              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11069              pr "  }\n";
11070              pr "  strs[n] = NULL;\n";
11071              pr "  return strs;\n"
11072          | RStruct (_, typ) ->
11073              pr "  struct guestfs_%s *r;\n" typ;
11074              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11075              pr "  return r;\n"
11076          | RStructList (_, typ) ->
11077              pr "  struct guestfs_%s_list *r;\n" typ;
11078              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11079              pr "  sscanf (val, \"%%d\", &r->len);\n";
11080              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11081              pr "  return r;\n"
11082          | RHashtable _ ->
11083              pr "  char **strs;\n";
11084              pr "  int n, i;\n";
11085              pr "  sscanf (val, \"%%d\", &n);\n";
11086              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11087              pr "  for (i = 0; i < n; ++i) {\n";
11088              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11089              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11090              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11091              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11092              pr "  }\n";
11093              pr "  strs[n*2] = NULL;\n";
11094              pr "  return strs;\n"
11095          | RBufferOut _ ->
11096              pr "  return strdup (val);\n"
11097         );
11098         pr "}\n";
11099         pr "\n"
11100       ) else (
11101         pr "/* Test error return. */\n";
11102         generate_prototype ~extern:false ~semicolon:false ~newline:true
11103           ~handle:"g" ~prefix:"guestfs__" name style;
11104         pr "{\n";
11105         pr "  error (g, \"error\");\n";
11106         (match fst style with
11107          | RErr | RInt _ | RInt64 _ | RBool _ ->
11108              pr "  return -1;\n"
11109          | RConstString _ | RConstOptString _
11110          | RString _ | RStringList _ | RStruct _
11111          | RStructList _
11112          | RHashtable _
11113          | RBufferOut _ ->
11114              pr "  return NULL;\n"
11115         );
11116         pr "}\n";
11117         pr "\n"
11118       )
11119   ) tests
11120
11121 and generate_ocaml_bindtests () =
11122   generate_header OCamlStyle GPLv2plus;
11123
11124   pr "\
11125 let () =
11126   let g = Guestfs.create () in
11127 ";
11128
11129   let mkargs args =
11130     String.concat " " (
11131       List.map (
11132         function
11133         | CallString s -> "\"" ^ s ^ "\""
11134         | CallOptString None -> "None"
11135         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11136         | CallStringList xs ->
11137             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11138         | CallInt i when i >= 0 -> string_of_int i
11139         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11140         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11141         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11142         | CallBool b -> string_of_bool b
11143         | CallBuffer s -> sprintf "%S" s
11144       ) args
11145     )
11146   in
11147
11148   generate_lang_bindtests (
11149     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11150   );
11151
11152   pr "print_endline \"EOF\"\n"
11153
11154 and generate_perl_bindtests () =
11155   pr "#!/usr/bin/perl -w\n";
11156   generate_header HashStyle GPLv2plus;
11157
11158   pr "\
11159 use strict;
11160
11161 use Sys::Guestfs;
11162
11163 my $g = Sys::Guestfs->new ();
11164 ";
11165
11166   let mkargs args =
11167     String.concat ", " (
11168       List.map (
11169         function
11170         | CallString s -> "\"" ^ s ^ "\""
11171         | CallOptString None -> "undef"
11172         | CallOptString (Some s) -> sprintf "\"%s\"" s
11173         | CallStringList xs ->
11174             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11175         | CallInt i -> string_of_int i
11176         | CallInt64 i -> Int64.to_string i
11177         | CallBool b -> if b then "1" else "0"
11178         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11179       ) args
11180     )
11181   in
11182
11183   generate_lang_bindtests (
11184     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11185   );
11186
11187   pr "print \"EOF\\n\"\n"
11188
11189 and generate_python_bindtests () =
11190   generate_header HashStyle GPLv2plus;
11191
11192   pr "\
11193 import guestfs
11194
11195 g = guestfs.GuestFS ()
11196 ";
11197
11198   let mkargs args =
11199     String.concat ", " (
11200       List.map (
11201         function
11202         | CallString s -> "\"" ^ s ^ "\""
11203         | CallOptString None -> "None"
11204         | CallOptString (Some s) -> sprintf "\"%s\"" s
11205         | CallStringList xs ->
11206             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11207         | CallInt i -> string_of_int i
11208         | CallInt64 i -> Int64.to_string i
11209         | CallBool b -> if b then "1" else "0"
11210         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11211       ) args
11212     )
11213   in
11214
11215   generate_lang_bindtests (
11216     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11217   );
11218
11219   pr "print \"EOF\"\n"
11220
11221 and generate_ruby_bindtests () =
11222   generate_header HashStyle GPLv2plus;
11223
11224   pr "\
11225 require 'guestfs'
11226
11227 g = Guestfs::create()
11228 ";
11229
11230   let mkargs args =
11231     String.concat ", " (
11232       List.map (
11233         function
11234         | CallString s -> "\"" ^ s ^ "\""
11235         | CallOptString None -> "nil"
11236         | CallOptString (Some s) -> sprintf "\"%s\"" s
11237         | CallStringList xs ->
11238             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11239         | CallInt i -> string_of_int i
11240         | CallInt64 i -> Int64.to_string i
11241         | CallBool b -> string_of_bool b
11242         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11243       ) args
11244     )
11245   in
11246
11247   generate_lang_bindtests (
11248     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11249   );
11250
11251   pr "print \"EOF\\n\"\n"
11252
11253 and generate_java_bindtests () =
11254   generate_header CStyle GPLv2plus;
11255
11256   pr "\
11257 import com.redhat.et.libguestfs.*;
11258
11259 public class Bindtests {
11260     public static void main (String[] argv)
11261     {
11262         try {
11263             GuestFS g = new GuestFS ();
11264 ";
11265
11266   let mkargs args =
11267     String.concat ", " (
11268       List.map (
11269         function
11270         | CallString s -> "\"" ^ s ^ "\""
11271         | CallOptString None -> "null"
11272         | CallOptString (Some s) -> sprintf "\"%s\"" s
11273         | CallStringList xs ->
11274             "new String[]{" ^
11275               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11276         | CallInt i -> string_of_int i
11277         | CallInt64 i -> Int64.to_string i
11278         | CallBool b -> string_of_bool b
11279         | CallBuffer s ->
11280             "new byte[] { " ^ String.concat "," (
11281               map_chars (fun c -> string_of_int (Char.code c)) s
11282             ) ^ " }"
11283       ) args
11284     )
11285   in
11286
11287   generate_lang_bindtests (
11288     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11289   );
11290
11291   pr "
11292             System.out.println (\"EOF\");
11293         }
11294         catch (Exception exn) {
11295             System.err.println (exn);
11296             System.exit (1);
11297         }
11298     }
11299 }
11300 "
11301
11302 and generate_haskell_bindtests () =
11303   generate_header HaskellStyle GPLv2plus;
11304
11305   pr "\
11306 module Bindtests where
11307 import qualified Guestfs
11308
11309 main = do
11310   g <- Guestfs.create
11311 ";
11312
11313   let mkargs args =
11314     String.concat " " (
11315       List.map (
11316         function
11317         | CallString s -> "\"" ^ s ^ "\""
11318         | CallOptString None -> "Nothing"
11319         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11320         | CallStringList xs ->
11321             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11322         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11323         | CallInt i -> string_of_int i
11324         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11325         | CallInt64 i -> Int64.to_string i
11326         | CallBool true -> "True"
11327         | CallBool false -> "False"
11328         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11329       ) args
11330     )
11331   in
11332
11333   generate_lang_bindtests (
11334     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11335   );
11336
11337   pr "  putStrLn \"EOF\"\n"
11338
11339 (* Language-independent bindings tests - we do it this way to
11340  * ensure there is parity in testing bindings across all languages.
11341  *)
11342 and generate_lang_bindtests call =
11343   call "test0" [CallString "abc"; CallOptString (Some "def");
11344                 CallStringList []; CallBool false;
11345                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11346                 CallBuffer "abc\000abc"];
11347   call "test0" [CallString "abc"; CallOptString None;
11348                 CallStringList []; CallBool false;
11349                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11350                 CallBuffer "abc\000abc"];
11351   call "test0" [CallString ""; CallOptString (Some "def");
11352                 CallStringList []; CallBool false;
11353                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11354                 CallBuffer "abc\000abc"];
11355   call "test0" [CallString ""; CallOptString (Some "");
11356                 CallStringList []; CallBool false;
11357                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11358                 CallBuffer "abc\000abc"];
11359   call "test0" [CallString "abc"; CallOptString (Some "def");
11360                 CallStringList ["1"]; CallBool false;
11361                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11362                 CallBuffer "abc\000abc"];
11363   call "test0" [CallString "abc"; CallOptString (Some "def");
11364                 CallStringList ["1"; "2"]; CallBool false;
11365                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11366                 CallBuffer "abc\000abc"];
11367   call "test0" [CallString "abc"; CallOptString (Some "def");
11368                 CallStringList ["1"]; CallBool true;
11369                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11370                 CallBuffer "abc\000abc"];
11371   call "test0" [CallString "abc"; CallOptString (Some "def");
11372                 CallStringList ["1"]; CallBool false;
11373                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11374                 CallBuffer "abc\000abc"];
11375   call "test0" [CallString "abc"; CallOptString (Some "def");
11376                 CallStringList ["1"]; CallBool false;
11377                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11378                 CallBuffer "abc\000abc"];
11379   call "test0" [CallString "abc"; CallOptString (Some "def");
11380                 CallStringList ["1"]; CallBool false;
11381                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11382                 CallBuffer "abc\000abc"];
11383   call "test0" [CallString "abc"; CallOptString (Some "def");
11384                 CallStringList ["1"]; CallBool false;
11385                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11386                 CallBuffer "abc\000abc"];
11387   call "test0" [CallString "abc"; CallOptString (Some "def");
11388                 CallStringList ["1"]; CallBool false;
11389                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11390                 CallBuffer "abc\000abc"];
11391   call "test0" [CallString "abc"; CallOptString (Some "def");
11392                 CallStringList ["1"]; CallBool false;
11393                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11394                 CallBuffer "abc\000abc"]
11395
11396 (* XXX Add here tests of the return and error functions. *)
11397
11398 (* Code to generator bindings for virt-inspector.  Currently only
11399  * implemented for OCaml code (for virt-p2v 2.0).
11400  *)
11401 let rng_input = "inspector/virt-inspector.rng"
11402
11403 (* Read the input file and parse it into internal structures.  This is
11404  * by no means a complete RELAX NG parser, but is just enough to be
11405  * able to parse the specific input file.
11406  *)
11407 type rng =
11408   | Element of string * rng list        (* <element name=name/> *)
11409   | Attribute of string * rng list        (* <attribute name=name/> *)
11410   | Interleave of rng list                (* <interleave/> *)
11411   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11412   | OneOrMore of rng                        (* <oneOrMore/> *)
11413   | Optional of rng                        (* <optional/> *)
11414   | Choice of string list                (* <choice><value/>*</choice> *)
11415   | Value of string                        (* <value>str</value> *)
11416   | Text                                (* <text/> *)
11417
11418 let rec string_of_rng = function
11419   | Element (name, xs) ->
11420       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11421   | Attribute (name, xs) ->
11422       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11423   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11424   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11425   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11426   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11427   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11428   | Value value -> "Value \"" ^ value ^ "\""
11429   | Text -> "Text"
11430
11431 and string_of_rng_list xs =
11432   String.concat ", " (List.map string_of_rng xs)
11433
11434 let rec parse_rng ?defines context = function
11435   | [] -> []
11436   | Xml.Element ("element", ["name", name], children) :: rest ->
11437       Element (name, parse_rng ?defines context children)
11438       :: parse_rng ?defines context rest
11439   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11440       Attribute (name, parse_rng ?defines context children)
11441       :: parse_rng ?defines context rest
11442   | Xml.Element ("interleave", [], children) :: rest ->
11443       Interleave (parse_rng ?defines context children)
11444       :: parse_rng ?defines context rest
11445   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11446       let rng = parse_rng ?defines context [child] in
11447       (match rng with
11448        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11449        | _ ->
11450            failwithf "%s: <zeroOrMore> contains more than one child element"
11451              context
11452       )
11453   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11454       let rng = parse_rng ?defines context [child] in
11455       (match rng with
11456        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11457        | _ ->
11458            failwithf "%s: <oneOrMore> contains more than one child element"
11459              context
11460       )
11461   | Xml.Element ("optional", [], [child]) :: rest ->
11462       let rng = parse_rng ?defines context [child] in
11463       (match rng with
11464        | [child] -> Optional child :: parse_rng ?defines context rest
11465        | _ ->
11466            failwithf "%s: <optional> contains more than one child element"
11467              context
11468       )
11469   | Xml.Element ("choice", [], children) :: rest ->
11470       let values = List.map (
11471         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11472         | _ ->
11473             failwithf "%s: can't handle anything except <value> in <choice>"
11474               context
11475       ) children in
11476       Choice values
11477       :: parse_rng ?defines context rest
11478   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11479       Value value :: parse_rng ?defines context rest
11480   | Xml.Element ("text", [], []) :: rest ->
11481       Text :: parse_rng ?defines context rest
11482   | Xml.Element ("ref", ["name", name], []) :: rest ->
11483       (* Look up the reference.  Because of limitations in this parser,
11484        * we can't handle arbitrarily nested <ref> yet.  You can only
11485        * use <ref> from inside <start>.
11486        *)
11487       (match defines with
11488        | None ->
11489            failwithf "%s: contains <ref>, but no refs are defined yet" context
11490        | Some map ->
11491            let rng = StringMap.find name map in
11492            rng @ parse_rng ?defines context rest
11493       )
11494   | x :: _ ->
11495       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11496
11497 let grammar =
11498   let xml = Xml.parse_file rng_input in
11499   match xml with
11500   | Xml.Element ("grammar", _,
11501                  Xml.Element ("start", _, gram) :: defines) ->
11502       (* The <define/> elements are referenced in the <start> section,
11503        * so build a map of those first.
11504        *)
11505       let defines = List.fold_left (
11506         fun map ->
11507           function Xml.Element ("define", ["name", name], defn) ->
11508             StringMap.add name defn map
11509           | _ ->
11510               failwithf "%s: expected <define name=name/>" rng_input
11511       ) StringMap.empty defines in
11512       let defines = StringMap.mapi parse_rng defines in
11513
11514       (* Parse the <start> clause, passing the defines. *)
11515       parse_rng ~defines "<start>" gram
11516   | _ ->
11517       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11518         rng_input
11519
11520 let name_of_field = function
11521   | Element (name, _) | Attribute (name, _)
11522   | ZeroOrMore (Element (name, _))
11523   | OneOrMore (Element (name, _))
11524   | Optional (Element (name, _)) -> name
11525   | Optional (Attribute (name, _)) -> name
11526   | Text -> (* an unnamed field in an element *)
11527       "data"
11528   | rng ->
11529       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11530
11531 (* At the moment this function only generates OCaml types.  However we
11532  * should parameterize it later so it can generate types/structs in a
11533  * variety of languages.
11534  *)
11535 let generate_types xs =
11536   (* A simple type is one that can be printed out directly, eg.
11537    * "string option".  A complex type is one which has a name and has
11538    * to be defined via another toplevel definition, eg. a struct.
11539    *
11540    * generate_type generates code for either simple or complex types.
11541    * In the simple case, it returns the string ("string option").  In
11542    * the complex case, it returns the name ("mountpoint").  In the
11543    * complex case it has to print out the definition before returning,
11544    * so it should only be called when we are at the beginning of a
11545    * new line (BOL context).
11546    *)
11547   let rec generate_type = function
11548     | Text ->                                (* string *)
11549         "string", true
11550     | Choice values ->                        (* [`val1|`val2|...] *)
11551         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11552     | ZeroOrMore rng ->                        (* <rng> list *)
11553         let t, is_simple = generate_type rng in
11554         t ^ " list (* 0 or more *)", is_simple
11555     | OneOrMore rng ->                        (* <rng> list *)
11556         let t, is_simple = generate_type rng in
11557         t ^ " list (* 1 or more *)", is_simple
11558                                         (* virt-inspector hack: bool *)
11559     | Optional (Attribute (name, [Value "1"])) ->
11560         "bool", true
11561     | Optional rng ->                        (* <rng> list *)
11562         let t, is_simple = generate_type rng in
11563         t ^ " option", is_simple
11564                                         (* type name = { fields ... } *)
11565     | Element (name, fields) when is_attrs_interleave fields ->
11566         generate_type_struct name (get_attrs_interleave fields)
11567     | Element (name, [field])                (* type name = field *)
11568     | Attribute (name, [field]) ->
11569         let t, is_simple = generate_type field in
11570         if is_simple then (t, true)
11571         else (
11572           pr "type %s = %s\n" name t;
11573           name, false
11574         )
11575     | Element (name, fields) ->              (* type name = { fields ... } *)
11576         generate_type_struct name fields
11577     | rng ->
11578         failwithf "generate_type failed at: %s" (string_of_rng rng)
11579
11580   and is_attrs_interleave = function
11581     | [Interleave _] -> true
11582     | Attribute _ :: fields -> is_attrs_interleave fields
11583     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11584     | _ -> false
11585
11586   and get_attrs_interleave = function
11587     | [Interleave fields] -> fields
11588     | ((Attribute _) as field) :: fields
11589     | ((Optional (Attribute _)) as field) :: fields ->
11590         field :: get_attrs_interleave fields
11591     | _ -> assert false
11592
11593   and generate_types xs =
11594     List.iter (fun x -> ignore (generate_type x)) xs
11595
11596   and generate_type_struct name fields =
11597     (* Calculate the types of the fields first.  We have to do this
11598      * before printing anything so we are still in BOL context.
11599      *)
11600     let types = List.map fst (List.map generate_type fields) in
11601
11602     (* Special case of a struct containing just a string and another
11603      * field.  Turn it into an assoc list.
11604      *)
11605     match types with
11606     | ["string"; other] ->
11607         let fname1, fname2 =
11608           match fields with
11609           | [f1; f2] -> name_of_field f1, name_of_field f2
11610           | _ -> assert false in
11611         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11612         name, false
11613
11614     | types ->
11615         pr "type %s = {\n" name;
11616         List.iter (
11617           fun (field, ftype) ->
11618             let fname = name_of_field field in
11619             pr "  %s_%s : %s;\n" name fname ftype
11620         ) (List.combine fields types);
11621         pr "}\n";
11622         (* Return the name of this type, and
11623          * false because it's not a simple type.
11624          *)
11625         name, false
11626   in
11627
11628   generate_types xs
11629
11630 let generate_parsers xs =
11631   (* As for generate_type above, generate_parser makes a parser for
11632    * some type, and returns the name of the parser it has generated.
11633    * Because it (may) need to print something, it should always be
11634    * called in BOL context.
11635    *)
11636   let rec generate_parser = function
11637     | Text ->                                (* string *)
11638         "string_child_or_empty"
11639     | Choice values ->                        (* [`val1|`val2|...] *)
11640         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11641           (String.concat "|"
11642              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11643     | ZeroOrMore rng ->                        (* <rng> list *)
11644         let pa = generate_parser rng in
11645         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11646     | OneOrMore rng ->                        (* <rng> list *)
11647         let pa = generate_parser rng in
11648         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11649                                         (* virt-inspector hack: bool *)
11650     | Optional (Attribute (name, [Value "1"])) ->
11651         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11652     | Optional rng ->                        (* <rng> list *)
11653         let pa = generate_parser rng in
11654         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11655                                         (* type name = { fields ... } *)
11656     | Element (name, fields) when is_attrs_interleave fields ->
11657         generate_parser_struct name (get_attrs_interleave fields)
11658     | Element (name, [field]) ->        (* type name = field *)
11659         let pa = generate_parser field in
11660         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11661         pr "let %s =\n" parser_name;
11662         pr "  %s\n" pa;
11663         pr "let parse_%s = %s\n" name parser_name;
11664         parser_name
11665     | Attribute (name, [field]) ->
11666         let pa = generate_parser field in
11667         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11668         pr "let %s =\n" parser_name;
11669         pr "  %s\n" pa;
11670         pr "let parse_%s = %s\n" name parser_name;
11671         parser_name
11672     | Element (name, fields) ->              (* type name = { fields ... } *)
11673         generate_parser_struct name ([], fields)
11674     | rng ->
11675         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11676
11677   and is_attrs_interleave = function
11678     | [Interleave _] -> true
11679     | Attribute _ :: fields -> is_attrs_interleave fields
11680     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11681     | _ -> false
11682
11683   and get_attrs_interleave = function
11684     | [Interleave fields] -> [], fields
11685     | ((Attribute _) as field) :: fields
11686     | ((Optional (Attribute _)) as field) :: fields ->
11687         let attrs, interleaves = get_attrs_interleave fields in
11688         (field :: attrs), interleaves
11689     | _ -> assert false
11690
11691   and generate_parsers xs =
11692     List.iter (fun x -> ignore (generate_parser x)) xs
11693
11694   and generate_parser_struct name (attrs, interleaves) =
11695     (* Generate parsers for the fields first.  We have to do this
11696      * before printing anything so we are still in BOL context.
11697      *)
11698     let fields = attrs @ interleaves in
11699     let pas = List.map generate_parser fields in
11700
11701     (* Generate an intermediate tuple from all the fields first.
11702      * If the type is just a string + another field, then we will
11703      * return this directly, otherwise it is turned into a record.
11704      *
11705      * RELAX NG note: This code treats <interleave> and plain lists of
11706      * fields the same.  In other words, it doesn't bother enforcing
11707      * any ordering of fields in the XML.
11708      *)
11709     pr "let parse_%s x =\n" name;
11710     pr "  let t = (\n    ";
11711     let comma = ref false in
11712     List.iter (
11713       fun x ->
11714         if !comma then pr ",\n    ";
11715         comma := true;
11716         match x with
11717         | Optional (Attribute (fname, [field])), pa ->
11718             pr "%s x" pa
11719         | Optional (Element (fname, [field])), pa ->
11720             pr "%s (optional_child %S x)" pa fname
11721         | Attribute (fname, [Text]), _ ->
11722             pr "attribute %S x" fname
11723         | (ZeroOrMore _ | OneOrMore _), pa ->
11724             pr "%s x" pa
11725         | Text, pa ->
11726             pr "%s x" pa
11727         | (field, pa) ->
11728             let fname = name_of_field field in
11729             pr "%s (child %S x)" pa fname
11730     ) (List.combine fields pas);
11731     pr "\n  ) in\n";
11732
11733     (match fields with
11734      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11735          pr "  t\n"
11736
11737      | _ ->
11738          pr "  (Obj.magic t : %s)\n" name
11739 (*
11740          List.iter (
11741            function
11742            | (Optional (Attribute (fname, [field])), pa) ->
11743                pr "  %s_%s =\n" name fname;
11744                pr "    %s x;\n" pa
11745            | (Optional (Element (fname, [field])), pa) ->
11746                pr "  %s_%s =\n" name fname;
11747                pr "    (let x = optional_child %S x in\n" fname;
11748                pr "     %s x);\n" pa
11749            | (field, pa) ->
11750                let fname = name_of_field field in
11751                pr "  %s_%s =\n" name fname;
11752                pr "    (let x = child %S x in\n" fname;
11753                pr "     %s x);\n" pa
11754          ) (List.combine fields pas);
11755          pr "}\n"
11756 *)
11757     );
11758     sprintf "parse_%s" name
11759   in
11760
11761   generate_parsers xs
11762
11763 (* Generate ocaml/guestfs_inspector.mli. *)
11764 let generate_ocaml_inspector_mli () =
11765   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11766
11767   pr "\
11768 (** This is an OCaml language binding to the external [virt-inspector]
11769     program.
11770
11771     For more information, please read the man page [virt-inspector(1)].
11772 *)
11773
11774 ";
11775
11776   generate_types grammar;
11777   pr "(** The nested information returned from the {!inspect} function. *)\n";
11778   pr "\n";
11779
11780   pr "\
11781 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11782 (** To inspect a libvirt domain called [name], pass a singleton
11783     list: [inspect [name]].  When using libvirt only, you may
11784     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11785
11786     To inspect a disk image or images, pass a list of the filenames
11787     of the disk images: [inspect filenames]
11788
11789     This function inspects the given guest or disk images and
11790     returns a list of operating system(s) found and a large amount
11791     of information about them.  In the vast majority of cases,
11792     a virtual machine only contains a single operating system.
11793
11794     If the optional [~xml] parameter is given, then this function
11795     skips running the external virt-inspector program and just
11796     parses the given XML directly (which is expected to be XML
11797     produced from a previous run of virt-inspector).  The list of
11798     names and connect URI are ignored in this case.
11799
11800     This function can throw a wide variety of exceptions, for example
11801     if the external virt-inspector program cannot be found, or if
11802     it doesn't generate valid XML.
11803 *)
11804 "
11805
11806 (* Generate ocaml/guestfs_inspector.ml. *)
11807 let generate_ocaml_inspector_ml () =
11808   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11809
11810   pr "open Unix\n";
11811   pr "\n";
11812
11813   generate_types grammar;
11814   pr "\n";
11815
11816   pr "\
11817 (* Misc functions which are used by the parser code below. *)
11818 let first_child = function
11819   | Xml.Element (_, _, c::_) -> c
11820   | Xml.Element (name, _, []) ->
11821       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11822   | Xml.PCData str ->
11823       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11824
11825 let string_child_or_empty = function
11826   | Xml.Element (_, _, [Xml.PCData s]) -> s
11827   | Xml.Element (_, _, []) -> \"\"
11828   | Xml.Element (x, _, _) ->
11829       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11830                 x ^ \" instead\")
11831   | Xml.PCData str ->
11832       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11833
11834 let optional_child name xml =
11835   let children = Xml.children xml in
11836   try
11837     Some (List.find (function
11838                      | Xml.Element (n, _, _) when n = name -> true
11839                      | _ -> false) children)
11840   with
11841     Not_found -> None
11842
11843 let child name xml =
11844   match optional_child name xml with
11845   | Some c -> c
11846   | None ->
11847       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11848
11849 let attribute name xml =
11850   try Xml.attrib xml name
11851   with Xml.No_attribute _ ->
11852     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11853
11854 ";
11855
11856   generate_parsers grammar;
11857   pr "\n";
11858
11859   pr "\
11860 (* Run external virt-inspector, then use parser to parse the XML. *)
11861 let inspect ?connect ?xml names =
11862   let xml =
11863     match xml with
11864     | None ->
11865         if names = [] then invalid_arg \"inspect: no names given\";
11866         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11867           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11868           names in
11869         let cmd = List.map Filename.quote cmd in
11870         let cmd = String.concat \" \" cmd in
11871         let chan = open_process_in cmd in
11872         let xml = Xml.parse_in chan in
11873         (match close_process_in chan with
11874          | WEXITED 0 -> ()
11875          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11876          | WSIGNALED i | WSTOPPED i ->
11877              failwith (\"external virt-inspector command died or stopped on sig \" ^
11878                        string_of_int i)
11879         );
11880         xml
11881     | Some doc ->
11882         Xml.parse_string doc in
11883   parse_operatingsystems xml
11884 "
11885
11886 and generate_max_proc_nr () =
11887   pr "%d\n" max_proc_nr
11888
11889 let output_to filename k =
11890   let filename_new = filename ^ ".new" in
11891   chan := open_out filename_new;
11892   k ();
11893   close_out !chan;
11894   chan := Pervasives.stdout;
11895
11896   (* Is the new file different from the current file? *)
11897   if Sys.file_exists filename && files_equal filename filename_new then
11898     unlink filename_new                 (* same, so skip it *)
11899   else (
11900     (* different, overwrite old one *)
11901     (try chmod filename 0o644 with Unix_error _ -> ());
11902     rename filename_new filename;
11903     chmod filename 0o444;
11904     printf "written %s\n%!" filename;
11905   )
11906
11907 let perror msg = function
11908   | Unix_error (err, _, _) ->
11909       eprintf "%s: %s\n" msg (error_message err)
11910   | exn ->
11911       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11912
11913 (* Main program. *)
11914 let () =
11915   let lock_fd =
11916     try openfile "HACKING" [O_RDWR] 0
11917     with
11918     | Unix_error (ENOENT, _, _) ->
11919         eprintf "\
11920 You are probably running this from the wrong directory.
11921 Run it from the top source directory using the command
11922   src/generator.ml
11923 ";
11924         exit 1
11925     | exn ->
11926         perror "open: HACKING" exn;
11927         exit 1 in
11928
11929   (* Acquire a lock so parallel builds won't try to run the generator
11930    * twice at the same time.  Subsequent builds will wait for the first
11931    * one to finish.  Note the lock is released implicitly when the
11932    * program exits.
11933    *)
11934   (try lockf lock_fd F_LOCK 1
11935    with exn ->
11936      perror "lock: HACKING" exn;
11937      exit 1);
11938
11939   check_functions ();
11940
11941   output_to "src/guestfs_protocol.x" generate_xdr;
11942   output_to "src/guestfs-structs.h" generate_structs_h;
11943   output_to "src/guestfs-actions.h" generate_actions_h;
11944   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11945   output_to "src/guestfs-actions.c" generate_client_actions;
11946   output_to "src/guestfs-bindtests.c" generate_bindtests;
11947   output_to "src/guestfs-structs.pod" generate_structs_pod;
11948   output_to "src/guestfs-actions.pod" generate_actions_pod;
11949   output_to "src/guestfs-availability.pod" generate_availability_pod;
11950   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11951   output_to "src/libguestfs.syms" generate_linker_script;
11952   output_to "daemon/actions.h" generate_daemon_actions_h;
11953   output_to "daemon/stubs.c" generate_daemon_actions;
11954   output_to "daemon/names.c" generate_daemon_names;
11955   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11956   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11957   output_to "capitests/tests.c" generate_tests;
11958   output_to "fish/cmds.c" generate_fish_cmds;
11959   output_to "fish/completion.c" generate_fish_completion;
11960   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11961   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11962   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11963   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11964   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11965   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11966   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11967   output_to "perl/Guestfs.xs" generate_perl_xs;
11968   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11969   output_to "perl/bindtests.pl" generate_perl_bindtests;
11970   output_to "python/guestfs-py.c" generate_python_c;
11971   output_to "python/guestfs.py" generate_python_py;
11972   output_to "python/bindtests.py" generate_python_bindtests;
11973   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11974   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11975   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11976
11977   List.iter (
11978     fun (typ, jtyp) ->
11979       let cols = cols_of_struct typ in
11980       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11981       output_to filename (generate_java_struct jtyp cols);
11982   ) java_structs;
11983
11984   output_to "java/Makefile.inc" generate_java_makefile_inc;
11985   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11986   output_to "java/Bindtests.java" generate_java_bindtests;
11987   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11988   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11989   output_to "csharp/Libguestfs.cs" generate_csharp;
11990
11991   (* Always generate this file last, and unconditionally.  It's used
11992    * by the Makefile to know when we must re-run the generator.
11993    *)
11994   let chan = open_out "src/stamp-generator" in
11995   fprintf chan "1\n";
11996   close_out chan;
11997
11998   printf "generated %d lines of code\n" !lines