New API: available-all-groups to return list of all optional groups.
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <const char *, size_t> pair.
169      * Most other languages have a string type which can contain
170      * ASCII NUL.  We use whatever type is appropriate for each
171      * language.
172      * Buffers are limited by the total message size.  To transfer
173      * large blocks of data, use FileIn/FileOut parameters instead.
174      * To return an arbitrary buffer, use RBufferOut.
175      *)
176   | BufferIn of string
177
178 type flags =
179   | ProtocolLimitWarning  (* display warning about protocol size limits *)
180   | DangerWillRobinson    (* flags particularly dangerous commands *)
181   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
182   | FishOutput of fish_output_t (* how to display output in guestfish *)
183   | NotInFish             (* do not export via guestfish *)
184   | NotInDocs             (* do not add this function to documentation *)
185   | DeprecatedBy of string (* function is deprecated, use .. instead *)
186   | Optional of string    (* function is part of an optional group *)
187
188 and fish_output_t =
189   | FishOutputOctal       (* for int return, print in octal *)
190   | FishOutputHexadecimal (* for int return, print in hex *)
191
192 (* You can supply zero or as many tests as you want per API call.
193  *
194  * Note that the test environment has 3 block devices, of size 500MB,
195  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196  * a fourth ISO block device with some known files on it (/dev/sdd).
197  *
198  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199  * Number of cylinders was 63 for IDE emulated disks with precisely
200  * the same size.  How exactly this is calculated is a mystery.
201  *
202  * The ISO block device (/dev/sdd) comes from images/test.iso.
203  *
204  * To be able to run the tests in a reasonable amount of time,
205  * the virtual machine and block devices are reused between tests.
206  * So don't try testing kill_subprocess :-x
207  *
208  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
209  *
210  * Don't assume anything about the previous contents of the block
211  * devices.  Use 'Init*' to create some initial scenarios.
212  *
213  * You can add a prerequisite clause to any individual test.  This
214  * is a run-time check, which, if it fails, causes the test to be
215  * skipped.  Useful if testing a command which might not work on
216  * all variations of libguestfs builds.  A test that has prerequisite
217  * of 'Always' is run unconditionally.
218  *
219  * In addition, packagers can skip individual tests by setting the
220  * environment variables:     eg:
221  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
222  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
223  *)
224 type tests = (test_init * test_prereq * test) list
225 and test =
226     (* Run the command sequence and just expect nothing to fail. *)
227   | TestRun of seq
228
229     (* Run the command sequence and expect the output of the final
230      * command to be the string.
231      *)
232   | TestOutput of seq * string
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the list of strings.
236      *)
237   | TestOutputList of seq * string list
238
239     (* Run the command sequence and expect the output of the final
240      * command to be the list of block devices (could be either
241      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242      * character of each string).
243      *)
244   | TestOutputListOfDevices of seq * string list
245
246     (* Run the command sequence and expect the output of the final
247      * command to be the integer.
248      *)
249   | TestOutputInt of seq * int
250
251     (* Run the command sequence and expect the output of the final
252      * command to be <op> <int>, eg. ">=", "1".
253      *)
254   | TestOutputIntOp of seq * string * int
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a true value (!= 0 or != NULL).
258      *)
259   | TestOutputTrue of seq
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a false value (== 0 or == NULL, but not an error).
263      *)
264   | TestOutputFalse of seq
265
266     (* Run the command sequence and expect the output of the final
267      * command to be a list of the given length (but don't care about
268      * content).
269      *)
270   | TestOutputLength of seq * int
271
272     (* Run the command sequence and expect the output of the final
273      * command to be a buffer (RBufferOut), ie. string + size.
274      *)
275   | TestOutputBuffer of seq * string
276
277     (* Run the command sequence and expect the output of the final
278      * command to be a structure.
279      *)
280   | TestOutputStruct of seq * test_field_compare list
281
282     (* Run the command sequence and expect the final command (only)
283      * to fail.
284      *)
285   | TestLastFail of seq
286
287 and test_field_compare =
288   | CompareWithInt of string * int
289   | CompareWithIntOp of string * string * int
290   | CompareWithString of string * string
291   | CompareFieldsIntEq of string * string
292   | CompareFieldsStrEq of string * string
293
294 (* Test prerequisites. *)
295 and test_prereq =
296     (* Test always runs. *)
297   | Always
298
299     (* Test is currently disabled - eg. it fails, or it tests some
300      * unimplemented feature.
301      *)
302   | Disabled
303
304     (* 'string' is some C code (a function body) that should return
305      * true or false.  The test will run if the code returns true.
306      *)
307   | If of string
308
309     (* As for 'If' but the test runs _unless_ the code returns true. *)
310   | Unless of string
311
312 (* Some initial scenarios for testing. *)
313 and test_init =
314     (* Do nothing, block devices could contain random stuff including
315      * LVM PVs, and some filesystems might be mounted.  This is usually
316      * a bad idea.
317      *)
318   | InitNone
319
320     (* Block devices are empty and no filesystems are mounted. *)
321   | InitEmpty
322
323     (* /dev/sda contains a single partition /dev/sda1, with random
324      * content.  /dev/sdb and /dev/sdc may have random content.
325      * No LVM.
326      *)
327   | InitPartition
328
329     (* /dev/sda contains a single partition /dev/sda1, which is formatted
330      * as ext2, empty [except for lost+found] and mounted on /.
331      * /dev/sdb and /dev/sdc may have random content.
332      * No LVM.
333      *)
334   | InitBasicFS
335
336     (* /dev/sda:
337      *   /dev/sda1 (is a PV):
338      *     /dev/VG/LV (size 8MB):
339      *       formatted as ext2, empty [except for lost+found], mounted on /
340      * /dev/sdb and /dev/sdc may have random content.
341      *)
342   | InitBasicFSonLVM
343
344     (* /dev/sdd (the ISO, see images/ directory in source)
345      * is mounted on /
346      *)
347   | InitISOFS
348
349 (* Sequence of commands for testing. *)
350 and seq = cmd list
351 and cmd = string list
352
353 (* Note about long descriptions: When referring to another
354  * action, use the format C<guestfs_other> (ie. the full name of
355  * the C function).  This will be replaced as appropriate in other
356  * language bindings.
357  *
358  * Apart from that, long descriptions are just perldoc paragraphs.
359  *)
360
361 (* Generate a random UUID (used in tests). *)
362 let uuidgen () =
363   let chan = open_process_in "uuidgen" in
364   let uuid = input_line chan in
365   (match close_process_in chan with
366    | WEXITED 0 -> ()
367    | WEXITED _ ->
368        failwith "uuidgen: process exited with non-zero status"
369    | WSIGNALED _ | WSTOPPED _ ->
370        failwith "uuidgen: process signalled or stopped by signal"
371   );
372   uuid
373
374 (* These test functions are used in the language binding tests. *)
375
376 let test_all_args = [
377   String "str";
378   OptString "optstr";
379   StringList "strlist";
380   Bool "b";
381   Int "integer";
382   Int64 "integer64";
383   FileIn "filein";
384   FileOut "fileout";
385   BufferIn "bufferin";
386 ]
387
388 let test_all_rets = [
389   (* except for RErr, which is tested thoroughly elsewhere *)
390   "test0rint",         RInt "valout";
391   "test0rint64",       RInt64 "valout";
392   "test0rbool",        RBool "valout";
393   "test0rconststring", RConstString "valout";
394   "test0rconstoptstring", RConstOptString "valout";
395   "test0rstring",      RString "valout";
396   "test0rstringlist",  RStringList "valout";
397   "test0rstruct",      RStruct ("valout", "lvm_pv");
398   "test0rstructlist",  RStructList ("valout", "lvm_pv");
399   "test0rhashtable",   RHashtable "valout";
400 ]
401
402 let test_functions = [
403   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
404    [],
405    "internal test function - do not use",
406    "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 parameter type correctly.
410
411 It echos the contents of each parameter to stdout.
412
413 You probably don't want to call this function.");
414 ] @ List.flatten (
415   List.map (
416     fun (name, ret) ->
417       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
418         [],
419         "internal test function - do not use",
420         "\
421 This is an internal test function which is used to test whether
422 the automatically generated bindings can handle every possible
423 return type correctly.
424
425 It converts string C<val> to the return type.
426
427 You probably don't want to call this function.");
428        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
429         [],
430         "internal test function - do not use",
431         "\
432 This is an internal test function which is used to test whether
433 the automatically generated bindings can handle every possible
434 return type correctly.
435
436 This function always returns an error.
437
438 You probably don't want to call this function.")]
439   ) test_all_rets
440 )
441
442 (* non_daemon_functions are any functions which don't get processed
443  * in the daemon, eg. functions for setting and getting local
444  * configuration values.
445  *)
446
447 let non_daemon_functions = test_functions @ [
448   ("launch", (RErr, []), -1, [FishAlias "run"],
449    [],
450    "launch the qemu subprocess",
451    "\
452 Internally libguestfs is implemented by running a virtual machine
453 using L<qemu(1)>.
454
455 You should call this after configuring the handle
456 (eg. adding drives) but before performing any actions.");
457
458   ("wait_ready", (RErr, []), -1, [NotInFish],
459    [],
460    "wait until the qemu subprocess launches (no op)",
461    "\
462 This function is a no op.
463
464 In versions of the API E<lt> 1.0.71 you had to call this function
465 just after calling C<guestfs_launch> to wait for the launch
466 to complete.  However this is no longer necessary because
467 C<guestfs_launch> now does the waiting.
468
469 If you see any calls to this function in code then you can just
470 remove them, unless you want to retain compatibility with older
471 versions of the API.");
472
473   ("kill_subprocess", (RErr, []), -1, [],
474    [],
475    "kill the qemu subprocess",
476    "\
477 This kills the qemu subprocess.  You should never need to call this.");
478
479   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
480    [],
481    "add an image to examine or modify",
482    "\
483 This function adds a virtual machine disk image C<filename> to the
484 guest.  The first time you call this function, the disk appears as IDE
485 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
486 so on.
487
488 You don't necessarily need to be root when using libguestfs.  However
489 you obviously do need sufficient permissions to access the filename
490 for whatever operations you want to perform (ie. read access if you
491 just want to read the image or write access if you want to modify the
492 image).
493
494 This is equivalent to the qemu parameter
495 C<-drive file=filename,cache=off,if=...>.
496
497 C<cache=off> is omitted in cases where it is not supported by
498 the underlying filesystem.
499
500 C<if=...> is set at compile time by the configuration option
501 C<./configure --with-drive-if=...>.  In the rare case where you
502 might need to change this at run time, use C<guestfs_add_drive_with_if>
503 or C<guestfs_add_drive_ro_with_if>.
504
505 Note that this call checks for the existence of C<filename>.  This
506 stops you from specifying other types of drive which are supported
507 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
508 the general C<guestfs_config> call instead.");
509
510   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
511    [],
512    "add a CD-ROM disk image to examine",
513    "\
514 This function adds a virtual CD-ROM disk image to the guest.
515
516 This is equivalent to the qemu parameter C<-cdrom filename>.
517
518 Notes:
519
520 =over 4
521
522 =item *
523
524 This call checks for the existence of C<filename>.  This
525 stops you from specifying other types of drive which are supported
526 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
527 the general C<guestfs_config> call instead.
528
529 =item *
530
531 If you just want to add an ISO file (often you use this as an
532 efficient way to transfer large files into the guest), then you
533 should probably use C<guestfs_add_drive_ro> instead.
534
535 =back");
536
537   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
538    [],
539    "add a drive in snapshot mode (read-only)",
540    "\
541 This adds a drive in snapshot mode, making it effectively
542 read-only.
543
544 Note that writes to the device are allowed, and will be seen for
545 the duration of the guestfs handle, but they are written
546 to a temporary file which is discarded as soon as the guestfs
547 handle is closed.  We don't currently have any method to enable
548 changes to be committed, although qemu can support this.
549
550 This is equivalent to the qemu parameter
551 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
552
553 C<if=...> is set at compile time by the configuration option
554 C<./configure --with-drive-if=...>.  In the rare case where you
555 might need to change this at run time, use C<guestfs_add_drive_with_if>
556 or C<guestfs_add_drive_ro_with_if>.
557
558 C<readonly=on> is only added where qemu supports this option.
559
560 Note that this call checks for the existence of C<filename>.  This
561 stops you from specifying other types of drive which are supported
562 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
563 the general C<guestfs_config> call instead.");
564
565   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
566    [],
567    "add qemu parameters",
568    "\
569 This can be used to add arbitrary qemu command line parameters
570 of the form C<-param value>.  Actually it's not quite arbitrary - we
571 prevent you from setting some parameters which would interfere with
572 parameters that we use.
573
574 The first character of C<param> string must be a C<-> (dash).
575
576 C<value> can be NULL.");
577
578   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
579    [],
580    "set the qemu binary",
581    "\
582 Set the qemu binary that we will use.
583
584 The default is chosen when the library was compiled by the
585 configure script.
586
587 You can also override this by setting the C<LIBGUESTFS_QEMU>
588 environment variable.
589
590 Setting C<qemu> to C<NULL> restores the default qemu binary.
591
592 Note that you should call this function as early as possible
593 after creating the handle.  This is because some pre-launch
594 operations depend on testing qemu features (by running C<qemu -help>).
595 If the qemu binary changes, we don't retest features, and
596 so you might see inconsistent results.  Using the environment
597 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
598 the qemu binary at the same time as the handle is created.");
599
600   ("get_qemu", (RConstString "qemu", []), -1, [],
601    [InitNone, Always, TestRun (
602       [["get_qemu"]])],
603    "get the qemu binary",
604    "\
605 Return the current qemu binary.
606
607 This is always non-NULL.  If it wasn't set already, then this will
608 return the default qemu binary name.");
609
610   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
611    [],
612    "set the search path",
613    "\
614 Set the path that libguestfs searches for kernel and initrd.img.
615
616 The default is C<$libdir/guestfs> unless overridden by setting
617 C<LIBGUESTFS_PATH> environment variable.
618
619 Setting C<path> to C<NULL> restores the default path.");
620
621   ("get_path", (RConstString "path", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_path"]])],
624    "get the search path",
625    "\
626 Return the current search path.
627
628 This is always non-NULL.  If it wasn't set already, then this will
629 return the default path.");
630
631   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
632    [],
633    "add options to kernel command line",
634    "\
635 This function is used to add additional options to the
636 guest kernel command line.
637
638 The default is C<NULL> unless overridden by setting
639 C<LIBGUESTFS_APPEND> environment variable.
640
641 Setting C<append> to C<NULL> means I<no> additional options
642 are passed (libguestfs always adds a few of its own).");
643
644   ("get_append", (RConstOptString "append", []), -1, [],
645    (* This cannot be tested with the current framework.  The
646     * function can return NULL in normal operations, which the
647     * test framework interprets as an error.
648     *)
649    [],
650    "get the additional kernel options",
651    "\
652 Return the additional kernel options which are added to the
653 guest kernel command line.
654
655 If C<NULL> then no options are added.");
656
657   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658    [],
659    "set autosync mode",
660    "\
661 If C<autosync> is true, this enables autosync.  Libguestfs will make a
662 best effort attempt to run C<guestfs_umount_all> followed by
663 C<guestfs_sync> when the handle is closed
664 (also if the program exits without closing handles).
665
666 This is disabled by default (except in guestfish where it is
667 enabled by default).");
668
669   ("get_autosync", (RBool "autosync", []), -1, [],
670    [InitNone, Always, TestRun (
671       [["get_autosync"]])],
672    "get autosync mode",
673    "\
674 Get the autosync flag.");
675
676   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677    [],
678    "set verbose mode",
679    "\
680 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
681
682 Verbose messages are disabled unless the environment variable
683 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
684
685   ("get_verbose", (RBool "verbose", []), -1, [],
686    [],
687    "get verbose mode",
688    "\
689 This returns the verbose messages flag.");
690
691   ("is_ready", (RBool "ready", []), -1, [],
692    [InitNone, Always, TestOutputTrue (
693       [["is_ready"]])],
694    "is ready to accept commands",
695    "\
696 This returns true iff this handle is ready to accept commands
697 (in the C<READY> state).
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("is_config", (RBool "config", []), -1, [],
702    [InitNone, Always, TestOutputFalse (
703       [["is_config"]])],
704    "is in configuration state",
705    "\
706 This returns true iff this handle is being configured
707 (in the C<CONFIG> state).
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("is_launching", (RBool "launching", []), -1, [],
712    [InitNone, Always, TestOutputFalse (
713       [["is_launching"]])],
714    "is launching subprocess",
715    "\
716 This returns true iff this handle is launching the subprocess
717 (in the C<LAUNCHING> state).
718
719 For more information on states, see L<guestfs(3)>.");
720
721   ("is_busy", (RBool "busy", []), -1, [],
722    [InitNone, Always, TestOutputFalse (
723       [["is_busy"]])],
724    "is busy processing a command",
725    "\
726 This returns true iff this handle is busy processing a command
727 (in the C<BUSY> state).
728
729 For more information on states, see L<guestfs(3)>.");
730
731   ("get_state", (RInt "state", []), -1, [],
732    [],
733    "get the current state",
734    "\
735 This returns the current state as an opaque integer.  This is
736 only useful for printing debug and internal error messages.
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
741    [InitNone, Always, TestOutputInt (
742       [["set_memsize"; "500"];
743        ["get_memsize"]], 500)],
744    "set memory allocated to the qemu subprocess",
745    "\
746 This sets the memory size in megabytes allocated to the
747 qemu subprocess.  This only has any effect if called before
748 C<guestfs_launch>.
749
750 You can also change this by setting the environment
751 variable C<LIBGUESTFS_MEMSIZE> before the handle is
752 created.
753
754 For more information on the architecture of libguestfs,
755 see L<guestfs(3)>.");
756
757   ("get_memsize", (RInt "memsize", []), -1, [],
758    [InitNone, Always, TestOutputIntOp (
759       [["get_memsize"]], ">=", 256)],
760    "get memory allocated to the qemu subprocess",
761    "\
762 This gets the memory size in megabytes allocated to the
763 qemu subprocess.
764
765 If C<guestfs_set_memsize> was not called
766 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
767 then this returns the compiled-in default value for memsize.
768
769 For more information on the architecture of libguestfs,
770 see L<guestfs(3)>.");
771
772   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
773    [InitNone, Always, TestOutputIntOp (
774       [["get_pid"]], ">=", 1)],
775    "get PID of qemu subprocess",
776    "\
777 Return the process ID of the qemu subprocess.  If there is no
778 qemu subprocess, then this will return an error.
779
780 This is an internal call used for debugging and testing.");
781
782   ("version", (RStruct ("version", "version"), []), -1, [],
783    [InitNone, Always, TestOutputStruct (
784       [["version"]], [CompareWithInt ("major", 1)])],
785    "get the library version number",
786    "\
787 Return the libguestfs version number that the program is linked
788 against.
789
790 Note that because of dynamic linking this is not necessarily
791 the version of libguestfs that you compiled against.  You can
792 compile the program, and then at runtime dynamically link
793 against a completely different C<libguestfs.so> library.
794
795 This call was added in version C<1.0.58>.  In previous
796 versions of libguestfs there was no way to get the version
797 number.  From C code you can use dynamic linker functions
798 to find out if this symbol exists (if it doesn't, then
799 it's an earlier version).
800
801 The call returns a structure with four elements.  The first
802 three (C<major>, C<minor> and C<release>) are numbers and
803 correspond to the usual version triplet.  The fourth element
804 (C<extra>) is a string and is normally empty, but may be
805 used for distro-specific information.
806
807 To construct the original version string:
808 C<$major.$minor.$release$extra>
809
810 I<Note:> Don't use this call to test for availability
811 of features.  Distro backports makes this unreliable.  Use
812 C<guestfs_available> instead.");
813
814   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
815    [InitNone, Always, TestOutputTrue (
816       [["set_selinux"; "true"];
817        ["get_selinux"]])],
818    "set SELinux enabled or disabled at appliance boot",
819    "\
820 This sets the selinux flag that is passed to the appliance
821 at boot time.  The default is C<selinux=0> (disabled).
822
823 Note that if SELinux is enabled, it is always in
824 Permissive mode (C<enforcing=0>).
825
826 For more information on the architecture of libguestfs,
827 see L<guestfs(3)>.");
828
829   ("get_selinux", (RBool "selinux", []), -1, [],
830    [],
831    "get SELinux enabled flag",
832    "\
833 This returns the current setting of the selinux flag which
834 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
835
836 For more information on the architecture of libguestfs,
837 see L<guestfs(3)>.");
838
839   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
840    [InitNone, Always, TestOutputFalse (
841       [["set_trace"; "false"];
842        ["get_trace"]])],
843    "enable or disable command traces",
844    "\
845 If the command trace flag is set to 1, then commands are
846 printed on stdout before they are executed in a format
847 which is very similar to the one used by guestfish.  In
848 other words, you can run a program with this enabled, and
849 you will get out a script which you can feed to guestfish
850 to perform the same set of actions.
851
852 If you want to trace C API calls into libguestfs (and
853 other libraries) then possibly a better way is to use
854 the external ltrace(1) command.
855
856 Command traces are disabled unless the environment variable
857 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
858
859   ("get_trace", (RBool "trace", []), -1, [],
860    [],
861    "get command trace enabled flag",
862    "\
863 Return the command trace flag.");
864
865   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
866    [InitNone, Always, TestOutputFalse (
867       [["set_direct"; "false"];
868        ["get_direct"]])],
869    "enable or disable direct appliance mode",
870    "\
871 If the direct appliance mode flag is enabled, then stdin and
872 stdout are passed directly through to the appliance once it
873 is launched.
874
875 One consequence of this is that log messages aren't caught
876 by the library and handled by C<guestfs_set_log_message_callback>,
877 but go straight to stdout.
878
879 You probably don't want to use this unless you know what you
880 are doing.
881
882 The default is disabled.");
883
884   ("get_direct", (RBool "direct", []), -1, [],
885    [],
886    "get direct appliance mode flag",
887    "\
888 Return the direct appliance mode flag.");
889
890   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
891    [InitNone, Always, TestOutputTrue (
892       [["set_recovery_proc"; "true"];
893        ["get_recovery_proc"]])],
894    "enable or disable the recovery process",
895    "\
896 If this is called with the parameter C<false> then
897 C<guestfs_launch> does not create a recovery process.  The
898 purpose of the recovery process is to stop runaway qemu
899 processes in the case where the main program aborts abruptly.
900
901 This only has any effect if called before C<guestfs_launch>,
902 and the default is true.
903
904 About the only time when you would want to disable this is
905 if the main process will fork itself into the background
906 (\"daemonize\" itself).  In this case the recovery process
907 thinks that the main program has disappeared and so kills
908 qemu, which is not very helpful.");
909
910   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
911    [],
912    "get recovery process enabled flag",
913    "\
914 Return the recovery process enabled flag.");
915
916   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
917    [],
918    "add a drive specifying the QEMU block emulation to use",
919    "\
920 This is the same as C<guestfs_add_drive> but it allows you
921 to specify the QEMU interface emulation to use at run time.");
922
923   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive read-only specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive_ro> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930 ]
931
932 (* daemon_functions are any functions which cause some action
933  * to take place in the daemon.
934  *)
935
936 let daemon_functions = [
937   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
938    [InitEmpty, Always, TestOutput (
939       [["part_disk"; "/dev/sda"; "mbr"];
940        ["mkfs"; "ext2"; "/dev/sda1"];
941        ["mount"; "/dev/sda1"; "/"];
942        ["write"; "/new"; "new file contents"];
943        ["cat"; "/new"]], "new file contents")],
944    "mount a guest disk at a position in the filesystem",
945    "\
946 Mount a guest disk at a position in the filesystem.  Block devices
947 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
948 the guest.  If those block devices contain partitions, they will have
949 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
950 names can be used.
951
952 The rules are the same as for L<mount(2)>:  A filesystem must
953 first be mounted on C</> before others can be mounted.  Other
954 filesystems can only be mounted on directories which already
955 exist.
956
957 The mounted filesystem is writable, if we have sufficient permissions
958 on the underlying device.
959
960 B<Important note:>
961 When you use this call, the filesystem options C<sync> and C<noatime>
962 are set implicitly.  This was originally done because we thought it
963 would improve reliability, but it turns out that I<-o sync> has a
964 very large negative performance impact and negligible effect on
965 reliability.  Therefore we recommend that you avoid using
966 C<guestfs_mount> in any code that needs performance, and instead
967 use C<guestfs_mount_options> (use an empty string for the first
968 parameter if you don't want any options).");
969
970   ("sync", (RErr, []), 2, [],
971    [ InitEmpty, Always, TestRun [["sync"]]],
972    "sync disks, writes are flushed through to the disk image",
973    "\
974 This syncs the disk, so that any writes are flushed through to the
975 underlying disk image.
976
977 You should always call this if you have modified a disk image, before
978 closing the handle.");
979
980   ("touch", (RErr, [Pathname "path"]), 3, [],
981    [InitBasicFS, Always, TestOutputTrue (
982       [["touch"; "/new"];
983        ["exists"; "/new"]])],
984    "update file timestamps or create a new file",
985    "\
986 Touch acts like the L<touch(1)> command.  It can be used to
987 update the timestamps on a file, or, if the file does not exist,
988 to create a new zero-length file.");
989
990   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
991    [InitISOFS, Always, TestOutput (
992       [["cat"; "/known-2"]], "abcdef\n")],
993    "list the contents of a file",
994    "\
995 Return the contents of the file named C<path>.
996
997 Note that this function cannot correctly handle binary files
998 (specifically, files containing C<\\0> character which is treated
999 as end of string).  For those you need to use the C<guestfs_read_file>
1000 or C<guestfs_download> functions which have a more complex interface.");
1001
1002   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1003    [], (* XXX Tricky to test because it depends on the exact format
1004         * of the 'ls -l' command, which changes between F10 and F11.
1005         *)
1006    "list the files in a directory (long format)",
1007    "\
1008 List the files in C<directory> (relative to the root directory,
1009 there is no cwd) in the format of 'ls -la'.
1010
1011 This command is mostly useful for interactive sessions.  It
1012 is I<not> intended that you try to parse the output string.");
1013
1014   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1015    [InitBasicFS, Always, TestOutputList (
1016       [["touch"; "/new"];
1017        ["touch"; "/newer"];
1018        ["touch"; "/newest"];
1019        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1020    "list the files in a directory",
1021    "\
1022 List the files in C<directory> (relative to the root directory,
1023 there is no cwd).  The '.' and '..' entries are not returned, but
1024 hidden files are shown.
1025
1026 This command is mostly useful for interactive sessions.  Programs
1027 should probably use C<guestfs_readdir> instead.");
1028
1029   ("list_devices", (RStringList "devices", []), 7, [],
1030    [InitEmpty, Always, TestOutputListOfDevices (
1031       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1032    "list the block devices",
1033    "\
1034 List all the block devices.
1035
1036 The full block device names are returned, eg. C</dev/sda>");
1037
1038   ("list_partitions", (RStringList "partitions", []), 8, [],
1039    [InitBasicFS, Always, TestOutputListOfDevices (
1040       [["list_partitions"]], ["/dev/sda1"]);
1041     InitEmpty, Always, TestOutputListOfDevices (
1042       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1043        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1044    "list the partitions",
1045    "\
1046 List all the partitions detected on all block devices.
1047
1048 The full partition device names are returned, eg. C</dev/sda1>
1049
1050 This does not return logical volumes.  For that you will need to
1051 call C<guestfs_lvs>.");
1052
1053   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1054    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1055       [["pvs"]], ["/dev/sda1"]);
1056     InitEmpty, Always, TestOutputListOfDevices (
1057       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1058        ["pvcreate"; "/dev/sda1"];
1059        ["pvcreate"; "/dev/sda2"];
1060        ["pvcreate"; "/dev/sda3"];
1061        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1062    "list the LVM physical volumes (PVs)",
1063    "\
1064 List all the physical volumes detected.  This is the equivalent
1065 of the L<pvs(8)> command.
1066
1067 This returns a list of just the device names that contain
1068 PVs (eg. C</dev/sda2>).
1069
1070 See also C<guestfs_pvs_full>.");
1071
1072   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1073    [InitBasicFSonLVM, Always, TestOutputList (
1074       [["vgs"]], ["VG"]);
1075     InitEmpty, Always, TestOutputList (
1076       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1077        ["pvcreate"; "/dev/sda1"];
1078        ["pvcreate"; "/dev/sda2"];
1079        ["pvcreate"; "/dev/sda3"];
1080        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1081        ["vgcreate"; "VG2"; "/dev/sda3"];
1082        ["vgs"]], ["VG1"; "VG2"])],
1083    "list the LVM volume groups (VGs)",
1084    "\
1085 List all the volumes groups detected.  This is the equivalent
1086 of the L<vgs(8)> command.
1087
1088 This returns a list of just the volume group names that were
1089 detected (eg. C<VolGroup00>).
1090
1091 See also C<guestfs_vgs_full>.");
1092
1093   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1094    [InitBasicFSonLVM, Always, TestOutputList (
1095       [["lvs"]], ["/dev/VG/LV"]);
1096     InitEmpty, Always, TestOutputList (
1097       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1098        ["pvcreate"; "/dev/sda1"];
1099        ["pvcreate"; "/dev/sda2"];
1100        ["pvcreate"; "/dev/sda3"];
1101        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1102        ["vgcreate"; "VG2"; "/dev/sda3"];
1103        ["lvcreate"; "LV1"; "VG1"; "50"];
1104        ["lvcreate"; "LV2"; "VG1"; "50"];
1105        ["lvcreate"; "LV3"; "VG2"; "50"];
1106        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1107    "list the LVM logical volumes (LVs)",
1108    "\
1109 List all the logical volumes detected.  This is the equivalent
1110 of the L<lvs(8)> command.
1111
1112 This returns a list of the logical volume device names
1113 (eg. C</dev/VolGroup00/LogVol00>).
1114
1115 See also C<guestfs_lvs_full>.");
1116
1117   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1118    [], (* XXX how to test? *)
1119    "list the LVM physical volumes (PVs)",
1120    "\
1121 List all the physical volumes detected.  This is the equivalent
1122 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1123
1124   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1125    [], (* XXX how to test? *)
1126    "list the LVM volume groups (VGs)",
1127    "\
1128 List all the volumes groups detected.  This is the equivalent
1129 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1130
1131   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1132    [], (* XXX how to test? *)
1133    "list the LVM logical volumes (LVs)",
1134    "\
1135 List all the logical volumes detected.  This is the equivalent
1136 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1137
1138   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1139    [InitISOFS, Always, TestOutputList (
1140       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1141     InitISOFS, Always, TestOutputList (
1142       [["read_lines"; "/empty"]], [])],
1143    "read file as lines",
1144    "\
1145 Return the contents of the file named C<path>.
1146
1147 The file contents are returned as a list of lines.  Trailing
1148 C<LF> and C<CRLF> character sequences are I<not> returned.
1149
1150 Note that this function cannot correctly handle binary files
1151 (specifically, files containing C<\\0> character which is treated
1152 as end of line).  For those you need to use the C<guestfs_read_file>
1153 function which has a more complex interface.");
1154
1155   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1156    [], (* XXX Augeas code needs tests. *)
1157    "create a new Augeas handle",
1158    "\
1159 Create a new Augeas handle for editing configuration files.
1160 If there was any previous Augeas handle associated with this
1161 guestfs session, then it is closed.
1162
1163 You must call this before using any other C<guestfs_aug_*>
1164 commands.
1165
1166 C<root> is the filesystem root.  C<root> must not be NULL,
1167 use C</> instead.
1168
1169 The flags are the same as the flags defined in
1170 E<lt>augeas.hE<gt>, the logical I<or> of the following
1171 integers:
1172
1173 =over 4
1174
1175 =item C<AUG_SAVE_BACKUP> = 1
1176
1177 Keep the original file with a C<.augsave> extension.
1178
1179 =item C<AUG_SAVE_NEWFILE> = 2
1180
1181 Save changes into a file with extension C<.augnew>, and
1182 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1183
1184 =item C<AUG_TYPE_CHECK> = 4
1185
1186 Typecheck lenses (can be expensive).
1187
1188 =item C<AUG_NO_STDINC> = 8
1189
1190 Do not use standard load path for modules.
1191
1192 =item C<AUG_SAVE_NOOP> = 16
1193
1194 Make save a no-op, just record what would have been changed.
1195
1196 =item C<AUG_NO_LOAD> = 32
1197
1198 Do not load the tree in C<guestfs_aug_init>.
1199
1200 =back
1201
1202 To close the handle, you can call C<guestfs_aug_close>.
1203
1204 To find out more about Augeas, see L<http://augeas.net/>.");
1205
1206   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1207    [], (* XXX Augeas code needs tests. *)
1208    "close the current Augeas handle",
1209    "\
1210 Close the current Augeas handle and free up any resources
1211 used by it.  After calling this, you have to call
1212 C<guestfs_aug_init> again before you can use any other
1213 Augeas functions.");
1214
1215   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1216    [], (* XXX Augeas code needs tests. *)
1217    "define an Augeas variable",
1218    "\
1219 Defines an Augeas variable C<name> whose value is the result
1220 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1221 undefined.
1222
1223 On success this returns the number of nodes in C<expr>, or
1224 C<0> if C<expr> evaluates to something which is not a nodeset.");
1225
1226   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1227    [], (* XXX Augeas code needs tests. *)
1228    "define an Augeas node",
1229    "\
1230 Defines a variable C<name> whose value is the result of
1231 evaluating C<expr>.
1232
1233 If C<expr> evaluates to an empty nodeset, a node is created,
1234 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1235 C<name> will be the nodeset containing that single node.
1236
1237 On success this returns a pair containing the
1238 number of nodes in the nodeset, and a boolean flag
1239 if a node was created.");
1240
1241   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1242    [], (* XXX Augeas code needs tests. *)
1243    "look up the value of an Augeas path",
1244    "\
1245 Look up the value associated with C<path>.  If C<path>
1246 matches exactly one node, the C<value> is returned.");
1247
1248   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1249    [], (* XXX Augeas code needs tests. *)
1250    "set Augeas path to value",
1251    "\
1252 Set the value associated with C<path> to C<val>.
1253
1254 In the Augeas API, it is possible to clear a node by setting
1255 the value to NULL.  Due to an oversight in the libguestfs API
1256 you cannot do that with this call.  Instead you must use the
1257 C<guestfs_aug_clear> call.");
1258
1259   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1260    [], (* XXX Augeas code needs tests. *)
1261    "insert a sibling Augeas node",
1262    "\
1263 Create a new sibling C<label> for C<path>, inserting it into
1264 the tree before or after C<path> (depending on the boolean
1265 flag C<before>).
1266
1267 C<path> must match exactly one existing node in the tree, and
1268 C<label> must be a label, ie. not contain C</>, C<*> or end
1269 with a bracketed index C<[N]>.");
1270
1271   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1272    [], (* XXX Augeas code needs tests. *)
1273    "remove an Augeas path",
1274    "\
1275 Remove C<path> and all of its children.
1276
1277 On success this returns the number of entries which were removed.");
1278
1279   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "move Augeas node",
1282    "\
1283 Move the node C<src> to C<dest>.  C<src> must match exactly
1284 one node.  C<dest> is overwritten if it exists.");
1285
1286   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1287    [], (* XXX Augeas code needs tests. *)
1288    "return Augeas nodes which match augpath",
1289    "\
1290 Returns a list of paths which match the path expression C<path>.
1291 The returned paths are sufficiently qualified so that they match
1292 exactly one node in the current tree.");
1293
1294   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "write all pending Augeas changes to disk",
1297    "\
1298 This writes all pending changes to disk.
1299
1300 The flags which were passed to C<guestfs_aug_init> affect exactly
1301 how files are saved.");
1302
1303   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1304    [], (* XXX Augeas code needs tests. *)
1305    "load files into the tree",
1306    "\
1307 Load files into the tree.
1308
1309 See C<aug_load> in the Augeas documentation for the full gory
1310 details.");
1311
1312   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1313    [], (* XXX Augeas code needs tests. *)
1314    "list Augeas nodes under augpath",
1315    "\
1316 This is just a shortcut for listing C<guestfs_aug_match>
1317 C<path/*> and sorting the resulting nodes into alphabetical order.");
1318
1319   ("rm", (RErr, [Pathname "path"]), 29, [],
1320    [InitBasicFS, Always, TestRun
1321       [["touch"; "/new"];
1322        ["rm"; "/new"]];
1323     InitBasicFS, Always, TestLastFail
1324       [["rm"; "/new"]];
1325     InitBasicFS, Always, TestLastFail
1326       [["mkdir"; "/new"];
1327        ["rm"; "/new"]]],
1328    "remove a file",
1329    "\
1330 Remove the single file C<path>.");
1331
1332   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1333    [InitBasicFS, Always, TestRun
1334       [["mkdir"; "/new"];
1335        ["rmdir"; "/new"]];
1336     InitBasicFS, Always, TestLastFail
1337       [["rmdir"; "/new"]];
1338     InitBasicFS, Always, TestLastFail
1339       [["touch"; "/new"];
1340        ["rmdir"; "/new"]]],
1341    "remove a directory",
1342    "\
1343 Remove the single directory C<path>.");
1344
1345   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1346    [InitBasicFS, Always, TestOutputFalse
1347       [["mkdir"; "/new"];
1348        ["mkdir"; "/new/foo"];
1349        ["touch"; "/new/foo/bar"];
1350        ["rm_rf"; "/new"];
1351        ["exists"; "/new"]]],
1352    "remove a file or directory recursively",
1353    "\
1354 Remove the file or directory C<path>, recursively removing the
1355 contents if its a directory.  This is like the C<rm -rf> shell
1356 command.");
1357
1358   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1359    [InitBasicFS, Always, TestOutputTrue
1360       [["mkdir"; "/new"];
1361        ["is_dir"; "/new"]];
1362     InitBasicFS, Always, TestLastFail
1363       [["mkdir"; "/new/foo/bar"]]],
1364    "create a directory",
1365    "\
1366 Create a directory named C<path>.");
1367
1368   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1369    [InitBasicFS, Always, TestOutputTrue
1370       [["mkdir_p"; "/new/foo/bar"];
1371        ["is_dir"; "/new/foo/bar"]];
1372     InitBasicFS, Always, TestOutputTrue
1373       [["mkdir_p"; "/new/foo/bar"];
1374        ["is_dir"; "/new/foo"]];
1375     InitBasicFS, Always, TestOutputTrue
1376       [["mkdir_p"; "/new/foo/bar"];
1377        ["is_dir"; "/new"]];
1378     (* Regression tests for RHBZ#503133: *)
1379     InitBasicFS, Always, TestRun
1380       [["mkdir"; "/new"];
1381        ["mkdir_p"; "/new"]];
1382     InitBasicFS, Always, TestLastFail
1383       [["touch"; "/new"];
1384        ["mkdir_p"; "/new"]]],
1385    "create a directory and parents",
1386    "\
1387 Create a directory named C<path>, creating any parent directories
1388 as necessary.  This is like the C<mkdir -p> shell command.");
1389
1390   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1391    [], (* XXX Need stat command to test *)
1392    "change file mode",
1393    "\
1394 Change the mode (permissions) of C<path> to C<mode>.  Only
1395 numeric modes are supported.
1396
1397 I<Note>: When using this command from guestfish, C<mode>
1398 by default would be decimal, unless you prefix it with
1399 C<0> to get octal, ie. use C<0700> not C<700>.
1400
1401 The mode actually set is affected by the umask.");
1402
1403   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1404    [], (* XXX Need stat command to test *)
1405    "change file owner and group",
1406    "\
1407 Change the file owner to C<owner> and group to C<group>.
1408
1409 Only numeric uid and gid are supported.  If you want to use
1410 names, you will need to locate and parse the password file
1411 yourself (Augeas support makes this relatively easy).");
1412
1413   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1414    [InitISOFS, Always, TestOutputTrue (
1415       [["exists"; "/empty"]]);
1416     InitISOFS, Always, TestOutputTrue (
1417       [["exists"; "/directory"]])],
1418    "test if file or directory exists",
1419    "\
1420 This returns C<true> if and only if there is a file, directory
1421 (or anything) with the given C<path> name.
1422
1423 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1424
1425   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1426    [InitISOFS, Always, TestOutputTrue (
1427       [["is_file"; "/known-1"]]);
1428     InitISOFS, Always, TestOutputFalse (
1429       [["is_file"; "/directory"]])],
1430    "test if file exists",
1431    "\
1432 This returns C<true> if and only if there is a file
1433 with the given C<path> name.  Note that it returns false for
1434 other objects like directories.
1435
1436 See also C<guestfs_stat>.");
1437
1438   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1439    [InitISOFS, Always, TestOutputFalse (
1440       [["is_dir"; "/known-3"]]);
1441     InitISOFS, Always, TestOutputTrue (
1442       [["is_dir"; "/directory"]])],
1443    "test if file exists",
1444    "\
1445 This returns C<true> if and only if there is a directory
1446 with the given C<path> name.  Note that it returns false for
1447 other objects like files.
1448
1449 See also C<guestfs_stat>.");
1450
1451   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1452    [InitEmpty, Always, TestOutputListOfDevices (
1453       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1454        ["pvcreate"; "/dev/sda1"];
1455        ["pvcreate"; "/dev/sda2"];
1456        ["pvcreate"; "/dev/sda3"];
1457        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1458    "create an LVM physical volume",
1459    "\
1460 This creates an LVM physical volume on the named C<device>,
1461 where C<device> should usually be a partition name such
1462 as C</dev/sda1>.");
1463
1464   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1465    [InitEmpty, Always, TestOutputList (
1466       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1467        ["pvcreate"; "/dev/sda1"];
1468        ["pvcreate"; "/dev/sda2"];
1469        ["pvcreate"; "/dev/sda3"];
1470        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1471        ["vgcreate"; "VG2"; "/dev/sda3"];
1472        ["vgs"]], ["VG1"; "VG2"])],
1473    "create an LVM volume group",
1474    "\
1475 This creates an LVM volume group called C<volgroup>
1476 from the non-empty list of physical volumes C<physvols>.");
1477
1478   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1479    [InitEmpty, Always, TestOutputList (
1480       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1481        ["pvcreate"; "/dev/sda1"];
1482        ["pvcreate"; "/dev/sda2"];
1483        ["pvcreate"; "/dev/sda3"];
1484        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1485        ["vgcreate"; "VG2"; "/dev/sda3"];
1486        ["lvcreate"; "LV1"; "VG1"; "50"];
1487        ["lvcreate"; "LV2"; "VG1"; "50"];
1488        ["lvcreate"; "LV3"; "VG2"; "50"];
1489        ["lvcreate"; "LV4"; "VG2"; "50"];
1490        ["lvcreate"; "LV5"; "VG2"; "50"];
1491        ["lvs"]],
1492       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1493        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1494    "create an LVM logical volume",
1495    "\
1496 This creates an LVM logical volume called C<logvol>
1497 on the volume group C<volgroup>, with C<size> megabytes.");
1498
1499   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1500    [InitEmpty, Always, TestOutput (
1501       [["part_disk"; "/dev/sda"; "mbr"];
1502        ["mkfs"; "ext2"; "/dev/sda1"];
1503        ["mount_options"; ""; "/dev/sda1"; "/"];
1504        ["write"; "/new"; "new file contents"];
1505        ["cat"; "/new"]], "new file contents")],
1506    "make a filesystem",
1507    "\
1508 This creates a filesystem on C<device> (usually a partition
1509 or LVM logical volume).  The filesystem type is C<fstype>, for
1510 example C<ext3>.");
1511
1512   ("sfdisk", (RErr, [Device "device";
1513                      Int "cyls"; Int "heads"; Int "sectors";
1514                      StringList "lines"]), 43, [DangerWillRobinson],
1515    [],
1516    "create partitions on a block device",
1517    "\
1518 This is a direct interface to the L<sfdisk(8)> program for creating
1519 partitions on block devices.
1520
1521 C<device> should be a block device, for example C</dev/sda>.
1522
1523 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1524 and sectors on the device, which are passed directly to sfdisk as
1525 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1526 of these, then the corresponding parameter is omitted.  Usually for
1527 'large' disks, you can just pass C<0> for these, but for small
1528 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1529 out the right geometry and you will need to tell it.
1530
1531 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1532 information refer to the L<sfdisk(8)> manpage.
1533
1534 To create a single partition occupying the whole disk, you would
1535 pass C<lines> as a single element list, when the single element being
1536 the string C<,> (comma).
1537
1538 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1539 C<guestfs_part_init>");
1540
1541   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1542    [],
1543    "create a file",
1544    "\
1545 This call creates a file called C<path>.  The contents of the
1546 file is the string C<content> (which can contain any 8 bit data),
1547 with length C<size>.
1548
1549 As a special case, if C<size> is C<0>
1550 then the length is calculated using C<strlen> (so in this case
1551 the content cannot contain embedded ASCII NULs).
1552
1553 I<NB.> Owing to a bug, writing content containing ASCII NUL
1554 characters does I<not> work, even if the length is specified.");
1555
1556   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1557    [InitEmpty, Always, TestOutputListOfDevices (
1558       [["part_disk"; "/dev/sda"; "mbr"];
1559        ["mkfs"; "ext2"; "/dev/sda1"];
1560        ["mount_options"; ""; "/dev/sda1"; "/"];
1561        ["mounts"]], ["/dev/sda1"]);
1562     InitEmpty, Always, TestOutputList (
1563       [["part_disk"; "/dev/sda"; "mbr"];
1564        ["mkfs"; "ext2"; "/dev/sda1"];
1565        ["mount_options"; ""; "/dev/sda1"; "/"];
1566        ["umount"; "/"];
1567        ["mounts"]], [])],
1568    "unmount a filesystem",
1569    "\
1570 This unmounts the given filesystem.  The filesystem may be
1571 specified either by its mountpoint (path) or the device which
1572 contains the filesystem.");
1573
1574   ("mounts", (RStringList "devices", []), 46, [],
1575    [InitBasicFS, Always, TestOutputListOfDevices (
1576       [["mounts"]], ["/dev/sda1"])],
1577    "show mounted filesystems",
1578    "\
1579 This returns the list of currently mounted filesystems.  It returns
1580 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1581
1582 Some internal mounts are not shown.
1583
1584 See also: C<guestfs_mountpoints>");
1585
1586   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1587    [InitBasicFS, Always, TestOutputList (
1588       [["umount_all"];
1589        ["mounts"]], []);
1590     (* check that umount_all can unmount nested mounts correctly: *)
1591     InitEmpty, Always, TestOutputList (
1592       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1593        ["mkfs"; "ext2"; "/dev/sda1"];
1594        ["mkfs"; "ext2"; "/dev/sda2"];
1595        ["mkfs"; "ext2"; "/dev/sda3"];
1596        ["mount_options"; ""; "/dev/sda1"; "/"];
1597        ["mkdir"; "/mp1"];
1598        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1599        ["mkdir"; "/mp1/mp2"];
1600        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1601        ["mkdir"; "/mp1/mp2/mp3"];
1602        ["umount_all"];
1603        ["mounts"]], [])],
1604    "unmount all filesystems",
1605    "\
1606 This unmounts all mounted filesystems.
1607
1608 Some internal mounts are not unmounted by this call.");
1609
1610   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1611    [],
1612    "remove all LVM LVs, VGs and PVs",
1613    "\
1614 This command removes all LVM logical volumes, volume groups
1615 and physical volumes.");
1616
1617   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1618    [InitISOFS, Always, TestOutput (
1619       [["file"; "/empty"]], "empty");
1620     InitISOFS, Always, TestOutput (
1621       [["file"; "/known-1"]], "ASCII text");
1622     InitISOFS, Always, TestLastFail (
1623       [["file"; "/notexists"]])],
1624    "determine file type",
1625    "\
1626 This call uses the standard L<file(1)> command to determine
1627 the type or contents of the file.  This also works on devices,
1628 for example to find out whether a partition contains a filesystem.
1629
1630 This call will also transparently look inside various types
1631 of compressed file.
1632
1633 The exact command which runs is C<file -zbsL path>.  Note in
1634 particular that the filename is not prepended to the output
1635 (the C<-b> option).");
1636
1637   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1638    [InitBasicFS, Always, TestOutput (
1639       [["upload"; "test-command"; "/test-command"];
1640        ["chmod"; "0o755"; "/test-command"];
1641        ["command"; "/test-command 1"]], "Result1");
1642     InitBasicFS, Always, TestOutput (
1643       [["upload"; "test-command"; "/test-command"];
1644        ["chmod"; "0o755"; "/test-command"];
1645        ["command"; "/test-command 2"]], "Result2\n");
1646     InitBasicFS, Always, TestOutput (
1647       [["upload"; "test-command"; "/test-command"];
1648        ["chmod"; "0o755"; "/test-command"];
1649        ["command"; "/test-command 3"]], "\nResult3");
1650     InitBasicFS, Always, TestOutput (
1651       [["upload"; "test-command"; "/test-command"];
1652        ["chmod"; "0o755"; "/test-command"];
1653        ["command"; "/test-command 4"]], "\nResult4\n");
1654     InitBasicFS, Always, TestOutput (
1655       [["upload"; "test-command"; "/test-command"];
1656        ["chmod"; "0o755"; "/test-command"];
1657        ["command"; "/test-command 5"]], "\nResult5\n\n");
1658     InitBasicFS, Always, TestOutput (
1659       [["upload"; "test-command"; "/test-command"];
1660        ["chmod"; "0o755"; "/test-command"];
1661        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1662     InitBasicFS, Always, TestOutput (
1663       [["upload"; "test-command"; "/test-command"];
1664        ["chmod"; "0o755"; "/test-command"];
1665        ["command"; "/test-command 7"]], "");
1666     InitBasicFS, Always, TestOutput (
1667       [["upload"; "test-command"; "/test-command"];
1668        ["chmod"; "0o755"; "/test-command"];
1669        ["command"; "/test-command 8"]], "\n");
1670     InitBasicFS, Always, TestOutput (
1671       [["upload"; "test-command"; "/test-command"];
1672        ["chmod"; "0o755"; "/test-command"];
1673        ["command"; "/test-command 9"]], "\n\n");
1674     InitBasicFS, Always, TestOutput (
1675       [["upload"; "test-command"; "/test-command"];
1676        ["chmod"; "0o755"; "/test-command"];
1677        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1678     InitBasicFS, Always, TestOutput (
1679       [["upload"; "test-command"; "/test-command"];
1680        ["chmod"; "0o755"; "/test-command"];
1681        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1682     InitBasicFS, Always, TestLastFail (
1683       [["upload"; "test-command"; "/test-command"];
1684        ["chmod"; "0o755"; "/test-command"];
1685        ["command"; "/test-command"]])],
1686    "run a command from the guest filesystem",
1687    "\
1688 This call runs a command from the guest filesystem.  The
1689 filesystem must be mounted, and must contain a compatible
1690 operating system (ie. something Linux, with the same
1691 or compatible processor architecture).
1692
1693 The single parameter is an argv-style list of arguments.
1694 The first element is the name of the program to run.
1695 Subsequent elements are parameters.  The list must be
1696 non-empty (ie. must contain a program name).  Note that
1697 the command runs directly, and is I<not> invoked via
1698 the shell (see C<guestfs_sh>).
1699
1700 The return value is anything printed to I<stdout> by
1701 the command.
1702
1703 If the command returns a non-zero exit status, then
1704 this function returns an error message.  The error message
1705 string is the content of I<stderr> from the command.
1706
1707 The C<$PATH> environment variable will contain at least
1708 C</usr/bin> and C</bin>.  If you require a program from
1709 another location, you should provide the full path in the
1710 first parameter.
1711
1712 Shared libraries and data files required by the program
1713 must be available on filesystems which are mounted in the
1714 correct places.  It is the caller's responsibility to ensure
1715 all filesystems that are needed are mounted at the right
1716 locations.");
1717
1718   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1719    [InitBasicFS, Always, TestOutputList (
1720       [["upload"; "test-command"; "/test-command"];
1721        ["chmod"; "0o755"; "/test-command"];
1722        ["command_lines"; "/test-command 1"]], ["Result1"]);
1723     InitBasicFS, Always, TestOutputList (
1724       [["upload"; "test-command"; "/test-command"];
1725        ["chmod"; "0o755"; "/test-command"];
1726        ["command_lines"; "/test-command 2"]], ["Result2"]);
1727     InitBasicFS, Always, TestOutputList (
1728       [["upload"; "test-command"; "/test-command"];
1729        ["chmod"; "0o755"; "/test-command"];
1730        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1731     InitBasicFS, Always, TestOutputList (
1732       [["upload"; "test-command"; "/test-command"];
1733        ["chmod"; "0o755"; "/test-command"];
1734        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1735     InitBasicFS, Always, TestOutputList (
1736       [["upload"; "test-command"; "/test-command"];
1737        ["chmod"; "0o755"; "/test-command"];
1738        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1739     InitBasicFS, Always, TestOutputList (
1740       [["upload"; "test-command"; "/test-command"];
1741        ["chmod"; "0o755"; "/test-command"];
1742        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1743     InitBasicFS, Always, TestOutputList (
1744       [["upload"; "test-command"; "/test-command"];
1745        ["chmod"; "0o755"; "/test-command"];
1746        ["command_lines"; "/test-command 7"]], []);
1747     InitBasicFS, Always, TestOutputList (
1748       [["upload"; "test-command"; "/test-command"];
1749        ["chmod"; "0o755"; "/test-command"];
1750        ["command_lines"; "/test-command 8"]], [""]);
1751     InitBasicFS, Always, TestOutputList (
1752       [["upload"; "test-command"; "/test-command"];
1753        ["chmod"; "0o755"; "/test-command"];
1754        ["command_lines"; "/test-command 9"]], ["";""]);
1755     InitBasicFS, Always, TestOutputList (
1756       [["upload"; "test-command"; "/test-command"];
1757        ["chmod"; "0o755"; "/test-command"];
1758        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1759     InitBasicFS, Always, TestOutputList (
1760       [["upload"; "test-command"; "/test-command"];
1761        ["chmod"; "0o755"; "/test-command"];
1762        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1763    "run a command, returning lines",
1764    "\
1765 This is the same as C<guestfs_command>, but splits the
1766 result into a list of lines.
1767
1768 See also: C<guestfs_sh_lines>");
1769
1770   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1771    [InitISOFS, Always, TestOutputStruct (
1772       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1773    "get file information",
1774    "\
1775 Returns file information for the given C<path>.
1776
1777 This is the same as the C<stat(2)> system call.");
1778
1779   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1780    [InitISOFS, Always, TestOutputStruct (
1781       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1782    "get file information for a symbolic link",
1783    "\
1784 Returns file information for the given C<path>.
1785
1786 This is the same as C<guestfs_stat> except that if C<path>
1787 is a symbolic link, then the link is stat-ed, not the file it
1788 refers to.
1789
1790 This is the same as the C<lstat(2)> system call.");
1791
1792   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1793    [InitISOFS, Always, TestOutputStruct (
1794       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1795    "get file system statistics",
1796    "\
1797 Returns file system statistics for any mounted file system.
1798 C<path> should be a file or directory in the mounted file system
1799 (typically it is the mount point itself, but it doesn't need to be).
1800
1801 This is the same as the C<statvfs(2)> system call.");
1802
1803   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1804    [], (* XXX test *)
1805    "get ext2/ext3/ext4 superblock details",
1806    "\
1807 This returns the contents of the ext2, ext3 or ext4 filesystem
1808 superblock on C<device>.
1809
1810 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1811 manpage for more details.  The list of fields returned isn't
1812 clearly defined, and depends on both the version of C<tune2fs>
1813 that libguestfs was built against, and the filesystem itself.");
1814
1815   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1816    [InitEmpty, Always, TestOutputTrue (
1817       [["blockdev_setro"; "/dev/sda"];
1818        ["blockdev_getro"; "/dev/sda"]])],
1819    "set block device to read-only",
1820    "\
1821 Sets the block device named C<device> to read-only.
1822
1823 This uses the L<blockdev(8)> command.");
1824
1825   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1826    [InitEmpty, Always, TestOutputFalse (
1827       [["blockdev_setrw"; "/dev/sda"];
1828        ["blockdev_getro"; "/dev/sda"]])],
1829    "set block device to read-write",
1830    "\
1831 Sets the block device named C<device> to read-write.
1832
1833 This uses the L<blockdev(8)> command.");
1834
1835   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1836    [InitEmpty, Always, TestOutputTrue (
1837       [["blockdev_setro"; "/dev/sda"];
1838        ["blockdev_getro"; "/dev/sda"]])],
1839    "is block device set to read-only",
1840    "\
1841 Returns a boolean indicating if the block device is read-only
1842 (true if read-only, false if not).
1843
1844 This uses the L<blockdev(8)> command.");
1845
1846   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1847    [InitEmpty, Always, TestOutputInt (
1848       [["blockdev_getss"; "/dev/sda"]], 512)],
1849    "get sectorsize of block device",
1850    "\
1851 This returns the size of sectors on a block device.
1852 Usually 512, but can be larger for modern devices.
1853
1854 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1855 for that).
1856
1857 This uses the L<blockdev(8)> command.");
1858
1859   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1860    [InitEmpty, Always, TestOutputInt (
1861       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1862    "get blocksize of block device",
1863    "\
1864 This returns the block size of a device.
1865
1866 (Note this is different from both I<size in blocks> and
1867 I<filesystem block size>).
1868
1869 This uses the L<blockdev(8)> command.");
1870
1871   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1872    [], (* XXX test *)
1873    "set blocksize of block device",
1874    "\
1875 This sets the block size of a device.
1876
1877 (Note this is different from both I<size in blocks> and
1878 I<filesystem block size>).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1883    [InitEmpty, Always, TestOutputInt (
1884       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1885    "get total size of device in 512-byte sectors",
1886    "\
1887 This returns the size of the device in units of 512-byte sectors
1888 (even if the sectorsize isn't 512 bytes ... weird).
1889
1890 See also C<guestfs_blockdev_getss> for the real sector size of
1891 the device, and C<guestfs_blockdev_getsize64> for the more
1892 useful I<size in bytes>.
1893
1894 This uses the L<blockdev(8)> command.");
1895
1896   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1897    [InitEmpty, Always, TestOutputInt (
1898       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1899    "get total size of device in bytes",
1900    "\
1901 This returns the size of the device in bytes.
1902
1903 See also C<guestfs_blockdev_getsz>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1908    [InitEmpty, Always, TestRun
1909       [["blockdev_flushbufs"; "/dev/sda"]]],
1910    "flush device buffers",
1911    "\
1912 This tells the kernel to flush internal buffers associated
1913 with C<device>.
1914
1915 This uses the L<blockdev(8)> command.");
1916
1917   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1918    [InitEmpty, Always, TestRun
1919       [["blockdev_rereadpt"; "/dev/sda"]]],
1920    "reread partition table",
1921    "\
1922 Reread the partition table on C<device>.
1923
1924 This uses the L<blockdev(8)> command.");
1925
1926   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1927    [InitBasicFS, Always, TestOutput (
1928       (* Pick a file from cwd which isn't likely to change. *)
1929       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1930        ["checksum"; "md5"; "/COPYING.LIB"]],
1931       Digest.to_hex (Digest.file "COPYING.LIB"))],
1932    "upload a file from the local machine",
1933    "\
1934 Upload local file C<filename> to C<remotefilename> on the
1935 filesystem.
1936
1937 C<filename> can also be a named pipe.
1938
1939 See also C<guestfs_download>.");
1940
1941   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1942    [InitBasicFS, Always, TestOutput (
1943       (* Pick a file from cwd which isn't likely to change. *)
1944       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1945        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1946        ["upload"; "testdownload.tmp"; "/upload"];
1947        ["checksum"; "md5"; "/upload"]],
1948       Digest.to_hex (Digest.file "COPYING.LIB"))],
1949    "download a file to the local machine",
1950    "\
1951 Download file C<remotefilename> and save it as C<filename>
1952 on the local machine.
1953
1954 C<filename> can also be a named pipe.
1955
1956 See also C<guestfs_upload>, C<guestfs_cat>.");
1957
1958   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1959    [InitISOFS, Always, TestOutput (
1960       [["checksum"; "crc"; "/known-3"]], "2891671662");
1961     InitISOFS, Always, TestLastFail (
1962       [["checksum"; "crc"; "/notexists"]]);
1963     InitISOFS, Always, TestOutput (
1964       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1965     InitISOFS, Always, TestOutput (
1966       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1967     InitISOFS, Always, TestOutput (
1968       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1969     InitISOFS, Always, TestOutput (
1970       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1971     InitISOFS, Always, TestOutput (
1972       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1973     InitISOFS, Always, TestOutput (
1974       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1975     (* Test for RHBZ#579608, absolute symbolic links. *)
1976     InitISOFS, Always, TestOutput (
1977       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1978    "compute MD5, SHAx or CRC checksum of file",
1979    "\
1980 This call computes the MD5, SHAx or CRC checksum of the
1981 file named C<path>.
1982
1983 The type of checksum to compute is given by the C<csumtype>
1984 parameter which must have one of the following values:
1985
1986 =over 4
1987
1988 =item C<crc>
1989
1990 Compute the cyclic redundancy check (CRC) specified by POSIX
1991 for the C<cksum> command.
1992
1993 =item C<md5>
1994
1995 Compute the MD5 hash (using the C<md5sum> program).
1996
1997 =item C<sha1>
1998
1999 Compute the SHA1 hash (using the C<sha1sum> program).
2000
2001 =item C<sha224>
2002
2003 Compute the SHA224 hash (using the C<sha224sum> program).
2004
2005 =item C<sha256>
2006
2007 Compute the SHA256 hash (using the C<sha256sum> program).
2008
2009 =item C<sha384>
2010
2011 Compute the SHA384 hash (using the C<sha384sum> program).
2012
2013 =item C<sha512>
2014
2015 Compute the SHA512 hash (using the C<sha512sum> program).
2016
2017 =back
2018
2019 The checksum is returned as a printable string.
2020
2021 To get the checksum for a device, use C<guestfs_checksum_device>.
2022
2023 To get the checksums for many files, use C<guestfs_checksums_out>.");
2024
2025   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2026    [InitBasicFS, Always, TestOutput (
2027       [["tar_in"; "../images/helloworld.tar"; "/"];
2028        ["cat"; "/hello"]], "hello\n")],
2029    "unpack tarfile to directory",
2030    "\
2031 This command uploads and unpacks local file C<tarfile> (an
2032 I<uncompressed> tar file) into C<directory>.
2033
2034 To upload a compressed tarball, use C<guestfs_tgz_in>
2035 or C<guestfs_txz_in>.");
2036
2037   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2038    [],
2039    "pack directory into tarfile",
2040    "\
2041 This command packs the contents of C<directory> and downloads
2042 it to local file C<tarfile>.
2043
2044 To download a compressed tarball, use C<guestfs_tgz_out>
2045 or C<guestfs_txz_out>.");
2046
2047   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2048    [InitBasicFS, Always, TestOutput (
2049       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2050        ["cat"; "/hello"]], "hello\n")],
2051    "unpack compressed tarball to directory",
2052    "\
2053 This command uploads and unpacks local file C<tarball> (a
2054 I<gzip compressed> tar file) into C<directory>.
2055
2056 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2057
2058   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2059    [],
2060    "pack directory into compressed tarball",
2061    "\
2062 This command packs the contents of C<directory> and downloads
2063 it to local file C<tarball>.
2064
2065 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2066
2067   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2068    [InitBasicFS, Always, TestLastFail (
2069       [["umount"; "/"];
2070        ["mount_ro"; "/dev/sda1"; "/"];
2071        ["touch"; "/new"]]);
2072     InitBasicFS, Always, TestOutput (
2073       [["write"; "/new"; "data"];
2074        ["umount"; "/"];
2075        ["mount_ro"; "/dev/sda1"; "/"];
2076        ["cat"; "/new"]], "data")],
2077    "mount a guest disk, read-only",
2078    "\
2079 This is the same as the C<guestfs_mount> command, but it
2080 mounts the filesystem with the read-only (I<-o ro>) flag.");
2081
2082   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2083    [],
2084    "mount a guest disk with mount options",
2085    "\
2086 This is the same as the C<guestfs_mount> command, but it
2087 allows you to set the mount options as for the
2088 L<mount(8)> I<-o> flag.
2089
2090 If the C<options> parameter is an empty string, then
2091 no options are passed (all options default to whatever
2092 the filesystem uses).");
2093
2094   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2095    [],
2096    "mount a guest disk with mount options and vfstype",
2097    "\
2098 This is the same as the C<guestfs_mount> command, but it
2099 allows you to set both the mount options and the vfstype
2100 as for the L<mount(8)> I<-o> and I<-t> flags.");
2101
2102   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2103    [],
2104    "debugging and internals",
2105    "\
2106 The C<guestfs_debug> command exposes some internals of
2107 C<guestfsd> (the guestfs daemon) that runs inside the
2108 qemu subprocess.
2109
2110 There is no comprehensive help for this command.  You have
2111 to look at the file C<daemon/debug.c> in the libguestfs source
2112 to find out what you can do.");
2113
2114   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2115    [InitEmpty, Always, TestOutputList (
2116       [["part_disk"; "/dev/sda"; "mbr"];
2117        ["pvcreate"; "/dev/sda1"];
2118        ["vgcreate"; "VG"; "/dev/sda1"];
2119        ["lvcreate"; "LV1"; "VG"; "50"];
2120        ["lvcreate"; "LV2"; "VG"; "50"];
2121        ["lvremove"; "/dev/VG/LV1"];
2122        ["lvs"]], ["/dev/VG/LV2"]);
2123     InitEmpty, Always, TestOutputList (
2124       [["part_disk"; "/dev/sda"; "mbr"];
2125        ["pvcreate"; "/dev/sda1"];
2126        ["vgcreate"; "VG"; "/dev/sda1"];
2127        ["lvcreate"; "LV1"; "VG"; "50"];
2128        ["lvcreate"; "LV2"; "VG"; "50"];
2129        ["lvremove"; "/dev/VG"];
2130        ["lvs"]], []);
2131     InitEmpty, Always, TestOutputList (
2132       [["part_disk"; "/dev/sda"; "mbr"];
2133        ["pvcreate"; "/dev/sda1"];
2134        ["vgcreate"; "VG"; "/dev/sda1"];
2135        ["lvcreate"; "LV1"; "VG"; "50"];
2136        ["lvcreate"; "LV2"; "VG"; "50"];
2137        ["lvremove"; "/dev/VG"];
2138        ["vgs"]], ["VG"])],
2139    "remove an LVM logical volume",
2140    "\
2141 Remove an LVM logical volume C<device>, where C<device> is
2142 the path to the LV, such as C</dev/VG/LV>.
2143
2144 You can also remove all LVs in a volume group by specifying
2145 the VG name, C</dev/VG>.");
2146
2147   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2148    [InitEmpty, Always, TestOutputList (
2149       [["part_disk"; "/dev/sda"; "mbr"];
2150        ["pvcreate"; "/dev/sda1"];
2151        ["vgcreate"; "VG"; "/dev/sda1"];
2152        ["lvcreate"; "LV1"; "VG"; "50"];
2153        ["lvcreate"; "LV2"; "VG"; "50"];
2154        ["vgremove"; "VG"];
2155        ["lvs"]], []);
2156     InitEmpty, Always, TestOutputList (
2157       [["part_disk"; "/dev/sda"; "mbr"];
2158        ["pvcreate"; "/dev/sda1"];
2159        ["vgcreate"; "VG"; "/dev/sda1"];
2160        ["lvcreate"; "LV1"; "VG"; "50"];
2161        ["lvcreate"; "LV2"; "VG"; "50"];
2162        ["vgremove"; "VG"];
2163        ["vgs"]], [])],
2164    "remove an LVM volume group",
2165    "\
2166 Remove an LVM volume group C<vgname>, (for example C<VG>).
2167
2168 This also forcibly removes all logical volumes in the volume
2169 group (if any).");
2170
2171   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2172    [InitEmpty, Always, TestOutputListOfDevices (
2173       [["part_disk"; "/dev/sda"; "mbr"];
2174        ["pvcreate"; "/dev/sda1"];
2175        ["vgcreate"; "VG"; "/dev/sda1"];
2176        ["lvcreate"; "LV1"; "VG"; "50"];
2177        ["lvcreate"; "LV2"; "VG"; "50"];
2178        ["vgremove"; "VG"];
2179        ["pvremove"; "/dev/sda1"];
2180        ["lvs"]], []);
2181     InitEmpty, Always, TestOutputListOfDevices (
2182       [["part_disk"; "/dev/sda"; "mbr"];
2183        ["pvcreate"; "/dev/sda1"];
2184        ["vgcreate"; "VG"; "/dev/sda1"];
2185        ["lvcreate"; "LV1"; "VG"; "50"];
2186        ["lvcreate"; "LV2"; "VG"; "50"];
2187        ["vgremove"; "VG"];
2188        ["pvremove"; "/dev/sda1"];
2189        ["vgs"]], []);
2190     InitEmpty, Always, TestOutputListOfDevices (
2191       [["part_disk"; "/dev/sda"; "mbr"];
2192        ["pvcreate"; "/dev/sda1"];
2193        ["vgcreate"; "VG"; "/dev/sda1"];
2194        ["lvcreate"; "LV1"; "VG"; "50"];
2195        ["lvcreate"; "LV2"; "VG"; "50"];
2196        ["vgremove"; "VG"];
2197        ["pvremove"; "/dev/sda1"];
2198        ["pvs"]], [])],
2199    "remove an LVM physical volume",
2200    "\
2201 This wipes a physical volume C<device> so that LVM will no longer
2202 recognise it.
2203
2204 The implementation uses the C<pvremove> command which refuses to
2205 wipe physical volumes that contain any volume groups, so you have
2206 to remove those first.");
2207
2208   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2209    [InitBasicFS, Always, TestOutput (
2210       [["set_e2label"; "/dev/sda1"; "testlabel"];
2211        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2212    "set the ext2/3/4 filesystem label",
2213    "\
2214 This sets the ext2/3/4 filesystem label of the filesystem on
2215 C<device> to C<label>.  Filesystem labels are limited to
2216 16 characters.
2217
2218 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2219 to return the existing label on a filesystem.");
2220
2221   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2222    [],
2223    "get the ext2/3/4 filesystem label",
2224    "\
2225 This returns the ext2/3/4 filesystem label of the filesystem on
2226 C<device>.");
2227
2228   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2229    (let uuid = uuidgen () in
2230     [InitBasicFS, Always, TestOutput (
2231        [["set_e2uuid"; "/dev/sda1"; uuid];
2232         ["get_e2uuid"; "/dev/sda1"]], uuid);
2233      InitBasicFS, Always, TestOutput (
2234        [["set_e2uuid"; "/dev/sda1"; "clear"];
2235         ["get_e2uuid"; "/dev/sda1"]], "");
2236      (* We can't predict what UUIDs will be, so just check the commands run. *)
2237      InitBasicFS, Always, TestRun (
2238        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2239      InitBasicFS, Always, TestRun (
2240        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2241    "set the ext2/3/4 filesystem UUID",
2242    "\
2243 This sets the ext2/3/4 filesystem UUID of the filesystem on
2244 C<device> to C<uuid>.  The format of the UUID and alternatives
2245 such as C<clear>, C<random> and C<time> are described in the
2246 L<tune2fs(8)> manpage.
2247
2248 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2249 to return the existing UUID of a filesystem.");
2250
2251   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2252    [],
2253    "get the ext2/3/4 filesystem UUID",
2254    "\
2255 This returns the ext2/3/4 filesystem UUID of the filesystem on
2256 C<device>.");
2257
2258   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2259    [InitBasicFS, Always, TestOutputInt (
2260       [["umount"; "/dev/sda1"];
2261        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2262     InitBasicFS, Always, TestOutputInt (
2263       [["umount"; "/dev/sda1"];
2264        ["zero"; "/dev/sda1"];
2265        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2266    "run the filesystem checker",
2267    "\
2268 This runs the filesystem checker (fsck) on C<device> which
2269 should have filesystem type C<fstype>.
2270
2271 The returned integer is the status.  See L<fsck(8)> for the
2272 list of status codes from C<fsck>.
2273
2274 Notes:
2275
2276 =over 4
2277
2278 =item *
2279
2280 Multiple status codes can be summed together.
2281
2282 =item *
2283
2284 A non-zero return code can mean \"success\", for example if
2285 errors have been corrected on the filesystem.
2286
2287 =item *
2288
2289 Checking or repairing NTFS volumes is not supported
2290 (by linux-ntfs).
2291
2292 =back
2293
2294 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2295
2296   ("zero", (RErr, [Device "device"]), 85, [],
2297    [InitBasicFS, Always, TestOutput (
2298       [["umount"; "/dev/sda1"];
2299        ["zero"; "/dev/sda1"];
2300        ["file"; "/dev/sda1"]], "data")],
2301    "write zeroes to the device",
2302    "\
2303 This command writes zeroes over the first few blocks of C<device>.
2304
2305 How many blocks are zeroed isn't specified (but it's I<not> enough
2306 to securely wipe the device).  It should be sufficient to remove
2307 any partition tables, filesystem superblocks and so on.
2308
2309 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2310
2311   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2312    (* Test disabled because grub-install incompatible with virtio-blk driver.
2313     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2314     *)
2315    [InitBasicFS, Disabled, TestOutputTrue (
2316       [["grub_install"; "/"; "/dev/sda1"];
2317        ["is_dir"; "/boot"]])],
2318    "install GRUB",
2319    "\
2320 This command installs GRUB (the Grand Unified Bootloader) on
2321 C<device>, with the root directory being C<root>.");
2322
2323   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2324    [InitBasicFS, Always, TestOutput (
2325       [["write"; "/old"; "file content"];
2326        ["cp"; "/old"; "/new"];
2327        ["cat"; "/new"]], "file content");
2328     InitBasicFS, Always, TestOutputTrue (
2329       [["write"; "/old"; "file content"];
2330        ["cp"; "/old"; "/new"];
2331        ["is_file"; "/old"]]);
2332     InitBasicFS, Always, TestOutput (
2333       [["write"; "/old"; "file content"];
2334        ["mkdir"; "/dir"];
2335        ["cp"; "/old"; "/dir/new"];
2336        ["cat"; "/dir/new"]], "file content")],
2337    "copy a file",
2338    "\
2339 This copies a file from C<src> to C<dest> where C<dest> is
2340 either a destination filename or destination directory.");
2341
2342   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2343    [InitBasicFS, Always, TestOutput (
2344       [["mkdir"; "/olddir"];
2345        ["mkdir"; "/newdir"];
2346        ["write"; "/olddir/file"; "file content"];
2347        ["cp_a"; "/olddir"; "/newdir"];
2348        ["cat"; "/newdir/olddir/file"]], "file content")],
2349    "copy a file or directory recursively",
2350    "\
2351 This copies a file or directory from C<src> to C<dest>
2352 recursively using the C<cp -a> command.");
2353
2354   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2355    [InitBasicFS, Always, TestOutput (
2356       [["write"; "/old"; "file content"];
2357        ["mv"; "/old"; "/new"];
2358        ["cat"; "/new"]], "file content");
2359     InitBasicFS, Always, TestOutputFalse (
2360       [["write"; "/old"; "file content"];
2361        ["mv"; "/old"; "/new"];
2362        ["is_file"; "/old"]])],
2363    "move a file",
2364    "\
2365 This moves a file from C<src> to C<dest> where C<dest> is
2366 either a destination filename or destination directory.");
2367
2368   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2369    [InitEmpty, Always, TestRun (
2370       [["drop_caches"; "3"]])],
2371    "drop kernel page cache, dentries and inodes",
2372    "\
2373 This instructs the guest kernel to drop its page cache,
2374 and/or dentries and inode caches.  The parameter C<whattodrop>
2375 tells the kernel what precisely to drop, see
2376 L<http://linux-mm.org/Drop_Caches>
2377
2378 Setting C<whattodrop> to 3 should drop everything.
2379
2380 This automatically calls L<sync(2)> before the operation,
2381 so that the maximum guest memory is freed.");
2382
2383   ("dmesg", (RString "kmsgs", []), 91, [],
2384    [InitEmpty, Always, TestRun (
2385       [["dmesg"]])],
2386    "return kernel messages",
2387    "\
2388 This returns the kernel messages (C<dmesg> output) from
2389 the guest kernel.  This is sometimes useful for extended
2390 debugging of problems.
2391
2392 Another way to get the same information is to enable
2393 verbose messages with C<guestfs_set_verbose> or by setting
2394 the environment variable C<LIBGUESTFS_DEBUG=1> before
2395 running the program.");
2396
2397   ("ping_daemon", (RErr, []), 92, [],
2398    [InitEmpty, Always, TestRun (
2399       [["ping_daemon"]])],
2400    "ping the guest daemon",
2401    "\
2402 This is a test probe into the guestfs daemon running inside
2403 the qemu subprocess.  Calling this function checks that the
2404 daemon responds to the ping message, without affecting the daemon
2405 or attached block device(s) in any other way.");
2406
2407   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2408    [InitBasicFS, Always, TestOutputTrue (
2409       [["write"; "/file1"; "contents of a file"];
2410        ["cp"; "/file1"; "/file2"];
2411        ["equal"; "/file1"; "/file2"]]);
2412     InitBasicFS, Always, TestOutputFalse (
2413       [["write"; "/file1"; "contents of a file"];
2414        ["write"; "/file2"; "contents of another file"];
2415        ["equal"; "/file1"; "/file2"]]);
2416     InitBasicFS, Always, TestLastFail (
2417       [["equal"; "/file1"; "/file2"]])],
2418    "test if two files have equal contents",
2419    "\
2420 This compares the two files C<file1> and C<file2> and returns
2421 true if their content is exactly equal, or false otherwise.
2422
2423 The external L<cmp(1)> program is used for the comparison.");
2424
2425   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2426    [InitISOFS, Always, TestOutputList (
2427       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2428     InitISOFS, Always, TestOutputList (
2429       [["strings"; "/empty"]], []);
2430     (* Test for RHBZ#579608, absolute symbolic links. *)
2431     InitISOFS, Always, TestRun (
2432       [["strings"; "/abssymlink"]])],
2433    "print the printable strings in a file",
2434    "\
2435 This runs the L<strings(1)> command on a file and returns
2436 the list of printable strings found.");
2437
2438   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2439    [InitISOFS, Always, TestOutputList (
2440       [["strings_e"; "b"; "/known-5"]], []);
2441     InitBasicFS, Always, TestOutputList (
2442       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2443        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2444    "print the printable strings in a file",
2445    "\
2446 This is like the C<guestfs_strings> command, but allows you to
2447 specify the encoding of strings that are looked for in
2448 the source file C<path>.
2449
2450 Allowed encodings are:
2451
2452 =over 4
2453
2454 =item s
2455
2456 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2457 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2458
2459 =item S
2460
2461 Single 8-bit-byte characters.
2462
2463 =item b
2464
2465 16-bit big endian strings such as those encoded in
2466 UTF-16BE or UCS-2BE.
2467
2468 =item l (lower case letter L)
2469
2470 16-bit little endian such as UTF-16LE and UCS-2LE.
2471 This is useful for examining binaries in Windows guests.
2472
2473 =item B
2474
2475 32-bit big endian such as UCS-4BE.
2476
2477 =item L
2478
2479 32-bit little endian such as UCS-4LE.
2480
2481 =back
2482
2483 The returned strings are transcoded to UTF-8.");
2484
2485   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2486    [InitISOFS, Always, TestOutput (
2487       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2488     (* Test for RHBZ#501888c2 regression which caused large hexdump
2489      * commands to segfault.
2490      *)
2491     InitISOFS, Always, TestRun (
2492       [["hexdump"; "/100krandom"]]);
2493     (* Test for RHBZ#579608, absolute symbolic links. *)
2494     InitISOFS, Always, TestRun (
2495       [["hexdump"; "/abssymlink"]])],
2496    "dump a file in hexadecimal",
2497    "\
2498 This runs C<hexdump -C> on the given C<path>.  The result is
2499 the human-readable, canonical hex dump of the file.");
2500
2501   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2502    [InitNone, Always, TestOutput (
2503       [["part_disk"; "/dev/sda"; "mbr"];
2504        ["mkfs"; "ext3"; "/dev/sda1"];
2505        ["mount_options"; ""; "/dev/sda1"; "/"];
2506        ["write"; "/new"; "test file"];
2507        ["umount"; "/dev/sda1"];
2508        ["zerofree"; "/dev/sda1"];
2509        ["mount_options"; ""; "/dev/sda1"; "/"];
2510        ["cat"; "/new"]], "test file")],
2511    "zero unused inodes and disk blocks on ext2/3 filesystem",
2512    "\
2513 This runs the I<zerofree> program on C<device>.  This program
2514 claims to zero unused inodes and disk blocks on an ext2/3
2515 filesystem, thus making it possible to compress the filesystem
2516 more effectively.
2517
2518 You should B<not> run this program if the filesystem is
2519 mounted.
2520
2521 It is possible that using this program can damage the filesystem
2522 or data on the filesystem.");
2523
2524   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2525    [],
2526    "resize an LVM physical volume",
2527    "\
2528 This resizes (expands or shrinks) an existing LVM physical
2529 volume to match the new size of the underlying device.");
2530
2531   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2532                        Int "cyls"; Int "heads"; Int "sectors";
2533                        String "line"]), 99, [DangerWillRobinson],
2534    [],
2535    "modify a single partition on a block device",
2536    "\
2537 This runs L<sfdisk(8)> option to modify just the single
2538 partition C<n> (note: C<n> counts from 1).
2539
2540 For other parameters, see C<guestfs_sfdisk>.  You should usually
2541 pass C<0> for the cyls/heads/sectors parameters.
2542
2543 See also: C<guestfs_part_add>");
2544
2545   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2546    [],
2547    "display the partition table",
2548    "\
2549 This displays the partition table on C<device>, in the
2550 human-readable output of the L<sfdisk(8)> command.  It is
2551 not intended to be parsed.
2552
2553 See also: C<guestfs_part_list>");
2554
2555   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2556    [],
2557    "display the kernel geometry",
2558    "\
2559 This displays the kernel's idea of the geometry of C<device>.
2560
2561 The result is in human-readable format, and not designed to
2562 be parsed.");
2563
2564   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2565    [],
2566    "display the disk geometry from the partition table",
2567    "\
2568 This displays the disk geometry of C<device> read from the
2569 partition table.  Especially in the case where the underlying
2570 block device has been resized, this can be different from the
2571 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2572
2573 The result is in human-readable format, and not designed to
2574 be parsed.");
2575
2576   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2577    [],
2578    "activate or deactivate all volume groups",
2579    "\
2580 This command activates or (if C<activate> is false) deactivates
2581 all logical volumes in all volume groups.
2582 If activated, then they are made known to the
2583 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2584 then those devices disappear.
2585
2586 This command is the same as running C<vgchange -a y|n>");
2587
2588   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2589    [],
2590    "activate or deactivate some volume groups",
2591    "\
2592 This command activates or (if C<activate> is false) deactivates
2593 all logical volumes in the listed volume groups C<volgroups>.
2594 If activated, then they are made known to the
2595 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2596 then those devices disappear.
2597
2598 This command is the same as running C<vgchange -a y|n volgroups...>
2599
2600 Note that if C<volgroups> is an empty list then B<all> volume groups
2601 are activated or deactivated.");
2602
2603   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2604    [InitNone, Always, TestOutput (
2605       [["part_disk"; "/dev/sda"; "mbr"];
2606        ["pvcreate"; "/dev/sda1"];
2607        ["vgcreate"; "VG"; "/dev/sda1"];
2608        ["lvcreate"; "LV"; "VG"; "10"];
2609        ["mkfs"; "ext2"; "/dev/VG/LV"];
2610        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2611        ["write"; "/new"; "test content"];
2612        ["umount"; "/"];
2613        ["lvresize"; "/dev/VG/LV"; "20"];
2614        ["e2fsck_f"; "/dev/VG/LV"];
2615        ["resize2fs"; "/dev/VG/LV"];
2616        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2617        ["cat"; "/new"]], "test content");
2618     InitNone, Always, TestRun (
2619       (* Make an LV smaller to test RHBZ#587484. *)
2620       [["part_disk"; "/dev/sda"; "mbr"];
2621        ["pvcreate"; "/dev/sda1"];
2622        ["vgcreate"; "VG"; "/dev/sda1"];
2623        ["lvcreate"; "LV"; "VG"; "20"];
2624        ["lvresize"; "/dev/VG/LV"; "10"]])],
2625    "resize an LVM logical volume",
2626    "\
2627 This resizes (expands or shrinks) an existing LVM logical
2628 volume to C<mbytes>.  When reducing, data in the reduced part
2629 is lost.");
2630
2631   ("resize2fs", (RErr, [Device "device"]), 106, [],
2632    [], (* lvresize tests this *)
2633    "resize an ext2/ext3 filesystem",
2634    "\
2635 This resizes an ext2 or ext3 filesystem to match the size of
2636 the underlying device.
2637
2638 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2639 on the C<device> before calling this command.  For unknown reasons
2640 C<resize2fs> sometimes gives an error about this and sometimes not.
2641 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2642 calling this function.");
2643
2644   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2645    [InitBasicFS, Always, TestOutputList (
2646       [["find"; "/"]], ["lost+found"]);
2647     InitBasicFS, Always, TestOutputList (
2648       [["touch"; "/a"];
2649        ["mkdir"; "/b"];
2650        ["touch"; "/b/c"];
2651        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2652     InitBasicFS, Always, TestOutputList (
2653       [["mkdir_p"; "/a/b/c"];
2654        ["touch"; "/a/b/c/d"];
2655        ["find"; "/a/b/"]], ["c"; "c/d"])],
2656    "find all files and directories",
2657    "\
2658 This command lists out all files and directories, recursively,
2659 starting at C<directory>.  It is essentially equivalent to
2660 running the shell command C<find directory -print> but some
2661 post-processing happens on the output, described below.
2662
2663 This returns a list of strings I<without any prefix>.  Thus
2664 if the directory structure was:
2665
2666  /tmp/a
2667  /tmp/b
2668  /tmp/c/d
2669
2670 then the returned list from C<guestfs_find> C</tmp> would be
2671 4 elements:
2672
2673  a
2674  b
2675  c
2676  c/d
2677
2678 If C<directory> is not a directory, then this command returns
2679 an error.
2680
2681 The returned list is sorted.
2682
2683 See also C<guestfs_find0>.");
2684
2685   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2686    [], (* lvresize tests this *)
2687    "check an ext2/ext3 filesystem",
2688    "\
2689 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2690 filesystem checker on C<device>, noninteractively (C<-p>),
2691 even if the filesystem appears to be clean (C<-f>).
2692
2693 This command is only needed because of C<guestfs_resize2fs>
2694 (q.v.).  Normally you should use C<guestfs_fsck>.");
2695
2696   ("sleep", (RErr, [Int "secs"]), 109, [],
2697    [InitNone, Always, TestRun (
2698       [["sleep"; "1"]])],
2699    "sleep for some seconds",
2700    "\
2701 Sleep for C<secs> seconds.");
2702
2703   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2704    [InitNone, Always, TestOutputInt (
2705       [["part_disk"; "/dev/sda"; "mbr"];
2706        ["mkfs"; "ntfs"; "/dev/sda1"];
2707        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2708     InitNone, Always, TestOutputInt (
2709       [["part_disk"; "/dev/sda"; "mbr"];
2710        ["mkfs"; "ext2"; "/dev/sda1"];
2711        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2712    "probe NTFS volume",
2713    "\
2714 This command runs the L<ntfs-3g.probe(8)> command which probes
2715 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2716 be mounted read-write, and some cannot be mounted at all).
2717
2718 C<rw> is a boolean flag.  Set it to true if you want to test
2719 if the volume can be mounted read-write.  Set it to false if
2720 you want to test if the volume can be mounted read-only.
2721
2722 The return value is an integer which C<0> if the operation
2723 would succeed, or some non-zero value documented in the
2724 L<ntfs-3g.probe(8)> manual page.");
2725
2726   ("sh", (RString "output", [String "command"]), 111, [],
2727    [], (* XXX needs tests *)
2728    "run a command via the shell",
2729    "\
2730 This call runs a command from the guest filesystem via the
2731 guest's C</bin/sh>.
2732
2733 This is like C<guestfs_command>, but passes the command to:
2734
2735  /bin/sh -c \"command\"
2736
2737 Depending on the guest's shell, this usually results in
2738 wildcards being expanded, shell expressions being interpolated
2739 and so on.
2740
2741 All the provisos about C<guestfs_command> apply to this call.");
2742
2743   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2744    [], (* XXX needs tests *)
2745    "run a command via the shell returning lines",
2746    "\
2747 This is the same as C<guestfs_sh>, but splits the result
2748 into a list of lines.
2749
2750 See also: C<guestfs_command_lines>");
2751
2752   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2753    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2754     * code in stubs.c, since all valid glob patterns must start with "/".
2755     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2756     *)
2757    [InitBasicFS, Always, TestOutputList (
2758       [["mkdir_p"; "/a/b/c"];
2759        ["touch"; "/a/b/c/d"];
2760        ["touch"; "/a/b/c/e"];
2761        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2762     InitBasicFS, Always, TestOutputList (
2763       [["mkdir_p"; "/a/b/c"];
2764        ["touch"; "/a/b/c/d"];
2765        ["touch"; "/a/b/c/e"];
2766        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2767     InitBasicFS, Always, TestOutputList (
2768       [["mkdir_p"; "/a/b/c"];
2769        ["touch"; "/a/b/c/d"];
2770        ["touch"; "/a/b/c/e"];
2771        ["glob_expand"; "/a/*/x/*"]], [])],
2772    "expand a wildcard path",
2773    "\
2774 This command searches for all the pathnames matching
2775 C<pattern> according to the wildcard expansion rules
2776 used by the shell.
2777
2778 If no paths match, then this returns an empty list
2779 (note: not an error).
2780
2781 It is just a wrapper around the C L<glob(3)> function
2782 with flags C<GLOB_MARK|GLOB_BRACE>.
2783 See that manual page for more details.");
2784
2785   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2786    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2787       [["scrub_device"; "/dev/sdc"]])],
2788    "scrub (securely wipe) a device",
2789    "\
2790 This command writes patterns over C<device> to make data retrieval
2791 more difficult.
2792
2793 It is an interface to the L<scrub(1)> program.  See that
2794 manual page for more details.");
2795
2796   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2797    [InitBasicFS, Always, TestRun (
2798       [["write"; "/file"; "content"];
2799        ["scrub_file"; "/file"]])],
2800    "scrub (securely wipe) a file",
2801    "\
2802 This command writes patterns over a file to make data retrieval
2803 more difficult.
2804
2805 The file is I<removed> after scrubbing.
2806
2807 It is an interface to the L<scrub(1)> program.  See that
2808 manual page for more details.");
2809
2810   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2811    [], (* XXX needs testing *)
2812    "scrub (securely wipe) free space",
2813    "\
2814 This command creates the directory C<dir> and then fills it
2815 with files until the filesystem is full, and scrubs the files
2816 as for C<guestfs_scrub_file>, and deletes them.
2817 The intention is to scrub any free space on the partition
2818 containing C<dir>.
2819
2820 It is an interface to the L<scrub(1)> program.  See that
2821 manual page for more details.");
2822
2823   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2824    [InitBasicFS, Always, TestRun (
2825       [["mkdir"; "/tmp"];
2826        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2827    "create a temporary directory",
2828    "\
2829 This command creates a temporary directory.  The
2830 C<template> parameter should be a full pathname for the
2831 temporary directory name with the final six characters being
2832 \"XXXXXX\".
2833
2834 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2835 the second one being suitable for Windows filesystems.
2836
2837 The name of the temporary directory that was created
2838 is returned.
2839
2840 The temporary directory is created with mode 0700
2841 and is owned by root.
2842
2843 The caller is responsible for deleting the temporary
2844 directory and its contents after use.
2845
2846 See also: L<mkdtemp(3)>");
2847
2848   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2849    [InitISOFS, Always, TestOutputInt (
2850       [["wc_l"; "/10klines"]], 10000);
2851     (* Test for RHBZ#579608, absolute symbolic links. *)
2852     InitISOFS, Always, TestOutputInt (
2853       [["wc_l"; "/abssymlink"]], 10000)],
2854    "count lines in a file",
2855    "\
2856 This command counts the lines in a file, using the
2857 C<wc -l> external command.");
2858
2859   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2860    [InitISOFS, Always, TestOutputInt (
2861       [["wc_w"; "/10klines"]], 10000)],
2862    "count words in a file",
2863    "\
2864 This command counts the words in a file, using the
2865 C<wc -w> external command.");
2866
2867   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2868    [InitISOFS, Always, TestOutputInt (
2869       [["wc_c"; "/100kallspaces"]], 102400)],
2870    "count characters in a file",
2871    "\
2872 This command counts the characters in a file, using the
2873 C<wc -c> external command.");
2874
2875   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2876    [InitISOFS, Always, TestOutputList (
2877       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2878     (* Test for RHBZ#579608, absolute symbolic links. *)
2879     InitISOFS, Always, TestOutputList (
2880       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2881    "return first 10 lines of a file",
2882    "\
2883 This command returns up to the first 10 lines of a file as
2884 a list of strings.");
2885
2886   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2887    [InitISOFS, Always, TestOutputList (
2888       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2889     InitISOFS, Always, TestOutputList (
2890       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2891     InitISOFS, Always, TestOutputList (
2892       [["head_n"; "0"; "/10klines"]], [])],
2893    "return first N lines of a file",
2894    "\
2895 If the parameter C<nrlines> is a positive number, this returns the first
2896 C<nrlines> lines of the file C<path>.
2897
2898 If the parameter C<nrlines> is a negative number, this returns lines
2899 from the file C<path>, excluding the last C<nrlines> lines.
2900
2901 If the parameter C<nrlines> is zero, this returns an empty list.");
2902
2903   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2904    [InitISOFS, Always, TestOutputList (
2905       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2906    "return last 10 lines of a file",
2907    "\
2908 This command returns up to the last 10 lines of a file as
2909 a list of strings.");
2910
2911   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2912    [InitISOFS, Always, TestOutputList (
2913       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2914     InitISOFS, Always, TestOutputList (
2915       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2916     InitISOFS, Always, TestOutputList (
2917       [["tail_n"; "0"; "/10klines"]], [])],
2918    "return last N lines of a file",
2919    "\
2920 If the parameter C<nrlines> is a positive number, this returns the last
2921 C<nrlines> lines of the file C<path>.
2922
2923 If the parameter C<nrlines> is a negative number, this returns lines
2924 from the file C<path>, starting with the C<-nrlines>th line.
2925
2926 If the parameter C<nrlines> is zero, this returns an empty list.");
2927
2928   ("df", (RString "output", []), 125, [],
2929    [], (* XXX Tricky to test because it depends on the exact format
2930         * of the 'df' command and other imponderables.
2931         *)
2932    "report file system disk space usage",
2933    "\
2934 This command runs the C<df> command to report disk space used.
2935
2936 This command is mostly useful for interactive sessions.  It
2937 is I<not> intended that you try to parse the output string.
2938 Use C<statvfs> from programs.");
2939
2940   ("df_h", (RString "output", []), 126, [],
2941    [], (* XXX Tricky to test because it depends on the exact format
2942         * of the 'df' command and other imponderables.
2943         *)
2944    "report file system disk space usage (human readable)",
2945    "\
2946 This command runs the C<df -h> command to report disk space used
2947 in human-readable format.
2948
2949 This command is mostly useful for interactive sessions.  It
2950 is I<not> intended that you try to parse the output string.
2951 Use C<statvfs> from programs.");
2952
2953   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2954    [InitISOFS, Always, TestOutputInt (
2955       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2956    "estimate file space usage",
2957    "\
2958 This command runs the C<du -s> command to estimate file space
2959 usage for C<path>.
2960
2961 C<path> can be a file or a directory.  If C<path> is a directory
2962 then the estimate includes the contents of the directory and all
2963 subdirectories (recursively).
2964
2965 The result is the estimated size in I<kilobytes>
2966 (ie. units of 1024 bytes).");
2967
2968   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2969    [InitISOFS, Always, TestOutputList (
2970       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2971    "list files in an initrd",
2972    "\
2973 This command lists out files contained in an initrd.
2974
2975 The files are listed without any initial C</> character.  The
2976 files are listed in the order they appear (not necessarily
2977 alphabetical).  Directory names are listed as separate items.
2978
2979 Old Linux kernels (2.4 and earlier) used a compressed ext2
2980 filesystem as initrd.  We I<only> support the newer initramfs
2981 format (compressed cpio files).");
2982
2983   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2984    [],
2985    "mount a file using the loop device",
2986    "\
2987 This command lets you mount C<file> (a filesystem image
2988 in a file) on a mount point.  It is entirely equivalent to
2989 the command C<mount -o loop file mountpoint>.");
2990
2991   ("mkswap", (RErr, [Device "device"]), 130, [],
2992    [InitEmpty, Always, TestRun (
2993       [["part_disk"; "/dev/sda"; "mbr"];
2994        ["mkswap"; "/dev/sda1"]])],
2995    "create a swap partition",
2996    "\
2997 Create a swap partition on C<device>.");
2998
2999   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3000    [InitEmpty, Always, TestRun (
3001       [["part_disk"; "/dev/sda"; "mbr"];
3002        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3003    "create a swap partition with a label",
3004    "\
3005 Create a swap partition on C<device> with label C<label>.
3006
3007 Note that you cannot attach a swap label to a block device
3008 (eg. C</dev/sda>), just to a partition.  This appears to be
3009 a limitation of the kernel or swap tools.");
3010
3011   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3012    (let uuid = uuidgen () in
3013     [InitEmpty, Always, TestRun (
3014        [["part_disk"; "/dev/sda"; "mbr"];
3015         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3016    "create a swap partition with an explicit UUID",
3017    "\
3018 Create a swap partition on C<device> with UUID C<uuid>.");
3019
3020   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3021    [InitBasicFS, Always, TestOutputStruct (
3022       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3023        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3024        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3025     InitBasicFS, Always, TestOutputStruct (
3026       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3027        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3028    "make block, character or FIFO devices",
3029    "\
3030 This call creates block or character special devices, or
3031 named pipes (FIFOs).
3032
3033 The C<mode> parameter should be the mode, using the standard
3034 constants.  C<devmajor> and C<devminor> are the
3035 device major and minor numbers, only used when creating block
3036 and character special devices.
3037
3038 Note that, just like L<mknod(2)>, the mode must be bitwise
3039 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3040 just creates a regular file).  These constants are
3041 available in the standard Linux header files, or you can use
3042 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3043 which are wrappers around this command which bitwise OR
3044 in the appropriate constant for you.
3045
3046 The mode actually set is affected by the umask.");
3047
3048   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3049    [InitBasicFS, Always, TestOutputStruct (
3050       [["mkfifo"; "0o777"; "/node"];
3051        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3052    "make FIFO (named pipe)",
3053    "\
3054 This call creates a FIFO (named pipe) called C<path> with
3055 mode C<mode>.  It is just a convenient wrapper around
3056 C<guestfs_mknod>.
3057
3058 The mode actually set is affected by the umask.");
3059
3060   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3061    [InitBasicFS, Always, TestOutputStruct (
3062       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3063        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3064    "make block device node",
3065    "\
3066 This call creates a block device node called C<path> with
3067 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3068 It is just a convenient wrapper around C<guestfs_mknod>.
3069
3070 The mode actually set is affected by the umask.");
3071
3072   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3073    [InitBasicFS, Always, TestOutputStruct (
3074       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3075        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3076    "make char device node",
3077    "\
3078 This call creates a char device node called C<path> with
3079 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3080 It is just a convenient wrapper around C<guestfs_mknod>.
3081
3082 The mode actually set is affected by the umask.");
3083
3084   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3085    [InitEmpty, Always, TestOutputInt (
3086       [["umask"; "0o22"]], 0o22)],
3087    "set file mode creation mask (umask)",
3088    "\
3089 This function sets the mask used for creating new files and
3090 device nodes to C<mask & 0777>.
3091
3092 Typical umask values would be C<022> which creates new files
3093 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3094 C<002> which creates new files with permissions like
3095 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3096
3097 The default umask is C<022>.  This is important because it
3098 means that directories and device nodes will be created with
3099 C<0644> or C<0755> mode even if you specify C<0777>.
3100
3101 See also C<guestfs_get_umask>,
3102 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3103
3104 This call returns the previous umask.");
3105
3106   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3107    [],
3108    "read directories entries",
3109    "\
3110 This returns the list of directory entries in directory C<dir>.
3111
3112 All entries in the directory are returned, including C<.> and
3113 C<..>.  The entries are I<not> sorted, but returned in the same
3114 order as the underlying filesystem.
3115
3116 Also this call returns basic file type information about each
3117 file.  The C<ftyp> field will contain one of the following characters:
3118
3119 =over 4
3120
3121 =item 'b'
3122
3123 Block special
3124
3125 =item 'c'
3126
3127 Char special
3128
3129 =item 'd'
3130
3131 Directory
3132
3133 =item 'f'
3134
3135 FIFO (named pipe)
3136
3137 =item 'l'
3138
3139 Symbolic link
3140
3141 =item 'r'
3142
3143 Regular file
3144
3145 =item 's'
3146
3147 Socket
3148
3149 =item 'u'
3150
3151 Unknown file type
3152
3153 =item '?'
3154
3155 The L<readdir(3)> returned a C<d_type> field with an
3156 unexpected value
3157
3158 =back
3159
3160 This function is primarily intended for use by programs.  To
3161 get a simple list of names, use C<guestfs_ls>.  To get a printable
3162 directory for human consumption, use C<guestfs_ll>.");
3163
3164   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3165    [],
3166    "create partitions on a block device",
3167    "\
3168 This is a simplified interface to the C<guestfs_sfdisk>
3169 command, where partition sizes are specified in megabytes
3170 only (rounded to the nearest cylinder) and you don't need
3171 to specify the cyls, heads and sectors parameters which
3172 were rarely if ever used anyway.
3173
3174 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3175 and C<guestfs_part_disk>");
3176
3177   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3178    [],
3179    "determine file type inside a compressed file",
3180    "\
3181 This command runs C<file> after first decompressing C<path>
3182 using C<method>.
3183
3184 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3185
3186 Since 1.0.63, use C<guestfs_file> instead which can now
3187 process compressed files.");
3188
3189   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3190    [],
3191    "list extended attributes of a file or directory",
3192    "\
3193 This call lists the extended attributes of the file or directory
3194 C<path>.
3195
3196 At the system call level, this is a combination of the
3197 L<listxattr(2)> and L<getxattr(2)> calls.
3198
3199 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3200
3201   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3202    [],
3203    "list extended attributes of a file or directory",
3204    "\
3205 This is the same as C<guestfs_getxattrs>, but if C<path>
3206 is a symbolic link, then it returns the extended attributes
3207 of the link itself.");
3208
3209   ("setxattr", (RErr, [String "xattr";
3210                        String "val"; Int "vallen"; (* will be BufferIn *)
3211                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3212    [],
3213    "set extended attribute of a file or directory",
3214    "\
3215 This call sets the extended attribute named C<xattr>
3216 of the file C<path> to the value C<val> (of length C<vallen>).
3217 The value is arbitrary 8 bit data.
3218
3219 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3220
3221   ("lsetxattr", (RErr, [String "xattr";
3222                         String "val"; Int "vallen"; (* will be BufferIn *)
3223                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3224    [],
3225    "set extended attribute of a file or directory",
3226    "\
3227 This is the same as C<guestfs_setxattr>, but if C<path>
3228 is a symbolic link, then it sets an extended attribute
3229 of the link itself.");
3230
3231   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3232    [],
3233    "remove extended attribute of a file or directory",
3234    "\
3235 This call removes the extended attribute named C<xattr>
3236 of the file C<path>.
3237
3238 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3239
3240   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3241    [],
3242    "remove extended attribute of a file or directory",
3243    "\
3244 This is the same as C<guestfs_removexattr>, but if C<path>
3245 is a symbolic link, then it removes an extended attribute
3246 of the link itself.");
3247
3248   ("mountpoints", (RHashtable "mps", []), 147, [],
3249    [],
3250    "show mountpoints",
3251    "\
3252 This call is similar to C<guestfs_mounts>.  That call returns
3253 a list of devices.  This one returns a hash table (map) of
3254 device name to directory where the device is mounted.");
3255
3256   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3257    (* This is a special case: while you would expect a parameter
3258     * of type "Pathname", that doesn't work, because it implies
3259     * NEED_ROOT in the generated calling code in stubs.c, and
3260     * this function cannot use NEED_ROOT.
3261     *)
3262    [],
3263    "create a mountpoint",
3264    "\
3265 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3266 specialized calls that can be used to create extra mountpoints
3267 before mounting the first filesystem.
3268
3269 These calls are I<only> necessary in some very limited circumstances,
3270 mainly the case where you want to mount a mix of unrelated and/or
3271 read-only filesystems together.
3272
3273 For example, live CDs often contain a \"Russian doll\" nest of
3274 filesystems, an ISO outer layer, with a squashfs image inside, with
3275 an ext2/3 image inside that.  You can unpack this as follows
3276 in guestfish:
3277
3278  add-ro Fedora-11-i686-Live.iso
3279  run
3280  mkmountpoint /cd
3281  mkmountpoint /squash
3282  mkmountpoint /ext3
3283  mount /dev/sda /cd
3284  mount-loop /cd/LiveOS/squashfs.img /squash
3285  mount-loop /squash/LiveOS/ext3fs.img /ext3
3286
3287 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3288
3289   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3290    [],
3291    "remove a mountpoint",
3292    "\
3293 This calls removes a mountpoint that was previously created
3294 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3295 for full details.");
3296
3297   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3298    [InitISOFS, Always, TestOutputBuffer (
3299       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3300     (* Test various near large, large and too large files (RHBZ#589039). *)
3301     InitBasicFS, Always, TestLastFail (
3302       [["touch"; "/a"];
3303        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3304        ["read_file"; "/a"]]);
3305     InitBasicFS, Always, TestLastFail (
3306       [["touch"; "/a"];
3307        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3308        ["read_file"; "/a"]]);
3309     InitBasicFS, Always, TestLastFail (
3310       [["touch"; "/a"];
3311        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3312        ["read_file"; "/a"]])],
3313    "read a file",
3314    "\
3315 This calls returns the contents of the file C<path> as a
3316 buffer.
3317
3318 Unlike C<guestfs_cat>, this function can correctly
3319 handle files that contain embedded ASCII NUL characters.
3320 However unlike C<guestfs_download>, this function is limited
3321 in the total size of file that can be handled.");
3322
3323   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3324    [InitISOFS, Always, TestOutputList (
3325       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3326     InitISOFS, Always, TestOutputList (
3327       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3328     (* Test for RHBZ#579608, absolute symbolic links. *)
3329     InitISOFS, Always, TestOutputList (
3330       [["grep"; "nomatch"; "/abssymlink"]], [])],
3331    "return lines matching a pattern",
3332    "\
3333 This calls the external C<grep> program and returns the
3334 matching lines.");
3335
3336   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3337    [InitISOFS, Always, TestOutputList (
3338       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3339    "return lines matching a pattern",
3340    "\
3341 This calls the external C<egrep> program and returns the
3342 matching lines.");
3343
3344   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3345    [InitISOFS, Always, TestOutputList (
3346       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3347    "return lines matching a pattern",
3348    "\
3349 This calls the external C<fgrep> program and returns the
3350 matching lines.");
3351
3352   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3353    [InitISOFS, Always, TestOutputList (
3354       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3355    "return lines matching a pattern",
3356    "\
3357 This calls the external C<grep -i> program and returns the
3358 matching lines.");
3359
3360   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3361    [InitISOFS, Always, TestOutputList (
3362       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3363    "return lines matching a pattern",
3364    "\
3365 This calls the external C<egrep -i> program and returns the
3366 matching lines.");
3367
3368   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3369    [InitISOFS, Always, TestOutputList (
3370       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3371    "return lines matching a pattern",
3372    "\
3373 This calls the external C<fgrep -i> program and returns the
3374 matching lines.");
3375
3376   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3377    [InitISOFS, Always, TestOutputList (
3378       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3379    "return lines matching a pattern",
3380    "\
3381 This calls the external C<zgrep> program and returns the
3382 matching lines.");
3383
3384   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3385    [InitISOFS, Always, TestOutputList (
3386       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3387    "return lines matching a pattern",
3388    "\
3389 This calls the external C<zegrep> program and returns the
3390 matching lines.");
3391
3392   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3393    [InitISOFS, Always, TestOutputList (
3394       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3395    "return lines matching a pattern",
3396    "\
3397 This calls the external C<zfgrep> program and returns the
3398 matching lines.");
3399
3400   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3401    [InitISOFS, Always, TestOutputList (
3402       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3403    "return lines matching a pattern",
3404    "\
3405 This calls the external C<zgrep -i> program and returns the
3406 matching lines.");
3407
3408   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3409    [InitISOFS, Always, TestOutputList (
3410       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3411    "return lines matching a pattern",
3412    "\
3413 This calls the external C<zegrep -i> program and returns the
3414 matching lines.");
3415
3416   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3417    [InitISOFS, Always, TestOutputList (
3418       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3419    "return lines matching a pattern",
3420    "\
3421 This calls the external C<zfgrep -i> program and returns the
3422 matching lines.");
3423
3424   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3425    [InitISOFS, Always, TestOutput (
3426       [["realpath"; "/../directory"]], "/directory")],
3427    "canonicalized absolute pathname",
3428    "\
3429 Return the canonicalized absolute pathname of C<path>.  The
3430 returned path has no C<.>, C<..> or symbolic link path elements.");
3431
3432   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3433    [InitBasicFS, Always, TestOutputStruct (
3434       [["touch"; "/a"];
3435        ["ln"; "/a"; "/b"];
3436        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3437    "create a hard link",
3438    "\
3439 This command creates a hard link using the C<ln> command.");
3440
3441   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3442    [InitBasicFS, Always, TestOutputStruct (
3443       [["touch"; "/a"];
3444        ["touch"; "/b"];
3445        ["ln_f"; "/a"; "/b"];
3446        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3447    "create a hard link",
3448    "\
3449 This command creates a hard link using the C<ln -f> command.
3450 The C<-f> option removes the link (C<linkname>) if it exists already.");
3451
3452   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3453    [InitBasicFS, Always, TestOutputStruct (
3454       [["touch"; "/a"];
3455        ["ln_s"; "a"; "/b"];
3456        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3457    "create a symbolic link",
3458    "\
3459 This command creates a symbolic link using the C<ln -s> command.");
3460
3461   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3462    [InitBasicFS, Always, TestOutput (
3463       [["mkdir_p"; "/a/b"];
3464        ["touch"; "/a/b/c"];
3465        ["ln_sf"; "../d"; "/a/b/c"];
3466        ["readlink"; "/a/b/c"]], "../d")],
3467    "create a symbolic link",
3468    "\
3469 This command creates a symbolic link using the C<ln -sf> command,
3470 The C<-f> option removes the link (C<linkname>) if it exists already.");
3471
3472   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3473    [] (* XXX tested above *),
3474    "read the target of a symbolic link",
3475    "\
3476 This command reads the target of a symbolic link.");
3477
3478   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3479    [InitBasicFS, Always, TestOutputStruct (
3480       [["fallocate"; "/a"; "1000000"];
3481        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3482    "preallocate a file in the guest filesystem",
3483    "\
3484 This command preallocates a file (containing zero bytes) named
3485 C<path> of size C<len> bytes.  If the file exists already, it
3486 is overwritten.
3487
3488 Do not confuse this with the guestfish-specific
3489 C<alloc> command which allocates a file in the host and
3490 attaches it as a device.");
3491
3492   ("swapon_device", (RErr, [Device "device"]), 170, [],
3493    [InitPartition, Always, TestRun (
3494       [["mkswap"; "/dev/sda1"];
3495        ["swapon_device"; "/dev/sda1"];
3496        ["swapoff_device"; "/dev/sda1"]])],
3497    "enable swap on device",
3498    "\
3499 This command enables the libguestfs appliance to use the
3500 swap device or partition named C<device>.  The increased
3501 memory is made available for all commands, for example
3502 those run using C<guestfs_command> or C<guestfs_sh>.
3503
3504 Note that you should not swap to existing guest swap
3505 partitions unless you know what you are doing.  They may
3506 contain hibernation information, or other information that
3507 the guest doesn't want you to trash.  You also risk leaking
3508 information about the host to the guest this way.  Instead,
3509 attach a new host device to the guest and swap on that.");
3510
3511   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3512    [], (* XXX tested by swapon_device *)
3513    "disable swap on device",
3514    "\
3515 This command disables the libguestfs appliance swap
3516 device or partition named C<device>.
3517 See C<guestfs_swapon_device>.");
3518
3519   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3520    [InitBasicFS, Always, TestRun (
3521       [["fallocate"; "/swap"; "8388608"];
3522        ["mkswap_file"; "/swap"];
3523        ["swapon_file"; "/swap"];
3524        ["swapoff_file"; "/swap"]])],
3525    "enable swap on file",
3526    "\
3527 This command enables swap to a file.
3528 See C<guestfs_swapon_device> for other notes.");
3529
3530   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3531    [], (* XXX tested by swapon_file *)
3532    "disable swap on file",
3533    "\
3534 This command disables the libguestfs appliance swap on file.");
3535
3536   ("swapon_label", (RErr, [String "label"]), 174, [],
3537    [InitEmpty, Always, TestRun (
3538       [["part_disk"; "/dev/sdb"; "mbr"];
3539        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3540        ["swapon_label"; "swapit"];
3541        ["swapoff_label"; "swapit"];
3542        ["zero"; "/dev/sdb"];
3543        ["blockdev_rereadpt"; "/dev/sdb"]])],
3544    "enable swap on labeled swap partition",
3545    "\
3546 This command enables swap to a labeled swap partition.
3547 See C<guestfs_swapon_device> for other notes.");
3548
3549   ("swapoff_label", (RErr, [String "label"]), 175, [],
3550    [], (* XXX tested by swapon_label *)
3551    "disable swap on labeled swap partition",
3552    "\
3553 This command disables the libguestfs appliance swap on
3554 labeled swap partition.");
3555
3556   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3557    (let uuid = uuidgen () in
3558     [InitEmpty, Always, TestRun (
3559        [["mkswap_U"; uuid; "/dev/sdb"];
3560         ["swapon_uuid"; uuid];
3561         ["swapoff_uuid"; uuid]])]),
3562    "enable swap on swap partition by UUID",
3563    "\
3564 This command enables swap to a swap partition with the given UUID.
3565 See C<guestfs_swapon_device> for other notes.");
3566
3567   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3568    [], (* XXX tested by swapon_uuid *)
3569    "disable swap on swap partition by UUID",
3570    "\
3571 This command disables the libguestfs appliance swap partition
3572 with the given UUID.");
3573
3574   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3575    [InitBasicFS, Always, TestRun (
3576       [["fallocate"; "/swap"; "8388608"];
3577        ["mkswap_file"; "/swap"]])],
3578    "create a swap file",
3579    "\
3580 Create a swap file.
3581
3582 This command just writes a swap file signature to an existing
3583 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3584
3585   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3586    [InitISOFS, Always, TestRun (
3587       [["inotify_init"; "0"]])],
3588    "create an inotify handle",
3589    "\
3590 This command creates a new inotify handle.
3591 The inotify subsystem can be used to notify events which happen to
3592 objects in the guest filesystem.
3593
3594 C<maxevents> is the maximum number of events which will be
3595 queued up between calls to C<guestfs_inotify_read> or
3596 C<guestfs_inotify_files>.
3597 If this is passed as C<0>, then the kernel (or previously set)
3598 default is used.  For Linux 2.6.29 the default was 16384 events.
3599 Beyond this limit, the kernel throws away events, but records
3600 the fact that it threw them away by setting a flag
3601 C<IN_Q_OVERFLOW> in the returned structure list (see
3602 C<guestfs_inotify_read>).
3603
3604 Before any events are generated, you have to add some
3605 watches to the internal watch list.  See:
3606 C<guestfs_inotify_add_watch>,
3607 C<guestfs_inotify_rm_watch> and
3608 C<guestfs_inotify_watch_all>.
3609
3610 Queued up events should be read periodically by calling
3611 C<guestfs_inotify_read>
3612 (or C<guestfs_inotify_files> which is just a helpful
3613 wrapper around C<guestfs_inotify_read>).  If you don't
3614 read the events out often enough then you risk the internal
3615 queue overflowing.
3616
3617 The handle should be closed after use by calling
3618 C<guestfs_inotify_close>.  This also removes any
3619 watches automatically.
3620
3621 See also L<inotify(7)> for an overview of the inotify interface
3622 as exposed by the Linux kernel, which is roughly what we expose
3623 via libguestfs.  Note that there is one global inotify handle
3624 per libguestfs instance.");
3625
3626   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3627    [InitBasicFS, Always, TestOutputList (
3628       [["inotify_init"; "0"];
3629        ["inotify_add_watch"; "/"; "1073741823"];
3630        ["touch"; "/a"];
3631        ["touch"; "/b"];
3632        ["inotify_files"]], ["a"; "b"])],
3633    "add an inotify watch",
3634    "\
3635 Watch C<path> for the events listed in C<mask>.
3636
3637 Note that if C<path> is a directory then events within that
3638 directory are watched, but this does I<not> happen recursively
3639 (in subdirectories).
3640
3641 Note for non-C or non-Linux callers: the inotify events are
3642 defined by the Linux kernel ABI and are listed in
3643 C</usr/include/sys/inotify.h>.");
3644
3645   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3646    [],
3647    "remove an inotify watch",
3648    "\
3649 Remove a previously defined inotify watch.
3650 See C<guestfs_inotify_add_watch>.");
3651
3652   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3653    [],
3654    "return list of inotify events",
3655    "\
3656 Return the complete queue of events that have happened
3657 since the previous read call.
3658
3659 If no events have happened, this returns an empty list.
3660
3661 I<Note>: In order to make sure that all events have been
3662 read, you must call this function repeatedly until it
3663 returns an empty list.  The reason is that the call will
3664 read events up to the maximum appliance-to-host message
3665 size and leave remaining events in the queue.");
3666
3667   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3668    [],
3669    "return list of watched files that had events",
3670    "\
3671 This function is a helpful wrapper around C<guestfs_inotify_read>
3672 which just returns a list of pathnames of objects that were
3673 touched.  The returned pathnames are sorted and deduplicated.");
3674
3675   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3676    [],
3677    "close the inotify handle",
3678    "\
3679 This closes the inotify handle which was previously
3680 opened by inotify_init.  It removes all watches, throws
3681 away any pending events, and deallocates all resources.");
3682
3683   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3684    [],
3685    "set SELinux security context",
3686    "\
3687 This sets the SELinux security context of the daemon
3688 to the string C<context>.
3689
3690 See the documentation about SELINUX in L<guestfs(3)>.");
3691
3692   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3693    [],
3694    "get SELinux security context",
3695    "\
3696 This gets the SELinux security context of the daemon.
3697
3698 See the documentation about SELINUX in L<guestfs(3)>,
3699 and C<guestfs_setcon>");
3700
3701   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3702    [InitEmpty, Always, TestOutput (
3703       [["part_disk"; "/dev/sda"; "mbr"];
3704        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3705        ["mount_options"; ""; "/dev/sda1"; "/"];
3706        ["write"; "/new"; "new file contents"];
3707        ["cat"; "/new"]], "new file contents")],
3708    "make a filesystem with block size",
3709    "\
3710 This call is similar to C<guestfs_mkfs>, but it allows you to
3711 control the block size of the resulting filesystem.  Supported
3712 block sizes depend on the filesystem type, but typically they
3713 are C<1024>, C<2048> or C<4096> only.");
3714
3715   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3716    [InitEmpty, Always, TestOutput (
3717       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3718        ["mke2journal"; "4096"; "/dev/sda1"];
3719        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3720        ["mount_options"; ""; "/dev/sda2"; "/"];
3721        ["write"; "/new"; "new file contents"];
3722        ["cat"; "/new"]], "new file contents")],
3723    "make ext2/3/4 external journal",
3724    "\
3725 This creates an ext2 external journal on C<device>.  It is equivalent
3726 to the command:
3727
3728  mke2fs -O journal_dev -b blocksize device");
3729
3730   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3731    [InitEmpty, Always, TestOutput (
3732       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3733        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3734        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3735        ["mount_options"; ""; "/dev/sda2"; "/"];
3736        ["write"; "/new"; "new file contents"];
3737        ["cat"; "/new"]], "new file contents")],
3738    "make ext2/3/4 external journal with label",
3739    "\
3740 This creates an ext2 external journal on C<device> with label C<label>.");
3741
3742   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3743    (let uuid = uuidgen () in
3744     [InitEmpty, Always, TestOutput (
3745        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3746         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3747         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3748         ["mount_options"; ""; "/dev/sda2"; "/"];
3749         ["write"; "/new"; "new file contents"];
3750         ["cat"; "/new"]], "new file contents")]),
3751    "make ext2/3/4 external journal with UUID",
3752    "\
3753 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3754
3755   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3756    [],
3757    "make ext2/3/4 filesystem with external journal",
3758    "\
3759 This creates an ext2/3/4 filesystem on C<device> with
3760 an external journal on C<journal>.  It is equivalent
3761 to the command:
3762
3763  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3764
3765 See also C<guestfs_mke2journal>.");
3766
3767   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3768    [],
3769    "make ext2/3/4 filesystem with external journal",
3770    "\
3771 This creates an ext2/3/4 filesystem on C<device> with
3772 an external journal on the journal labeled C<label>.
3773
3774 See also C<guestfs_mke2journal_L>.");
3775
3776   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3777    [],
3778    "make ext2/3/4 filesystem with external journal",
3779    "\
3780 This creates an ext2/3/4 filesystem on C<device> with
3781 an external journal on the journal with UUID C<uuid>.
3782
3783 See also C<guestfs_mke2journal_U>.");
3784
3785   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3786    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3787    "load a kernel module",
3788    "\
3789 This loads a kernel module in the appliance.
3790
3791 The kernel module must have been whitelisted when libguestfs
3792 was built (see C<appliance/kmod.whitelist.in> in the source).");
3793
3794   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3795    [InitNone, Always, TestOutput (
3796       [["echo_daemon"; "This is a test"]], "This is a test"
3797     )],
3798    "echo arguments back to the client",
3799    "\
3800 This command concatenate the list of C<words> passed with single spaces between
3801 them and returns the resulting string.
3802
3803 You can use this command to test the connection through to the daemon.
3804
3805 See also C<guestfs_ping_daemon>.");
3806
3807   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3808    [], (* There is a regression test for this. *)
3809    "find all files and directories, returning NUL-separated list",
3810    "\
3811 This command lists out all files and directories, recursively,
3812 starting at C<directory>, placing the resulting list in the
3813 external file called C<files>.
3814
3815 This command works the same way as C<guestfs_find> with the
3816 following exceptions:
3817
3818 =over 4
3819
3820 =item *
3821
3822 The resulting list is written to an external file.
3823
3824 =item *
3825
3826 Items (filenames) in the result are separated
3827 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3828
3829 =item *
3830
3831 This command is not limited in the number of names that it
3832 can return.
3833
3834 =item *
3835
3836 The result list is not sorted.
3837
3838 =back");
3839
3840   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3841    [InitISOFS, Always, TestOutput (
3842       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3843     InitISOFS, Always, TestOutput (
3844       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3845     InitISOFS, Always, TestOutput (
3846       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3847     InitISOFS, Always, TestLastFail (
3848       [["case_sensitive_path"; "/Known-1/"]]);
3849     InitBasicFS, Always, TestOutput (
3850       [["mkdir"; "/a"];
3851        ["mkdir"; "/a/bbb"];
3852        ["touch"; "/a/bbb/c"];
3853        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3854     InitBasicFS, Always, TestOutput (
3855       [["mkdir"; "/a"];
3856        ["mkdir"; "/a/bbb"];
3857        ["touch"; "/a/bbb/c"];
3858        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3859     InitBasicFS, Always, TestLastFail (
3860       [["mkdir"; "/a"];
3861        ["mkdir"; "/a/bbb"];
3862        ["touch"; "/a/bbb/c"];
3863        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3864    "return true path on case-insensitive filesystem",
3865    "\
3866 This can be used to resolve case insensitive paths on
3867 a filesystem which is case sensitive.  The use case is
3868 to resolve paths which you have read from Windows configuration
3869 files or the Windows Registry, to the true path.
3870
3871 The command handles a peculiarity of the Linux ntfs-3g
3872 filesystem driver (and probably others), which is that although
3873 the underlying filesystem is case-insensitive, the driver
3874 exports the filesystem to Linux as case-sensitive.
3875
3876 One consequence of this is that special directories such
3877 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3878 (or other things) depending on the precise details of how
3879 they were created.  In Windows itself this would not be
3880 a problem.
3881
3882 Bug or feature?  You decide:
3883 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3884
3885 This function resolves the true case of each element in the
3886 path and returns the case-sensitive path.
3887
3888 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3889 might return C<\"/WINDOWS/system32\"> (the exact return value
3890 would depend on details of how the directories were originally
3891 created under Windows).
3892
3893 I<Note>:
3894 This function does not handle drive names, backslashes etc.
3895
3896 See also C<guestfs_realpath>.");
3897
3898   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3899    [InitBasicFS, Always, TestOutput (
3900       [["vfs_type"; "/dev/sda1"]], "ext2")],
3901    "get the Linux VFS type corresponding to a mounted device",
3902    "\
3903 This command gets the block device type corresponding to
3904 a mounted device called C<device>.
3905
3906 Usually the result is the name of the Linux VFS module that
3907 is used to mount this device (probably determined automatically
3908 if you used the C<guestfs_mount> call).");
3909
3910   ("truncate", (RErr, [Pathname "path"]), 199, [],
3911    [InitBasicFS, Always, TestOutputStruct (
3912       [["write"; "/test"; "some stuff so size is not zero"];
3913        ["truncate"; "/test"];
3914        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3915    "truncate a file to zero size",
3916    "\
3917 This command truncates C<path> to a zero-length file.  The
3918 file must exist already.");
3919
3920   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3921    [InitBasicFS, Always, TestOutputStruct (
3922       [["touch"; "/test"];
3923        ["truncate_size"; "/test"; "1000"];
3924        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3925    "truncate a file to a particular size",
3926    "\
3927 This command truncates C<path> to size C<size> bytes.  The file
3928 must exist already.  If the file is smaller than C<size> then
3929 the file is extended to the required size with null bytes.");
3930
3931   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3932    [InitBasicFS, Always, TestOutputStruct (
3933       [["touch"; "/test"];
3934        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3935        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3936    "set timestamp of a file with nanosecond precision",
3937    "\
3938 This command sets the timestamps of a file with nanosecond
3939 precision.
3940
3941 C<atsecs, atnsecs> are the last access time (atime) in secs and
3942 nanoseconds from the epoch.
3943
3944 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3945 secs and nanoseconds from the epoch.
3946
3947 If the C<*nsecs> field contains the special value C<-1> then
3948 the corresponding timestamp is set to the current time.  (The
3949 C<*secs> field is ignored in this case).
3950
3951 If the C<*nsecs> field contains the special value C<-2> then
3952 the corresponding timestamp is left unchanged.  (The
3953 C<*secs> field is ignored in this case).");
3954
3955   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3956    [InitBasicFS, Always, TestOutputStruct (
3957       [["mkdir_mode"; "/test"; "0o111"];
3958        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3959    "create a directory with a particular mode",
3960    "\
3961 This command creates a directory, setting the initial permissions
3962 of the directory to C<mode>.
3963
3964 For common Linux filesystems, the actual mode which is set will
3965 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3966 interpret the mode in other ways.
3967
3968 See also C<guestfs_mkdir>, C<guestfs_umask>");
3969
3970   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3971    [], (* XXX *)
3972    "change file owner and group",
3973    "\
3974 Change the file owner to C<owner> and group to C<group>.
3975 This is like C<guestfs_chown> but if C<path> is a symlink then
3976 the link itself is changed, not the target.
3977
3978 Only numeric uid and gid are supported.  If you want to use
3979 names, you will need to locate and parse the password file
3980 yourself (Augeas support makes this relatively easy).");
3981
3982   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3983    [], (* XXX *)
3984    "lstat on multiple files",
3985    "\
3986 This call allows you to perform the C<guestfs_lstat> operation
3987 on multiple files, where all files are in the directory C<path>.
3988 C<names> is the list of files from this directory.
3989
3990 On return you get a list of stat structs, with a one-to-one
3991 correspondence to the C<names> list.  If any name did not exist
3992 or could not be lstat'd, then the C<ino> field of that structure
3993 is set to C<-1>.
3994
3995 This call is intended for programs that want to efficiently
3996 list a directory contents without making many round-trips.
3997 See also C<guestfs_lxattrlist> for a similarly efficient call
3998 for getting extended attributes.  Very long directory listings
3999 might cause the protocol message size to be exceeded, causing
4000 this call to fail.  The caller must split up such requests
4001 into smaller groups of names.");
4002
4003   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4004    [], (* XXX *)
4005    "lgetxattr on multiple files",
4006    "\
4007 This call allows you to get the extended attributes
4008 of multiple files, where all files are in the directory C<path>.
4009 C<names> is the list of files from this directory.
4010
4011 On return you get a flat list of xattr structs which must be
4012 interpreted sequentially.  The first xattr struct always has a zero-length
4013 C<attrname>.  C<attrval> in this struct is zero-length
4014 to indicate there was an error doing C<lgetxattr> for this
4015 file, I<or> is a C string which is a decimal number
4016 (the number of following attributes for this file, which could
4017 be C<\"0\">).  Then after the first xattr struct are the
4018 zero or more attributes for the first named file.
4019 This repeats for the second and subsequent files.
4020
4021 This call is intended for programs that want to efficiently
4022 list a directory contents without making many round-trips.
4023 See also C<guestfs_lstatlist> for a similarly efficient call
4024 for getting standard stats.  Very long directory listings
4025 might cause the protocol message size to be exceeded, causing
4026 this call to fail.  The caller must split up such requests
4027 into smaller groups of names.");
4028
4029   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4030    [], (* XXX *)
4031    "readlink on multiple files",
4032    "\
4033 This call allows you to do a C<readlink> operation
4034 on multiple files, where all files are in the directory C<path>.
4035 C<names> is the list of files from this directory.
4036
4037 On return you get a list of strings, with a one-to-one
4038 correspondence to the C<names> list.  Each string is the
4039 value of the symbol link.
4040
4041 If the C<readlink(2)> operation fails on any name, then
4042 the corresponding result string is the empty string C<\"\">.
4043 However the whole operation is completed even if there
4044 were C<readlink(2)> errors, and so you can call this
4045 function with names where you don't know if they are
4046 symbolic links already (albeit slightly less efficient).
4047
4048 This call is intended for programs that want to efficiently
4049 list a directory contents without making many round-trips.
4050 Very long directory listings might cause the protocol
4051 message size to be exceeded, causing
4052 this call to fail.  The caller must split up such requests
4053 into smaller groups of names.");
4054
4055   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4056    [InitISOFS, Always, TestOutputBuffer (
4057       [["pread"; "/known-4"; "1"; "3"]], "\n");
4058     InitISOFS, Always, TestOutputBuffer (
4059       [["pread"; "/empty"; "0"; "100"]], "")],
4060    "read part of a file",
4061    "\
4062 This command lets you read part of a file.  It reads C<count>
4063 bytes of the file, starting at C<offset>, from file C<path>.
4064
4065 This may read fewer bytes than requested.  For further details
4066 see the L<pread(2)> system call.
4067
4068 See also C<guestfs_pwrite>.");
4069
4070   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4071    [InitEmpty, Always, TestRun (
4072       [["part_init"; "/dev/sda"; "gpt"]])],
4073    "create an empty partition table",
4074    "\
4075 This creates an empty partition table on C<device> of one of the
4076 partition types listed below.  Usually C<parttype> should be
4077 either C<msdos> or C<gpt> (for large disks).
4078
4079 Initially there are no partitions.  Following this, you should
4080 call C<guestfs_part_add> for each partition required.
4081
4082 Possible values for C<parttype> are:
4083
4084 =over 4
4085
4086 =item B<efi> | B<gpt>
4087
4088 Intel EFI / GPT partition table.
4089
4090 This is recommended for >= 2 TB partitions that will be accessed
4091 from Linux and Intel-based Mac OS X.  It also has limited backwards
4092 compatibility with the C<mbr> format.
4093
4094 =item B<mbr> | B<msdos>
4095
4096 The standard PC \"Master Boot Record\" (MBR) format used
4097 by MS-DOS and Windows.  This partition type will B<only> work
4098 for device sizes up to 2 TB.  For large disks we recommend
4099 using C<gpt>.
4100
4101 =back
4102
4103 Other partition table types that may work but are not
4104 supported include:
4105
4106 =over 4
4107
4108 =item B<aix>
4109
4110 AIX disk labels.
4111
4112 =item B<amiga> | B<rdb>
4113
4114 Amiga \"Rigid Disk Block\" format.
4115
4116 =item B<bsd>
4117
4118 BSD disk labels.
4119
4120 =item B<dasd>
4121
4122 DASD, used on IBM mainframes.
4123
4124 =item B<dvh>
4125
4126 MIPS/SGI volumes.
4127
4128 =item B<mac>
4129
4130 Old Mac partition format.  Modern Macs use C<gpt>.
4131
4132 =item B<pc98>
4133
4134 NEC PC-98 format, common in Japan apparently.
4135
4136 =item B<sun>
4137
4138 Sun disk labels.
4139
4140 =back");
4141
4142   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4143    [InitEmpty, Always, TestRun (
4144       [["part_init"; "/dev/sda"; "mbr"];
4145        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4146     InitEmpty, Always, TestRun (
4147       [["part_init"; "/dev/sda"; "gpt"];
4148        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4149        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4150     InitEmpty, Always, TestRun (
4151       [["part_init"; "/dev/sda"; "mbr"];
4152        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4153        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4154        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4155        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4156    "add a partition to the device",
4157    "\
4158 This command adds a partition to C<device>.  If there is no partition
4159 table on the device, call C<guestfs_part_init> first.
4160
4161 The C<prlogex> parameter is the type of partition.  Normally you
4162 should pass C<p> or C<primary> here, but MBR partition tables also
4163 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4164 types.
4165
4166 C<startsect> and C<endsect> are the start and end of the partition
4167 in I<sectors>.  C<endsect> may be negative, which means it counts
4168 backwards from the end of the disk (C<-1> is the last sector).
4169
4170 Creating a partition which covers the whole disk is not so easy.
4171 Use C<guestfs_part_disk> to do that.");
4172
4173   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4174    [InitEmpty, Always, TestRun (
4175       [["part_disk"; "/dev/sda"; "mbr"]]);
4176     InitEmpty, Always, TestRun (
4177       [["part_disk"; "/dev/sda"; "gpt"]])],
4178    "partition whole disk with a single primary partition",
4179    "\
4180 This command is simply a combination of C<guestfs_part_init>
4181 followed by C<guestfs_part_add> to create a single primary partition
4182 covering the whole disk.
4183
4184 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4185 but other possible values are described in C<guestfs_part_init>.");
4186
4187   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4188    [InitEmpty, Always, TestRun (
4189       [["part_disk"; "/dev/sda"; "mbr"];
4190        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4191    "make a partition bootable",
4192    "\
4193 This sets the bootable flag on partition numbered C<partnum> on
4194 device C<device>.  Note that partitions are numbered from 1.
4195
4196 The bootable flag is used by some operating systems (notably
4197 Windows) to determine which partition to boot from.  It is by
4198 no means universally recognized.");
4199
4200   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4201    [InitEmpty, Always, TestRun (
4202       [["part_disk"; "/dev/sda"; "gpt"];
4203        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4204    "set partition name",
4205    "\
4206 This sets the partition name on partition numbered C<partnum> on
4207 device C<device>.  Note that partitions are numbered from 1.
4208
4209 The partition name can only be set on certain types of partition
4210 table.  This works on C<gpt> but not on C<mbr> partitions.");
4211
4212   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4213    [], (* XXX Add a regression test for this. *)
4214    "list partitions on a device",
4215    "\
4216 This command parses the partition table on C<device> and
4217 returns the list of partitions found.
4218
4219 The fields in the returned structure are:
4220
4221 =over 4
4222
4223 =item B<part_num>
4224
4225 Partition number, counting from 1.
4226
4227 =item B<part_start>
4228
4229 Start of the partition I<in bytes>.  To get sectors you have to
4230 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4231
4232 =item B<part_end>
4233
4234 End of the partition in bytes.
4235
4236 =item B<part_size>
4237
4238 Size of the partition in bytes.
4239
4240 =back");
4241
4242   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4243    [InitEmpty, Always, TestOutput (
4244       [["part_disk"; "/dev/sda"; "gpt"];
4245        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4246    "get the partition table type",
4247    "\
4248 This command examines the partition table on C<device> and
4249 returns the partition table type (format) being used.
4250
4251 Common return values include: C<msdos> (a DOS/Windows style MBR
4252 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4253 values are possible, although unusual.  See C<guestfs_part_init>
4254 for a full list.");
4255
4256   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4257    [InitBasicFS, Always, TestOutputBuffer (
4258       [["fill"; "0x63"; "10"; "/test"];
4259        ["read_file"; "/test"]], "cccccccccc")],
4260    "fill a file with octets",
4261    "\
4262 This command creates a new file called C<path>.  The initial
4263 content of the file is C<len> octets of C<c>, where C<c>
4264 must be a number in the range C<[0..255]>.
4265
4266 To fill a file with zero bytes (sparsely), it is
4267 much more efficient to use C<guestfs_truncate_size>.
4268 To create a file with a pattern of repeating bytes
4269 use C<guestfs_fill_pattern>.");
4270
4271   ("available", (RErr, [StringList "groups"]), 216, [],
4272    [InitNone, Always, TestRun [["available"; ""]]],
4273    "test availability of some parts of the API",
4274    "\
4275 This command is used to check the availability of some
4276 groups of functionality in the appliance, which not all builds of
4277 the libguestfs appliance will be able to provide.
4278
4279 The libguestfs groups, and the functions that those
4280 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4281 You can also fetch this list at runtime by calling
4282 C<guestfs_available_all_groups>.
4283
4284 The argument C<groups> is a list of group names, eg:
4285 C<[\"inotify\", \"augeas\"]> would check for the availability of
4286 the Linux inotify functions and Augeas (configuration file
4287 editing) functions.
4288
4289 The command returns no error if I<all> requested groups are available.
4290
4291 It fails with an error if one or more of the requested
4292 groups is unavailable in the appliance.
4293
4294 If an unknown group name is included in the
4295 list of groups then an error is always returned.
4296
4297 I<Notes:>
4298
4299 =over 4
4300
4301 =item *
4302
4303 You must call C<guestfs_launch> before calling this function.
4304
4305 The reason is because we don't know what groups are
4306 supported by the appliance/daemon until it is running and can
4307 be queried.
4308
4309 =item *
4310
4311 If a group of functions is available, this does not necessarily
4312 mean that they will work.  You still have to check for errors
4313 when calling individual API functions even if they are
4314 available.
4315
4316 =item *
4317
4318 It is usually the job of distro packagers to build
4319 complete functionality into the libguestfs appliance.
4320 Upstream libguestfs, if built from source with all
4321 requirements satisfied, will support everything.
4322
4323 =item *
4324
4325 This call was added in version C<1.0.80>.  In previous
4326 versions of libguestfs all you could do would be to speculatively
4327 execute a command to find out if the daemon implemented it.
4328 See also C<guestfs_version>.
4329
4330 =back");
4331
4332   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4333    [InitBasicFS, Always, TestOutputBuffer (
4334       [["write"; "/src"; "hello, world"];
4335        ["dd"; "/src"; "/dest"];
4336        ["read_file"; "/dest"]], "hello, world")],
4337    "copy from source to destination using dd",
4338    "\
4339 This command copies from one source device or file C<src>
4340 to another destination device or file C<dest>.  Normally you
4341 would use this to copy to or from a device or partition, for
4342 example to duplicate a filesystem.
4343
4344 If the destination is a device, it must be as large or larger
4345 than the source file or device, otherwise the copy will fail.
4346 This command cannot do partial copies (see C<guestfs_copy_size>).");
4347
4348   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4349    [InitBasicFS, Always, TestOutputInt (
4350       [["write"; "/file"; "hello, world"];
4351        ["filesize"; "/file"]], 12)],
4352    "return the size of the file in bytes",
4353    "\
4354 This command returns the size of C<file> in bytes.
4355
4356 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4357 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4358 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4359
4360   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4361    [InitBasicFSonLVM, Always, TestOutputList (
4362       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4363        ["lvs"]], ["/dev/VG/LV2"])],
4364    "rename an LVM logical volume",
4365    "\
4366 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4367
4368   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4369    [InitBasicFSonLVM, Always, TestOutputList (
4370       [["umount"; "/"];
4371        ["vg_activate"; "false"; "VG"];
4372        ["vgrename"; "VG"; "VG2"];
4373        ["vg_activate"; "true"; "VG2"];
4374        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4375        ["vgs"]], ["VG2"])],
4376    "rename an LVM volume group",
4377    "\
4378 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4379
4380   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4381    [InitISOFS, Always, TestOutputBuffer (
4382       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4383    "list the contents of a single file in an initrd",
4384    "\
4385 This command unpacks the file C<filename> from the initrd file
4386 called C<initrdpath>.  The filename must be given I<without> the
4387 initial C</> character.
4388
4389 For example, in guestfish you could use the following command
4390 to examine the boot script (usually called C</init>)
4391 contained in a Linux initrd or initramfs image:
4392
4393  initrd-cat /boot/initrd-<version>.img init
4394
4395 See also C<guestfs_initrd_list>.");
4396
4397   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4398    [],
4399    "get the UUID of a physical volume",
4400    "\
4401 This command returns the UUID of the LVM PV C<device>.");
4402
4403   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4404    [],
4405    "get the UUID of a volume group",
4406    "\
4407 This command returns the UUID of the LVM VG named C<vgname>.");
4408
4409   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4410    [],
4411    "get the UUID of a logical volume",
4412    "\
4413 This command returns the UUID of the LVM LV C<device>.");
4414
4415   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4416    [],
4417    "get the PV UUIDs containing the volume group",
4418    "\
4419 Given a VG called C<vgname>, this returns the UUIDs of all
4420 the physical volumes that this volume group resides on.
4421
4422 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4423 calls to associate physical volumes and volume groups.
4424
4425 See also C<guestfs_vglvuuids>.");
4426
4427   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4428    [],
4429    "get the LV UUIDs of all LVs in the volume group",
4430    "\
4431 Given a VG called C<vgname>, this returns the UUIDs of all
4432 the logical volumes created in this volume group.
4433
4434 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4435 calls to associate logical volumes and volume groups.
4436
4437 See also C<guestfs_vgpvuuids>.");
4438
4439   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4440    [InitBasicFS, Always, TestOutputBuffer (
4441       [["write"; "/src"; "hello, world"];
4442        ["copy_size"; "/src"; "/dest"; "5"];
4443        ["read_file"; "/dest"]], "hello")],
4444    "copy size bytes from source to destination using dd",
4445    "\
4446 This command copies exactly C<size> bytes from one source device
4447 or file C<src> to another destination device or file C<dest>.
4448
4449 Note this will fail if the source is too short or if the destination
4450 is not large enough.");
4451
4452   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4453    [InitBasicFSonLVM, Always, TestRun (
4454       [["zero_device"; "/dev/VG/LV"]])],
4455    "write zeroes to an entire device",
4456    "\
4457 This command writes zeroes over the entire C<device>.  Compare
4458 with C<guestfs_zero> which just zeroes the first few blocks of
4459 a device.");
4460
4461   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4462    [InitBasicFS, Always, TestOutput (
4463       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4464        ["cat"; "/hello"]], "hello\n")],
4465    "unpack compressed tarball to directory",
4466    "\
4467 This command uploads and unpacks local file C<tarball> (an
4468 I<xz compressed> tar file) into C<directory>.");
4469
4470   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4471    [],
4472    "pack directory into compressed tarball",
4473    "\
4474 This command packs the contents of C<directory> and downloads
4475 it to local file C<tarball> (as an xz compressed tar archive).");
4476
4477   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4478    [],
4479    "resize an NTFS filesystem",
4480    "\
4481 This command resizes an NTFS filesystem, expanding or
4482 shrinking it to the size of the underlying device.
4483 See also L<ntfsresize(8)>.");
4484
4485   ("vgscan", (RErr, []), 232, [],
4486    [InitEmpty, Always, TestRun (
4487       [["vgscan"]])],
4488    "rescan for LVM physical volumes, volume groups and logical volumes",
4489    "\
4490 This rescans all block devices and rebuilds the list of LVM
4491 physical volumes, volume groups and logical volumes.");
4492
4493   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4494    [InitEmpty, Always, TestRun (
4495       [["part_init"; "/dev/sda"; "mbr"];
4496        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4497        ["part_del"; "/dev/sda"; "1"]])],
4498    "delete a partition",
4499    "\
4500 This command deletes the partition numbered C<partnum> on C<device>.
4501
4502 Note that in the case of MBR partitioning, deleting an
4503 extended partition also deletes any logical partitions
4504 it contains.");
4505
4506   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4507    [InitEmpty, Always, TestOutputTrue (
4508       [["part_init"; "/dev/sda"; "mbr"];
4509        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4510        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4511        ["part_get_bootable"; "/dev/sda"; "1"]])],
4512    "return true if a partition is bootable",
4513    "\
4514 This command returns true if the partition C<partnum> on
4515 C<device> has the bootable flag set.
4516
4517 See also C<guestfs_part_set_bootable>.");
4518
4519   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4520    [InitEmpty, Always, TestOutputInt (
4521       [["part_init"; "/dev/sda"; "mbr"];
4522        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4523        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4524        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4525    "get the MBR type byte (ID byte) from a partition",
4526    "\
4527 Returns the MBR type byte (also known as the ID byte) from
4528 the numbered partition C<partnum>.
4529
4530 Note that only MBR (old DOS-style) partitions have type bytes.
4531 You will get undefined results for other partition table
4532 types (see C<guestfs_part_get_parttype>).");
4533
4534   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4535    [], (* tested by part_get_mbr_id *)
4536    "set the MBR type byte (ID byte) of a partition",
4537    "\
4538 Sets the MBR type byte (also known as the ID byte) of
4539 the numbered partition C<partnum> to C<idbyte>.  Note
4540 that the type bytes quoted in most documentation are
4541 in fact hexadecimal numbers, but usually documented
4542 without any leading \"0x\" which might be confusing.
4543
4544 Note that only MBR (old DOS-style) partitions have type bytes.
4545 You will get undefined results for other partition table
4546 types (see C<guestfs_part_get_parttype>).");
4547
4548   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4549    [InitISOFS, Always, TestOutput (
4550       [["checksum_device"; "md5"; "/dev/sdd"]],
4551       (Digest.to_hex (Digest.file "images/test.iso")))],
4552    "compute MD5, SHAx or CRC checksum of the contents of a device",
4553    "\
4554 This call computes the MD5, SHAx or CRC checksum of the
4555 contents of the device named C<device>.  For the types of
4556 checksums supported see the C<guestfs_checksum> command.");
4557
4558   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4559    [InitNone, Always, TestRun (
4560       [["part_disk"; "/dev/sda"; "mbr"];
4561        ["pvcreate"; "/dev/sda1"];
4562        ["vgcreate"; "VG"; "/dev/sda1"];
4563        ["lvcreate"; "LV"; "VG"; "10"];
4564        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4565    "expand an LV to fill free space",
4566    "\
4567 This expands an existing logical volume C<lv> so that it fills
4568 C<pc>% of the remaining free space in the volume group.  Commonly
4569 you would call this with pc = 100 which expands the logical volume
4570 as much as possible, using all remaining free space in the volume
4571 group.");
4572
4573   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4574    [], (* XXX Augeas code needs tests. *)
4575    "clear Augeas path",
4576    "\
4577 Set the value associated with C<path> to C<NULL>.  This
4578 is the same as the L<augtool(1)> C<clear> command.");
4579
4580   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4581    [InitEmpty, Always, TestOutputInt (
4582       [["get_umask"]], 0o22)],
4583    "get the current umask",
4584    "\
4585 Return the current umask.  By default the umask is C<022>
4586 unless it has been set by calling C<guestfs_umask>.");
4587
4588   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4589    [],
4590    "upload a file to the appliance (internal use only)",
4591    "\
4592 The C<guestfs_debug_upload> command uploads a file to
4593 the libguestfs appliance.
4594
4595 There is no comprehensive help for this command.  You have
4596 to look at the file C<daemon/debug.c> in the libguestfs source
4597 to find out what it is for.");
4598
4599   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4600    [InitBasicFS, Always, TestOutput (
4601       [["base64_in"; "../images/hello.b64"; "/hello"];
4602        ["cat"; "/hello"]], "hello\n")],
4603    "upload base64-encoded data to file",
4604    "\
4605 This command uploads base64-encoded data from C<base64file>
4606 to C<filename>.");
4607
4608   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4609    [],
4610    "download file and encode as base64",
4611    "\
4612 This command downloads the contents of C<filename>, writing
4613 it out to local file C<base64file> encoded as base64.");
4614
4615   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4616    [],
4617    "compute MD5, SHAx or CRC checksum of files in a directory",
4618    "\
4619 This command computes the checksums of all regular files in
4620 C<directory> and then emits a list of those checksums to
4621 the local output file C<sumsfile>.
4622
4623 This can be used for verifying the integrity of a virtual
4624 machine.  However to be properly secure you should pay
4625 attention to the output of the checksum command (it uses
4626 the ones from GNU coreutils).  In particular when the
4627 filename is not printable, coreutils uses a special
4628 backslash syntax.  For more information, see the GNU
4629 coreutils info file.");
4630
4631   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4632    [InitBasicFS, Always, TestOutputBuffer (
4633       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4634        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4635    "fill a file with a repeating pattern of bytes",
4636    "\
4637 This function is like C<guestfs_fill> except that it creates
4638 a new file of length C<len> containing the repeating pattern
4639 of bytes in C<pattern>.  The pattern is truncated if necessary
4640 to ensure the length of the file is exactly C<len> bytes.");
4641
4642   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4643    [InitBasicFS, Always, TestOutput (
4644       [["write"; "/new"; "new file contents"];
4645        ["cat"; "/new"]], "new file contents");
4646     InitBasicFS, Always, TestOutput (
4647       [["write"; "/new"; "\nnew file contents\n"];
4648        ["cat"; "/new"]], "\nnew file contents\n");
4649     InitBasicFS, Always, TestOutput (
4650       [["write"; "/new"; "\n\n"];
4651        ["cat"; "/new"]], "\n\n");
4652     InitBasicFS, Always, TestOutput (
4653       [["write"; "/new"; ""];
4654        ["cat"; "/new"]], "");
4655     InitBasicFS, Always, TestOutput (
4656       [["write"; "/new"; "\n\n\n"];
4657        ["cat"; "/new"]], "\n\n\n");
4658     InitBasicFS, Always, TestOutput (
4659       [["write"; "/new"; "\n"];
4660        ["cat"; "/new"]], "\n")],
4661    "create a new file",
4662    "\
4663 This call creates a file called C<path>.  The content of the
4664 file is the string C<content> (which can contain any 8 bit data).");
4665
4666   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4667    [InitBasicFS, Always, TestOutput (
4668       [["write"; "/new"; "new file contents"];
4669        ["pwrite"; "/new"; "data"; "4"];
4670        ["cat"; "/new"]], "new data contents");
4671     InitBasicFS, Always, TestOutput (
4672       [["write"; "/new"; "new file contents"];
4673        ["pwrite"; "/new"; "is extended"; "9"];
4674        ["cat"; "/new"]], "new file is extended");
4675     InitBasicFS, Always, TestOutput (
4676       [["write"; "/new"; "new file contents"];
4677        ["pwrite"; "/new"; ""; "4"];
4678        ["cat"; "/new"]], "new file contents")],
4679    "write to part of a file",
4680    "\
4681 This command writes to part of a file.  It writes the data
4682 buffer C<content> to the file C<path> starting at offset C<offset>.
4683
4684 This command implements the L<pwrite(2)> system call, and like
4685 that system call it may not write the full data requested.  The
4686 return value is the number of bytes that were actually written
4687 to the file.  This could even be 0, although short writes are
4688 unlikely for regular files in ordinary circumstances.
4689
4690 See also C<guestfs_pread>.");
4691
4692   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4693    [],
4694    "resize an ext2/ext3 filesystem (with size)",
4695    "\
4696 This command is the same as C<guestfs_resize2fs> except that it
4697 allows you to specify the new size (in bytes) explicitly.");
4698
4699   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4700    [],
4701    "resize an LVM physical volume (with size)",
4702    "\
4703 This command is the same as C<guestfs_pvresize> except that it
4704 allows you to specify the new size (in bytes) explicitly.");
4705
4706   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4707    [],
4708    "resize an NTFS filesystem (with size)",
4709    "\
4710 This command is the same as C<guestfs_ntfsresize> except that it
4711 allows you to specify the new size (in bytes) explicitly.");
4712
4713   ("available_all_groups", (RStringList "groups", []), 251, [],
4714    [],
4715    "return a list of all optional groups",
4716    "\
4717 This command returns a list of all optional groups that this
4718 daemon knows about.  Note this returns both supported and unsupported
4719 groups.  To find out which ones the daemon can actually support
4720 you have to call C<guestfs_available> on each member of the
4721 returned list.
4722
4723 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4724
4725 ]
4726
4727 let all_functions = non_daemon_functions @ daemon_functions
4728
4729 (* In some places we want the functions to be displayed sorted
4730  * alphabetically, so this is useful:
4731  *)
4732 let all_functions_sorted =
4733   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4734                compare n1 n2) all_functions
4735
4736 (* This is used to generate the src/MAX_PROC_NR file which
4737  * contains the maximum procedure number, a surrogate for the
4738  * ABI version number.  See src/Makefile.am for the details.
4739  *)
4740 let max_proc_nr =
4741   let proc_nrs = List.map (
4742     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4743   ) daemon_functions in
4744   List.fold_left max 0 proc_nrs
4745
4746 (* Field types for structures. *)
4747 type field =
4748   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4749   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4750   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4751   | FUInt32
4752   | FInt32
4753   | FUInt64
4754   | FInt64
4755   | FBytes                      (* Any int measure that counts bytes. *)
4756   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4757   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4758
4759 (* Because we generate extra parsing code for LVM command line tools,
4760  * we have to pull out the LVM columns separately here.
4761  *)
4762 let lvm_pv_cols = [
4763   "pv_name", FString;
4764   "pv_uuid", FUUID;
4765   "pv_fmt", FString;
4766   "pv_size", FBytes;
4767   "dev_size", FBytes;
4768   "pv_free", FBytes;
4769   "pv_used", FBytes;
4770   "pv_attr", FString (* XXX *);
4771   "pv_pe_count", FInt64;
4772   "pv_pe_alloc_count", FInt64;
4773   "pv_tags", FString;
4774   "pe_start", FBytes;
4775   "pv_mda_count", FInt64;
4776   "pv_mda_free", FBytes;
4777   (* Not in Fedora 10:
4778      "pv_mda_size", FBytes;
4779   *)
4780 ]
4781 let lvm_vg_cols = [
4782   "vg_name", FString;
4783   "vg_uuid", FUUID;
4784   "vg_fmt", FString;
4785   "vg_attr", FString (* XXX *);
4786   "vg_size", FBytes;
4787   "vg_free", FBytes;
4788   "vg_sysid", FString;
4789   "vg_extent_size", FBytes;
4790   "vg_extent_count", FInt64;
4791   "vg_free_count", FInt64;
4792   "max_lv", FInt64;
4793   "max_pv", FInt64;
4794   "pv_count", FInt64;
4795   "lv_count", FInt64;
4796   "snap_count", FInt64;
4797   "vg_seqno", FInt64;
4798   "vg_tags", FString;
4799   "vg_mda_count", FInt64;
4800   "vg_mda_free", FBytes;
4801   (* Not in Fedora 10:
4802      "vg_mda_size", FBytes;
4803   *)
4804 ]
4805 let lvm_lv_cols = [
4806   "lv_name", FString;
4807   "lv_uuid", FUUID;
4808   "lv_attr", FString (* XXX *);
4809   "lv_major", FInt64;
4810   "lv_minor", FInt64;
4811   "lv_kernel_major", FInt64;
4812   "lv_kernel_minor", FInt64;
4813   "lv_size", FBytes;
4814   "seg_count", FInt64;
4815   "origin", FString;
4816   "snap_percent", FOptPercent;
4817   "copy_percent", FOptPercent;
4818   "move_pv", FString;
4819   "lv_tags", FString;
4820   "mirror_log", FString;
4821   "modules", FString;
4822 ]
4823
4824 (* Names and fields in all structures (in RStruct and RStructList)
4825  * that we support.
4826  *)
4827 let structs = [
4828   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4829    * not use this struct in any new code.
4830    *)
4831   "int_bool", [
4832     "i", FInt32;                (* for historical compatibility *)
4833     "b", FInt32;                (* for historical compatibility *)
4834   ];
4835
4836   (* LVM PVs, VGs, LVs. *)
4837   "lvm_pv", lvm_pv_cols;
4838   "lvm_vg", lvm_vg_cols;
4839   "lvm_lv", lvm_lv_cols;
4840
4841   (* Column names and types from stat structures.
4842    * NB. Can't use things like 'st_atime' because glibc header files
4843    * define some of these as macros.  Ugh.
4844    *)
4845   "stat", [
4846     "dev", FInt64;
4847     "ino", FInt64;
4848     "mode", FInt64;
4849     "nlink", FInt64;
4850     "uid", FInt64;
4851     "gid", FInt64;
4852     "rdev", FInt64;
4853     "size", FInt64;
4854     "blksize", FInt64;
4855     "blocks", FInt64;
4856     "atime", FInt64;
4857     "mtime", FInt64;
4858     "ctime", FInt64;
4859   ];
4860   "statvfs", [
4861     "bsize", FInt64;
4862     "frsize", FInt64;
4863     "blocks", FInt64;
4864     "bfree", FInt64;
4865     "bavail", FInt64;
4866     "files", FInt64;
4867     "ffree", FInt64;
4868     "favail", FInt64;
4869     "fsid", FInt64;
4870     "flag", FInt64;
4871     "namemax", FInt64;
4872   ];
4873
4874   (* Column names in dirent structure. *)
4875   "dirent", [
4876     "ino", FInt64;
4877     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4878     "ftyp", FChar;
4879     "name", FString;
4880   ];
4881
4882   (* Version numbers. *)
4883   "version", [
4884     "major", FInt64;
4885     "minor", FInt64;
4886     "release", FInt64;
4887     "extra", FString;
4888   ];
4889
4890   (* Extended attribute. *)
4891   "xattr", [
4892     "attrname", FString;
4893     "attrval", FBuffer;
4894   ];
4895
4896   (* Inotify events. *)
4897   "inotify_event", [
4898     "in_wd", FInt64;
4899     "in_mask", FUInt32;
4900     "in_cookie", FUInt32;
4901     "in_name", FString;
4902   ];
4903
4904   (* Partition table entry. *)
4905   "partition", [
4906     "part_num", FInt32;
4907     "part_start", FBytes;
4908     "part_end", FBytes;
4909     "part_size", FBytes;
4910   ];
4911 ] (* end of structs *)
4912
4913 (* Ugh, Java has to be different ..
4914  * These names are also used by the Haskell bindings.
4915  *)
4916 let java_structs = [
4917   "int_bool", "IntBool";
4918   "lvm_pv", "PV";
4919   "lvm_vg", "VG";
4920   "lvm_lv", "LV";
4921   "stat", "Stat";
4922   "statvfs", "StatVFS";
4923   "dirent", "Dirent";
4924   "version", "Version";
4925   "xattr", "XAttr";
4926   "inotify_event", "INotifyEvent";
4927   "partition", "Partition";
4928 ]
4929
4930 (* What structs are actually returned. *)
4931 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4932
4933 (* Returns a list of RStruct/RStructList structs that are returned
4934  * by any function.  Each element of returned list is a pair:
4935  *
4936  * (structname, RStructOnly)
4937  *    == there exists function which returns RStruct (_, structname)
4938  * (structname, RStructListOnly)
4939  *    == there exists function which returns RStructList (_, structname)
4940  * (structname, RStructAndList)
4941  *    == there are functions returning both RStruct (_, structname)
4942  *                                      and RStructList (_, structname)
4943  *)
4944 let rstructs_used_by functions =
4945   (* ||| is a "logical OR" for rstructs_used_t *)
4946   let (|||) a b =
4947     match a, b with
4948     | RStructAndList, _
4949     | _, RStructAndList -> RStructAndList
4950     | RStructOnly, RStructListOnly
4951     | RStructListOnly, RStructOnly -> RStructAndList
4952     | RStructOnly, RStructOnly -> RStructOnly
4953     | RStructListOnly, RStructListOnly -> RStructListOnly
4954   in
4955
4956   let h = Hashtbl.create 13 in
4957
4958   (* if elem->oldv exists, update entry using ||| operator,
4959    * else just add elem->newv to the hash
4960    *)
4961   let update elem newv =
4962     try  let oldv = Hashtbl.find h elem in
4963          Hashtbl.replace h elem (newv ||| oldv)
4964     with Not_found -> Hashtbl.add h elem newv
4965   in
4966
4967   List.iter (
4968     fun (_, style, _, _, _, _, _) ->
4969       match fst style with
4970       | RStruct (_, structname) -> update structname RStructOnly
4971       | RStructList (_, structname) -> update structname RStructListOnly
4972       | _ -> ()
4973   ) functions;
4974
4975   (* return key->values as a list of (key,value) *)
4976   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4977
4978 (* Used for testing language bindings. *)
4979 type callt =
4980   | CallString of string
4981   | CallOptString of string option
4982   | CallStringList of string list
4983   | CallInt of int
4984   | CallInt64 of int64
4985   | CallBool of bool
4986   | CallBuffer of string
4987
4988 (* Used to memoize the result of pod2text. *)
4989 let pod2text_memo_filename = "src/.pod2text.data"
4990 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4991   try
4992     let chan = open_in pod2text_memo_filename in
4993     let v = input_value chan in
4994     close_in chan;
4995     v
4996   with
4997     _ -> Hashtbl.create 13
4998 let pod2text_memo_updated () =
4999   let chan = open_out pod2text_memo_filename in
5000   output_value chan pod2text_memo;
5001   close_out chan
5002
5003 (* Useful functions.
5004  * Note we don't want to use any external OCaml libraries which
5005  * makes this a bit harder than it should be.
5006  *)
5007 module StringMap = Map.Make (String)
5008
5009 let failwithf fs = ksprintf failwith fs
5010
5011 let unique = let i = ref 0 in fun () -> incr i; !i
5012
5013 let replace_char s c1 c2 =
5014   let s2 = String.copy s in
5015   let r = ref false in
5016   for i = 0 to String.length s2 - 1 do
5017     if String.unsafe_get s2 i = c1 then (
5018       String.unsafe_set s2 i c2;
5019       r := true
5020     )
5021   done;
5022   if not !r then s else s2
5023
5024 let isspace c =
5025   c = ' '
5026   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5027
5028 let triml ?(test = isspace) str =
5029   let i = ref 0 in
5030   let n = ref (String.length str) in
5031   while !n > 0 && test str.[!i]; do
5032     decr n;
5033     incr i
5034   done;
5035   if !i = 0 then str
5036   else String.sub str !i !n
5037
5038 let trimr ?(test = isspace) str =
5039   let n = ref (String.length str) in
5040   while !n > 0 && test str.[!n-1]; do
5041     decr n
5042   done;
5043   if !n = String.length str then str
5044   else String.sub str 0 !n
5045
5046 let trim ?(test = isspace) str =
5047   trimr ~test (triml ~test str)
5048
5049 let rec find s sub =
5050   let len = String.length s in
5051   let sublen = String.length sub in
5052   let rec loop i =
5053     if i <= len-sublen then (
5054       let rec loop2 j =
5055         if j < sublen then (
5056           if s.[i+j] = sub.[j] then loop2 (j+1)
5057           else -1
5058         ) else
5059           i (* found *)
5060       in
5061       let r = loop2 0 in
5062       if r = -1 then loop (i+1) else r
5063     ) else
5064       -1 (* not found *)
5065   in
5066   loop 0
5067
5068 let rec replace_str s s1 s2 =
5069   let len = String.length s in
5070   let sublen = String.length s1 in
5071   let i = find s s1 in
5072   if i = -1 then s
5073   else (
5074     let s' = String.sub s 0 i in
5075     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5076     s' ^ s2 ^ replace_str s'' s1 s2
5077   )
5078
5079 let rec string_split sep str =
5080   let len = String.length str in
5081   let seplen = String.length sep in
5082   let i = find str sep in
5083   if i = -1 then [str]
5084   else (
5085     let s' = String.sub str 0 i in
5086     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5087     s' :: string_split sep s''
5088   )
5089
5090 let files_equal n1 n2 =
5091   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5092   match Sys.command cmd with
5093   | 0 -> true
5094   | 1 -> false
5095   | i -> failwithf "%s: failed with error code %d" cmd i
5096
5097 let rec filter_map f = function
5098   | [] -> []
5099   | x :: xs ->
5100       match f x with
5101       | Some y -> y :: filter_map f xs
5102       | None -> filter_map f xs
5103
5104 let rec find_map f = function
5105   | [] -> raise Not_found
5106   | x :: xs ->
5107       match f x with
5108       | Some y -> y
5109       | None -> find_map f xs
5110
5111 let iteri f xs =
5112   let rec loop i = function
5113     | [] -> ()
5114     | x :: xs -> f i x; loop (i+1) xs
5115   in
5116   loop 0 xs
5117
5118 let mapi f xs =
5119   let rec loop i = function
5120     | [] -> []
5121     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5122   in
5123   loop 0 xs
5124
5125 let count_chars c str =
5126   let count = ref 0 in
5127   for i = 0 to String.length str - 1 do
5128     if c = String.unsafe_get str i then incr count
5129   done;
5130   !count
5131
5132 let explode str =
5133   let r = ref [] in
5134   for i = 0 to String.length str - 1 do
5135     let c = String.unsafe_get str i in
5136     r := c :: !r;
5137   done;
5138   List.rev !r
5139
5140 let map_chars f str =
5141   List.map f (explode str)
5142
5143 let name_of_argt = function
5144   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5145   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5146   | FileIn n | FileOut n | BufferIn n -> n
5147
5148 let java_name_of_struct typ =
5149   try List.assoc typ java_structs
5150   with Not_found ->
5151     failwithf
5152       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5153
5154 let cols_of_struct typ =
5155   try List.assoc typ structs
5156   with Not_found ->
5157     failwithf "cols_of_struct: unknown struct %s" typ
5158
5159 let seq_of_test = function
5160   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5161   | TestOutputListOfDevices (s, _)
5162   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5163   | TestOutputTrue s | TestOutputFalse s
5164   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5165   | TestOutputStruct (s, _)
5166   | TestLastFail s -> s
5167
5168 (* Handling for function flags. *)
5169 let protocol_limit_warning =
5170   "Because of the message protocol, there is a transfer limit
5171 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5172
5173 let danger_will_robinson =
5174   "B<This command is dangerous.  Without careful use you
5175 can easily destroy all your data>."
5176
5177 let deprecation_notice flags =
5178   try
5179     let alt =
5180       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5181     let txt =
5182       sprintf "This function is deprecated.
5183 In new code, use the C<%s> call instead.
5184
5185 Deprecated functions will not be removed from the API, but the
5186 fact that they are deprecated indicates that there are problems
5187 with correct use of these functions." alt in
5188     Some txt
5189   with
5190     Not_found -> None
5191
5192 (* Create list of optional groups. *)
5193 let optgroups =
5194   let h = Hashtbl.create 13 in
5195   List.iter (
5196     fun (name, _, _, flags, _, _, _) ->
5197       List.iter (
5198         function
5199         | Optional group ->
5200             let names = try Hashtbl.find h group with Not_found -> [] in
5201             Hashtbl.replace h group (name :: names)
5202         | _ -> ()
5203       ) flags
5204   ) daemon_functions;
5205   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5206   let groups =
5207     List.map (
5208       fun group -> group, List.sort compare (Hashtbl.find h group)
5209     ) groups in
5210   List.sort (fun x y -> compare (fst x) (fst y)) groups
5211
5212 (* Check function names etc. for consistency. *)
5213 let check_functions () =
5214   let contains_uppercase str =
5215     let len = String.length str in
5216     let rec loop i =
5217       if i >= len then false
5218       else (
5219         let c = str.[i] in
5220         if c >= 'A' && c <= 'Z' then true
5221         else loop (i+1)
5222       )
5223     in
5224     loop 0
5225   in
5226
5227   (* Check function names. *)
5228   List.iter (
5229     fun (name, _, _, _, _, _, _) ->
5230       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5231         failwithf "function name %s does not need 'guestfs' prefix" name;
5232       if name = "" then
5233         failwithf "function name is empty";
5234       if name.[0] < 'a' || name.[0] > 'z' then
5235         failwithf "function name %s must start with lowercase a-z" name;
5236       if String.contains name '-' then
5237         failwithf "function name %s should not contain '-', use '_' instead."
5238           name
5239   ) all_functions;
5240
5241   (* Check function parameter/return names. *)
5242   List.iter (
5243     fun (name, style, _, _, _, _, _) ->
5244       let check_arg_ret_name n =
5245         if contains_uppercase n then
5246           failwithf "%s param/ret %s should not contain uppercase chars"
5247             name n;
5248         if String.contains n '-' || String.contains n '_' then
5249           failwithf "%s param/ret %s should not contain '-' or '_'"
5250             name n;
5251         if n = "value" then
5252           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;
5253         if n = "int" || n = "char" || n = "short" || n = "long" then
5254           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5255         if n = "i" || n = "n" then
5256           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5257         if n = "argv" || n = "args" then
5258           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5259
5260         (* List Haskell, OCaml and C keywords here.
5261          * http://www.haskell.org/haskellwiki/Keywords
5262          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5263          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5264          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5265          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5266          * Omitting _-containing words, since they're handled above.
5267          * Omitting the OCaml reserved word, "val", is ok,
5268          * and saves us from renaming several parameters.
5269          *)
5270         let reserved = [
5271           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5272           "char"; "class"; "const"; "constraint"; "continue"; "data";
5273           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5274           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5275           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5276           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5277           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5278           "interface";
5279           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5280           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5281           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5282           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5283           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5284           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5285           "volatile"; "when"; "where"; "while";
5286           ] in
5287         if List.mem n reserved then
5288           failwithf "%s has param/ret using reserved word %s" name n;
5289       in
5290
5291       (match fst style with
5292        | RErr -> ()
5293        | RInt n | RInt64 n | RBool n
5294        | RConstString n | RConstOptString n | RString n
5295        | RStringList n | RStruct (n, _) | RStructList (n, _)
5296        | RHashtable n | RBufferOut n ->
5297            check_arg_ret_name n
5298       );
5299       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5300   ) all_functions;
5301
5302   (* Check short descriptions. *)
5303   List.iter (
5304     fun (name, _, _, _, _, shortdesc, _) ->
5305       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5306         failwithf "short description of %s should begin with lowercase." name;
5307       let c = shortdesc.[String.length shortdesc-1] in
5308       if c = '\n' || c = '.' then
5309         failwithf "short description of %s should not end with . or \\n." name
5310   ) all_functions;
5311
5312   (* Check long descriptions. *)
5313   List.iter (
5314     fun (name, _, _, _, _, _, longdesc) ->
5315       if longdesc.[String.length longdesc-1] = '\n' then
5316         failwithf "long description of %s should not end with \\n." name
5317   ) all_functions;
5318
5319   (* Check proc_nrs. *)
5320   List.iter (
5321     fun (name, _, proc_nr, _, _, _, _) ->
5322       if proc_nr <= 0 then
5323         failwithf "daemon function %s should have proc_nr > 0" name
5324   ) daemon_functions;
5325
5326   List.iter (
5327     fun (name, _, proc_nr, _, _, _, _) ->
5328       if proc_nr <> -1 then
5329         failwithf "non-daemon function %s should have proc_nr -1" name
5330   ) non_daemon_functions;
5331
5332   let proc_nrs =
5333     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5334       daemon_functions in
5335   let proc_nrs =
5336     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5337   let rec loop = function
5338     | [] -> ()
5339     | [_] -> ()
5340     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5341         loop rest
5342     | (name1,nr1) :: (name2,nr2) :: _ ->
5343         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5344           name1 name2 nr1 nr2
5345   in
5346   loop proc_nrs;
5347
5348   (* Check tests. *)
5349   List.iter (
5350     function
5351       (* Ignore functions that have no tests.  We generate a
5352        * warning when the user does 'make check' instead.
5353        *)
5354     | name, _, _, _, [], _, _ -> ()
5355     | name, _, _, _, tests, _, _ ->
5356         let funcs =
5357           List.map (
5358             fun (_, _, test) ->
5359               match seq_of_test test with
5360               | [] ->
5361                   failwithf "%s has a test containing an empty sequence" name
5362               | cmds -> List.map List.hd cmds
5363           ) tests in
5364         let funcs = List.flatten funcs in
5365
5366         let tested = List.mem name funcs in
5367
5368         if not tested then
5369           failwithf "function %s has tests but does not test itself" name
5370   ) all_functions
5371
5372 (* 'pr' prints to the current output file. *)
5373 let chan = ref Pervasives.stdout
5374 let lines = ref 0
5375 let pr fs =
5376   ksprintf
5377     (fun str ->
5378        let i = count_chars '\n' str in
5379        lines := !lines + i;
5380        output_string !chan str
5381     ) fs
5382
5383 let copyright_years =
5384   let this_year = 1900 + (localtime (time ())).tm_year in
5385   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5386
5387 (* Generate a header block in a number of standard styles. *)
5388 type comment_style =
5389     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5390 type license = GPLv2plus | LGPLv2plus
5391
5392 let generate_header ?(extra_inputs = []) comment license =
5393   let inputs = "src/generator.ml" :: extra_inputs in
5394   let c = match comment with
5395     | CStyle ->         pr "/* "; " *"
5396     | CPlusPlusStyle -> pr "// "; "//"
5397     | HashStyle ->      pr "# ";  "#"
5398     | OCamlStyle ->     pr "(* "; " *"
5399     | HaskellStyle ->   pr "{- "; "  " in
5400   pr "libguestfs generated file\n";
5401   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5402   List.iter (pr "%s   %s\n" c) inputs;
5403   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5404   pr "%s\n" c;
5405   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5406   pr "%s\n" c;
5407   (match license with
5408    | GPLv2plus ->
5409        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5410        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5411        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5412        pr "%s (at your option) any later version.\n" c;
5413        pr "%s\n" c;
5414        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5415        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5416        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5417        pr "%s GNU General Public License for more details.\n" c;
5418        pr "%s\n" c;
5419        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5420        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5421        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5422
5423    | LGPLv2plus ->
5424        pr "%s This library is free software; you can redistribute it and/or\n" c;
5425        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5426        pr "%s License as published by the Free Software Foundation; either\n" c;
5427        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5428        pr "%s\n" c;
5429        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5430        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5431        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5432        pr "%s Lesser General Public License for more details.\n" c;
5433        pr "%s\n" c;
5434        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5435        pr "%s License along with this library; if not, write to the Free Software\n" c;
5436        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5437   );
5438   (match comment with
5439    | CStyle -> pr " */\n"
5440    | CPlusPlusStyle
5441    | HashStyle -> ()
5442    | OCamlStyle -> pr " *)\n"
5443    | HaskellStyle -> pr "-}\n"
5444   );
5445   pr "\n"
5446
5447 (* Start of main code generation functions below this line. *)
5448
5449 (* Generate the pod documentation for the C API. *)
5450 let rec generate_actions_pod () =
5451   List.iter (
5452     fun (shortname, style, _, flags, _, _, longdesc) ->
5453       if not (List.mem NotInDocs flags) then (
5454         let name = "guestfs_" ^ shortname in
5455         pr "=head2 %s\n\n" name;
5456         pr " ";
5457         generate_prototype ~extern:false ~handle:"g" name style;
5458         pr "\n\n";
5459         pr "%s\n\n" longdesc;
5460         (match fst style with
5461          | RErr ->
5462              pr "This function returns 0 on success or -1 on error.\n\n"
5463          | RInt _ ->
5464              pr "On error this function returns -1.\n\n"
5465          | RInt64 _ ->
5466              pr "On error this function returns -1.\n\n"
5467          | RBool _ ->
5468              pr "This function returns a C truth value on success or -1 on error.\n\n"
5469          | RConstString _ ->
5470              pr "This function returns a string, or NULL on error.
5471 The string is owned by the guest handle and must I<not> be freed.\n\n"
5472          | RConstOptString _ ->
5473              pr "This function returns a string which may be NULL.
5474 There is way to return an error from this function.
5475 The string is owned by the guest handle and must I<not> be freed.\n\n"
5476          | RString _ ->
5477              pr "This function returns a string, or NULL on error.
5478 I<The caller must free the returned string after use>.\n\n"
5479          | RStringList _ ->
5480              pr "This function returns a NULL-terminated array of strings
5481 (like L<environ(3)>), or NULL if there was an error.
5482 I<The caller must free the strings and the array after use>.\n\n"
5483          | RStruct (_, typ) ->
5484              pr "This function returns a C<struct guestfs_%s *>,
5485 or NULL if there was an error.
5486 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5487          | RStructList (_, typ) ->
5488              pr "This function returns a C<struct guestfs_%s_list *>
5489 (see E<lt>guestfs-structs.hE<gt>),
5490 or NULL if there was an error.
5491 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5492          | RHashtable _ ->
5493              pr "This function returns a NULL-terminated array of
5494 strings, or NULL if there was an error.
5495 The array of strings will always have length C<2n+1>, where
5496 C<n> keys and values alternate, followed by the trailing NULL entry.
5497 I<The caller must free the strings and the array after use>.\n\n"
5498          | RBufferOut _ ->
5499              pr "This function returns a buffer, or NULL on error.
5500 The size of the returned buffer is written to C<*size_r>.
5501 I<The caller must free the returned buffer after use>.\n\n"
5502         );
5503         if List.mem ProtocolLimitWarning flags then
5504           pr "%s\n\n" protocol_limit_warning;
5505         if List.mem DangerWillRobinson flags then
5506           pr "%s\n\n" danger_will_robinson;
5507         match deprecation_notice flags with
5508         | None -> ()
5509         | Some txt -> pr "%s\n\n" txt
5510       )
5511   ) all_functions_sorted
5512
5513 and generate_structs_pod () =
5514   (* Structs documentation. *)
5515   List.iter (
5516     fun (typ, cols) ->
5517       pr "=head2 guestfs_%s\n" typ;
5518       pr "\n";
5519       pr " struct guestfs_%s {\n" typ;
5520       List.iter (
5521         function
5522         | name, FChar -> pr "   char %s;\n" name
5523         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5524         | name, FInt32 -> pr "   int32_t %s;\n" name
5525         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5526         | name, FInt64 -> pr "   int64_t %s;\n" name
5527         | name, FString -> pr "   char *%s;\n" name
5528         | name, FBuffer ->
5529             pr "   /* The next two fields describe a byte array. */\n";
5530             pr "   uint32_t %s_len;\n" name;
5531             pr "   char *%s;\n" name
5532         | name, FUUID ->
5533             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5534             pr "   char %s[32];\n" name
5535         | name, FOptPercent ->
5536             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5537             pr "   float %s;\n" name
5538       ) cols;
5539       pr " };\n";
5540       pr " \n";
5541       pr " struct guestfs_%s_list {\n" typ;
5542       pr "   uint32_t len; /* Number of elements in list. */\n";
5543       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5544       pr " };\n";
5545       pr " \n";
5546       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5547       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5548         typ typ;
5549       pr "\n"
5550   ) structs
5551
5552 and generate_availability_pod () =
5553   (* Availability documentation. *)
5554   pr "=over 4\n";
5555   pr "\n";
5556   List.iter (
5557     fun (group, functions) ->
5558       pr "=item B<%s>\n" group;
5559       pr "\n";
5560       pr "The following functions:\n";
5561       List.iter (pr "L</guestfs_%s>\n") functions;
5562       pr "\n"
5563   ) optgroups;
5564   pr "=back\n";
5565   pr "\n"
5566
5567 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5568  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5569  *
5570  * We have to use an underscore instead of a dash because otherwise
5571  * rpcgen generates incorrect code.
5572  *
5573  * This header is NOT exported to clients, but see also generate_structs_h.
5574  *)
5575 and generate_xdr () =
5576   generate_header CStyle LGPLv2plus;
5577
5578   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5579   pr "typedef string str<>;\n";
5580   pr "\n";
5581
5582   (* Internal structures. *)
5583   List.iter (
5584     function
5585     | typ, cols ->
5586         pr "struct guestfs_int_%s {\n" typ;
5587         List.iter (function
5588                    | name, FChar -> pr "  char %s;\n" name
5589                    | name, FString -> pr "  string %s<>;\n" name
5590                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5591                    | name, FUUID -> pr "  opaque %s[32];\n" name
5592                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5593                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5594                    | name, FOptPercent -> pr "  float %s;\n" name
5595                   ) cols;
5596         pr "};\n";
5597         pr "\n";
5598         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5599         pr "\n";
5600   ) structs;
5601
5602   List.iter (
5603     fun (shortname, style, _, _, _, _, _) ->
5604       let name = "guestfs_" ^ shortname in
5605
5606       (match snd style with
5607        | [] -> ()
5608        | args ->
5609            pr "struct %s_args {\n" name;
5610            List.iter (
5611              function
5612              | Pathname n | Device n | Dev_or_Path n | String n ->
5613                  pr "  string %s<>;\n" n
5614              | OptString n -> pr "  str *%s;\n" n
5615              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5616              | Bool n -> pr "  bool %s;\n" n
5617              | Int n -> pr "  int %s;\n" n
5618              | Int64 n -> pr "  hyper %s;\n" n
5619              | BufferIn n ->
5620                  pr "  opaque %s<>;\n" n
5621              | FileIn _ | FileOut _ -> ()
5622            ) args;
5623            pr "};\n\n"
5624       );
5625       (match fst style with
5626        | RErr -> ()
5627        | RInt n ->
5628            pr "struct %s_ret {\n" name;
5629            pr "  int %s;\n" n;
5630            pr "};\n\n"
5631        | RInt64 n ->
5632            pr "struct %s_ret {\n" name;
5633            pr "  hyper %s;\n" n;
5634            pr "};\n\n"
5635        | RBool n ->
5636            pr "struct %s_ret {\n" name;
5637            pr "  bool %s;\n" n;
5638            pr "};\n\n"
5639        | RConstString _ | RConstOptString _ ->
5640            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5641        | RString n ->
5642            pr "struct %s_ret {\n" name;
5643            pr "  string %s<>;\n" n;
5644            pr "};\n\n"
5645        | RStringList n ->
5646            pr "struct %s_ret {\n" name;
5647            pr "  str %s<>;\n" n;
5648            pr "};\n\n"
5649        | RStruct (n, typ) ->
5650            pr "struct %s_ret {\n" name;
5651            pr "  guestfs_int_%s %s;\n" typ n;
5652            pr "};\n\n"
5653        | RStructList (n, typ) ->
5654            pr "struct %s_ret {\n" name;
5655            pr "  guestfs_int_%s_list %s;\n" typ n;
5656            pr "};\n\n"
5657        | RHashtable n ->
5658            pr "struct %s_ret {\n" name;
5659            pr "  str %s<>;\n" n;
5660            pr "};\n\n"
5661        | RBufferOut n ->
5662            pr "struct %s_ret {\n" name;
5663            pr "  opaque %s<>;\n" n;
5664            pr "};\n\n"
5665       );
5666   ) daemon_functions;
5667
5668   (* Table of procedure numbers. *)
5669   pr "enum guestfs_procedure {\n";
5670   List.iter (
5671     fun (shortname, _, proc_nr, _, _, _, _) ->
5672       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5673   ) daemon_functions;
5674   pr "  GUESTFS_PROC_NR_PROCS\n";
5675   pr "};\n";
5676   pr "\n";
5677
5678   (* Having to choose a maximum message size is annoying for several
5679    * reasons (it limits what we can do in the API), but it (a) makes
5680    * the protocol a lot simpler, and (b) provides a bound on the size
5681    * of the daemon which operates in limited memory space.
5682    *)
5683   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5684   pr "\n";
5685
5686   (* Message header, etc. *)
5687   pr "\
5688 /* The communication protocol is now documented in the guestfs(3)
5689  * manpage.
5690  */
5691
5692 const GUESTFS_PROGRAM = 0x2000F5F5;
5693 const GUESTFS_PROTOCOL_VERSION = 1;
5694
5695 /* These constants must be larger than any possible message length. */
5696 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5697 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5698
5699 enum guestfs_message_direction {
5700   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5701   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5702 };
5703
5704 enum guestfs_message_status {
5705   GUESTFS_STATUS_OK = 0,
5706   GUESTFS_STATUS_ERROR = 1
5707 };
5708
5709 const GUESTFS_ERROR_LEN = 256;
5710
5711 struct guestfs_message_error {
5712   string error_message<GUESTFS_ERROR_LEN>;
5713 };
5714
5715 struct guestfs_message_header {
5716   unsigned prog;                     /* GUESTFS_PROGRAM */
5717   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5718   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5719   guestfs_message_direction direction;
5720   unsigned serial;                   /* message serial number */
5721   guestfs_message_status status;
5722 };
5723
5724 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5725
5726 struct guestfs_chunk {
5727   int cancel;                        /* if non-zero, transfer is cancelled */
5728   /* data size is 0 bytes if the transfer has finished successfully */
5729   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5730 };
5731 "
5732
5733 (* Generate the guestfs-structs.h file. *)
5734 and generate_structs_h () =
5735   generate_header CStyle LGPLv2plus;
5736
5737   (* This is a public exported header file containing various
5738    * structures.  The structures are carefully written to have
5739    * exactly the same in-memory format as the XDR structures that
5740    * we use on the wire to the daemon.  The reason for creating
5741    * copies of these structures here is just so we don't have to
5742    * export the whole of guestfs_protocol.h (which includes much
5743    * unrelated and XDR-dependent stuff that we don't want to be
5744    * public, or required by clients).
5745    *
5746    * To reiterate, we will pass these structures to and from the
5747    * client with a simple assignment or memcpy, so the format
5748    * must be identical to what rpcgen / the RFC defines.
5749    *)
5750
5751   (* Public structures. *)
5752   List.iter (
5753     fun (typ, cols) ->
5754       pr "struct guestfs_%s {\n" typ;
5755       List.iter (
5756         function
5757         | name, FChar -> pr "  char %s;\n" name
5758         | name, FString -> pr "  char *%s;\n" name
5759         | name, FBuffer ->
5760             pr "  uint32_t %s_len;\n" name;
5761             pr "  char *%s;\n" name
5762         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5763         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5764         | name, FInt32 -> pr "  int32_t %s;\n" name
5765         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5766         | name, FInt64 -> pr "  int64_t %s;\n" name
5767         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5768       ) cols;
5769       pr "};\n";
5770       pr "\n";
5771       pr "struct guestfs_%s_list {\n" typ;
5772       pr "  uint32_t len;\n";
5773       pr "  struct guestfs_%s *val;\n" typ;
5774       pr "};\n";
5775       pr "\n";
5776       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5777       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5778       pr "\n"
5779   ) structs
5780
5781 (* Generate the guestfs-actions.h file. *)
5782 and generate_actions_h () =
5783   generate_header CStyle LGPLv2plus;
5784   List.iter (
5785     fun (shortname, style, _, _, _, _, _) ->
5786       let name = "guestfs_" ^ shortname in
5787       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5788         name style
5789   ) all_functions
5790
5791 (* Generate the guestfs-internal-actions.h file. *)
5792 and generate_internal_actions_h () =
5793   generate_header CStyle LGPLv2plus;
5794   List.iter (
5795     fun (shortname, style, _, _, _, _, _) ->
5796       let name = "guestfs__" ^ shortname in
5797       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5798         name style
5799   ) non_daemon_functions
5800
5801 (* Generate the client-side dispatch stubs. *)
5802 and generate_client_actions () =
5803   generate_header CStyle LGPLv2plus;
5804
5805   pr "\
5806 #include <stdio.h>
5807 #include <stdlib.h>
5808 #include <stdint.h>
5809 #include <string.h>
5810 #include <inttypes.h>
5811
5812 #include \"guestfs.h\"
5813 #include \"guestfs-internal.h\"
5814 #include \"guestfs-internal-actions.h\"
5815 #include \"guestfs_protocol.h\"
5816
5817 #define error guestfs_error
5818 //#define perrorf guestfs_perrorf
5819 #define safe_malloc guestfs_safe_malloc
5820 #define safe_realloc guestfs_safe_realloc
5821 //#define safe_strdup guestfs_safe_strdup
5822 #define safe_memdup guestfs_safe_memdup
5823
5824 /* Check the return message from a call for validity. */
5825 static int
5826 check_reply_header (guestfs_h *g,
5827                     const struct guestfs_message_header *hdr,
5828                     unsigned int proc_nr, unsigned int serial)
5829 {
5830   if (hdr->prog != GUESTFS_PROGRAM) {
5831     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5832     return -1;
5833   }
5834   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5835     error (g, \"wrong protocol version (%%d/%%d)\",
5836            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5837     return -1;
5838   }
5839   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5840     error (g, \"unexpected message direction (%%d/%%d)\",
5841            hdr->direction, GUESTFS_DIRECTION_REPLY);
5842     return -1;
5843   }
5844   if (hdr->proc != proc_nr) {
5845     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5846     return -1;
5847   }
5848   if (hdr->serial != serial) {
5849     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5850     return -1;
5851   }
5852
5853   return 0;
5854 }
5855
5856 /* Check we are in the right state to run a high-level action. */
5857 static int
5858 check_state (guestfs_h *g, const char *caller)
5859 {
5860   if (!guestfs__is_ready (g)) {
5861     if (guestfs__is_config (g) || guestfs__is_launching (g))
5862       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5863         caller);
5864     else
5865       error (g, \"%%s called from the wrong state, %%d != READY\",
5866         caller, guestfs__get_state (g));
5867     return -1;
5868   }
5869   return 0;
5870 }
5871
5872 ";
5873
5874   let error_code_of = function
5875     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5876     | RConstString _ | RConstOptString _
5877     | RString _ | RStringList _
5878     | RStruct _ | RStructList _
5879     | RHashtable _ | RBufferOut _ -> "NULL"
5880   in
5881
5882   (* Generate code to check String-like parameters are not passed in
5883    * as NULL (returning an error if they are).
5884    *)
5885   let check_null_strings shortname style =
5886     let pr_newline = ref false in
5887     List.iter (
5888       function
5889       (* parameters which should not be NULL *)
5890       | String n
5891       | Device n
5892       | Pathname n
5893       | Dev_or_Path n
5894       | FileIn n
5895       | FileOut n
5896       | BufferIn n
5897       | StringList n
5898       | DeviceList n ->
5899           pr "  if (%s == NULL) {\n" n;
5900           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5901           pr "           \"%s\", \"%s\");\n" shortname n;
5902           pr "    return %s;\n" (error_code_of (fst style));
5903           pr "  }\n";
5904           pr_newline := true
5905
5906       (* can be NULL *)
5907       | OptString _
5908
5909       (* not applicable *)
5910       | Bool _
5911       | Int _
5912       | Int64 _ -> ()
5913     ) (snd style);
5914
5915     if !pr_newline then pr "\n";
5916   in
5917
5918   (* Generate code to generate guestfish call traces. *)
5919   let trace_call shortname style =
5920     pr "  if (guestfs__get_trace (g)) {\n";
5921
5922     let needs_i =
5923       List.exists (function
5924                    | StringList _ | DeviceList _ -> true
5925                    | _ -> false) (snd style) in
5926     if needs_i then (
5927       pr "    int i;\n";
5928       pr "\n"
5929     );
5930
5931     pr "    printf (\"%s\");\n" shortname;
5932     List.iter (
5933       function
5934       | String n                        (* strings *)
5935       | Device n
5936       | Pathname n
5937       | Dev_or_Path n
5938       | FileIn n
5939       | FileOut n
5940       | BufferIn n ->
5941           (* guestfish doesn't support string escaping, so neither do we *)
5942           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5943       | OptString n ->                  (* string option *)
5944           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5945           pr "    else printf (\" null\");\n"
5946       | StringList n
5947       | DeviceList n ->                 (* string list *)
5948           pr "    putchar (' ');\n";
5949           pr "    putchar ('\"');\n";
5950           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5951           pr "      if (i > 0) putchar (' ');\n";
5952           pr "      fputs (%s[i], stdout);\n" n;
5953           pr "    }\n";
5954           pr "    putchar ('\"');\n";
5955       | Bool n ->                       (* boolean *)
5956           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5957       | Int n ->                        (* int *)
5958           pr "    printf (\" %%d\", %s);\n" n
5959       | Int64 n ->
5960           pr "    printf (\" %%\" PRIi64, %s);\n" n
5961     ) (snd style);
5962     pr "    putchar ('\\n');\n";
5963     pr "  }\n";
5964     pr "\n";
5965   in
5966
5967   (* For non-daemon functions, generate a wrapper around each function. *)
5968   List.iter (
5969     fun (shortname, style, _, _, _, _, _) ->
5970       let name = "guestfs_" ^ shortname in
5971
5972       generate_prototype ~extern:false ~semicolon:false ~newline:true
5973         ~handle:"g" name style;
5974       pr "{\n";
5975       check_null_strings shortname style;
5976       trace_call shortname style;
5977       pr "  return guestfs__%s " shortname;
5978       generate_c_call_args ~handle:"g" style;
5979       pr ";\n";
5980       pr "}\n";
5981       pr "\n"
5982   ) non_daemon_functions;
5983
5984   (* Client-side stubs for each function. *)
5985   List.iter (
5986     fun (shortname, style, _, _, _, _, _) ->
5987       let name = "guestfs_" ^ shortname in
5988       let error_code = error_code_of (fst style) in
5989
5990       (* Generate the action stub. *)
5991       generate_prototype ~extern:false ~semicolon:false ~newline:true
5992         ~handle:"g" name style;
5993
5994       pr "{\n";
5995
5996       (match snd style with
5997        | [] -> ()
5998        | _ -> pr "  struct %s_args args;\n" name
5999       );
6000
6001       pr "  guestfs_message_header hdr;\n";
6002       pr "  guestfs_message_error err;\n";
6003       let has_ret =
6004         match fst style with
6005         | RErr -> false
6006         | RConstString _ | RConstOptString _ ->
6007             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6008         | RInt _ | RInt64 _
6009         | RBool _ | RString _ | RStringList _
6010         | RStruct _ | RStructList _
6011         | RHashtable _ | RBufferOut _ ->
6012             pr "  struct %s_ret ret;\n" name;
6013             true in
6014
6015       pr "  int serial;\n";
6016       pr "  int r;\n";
6017       pr "\n";
6018       check_null_strings shortname style;
6019       trace_call shortname style;
6020       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6021         shortname error_code;
6022       pr "  guestfs___set_busy (g);\n";
6023       pr "\n";
6024
6025       (* Send the main header and arguments. *)
6026       (match snd style with
6027        | [] ->
6028            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6029              (String.uppercase shortname)
6030        | args ->
6031            List.iter (
6032              function
6033              | Pathname n | Device n | Dev_or_Path n | String n ->
6034                  pr "  args.%s = (char *) %s;\n" n n
6035              | OptString n ->
6036                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6037              | StringList n | DeviceList n ->
6038                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6039                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6040              | Bool n ->
6041                  pr "  args.%s = %s;\n" n n
6042              | Int n ->
6043                  pr "  args.%s = %s;\n" n n
6044              | Int64 n ->
6045                  pr "  args.%s = %s;\n" n n
6046              | FileIn _ | FileOut _ -> ()
6047              | BufferIn n ->
6048                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6049                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6050                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6051                    shortname;
6052                  pr "    guestfs___end_busy (g);\n";
6053                  pr "    return %s;\n" error_code;
6054                  pr "  }\n";
6055                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6056                  pr "  args.%s.%s_len = %s_size;\n" n n n
6057            ) args;
6058            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6059              (String.uppercase shortname);
6060            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6061              name;
6062       );
6063       pr "  if (serial == -1) {\n";
6064       pr "    guestfs___end_busy (g);\n";
6065       pr "    return %s;\n" error_code;
6066       pr "  }\n";
6067       pr "\n";
6068
6069       (* Send any additional files (FileIn) requested. *)
6070       let need_read_reply_label = ref false in
6071       List.iter (
6072         function
6073         | FileIn n ->
6074             pr "  r = guestfs___send_file (g, %s);\n" n;
6075             pr "  if (r == -1) {\n";
6076             pr "    guestfs___end_busy (g);\n";
6077             pr "    return %s;\n" error_code;
6078             pr "  }\n";
6079             pr "  if (r == -2) /* daemon cancelled */\n";
6080             pr "    goto read_reply;\n";
6081             need_read_reply_label := true;
6082             pr "\n";
6083         | _ -> ()
6084       ) (snd style);
6085
6086       (* Wait for the reply from the remote end. *)
6087       if !need_read_reply_label then pr " read_reply:\n";
6088       pr "  memset (&hdr, 0, sizeof hdr);\n";
6089       pr "  memset (&err, 0, sizeof err);\n";
6090       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6091       pr "\n";
6092       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6093       if not has_ret then
6094         pr "NULL, NULL"
6095       else
6096         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6097       pr ");\n";
6098
6099       pr "  if (r == -1) {\n";
6100       pr "    guestfs___end_busy (g);\n";
6101       pr "    return %s;\n" error_code;
6102       pr "  }\n";
6103       pr "\n";
6104
6105       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6106         (String.uppercase shortname);
6107       pr "    guestfs___end_busy (g);\n";
6108       pr "    return %s;\n" error_code;
6109       pr "  }\n";
6110       pr "\n";
6111
6112       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6113       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6114       pr "    free (err.error_message);\n";
6115       pr "    guestfs___end_busy (g);\n";
6116       pr "    return %s;\n" error_code;
6117       pr "  }\n";
6118       pr "\n";
6119
6120       (* Expecting to receive further files (FileOut)? *)
6121       List.iter (
6122         function
6123         | FileOut n ->
6124             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6125             pr "    guestfs___end_busy (g);\n";
6126             pr "    return %s;\n" error_code;
6127             pr "  }\n";
6128             pr "\n";
6129         | _ -> ()
6130       ) (snd style);
6131
6132       pr "  guestfs___end_busy (g);\n";
6133
6134       (match fst style with
6135        | RErr -> pr "  return 0;\n"
6136        | RInt n | RInt64 n | RBool n ->
6137            pr "  return ret.%s;\n" n
6138        | RConstString _ | RConstOptString _ ->
6139            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6140        | RString n ->
6141            pr "  return ret.%s; /* caller will free */\n" n
6142        | RStringList n | RHashtable n ->
6143            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6144            pr "  ret.%s.%s_val =\n" n n;
6145            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6146            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6147              n n;
6148            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6149            pr "  return ret.%s.%s_val;\n" n n
6150        | RStruct (n, _) ->
6151            pr "  /* caller will free this */\n";
6152            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6153        | RStructList (n, _) ->
6154            pr "  /* caller will free this */\n";
6155            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6156        | RBufferOut n ->
6157            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6158            pr "   * _val might be NULL here.  To make the API saner for\n";
6159            pr "   * callers, we turn this case into a unique pointer (using\n";
6160            pr "   * malloc(1)).\n";
6161            pr "   */\n";
6162            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6163            pr "    *size_r = ret.%s.%s_len;\n" n n;
6164            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6165            pr "  } else {\n";
6166            pr "    free (ret.%s.%s_val);\n" n n;
6167            pr "    char *p = safe_malloc (g, 1);\n";
6168            pr "    *size_r = ret.%s.%s_len;\n" n n;
6169            pr "    return p;\n";
6170            pr "  }\n";
6171       );
6172
6173       pr "}\n\n"
6174   ) daemon_functions;
6175
6176   (* Functions to free structures. *)
6177   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6178   pr " * structure format is identical to the XDR format.  See note in\n";
6179   pr " * generator.ml.\n";
6180   pr " */\n";
6181   pr "\n";
6182
6183   List.iter (
6184     fun (typ, _) ->
6185       pr "void\n";
6186       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6187       pr "{\n";
6188       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6189       pr "  free (x);\n";
6190       pr "}\n";
6191       pr "\n";
6192
6193       pr "void\n";
6194       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6195       pr "{\n";
6196       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6197       pr "  free (x);\n";
6198       pr "}\n";
6199       pr "\n";
6200
6201   ) structs;
6202
6203 (* Generate daemon/actions.h. *)
6204 and generate_daemon_actions_h () =
6205   generate_header CStyle GPLv2plus;
6206
6207   pr "#include \"../src/guestfs_protocol.h\"\n";
6208   pr "\n";
6209
6210   List.iter (
6211     fun (name, style, _, _, _, _, _) ->
6212       generate_prototype
6213         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6214         name style;
6215   ) daemon_functions
6216
6217 (* Generate the linker script which controls the visibility of
6218  * symbols in the public ABI and ensures no other symbols get
6219  * exported accidentally.
6220  *)
6221 and generate_linker_script () =
6222   generate_header HashStyle GPLv2plus;
6223
6224   let globals = [
6225     "guestfs_create";
6226     "guestfs_close";
6227     "guestfs_get_error_handler";
6228     "guestfs_get_out_of_memory_handler";
6229     "guestfs_last_error";
6230     "guestfs_set_error_handler";
6231     "guestfs_set_launch_done_callback";
6232     "guestfs_set_log_message_callback";
6233     "guestfs_set_out_of_memory_handler";
6234     "guestfs_set_subprocess_quit_callback";
6235
6236     (* Unofficial parts of the API: the bindings code use these
6237      * functions, so it is useful to export them.
6238      *)
6239     "guestfs_safe_calloc";
6240     "guestfs_safe_malloc";
6241   ] in
6242   let functions =
6243     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6244       all_functions in
6245   let structs =
6246     List.concat (
6247       List.map (fun (typ, _) ->
6248                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6249         structs
6250     ) in
6251   let globals = List.sort compare (globals @ functions @ structs) in
6252
6253   pr "{\n";
6254   pr "    global:\n";
6255   List.iter (pr "        %s;\n") globals;
6256   pr "\n";
6257
6258   pr "    local:\n";
6259   pr "        *;\n";
6260   pr "};\n"
6261
6262 (* Generate the server-side stubs. *)
6263 and generate_daemon_actions () =
6264   generate_header CStyle GPLv2plus;
6265
6266   pr "#include <config.h>\n";
6267   pr "\n";
6268   pr "#include <stdio.h>\n";
6269   pr "#include <stdlib.h>\n";
6270   pr "#include <string.h>\n";
6271   pr "#include <inttypes.h>\n";
6272   pr "#include <rpc/types.h>\n";
6273   pr "#include <rpc/xdr.h>\n";
6274   pr "\n";
6275   pr "#include \"daemon.h\"\n";
6276   pr "#include \"c-ctype.h\"\n";
6277   pr "#include \"../src/guestfs_protocol.h\"\n";
6278   pr "#include \"actions.h\"\n";
6279   pr "\n";
6280
6281   List.iter (
6282     fun (name, style, _, _, _, _, _) ->
6283       (* Generate server-side stubs. *)
6284       pr "static void %s_stub (XDR *xdr_in)\n" name;
6285       pr "{\n";
6286       let error_code =
6287         match fst style with
6288         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6289         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6290         | RBool _ -> pr "  int r;\n"; "-1"
6291         | RConstString _ | RConstOptString _ ->
6292             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6293         | RString _ -> pr "  char *r;\n"; "NULL"
6294         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6295         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6296         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6297         | RBufferOut _ ->
6298             pr "  size_t size = 1;\n";
6299             pr "  char *r;\n";
6300             "NULL" in
6301
6302       (match snd style with
6303        | [] -> ()
6304        | args ->
6305            pr "  struct guestfs_%s_args args;\n" name;
6306            List.iter (
6307              function
6308              | Device n | Dev_or_Path n
6309              | Pathname n
6310              | String n -> ()
6311              | OptString n -> pr "  char *%s;\n" n
6312              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6313              | Bool n -> pr "  int %s;\n" n
6314              | Int n -> pr "  int %s;\n" n
6315              | Int64 n -> pr "  int64_t %s;\n" n
6316              | FileIn _ | FileOut _ -> ()
6317              | BufferIn n ->
6318                  pr "  const char *%s;\n" n;
6319                  pr "  size_t %s_size;\n" n
6320            ) args
6321       );
6322       pr "\n";
6323
6324       let is_filein =
6325         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6326
6327       (match snd style with
6328        | [] -> ()
6329        | args ->
6330            pr "  memset (&args, 0, sizeof args);\n";
6331            pr "\n";
6332            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6333            if is_filein then
6334              pr "    if (cancel_receive () != -2)\n";
6335            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6336            pr "    goto done;\n";
6337            pr "  }\n";
6338            let pr_args n =
6339              pr "  char *%s = args.%s;\n" n n
6340            in
6341            let pr_list_handling_code n =
6342              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6343              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6344              pr "  if (%s == NULL) {\n" n;
6345              if is_filein then
6346                pr "    if (cancel_receive () != -2)\n";
6347              pr "      reply_with_perror (\"realloc\");\n";
6348              pr "    goto done;\n";
6349              pr "  }\n";
6350              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6351              pr "  args.%s.%s_val = %s;\n" n n n;
6352            in
6353            List.iter (
6354              function
6355              | Pathname n ->
6356                  pr_args n;
6357                  pr "  ABS_PATH (%s, %s, goto done);\n"
6358                    n (if is_filein then "cancel_receive ()" else "0");
6359              | Device n ->
6360                  pr_args n;
6361                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6362                    n (if is_filein then "cancel_receive ()" else "0");
6363              | Dev_or_Path n ->
6364                  pr_args n;
6365                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6366                    n (if is_filein then "cancel_receive ()" else "0");
6367              | String n -> pr_args n
6368              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6369              | StringList n ->
6370                  pr_list_handling_code n;
6371              | DeviceList n ->
6372                  pr_list_handling_code n;
6373                  pr "  /* Ensure that each is a device,\n";
6374                  pr "   * and perform device name translation. */\n";
6375                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6376                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6377                    (if is_filein then "cancel_receive ()" else "0");
6378                  pr "  }\n";
6379              | Bool n -> pr "  %s = args.%s;\n" n n
6380              | Int n -> pr "  %s = args.%s;\n" n n
6381              | Int64 n -> pr "  %s = args.%s;\n" n n
6382              | FileIn _ | FileOut _ -> ()
6383              | BufferIn n ->
6384                  pr "  %s = args.%s.%s_val;\n" n n n;
6385                  pr "  %s_size = args.%s.%s_len;\n" n n n
6386            ) args;
6387            pr "\n"
6388       );
6389
6390       (* this is used at least for do_equal *)
6391       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6392         (* Emit NEED_ROOT just once, even when there are two or
6393            more Pathname args *)
6394         pr "  NEED_ROOT (%s, goto done);\n"
6395           (if is_filein then "cancel_receive ()" else "0");
6396       );
6397
6398       (* Don't want to call the impl with any FileIn or FileOut
6399        * parameters, since these go "outside" the RPC protocol.
6400        *)
6401       let args' =
6402         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6403           (snd style) in
6404       pr "  r = do_%s " name;
6405       generate_c_call_args (fst style, args');
6406       pr ";\n";
6407
6408       (match fst style with
6409        | RErr | RInt _ | RInt64 _ | RBool _
6410        | RConstString _ | RConstOptString _
6411        | RString _ | RStringList _ | RHashtable _
6412        | RStruct (_, _) | RStructList (_, _) ->
6413            pr "  if (r == %s)\n" error_code;
6414            pr "    /* do_%s has already called reply_with_error */\n" name;
6415            pr "    goto done;\n";
6416            pr "\n"
6417        | RBufferOut _ ->
6418            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6419            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6420            pr "   */\n";
6421            pr "  if (size == 1 && r == %s)\n" error_code;
6422            pr "    /* do_%s has already called reply_with_error */\n" name;
6423            pr "    goto done;\n";
6424            pr "\n"
6425       );
6426
6427       (* If there are any FileOut parameters, then the impl must
6428        * send its own reply.
6429        *)
6430       let no_reply =
6431         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6432       if no_reply then
6433         pr "  /* do_%s has already sent a reply */\n" name
6434       else (
6435         match fst style with
6436         | RErr -> pr "  reply (NULL, NULL);\n"
6437         | RInt n | RInt64 n | RBool n ->
6438             pr "  struct guestfs_%s_ret ret;\n" name;
6439             pr "  ret.%s = r;\n" n;
6440             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6441               name
6442         | RConstString _ | RConstOptString _ ->
6443             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6444         | RString n ->
6445             pr "  struct guestfs_%s_ret ret;\n" name;
6446             pr "  ret.%s = r;\n" n;
6447             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6448               name;
6449             pr "  free (r);\n"
6450         | RStringList n | RHashtable n ->
6451             pr "  struct guestfs_%s_ret ret;\n" name;
6452             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6453             pr "  ret.%s.%s_val = r;\n" n n;
6454             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6455               name;
6456             pr "  free_strings (r);\n"
6457         | RStruct (n, _) ->
6458             pr "  struct guestfs_%s_ret ret;\n" name;
6459             pr "  ret.%s = *r;\n" n;
6460             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6461               name;
6462             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6463               name
6464         | RStructList (n, _) ->
6465             pr "  struct guestfs_%s_ret ret;\n" name;
6466             pr "  ret.%s = *r;\n" n;
6467             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6468               name;
6469             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6470               name
6471         | RBufferOut n ->
6472             pr "  struct guestfs_%s_ret ret;\n" name;
6473             pr "  ret.%s.%s_val = r;\n" n n;
6474             pr "  ret.%s.%s_len = size;\n" n n;
6475             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6476               name;
6477             pr "  free (r);\n"
6478       );
6479
6480       (* Free the args. *)
6481       pr "done:\n";
6482       (match snd style with
6483        | [] -> ()
6484        | _ ->
6485            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6486              name
6487       );
6488       pr "  return;\n";
6489       pr "}\n\n";
6490   ) daemon_functions;
6491
6492   (* Dispatch function. *)
6493   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6494   pr "{\n";
6495   pr "  switch (proc_nr) {\n";
6496
6497   List.iter (
6498     fun (name, style, _, _, _, _, _) ->
6499       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6500       pr "      %s_stub (xdr_in);\n" name;
6501       pr "      break;\n"
6502   ) daemon_functions;
6503
6504   pr "    default:\n";
6505   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";
6506   pr "  }\n";
6507   pr "}\n";
6508   pr "\n";
6509
6510   (* LVM columns and tokenization functions. *)
6511   (* XXX This generates crap code.  We should rethink how we
6512    * do this parsing.
6513    *)
6514   List.iter (
6515     function
6516     | typ, cols ->
6517         pr "static const char *lvm_%s_cols = \"%s\";\n"
6518           typ (String.concat "," (List.map fst cols));
6519         pr "\n";
6520
6521         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6522         pr "{\n";
6523         pr "  char *tok, *p, *next;\n";
6524         pr "  int i, j;\n";
6525         pr "\n";
6526         (*
6527           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6528           pr "\n";
6529         *)
6530         pr "  if (!str) {\n";
6531         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6532         pr "    return -1;\n";
6533         pr "  }\n";
6534         pr "  if (!*str || c_isspace (*str)) {\n";
6535         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6536         pr "    return -1;\n";
6537         pr "  }\n";
6538         pr "  tok = str;\n";
6539         List.iter (
6540           fun (name, coltype) ->
6541             pr "  if (!tok) {\n";
6542             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6543             pr "    return -1;\n";
6544             pr "  }\n";
6545             pr "  p = strchrnul (tok, ',');\n";
6546             pr "  if (*p) next = p+1; else next = NULL;\n";
6547             pr "  *p = '\\0';\n";
6548             (match coltype with
6549              | FString ->
6550                  pr "  r->%s = strdup (tok);\n" name;
6551                  pr "  if (r->%s == NULL) {\n" name;
6552                  pr "    perror (\"strdup\");\n";
6553                  pr "    return -1;\n";
6554                  pr "  }\n"
6555              | FUUID ->
6556                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6557                  pr "    if (tok[j] == '\\0') {\n";
6558                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6559                  pr "      return -1;\n";
6560                  pr "    } else if (tok[j] != '-')\n";
6561                  pr "      r->%s[i++] = tok[j];\n" name;
6562                  pr "  }\n";
6563              | FBytes ->
6564                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6565                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6566                  pr "    return -1;\n";
6567                  pr "  }\n";
6568              | FInt64 ->
6569                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6570                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6571                  pr "    return -1;\n";
6572                  pr "  }\n";
6573              | FOptPercent ->
6574                  pr "  if (tok[0] == '\\0')\n";
6575                  pr "    r->%s = -1;\n" name;
6576                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6577                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6578                  pr "    return -1;\n";
6579                  pr "  }\n";
6580              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6581                  assert false (* can never be an LVM column *)
6582             );
6583             pr "  tok = next;\n";
6584         ) cols;
6585
6586         pr "  if (tok != NULL) {\n";
6587         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6588         pr "    return -1;\n";
6589         pr "  }\n";
6590         pr "  return 0;\n";
6591         pr "}\n";
6592         pr "\n";
6593
6594         pr "guestfs_int_lvm_%s_list *\n" typ;
6595         pr "parse_command_line_%ss (void)\n" typ;
6596         pr "{\n";
6597         pr "  char *out, *err;\n";
6598         pr "  char *p, *pend;\n";
6599         pr "  int r, i;\n";
6600         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6601         pr "  void *newp;\n";
6602         pr "\n";
6603         pr "  ret = malloc (sizeof *ret);\n";
6604         pr "  if (!ret) {\n";
6605         pr "    reply_with_perror (\"malloc\");\n";
6606         pr "    return NULL;\n";
6607         pr "  }\n";
6608         pr "\n";
6609         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6610         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6611         pr "\n";
6612         pr "  r = command (&out, &err,\n";
6613         pr "           \"lvm\", \"%ss\",\n" typ;
6614         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6615         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6616         pr "  if (r == -1) {\n";
6617         pr "    reply_with_error (\"%%s\", err);\n";
6618         pr "    free (out);\n";
6619         pr "    free (err);\n";
6620         pr "    free (ret);\n";
6621         pr "    return NULL;\n";
6622         pr "  }\n";
6623         pr "\n";
6624         pr "  free (err);\n";
6625         pr "\n";
6626         pr "  /* Tokenize each line of the output. */\n";
6627         pr "  p = out;\n";
6628         pr "  i = 0;\n";
6629         pr "  while (p) {\n";
6630         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6631         pr "    if (pend) {\n";
6632         pr "      *pend = '\\0';\n";
6633         pr "      pend++;\n";
6634         pr "    }\n";
6635         pr "\n";
6636         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6637         pr "      p++;\n";
6638         pr "\n";
6639         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6640         pr "      p = pend;\n";
6641         pr "      continue;\n";
6642         pr "    }\n";
6643         pr "\n";
6644         pr "    /* Allocate some space to store this next entry. */\n";
6645         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6646         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6647         pr "    if (newp == NULL) {\n";
6648         pr "      reply_with_perror (\"realloc\");\n";
6649         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6650         pr "      free (ret);\n";
6651         pr "      free (out);\n";
6652         pr "      return NULL;\n";
6653         pr "    }\n";
6654         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6655         pr "\n";
6656         pr "    /* Tokenize the next entry. */\n";
6657         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6658         pr "    if (r == -1) {\n";
6659         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6660         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6661         pr "      free (ret);\n";
6662         pr "      free (out);\n";
6663         pr "      return NULL;\n";
6664         pr "    }\n";
6665         pr "\n";
6666         pr "    ++i;\n";
6667         pr "    p = pend;\n";
6668         pr "  }\n";
6669         pr "\n";
6670         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6671         pr "\n";
6672         pr "  free (out);\n";
6673         pr "  return ret;\n";
6674         pr "}\n"
6675
6676   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6677
6678 (* Generate a list of function names, for debugging in the daemon.. *)
6679 and generate_daemon_names () =
6680   generate_header CStyle GPLv2plus;
6681
6682   pr "#include <config.h>\n";
6683   pr "\n";
6684   pr "#include \"daemon.h\"\n";
6685   pr "\n";
6686
6687   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6688   pr "const char *function_names[] = {\n";
6689   List.iter (
6690     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6691   ) daemon_functions;
6692   pr "};\n";
6693
6694 (* Generate the optional groups for the daemon to implement
6695  * guestfs_available.
6696  *)
6697 and generate_daemon_optgroups_c () =
6698   generate_header CStyle GPLv2plus;
6699
6700   pr "#include <config.h>\n";
6701   pr "\n";
6702   pr "#include \"daemon.h\"\n";
6703   pr "#include \"optgroups.h\"\n";
6704   pr "\n";
6705
6706   pr "struct optgroup optgroups[] = {\n";
6707   List.iter (
6708     fun (group, _) ->
6709       pr "  { \"%s\", optgroup_%s_available },\n" group group
6710   ) optgroups;
6711   pr "  { NULL, NULL }\n";
6712   pr "};\n"
6713
6714 and generate_daemon_optgroups_h () =
6715   generate_header CStyle GPLv2plus;
6716
6717   List.iter (
6718     fun (group, _) ->
6719       pr "extern int optgroup_%s_available (void);\n" group
6720   ) optgroups
6721
6722 (* Generate the tests. *)
6723 and generate_tests () =
6724   generate_header CStyle GPLv2plus;
6725
6726   pr "\
6727 #include <stdio.h>
6728 #include <stdlib.h>
6729 #include <string.h>
6730 #include <unistd.h>
6731 #include <sys/types.h>
6732 #include <fcntl.h>
6733
6734 #include \"guestfs.h\"
6735 #include \"guestfs-internal.h\"
6736
6737 static guestfs_h *g;
6738 static int suppress_error = 0;
6739
6740 static void print_error (guestfs_h *g, void *data, const char *msg)
6741 {
6742   if (!suppress_error)
6743     fprintf (stderr, \"%%s\\n\", msg);
6744 }
6745
6746 /* FIXME: nearly identical code appears in fish.c */
6747 static void print_strings (char *const *argv)
6748 {
6749   int argc;
6750
6751   for (argc = 0; argv[argc] != NULL; ++argc)
6752     printf (\"\\t%%s\\n\", argv[argc]);
6753 }
6754
6755 /*
6756 static void print_table (char const *const *argv)
6757 {
6758   int i;
6759
6760   for (i = 0; argv[i] != NULL; i += 2)
6761     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6762 }
6763 */
6764
6765 ";
6766
6767   (* Generate a list of commands which are not tested anywhere. *)
6768   pr "static void no_test_warnings (void)\n";
6769   pr "{\n";
6770
6771   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6772   List.iter (
6773     fun (_, _, _, _, tests, _, _) ->
6774       let tests = filter_map (
6775         function
6776         | (_, (Always|If _|Unless _), test) -> Some test
6777         | (_, Disabled, _) -> None
6778       ) tests in
6779       let seq = List.concat (List.map seq_of_test tests) in
6780       let cmds_tested = List.map List.hd seq in
6781       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6782   ) all_functions;
6783
6784   List.iter (
6785     fun (name, _, _, _, _, _, _) ->
6786       if not (Hashtbl.mem hash name) then
6787         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6788   ) all_functions;
6789
6790   pr "}\n";
6791   pr "\n";
6792
6793   (* Generate the actual tests.  Note that we generate the tests
6794    * in reverse order, deliberately, so that (in general) the
6795    * newest tests run first.  This makes it quicker and easier to
6796    * debug them.
6797    *)
6798   let test_names =
6799     List.map (
6800       fun (name, _, _, flags, tests, _, _) ->
6801         mapi (generate_one_test name flags) tests
6802     ) (List.rev all_functions) in
6803   let test_names = List.concat test_names in
6804   let nr_tests = List.length test_names in
6805
6806   pr "\
6807 int main (int argc, char *argv[])
6808 {
6809   char c = 0;
6810   unsigned long int n_failed = 0;
6811   const char *filename;
6812   int fd;
6813   int nr_tests, test_num = 0;
6814
6815   setbuf (stdout, NULL);
6816
6817   no_test_warnings ();
6818
6819   g = guestfs_create ();
6820   if (g == NULL) {
6821     printf (\"guestfs_create FAILED\\n\");
6822     exit (EXIT_FAILURE);
6823   }
6824
6825   guestfs_set_error_handler (g, print_error, NULL);
6826
6827   guestfs_set_path (g, \"../appliance\");
6828
6829   filename = \"test1.img\";
6830   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6831   if (fd == -1) {
6832     perror (filename);
6833     exit (EXIT_FAILURE);
6834   }
6835   if (lseek (fd, %d, SEEK_SET) == -1) {
6836     perror (\"lseek\");
6837     close (fd);
6838     unlink (filename);
6839     exit (EXIT_FAILURE);
6840   }
6841   if (write (fd, &c, 1) == -1) {
6842     perror (\"write\");
6843     close (fd);
6844     unlink (filename);
6845     exit (EXIT_FAILURE);
6846   }
6847   if (close (fd) == -1) {
6848     perror (filename);
6849     unlink (filename);
6850     exit (EXIT_FAILURE);
6851   }
6852   if (guestfs_add_drive (g, filename) == -1) {
6853     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6854     exit (EXIT_FAILURE);
6855   }
6856
6857   filename = \"test2.img\";
6858   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6859   if (fd == -1) {
6860     perror (filename);
6861     exit (EXIT_FAILURE);
6862   }
6863   if (lseek (fd, %d, SEEK_SET) == -1) {
6864     perror (\"lseek\");
6865     close (fd);
6866     unlink (filename);
6867     exit (EXIT_FAILURE);
6868   }
6869   if (write (fd, &c, 1) == -1) {
6870     perror (\"write\");
6871     close (fd);
6872     unlink (filename);
6873     exit (EXIT_FAILURE);
6874   }
6875   if (close (fd) == -1) {
6876     perror (filename);
6877     unlink (filename);
6878     exit (EXIT_FAILURE);
6879   }
6880   if (guestfs_add_drive (g, filename) == -1) {
6881     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6882     exit (EXIT_FAILURE);
6883   }
6884
6885   filename = \"test3.img\";
6886   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6887   if (fd == -1) {
6888     perror (filename);
6889     exit (EXIT_FAILURE);
6890   }
6891   if (lseek (fd, %d, SEEK_SET) == -1) {
6892     perror (\"lseek\");
6893     close (fd);
6894     unlink (filename);
6895     exit (EXIT_FAILURE);
6896   }
6897   if (write (fd, &c, 1) == -1) {
6898     perror (\"write\");
6899     close (fd);
6900     unlink (filename);
6901     exit (EXIT_FAILURE);
6902   }
6903   if (close (fd) == -1) {
6904     perror (filename);
6905     unlink (filename);
6906     exit (EXIT_FAILURE);
6907   }
6908   if (guestfs_add_drive (g, filename) == -1) {
6909     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6910     exit (EXIT_FAILURE);
6911   }
6912
6913   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6914     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6915     exit (EXIT_FAILURE);
6916   }
6917
6918   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6919   alarm (600);
6920
6921   if (guestfs_launch (g) == -1) {
6922     printf (\"guestfs_launch FAILED\\n\");
6923     exit (EXIT_FAILURE);
6924   }
6925
6926   /* Cancel previous alarm. */
6927   alarm (0);
6928
6929   nr_tests = %d;
6930
6931 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6932
6933   iteri (
6934     fun i test_name ->
6935       pr "  test_num++;\n";
6936       pr "  if (guestfs_get_verbose (g))\n";
6937       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6938       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6939       pr "  if (%s () == -1) {\n" test_name;
6940       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6941       pr "    n_failed++;\n";
6942       pr "  }\n";
6943   ) test_names;
6944   pr "\n";
6945
6946   pr "  guestfs_close (g);\n";
6947   pr "  unlink (\"test1.img\");\n";
6948   pr "  unlink (\"test2.img\");\n";
6949   pr "  unlink (\"test3.img\");\n";
6950   pr "\n";
6951
6952   pr "  if (n_failed > 0) {\n";
6953   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6954   pr "    exit (EXIT_FAILURE);\n";
6955   pr "  }\n";
6956   pr "\n";
6957
6958   pr "  exit (EXIT_SUCCESS);\n";
6959   pr "}\n"
6960
6961 and generate_one_test name flags i (init, prereq, test) =
6962   let test_name = sprintf "test_%s_%d" name i in
6963
6964   pr "\
6965 static int %s_skip (void)
6966 {
6967   const char *str;
6968
6969   str = getenv (\"TEST_ONLY\");
6970   if (str)
6971     return strstr (str, \"%s\") == NULL;
6972   str = getenv (\"SKIP_%s\");
6973   if (str && STREQ (str, \"1\")) return 1;
6974   str = getenv (\"SKIP_TEST_%s\");
6975   if (str && STREQ (str, \"1\")) return 1;
6976   return 0;
6977 }
6978
6979 " test_name name (String.uppercase test_name) (String.uppercase name);
6980
6981   (match prereq with
6982    | Disabled | Always -> ()
6983    | If code | Unless code ->
6984        pr "static int %s_prereq (void)\n" test_name;
6985        pr "{\n";
6986        pr "  %s\n" code;
6987        pr "}\n";
6988        pr "\n";
6989   );
6990
6991   pr "\
6992 static int %s (void)
6993 {
6994   if (%s_skip ()) {
6995     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6996     return 0;
6997   }
6998
6999 " test_name test_name test_name;
7000
7001   (* Optional functions should only be tested if the relevant
7002    * support is available in the daemon.
7003    *)
7004   List.iter (
7005     function
7006     | Optional group ->
7007         pr "  {\n";
7008         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
7009         pr "    int r;\n";
7010         pr "    suppress_error = 1;\n";
7011         pr "    r = guestfs_available (g, (char **) groups);\n";
7012         pr "    suppress_error = 0;\n";
7013         pr "    if (r == -1) {\n";
7014         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
7015         pr "      return 0;\n";
7016         pr "    }\n";
7017         pr "  }\n";
7018     | _ -> ()
7019   ) flags;
7020
7021   (match prereq with
7022    | Disabled ->
7023        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7024    | If _ ->
7025        pr "  if (! %s_prereq ()) {\n" test_name;
7026        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7027        pr "    return 0;\n";
7028        pr "  }\n";
7029        pr "\n";
7030        generate_one_test_body name i test_name init test;
7031    | Unless _ ->
7032        pr "  if (%s_prereq ()) {\n" test_name;
7033        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7034        pr "    return 0;\n";
7035        pr "  }\n";
7036        pr "\n";
7037        generate_one_test_body name i test_name init test;
7038    | Always ->
7039        generate_one_test_body name i test_name init test
7040   );
7041
7042   pr "  return 0;\n";
7043   pr "}\n";
7044   pr "\n";
7045   test_name
7046
7047 and generate_one_test_body name i test_name init test =
7048   (match init with
7049    | InitNone (* XXX at some point, InitNone and InitEmpty became
7050                * folded together as the same thing.  Really we should
7051                * make InitNone do nothing at all, but the tests may
7052                * need to be checked to make sure this is OK.
7053                *)
7054    | InitEmpty ->
7055        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7056        List.iter (generate_test_command_call test_name)
7057          [["blockdev_setrw"; "/dev/sda"];
7058           ["umount_all"];
7059           ["lvm_remove_all"]]
7060    | InitPartition ->
7061        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7062        List.iter (generate_test_command_call test_name)
7063          [["blockdev_setrw"; "/dev/sda"];
7064           ["umount_all"];
7065           ["lvm_remove_all"];
7066           ["part_disk"; "/dev/sda"; "mbr"]]
7067    | InitBasicFS ->
7068        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7069        List.iter (generate_test_command_call test_name)
7070          [["blockdev_setrw"; "/dev/sda"];
7071           ["umount_all"];
7072           ["lvm_remove_all"];
7073           ["part_disk"; "/dev/sda"; "mbr"];
7074           ["mkfs"; "ext2"; "/dev/sda1"];
7075           ["mount_options"; ""; "/dev/sda1"; "/"]]
7076    | InitBasicFSonLVM ->
7077        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7078          test_name;
7079        List.iter (generate_test_command_call test_name)
7080          [["blockdev_setrw"; "/dev/sda"];
7081           ["umount_all"];
7082           ["lvm_remove_all"];
7083           ["part_disk"; "/dev/sda"; "mbr"];
7084           ["pvcreate"; "/dev/sda1"];
7085           ["vgcreate"; "VG"; "/dev/sda1"];
7086           ["lvcreate"; "LV"; "VG"; "8"];
7087           ["mkfs"; "ext2"; "/dev/VG/LV"];
7088           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7089    | InitISOFS ->
7090        pr "  /* InitISOFS for %s */\n" test_name;
7091        List.iter (generate_test_command_call test_name)
7092          [["blockdev_setrw"; "/dev/sda"];
7093           ["umount_all"];
7094           ["lvm_remove_all"];
7095           ["mount_ro"; "/dev/sdd"; "/"]]
7096   );
7097
7098   let get_seq_last = function
7099     | [] ->
7100         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7101           test_name
7102     | seq ->
7103         let seq = List.rev seq in
7104         List.rev (List.tl seq), List.hd seq
7105   in
7106
7107   match test with
7108   | TestRun seq ->
7109       pr "  /* TestRun for %s (%d) */\n" name i;
7110       List.iter (generate_test_command_call test_name) seq
7111   | TestOutput (seq, expected) ->
7112       pr "  /* TestOutput for %s (%d) */\n" name i;
7113       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7114       let seq, last = get_seq_last seq in
7115       let test () =
7116         pr "    if (STRNEQ (r, expected)) {\n";
7117         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7118         pr "      return -1;\n";
7119         pr "    }\n"
7120       in
7121       List.iter (generate_test_command_call test_name) seq;
7122       generate_test_command_call ~test test_name last
7123   | TestOutputList (seq, expected) ->
7124       pr "  /* TestOutputList for %s (%d) */\n" name i;
7125       let seq, last = get_seq_last seq in
7126       let test () =
7127         iteri (
7128           fun i str ->
7129             pr "    if (!r[%d]) {\n" i;
7130             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7131             pr "      print_strings (r);\n";
7132             pr "      return -1;\n";
7133             pr "    }\n";
7134             pr "    {\n";
7135             pr "      const char *expected = \"%s\";\n" (c_quote str);
7136             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7137             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7138             pr "        return -1;\n";
7139             pr "      }\n";
7140             pr "    }\n"
7141         ) expected;
7142         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7143         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7144           test_name;
7145         pr "      print_strings (r);\n";
7146         pr "      return -1;\n";
7147         pr "    }\n"
7148       in
7149       List.iter (generate_test_command_call test_name) seq;
7150       generate_test_command_call ~test test_name last
7151   | TestOutputListOfDevices (seq, expected) ->
7152       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7153       let seq, last = get_seq_last seq in
7154       let test () =
7155         iteri (
7156           fun i str ->
7157             pr "    if (!r[%d]) {\n" i;
7158             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7159             pr "      print_strings (r);\n";
7160             pr "      return -1;\n";
7161             pr "    }\n";
7162             pr "    {\n";
7163             pr "      const char *expected = \"%s\";\n" (c_quote str);
7164             pr "      r[%d][5] = 's';\n" i;
7165             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7166             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7167             pr "        return -1;\n";
7168             pr "      }\n";
7169             pr "    }\n"
7170         ) expected;
7171         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7172         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7173           test_name;
7174         pr "      print_strings (r);\n";
7175         pr "      return -1;\n";
7176         pr "    }\n"
7177       in
7178       List.iter (generate_test_command_call test_name) seq;
7179       generate_test_command_call ~test test_name last
7180   | TestOutputInt (seq, expected) ->
7181       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7182       let seq, last = get_seq_last seq in
7183       let test () =
7184         pr "    if (r != %d) {\n" expected;
7185         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7186           test_name expected;
7187         pr "               (int) r);\n";
7188         pr "      return -1;\n";
7189         pr "    }\n"
7190       in
7191       List.iter (generate_test_command_call test_name) seq;
7192       generate_test_command_call ~test test_name last
7193   | TestOutputIntOp (seq, op, expected) ->
7194       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7195       let seq, last = get_seq_last seq in
7196       let test () =
7197         pr "    if (! (r %s %d)) {\n" op expected;
7198         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7199           test_name op expected;
7200         pr "               (int) r);\n";
7201         pr "      return -1;\n";
7202         pr "    }\n"
7203       in
7204       List.iter (generate_test_command_call test_name) seq;
7205       generate_test_command_call ~test test_name last
7206   | TestOutputTrue seq ->
7207       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7208       let seq, last = get_seq_last seq in
7209       let test () =
7210         pr "    if (!r) {\n";
7211         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7212           test_name;
7213         pr "      return -1;\n";
7214         pr "    }\n"
7215       in
7216       List.iter (generate_test_command_call test_name) seq;
7217       generate_test_command_call ~test test_name last
7218   | TestOutputFalse seq ->
7219       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7220       let seq, last = get_seq_last seq in
7221       let test () =
7222         pr "    if (r) {\n";
7223         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7224           test_name;
7225         pr "      return -1;\n";
7226         pr "    }\n"
7227       in
7228       List.iter (generate_test_command_call test_name) seq;
7229       generate_test_command_call ~test test_name last
7230   | TestOutputLength (seq, expected) ->
7231       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7232       let seq, last = get_seq_last seq in
7233       let test () =
7234         pr "    int j;\n";
7235         pr "    for (j = 0; j < %d; ++j)\n" expected;
7236         pr "      if (r[j] == NULL) {\n";
7237         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7238           test_name;
7239         pr "        print_strings (r);\n";
7240         pr "        return -1;\n";
7241         pr "      }\n";
7242         pr "    if (r[j] != NULL) {\n";
7243         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7244           test_name;
7245         pr "      print_strings (r);\n";
7246         pr "      return -1;\n";
7247         pr "    }\n"
7248       in
7249       List.iter (generate_test_command_call test_name) seq;
7250       generate_test_command_call ~test test_name last
7251   | TestOutputBuffer (seq, expected) ->
7252       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7253       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7254       let seq, last = get_seq_last seq in
7255       let len = String.length expected in
7256       let test () =
7257         pr "    if (size != %d) {\n" len;
7258         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7259         pr "      return -1;\n";
7260         pr "    }\n";
7261         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7262         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7263         pr "      return -1;\n";
7264         pr "    }\n"
7265       in
7266       List.iter (generate_test_command_call test_name) seq;
7267       generate_test_command_call ~test test_name last
7268   | TestOutputStruct (seq, checks) ->
7269       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7270       let seq, last = get_seq_last seq in
7271       let test () =
7272         List.iter (
7273           function
7274           | CompareWithInt (field, expected) ->
7275               pr "    if (r->%s != %d) {\n" field expected;
7276               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7277                 test_name field expected;
7278               pr "               (int) r->%s);\n" field;
7279               pr "      return -1;\n";
7280               pr "    }\n"
7281           | CompareWithIntOp (field, op, expected) ->
7282               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7283               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7284                 test_name field op expected;
7285               pr "               (int) r->%s);\n" field;
7286               pr "      return -1;\n";
7287               pr "    }\n"
7288           | CompareWithString (field, expected) ->
7289               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7290               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7291                 test_name field expected;
7292               pr "               r->%s);\n" field;
7293               pr "      return -1;\n";
7294               pr "    }\n"
7295           | CompareFieldsIntEq (field1, field2) ->
7296               pr "    if (r->%s != r->%s) {\n" field1 field2;
7297               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7298                 test_name field1 field2;
7299               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7300               pr "      return -1;\n";
7301               pr "    }\n"
7302           | CompareFieldsStrEq (field1, field2) ->
7303               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7304               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7305                 test_name field1 field2;
7306               pr "               r->%s, r->%s);\n" field1 field2;
7307               pr "      return -1;\n";
7308               pr "    }\n"
7309         ) checks
7310       in
7311       List.iter (generate_test_command_call test_name) seq;
7312       generate_test_command_call ~test test_name last
7313   | TestLastFail seq ->
7314       pr "  /* TestLastFail for %s (%d) */\n" name i;
7315       let seq, last = get_seq_last seq in
7316       List.iter (generate_test_command_call test_name) seq;
7317       generate_test_command_call test_name ~expect_error:true last
7318
7319 (* Generate the code to run a command, leaving the result in 'r'.
7320  * If you expect to get an error then you should set expect_error:true.
7321  *)
7322 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7323   match cmd with
7324   | [] -> assert false
7325   | name :: args ->
7326       (* Look up the command to find out what args/ret it has. *)
7327       let style =
7328         try
7329           let _, style, _, _, _, _, _ =
7330             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7331           style
7332         with Not_found ->
7333           failwithf "%s: in test, command %s was not found" test_name name in
7334
7335       if List.length (snd style) <> List.length args then
7336         failwithf "%s: in test, wrong number of args given to %s"
7337           test_name name;
7338
7339       pr "  {\n";
7340
7341       List.iter (
7342         function
7343         | OptString n, "NULL" -> ()
7344         | Pathname n, arg
7345         | Device n, arg
7346         | Dev_or_Path n, arg
7347         | String n, arg
7348         | OptString n, arg ->
7349             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7350         | BufferIn n, arg ->
7351             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7352             pr "    size_t %s_size = %d;\n" n (String.length arg)
7353         | Int _, _
7354         | Int64 _, _
7355         | Bool _, _
7356         | FileIn _, _ | FileOut _, _ -> ()
7357         | StringList n, "" | DeviceList n, "" ->
7358             pr "    const char *const %s[1] = { NULL };\n" n
7359         | StringList n, arg | DeviceList n, arg ->
7360             let strs = string_split " " arg in
7361             iteri (
7362               fun i str ->
7363                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7364             ) strs;
7365             pr "    const char *const %s[] = {\n" n;
7366             iteri (
7367               fun i _ -> pr "      %s_%d,\n" n i
7368             ) strs;
7369             pr "      NULL\n";
7370             pr "    };\n";
7371       ) (List.combine (snd style) args);
7372
7373       let error_code =
7374         match fst style with
7375         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7376         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7377         | RConstString _ | RConstOptString _ ->
7378             pr "    const char *r;\n"; "NULL"
7379         | RString _ -> pr "    char *r;\n"; "NULL"
7380         | RStringList _ | RHashtable _ ->
7381             pr "    char **r;\n";
7382             pr "    int i;\n";
7383             "NULL"
7384         | RStruct (_, typ) ->
7385             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7386         | RStructList (_, typ) ->
7387             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7388         | RBufferOut _ ->
7389             pr "    char *r;\n";
7390             pr "    size_t size;\n";
7391             "NULL" in
7392
7393       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7394       pr "    r = guestfs_%s (g" name;
7395
7396       (* Generate the parameters. *)
7397       List.iter (
7398         function
7399         | OptString _, "NULL" -> pr ", NULL"
7400         | Pathname n, _
7401         | Device n, _ | Dev_or_Path n, _
7402         | String n, _
7403         | OptString n, _ ->
7404             pr ", %s" n
7405         | BufferIn n, _ ->
7406             pr ", %s, %s_size" n n
7407         | FileIn _, arg | FileOut _, arg ->
7408             pr ", \"%s\"" (c_quote arg)
7409         | StringList n, _ | DeviceList n, _ ->
7410             pr ", (char **) %s" n
7411         | Int _, arg ->
7412             let i =
7413               try int_of_string arg
7414               with Failure "int_of_string" ->
7415                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7416             pr ", %d" i
7417         | Int64 _, arg ->
7418             let i =
7419               try Int64.of_string arg
7420               with Failure "int_of_string" ->
7421                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7422             pr ", %Ld" i
7423         | Bool _, arg ->
7424             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7425       ) (List.combine (snd style) args);
7426
7427       (match fst style with
7428        | RBufferOut _ -> pr ", &size"
7429        | _ -> ()
7430       );
7431
7432       pr ");\n";
7433
7434       if not expect_error then
7435         pr "    if (r == %s)\n" error_code
7436       else
7437         pr "    if (r != %s)\n" error_code;
7438       pr "      return -1;\n";
7439
7440       (* Insert the test code. *)
7441       (match test with
7442        | None -> ()
7443        | Some f -> f ()
7444       );
7445
7446       (match fst style with
7447        | RErr | RInt _ | RInt64 _ | RBool _
7448        | RConstString _ | RConstOptString _ -> ()
7449        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7450        | RStringList _ | RHashtable _ ->
7451            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7452            pr "      free (r[i]);\n";
7453            pr "    free (r);\n"
7454        | RStruct (_, typ) ->
7455            pr "    guestfs_free_%s (r);\n" typ
7456        | RStructList (_, typ) ->
7457            pr "    guestfs_free_%s_list (r);\n" typ
7458       );
7459
7460       pr "  }\n"
7461
7462 and c_quote str =
7463   let str = replace_str str "\r" "\\r" in
7464   let str = replace_str str "\n" "\\n" in
7465   let str = replace_str str "\t" "\\t" in
7466   let str = replace_str str "\000" "\\0" in
7467   str
7468
7469 (* Generate a lot of different functions for guestfish. *)
7470 and generate_fish_cmds () =
7471   generate_header CStyle GPLv2plus;
7472
7473   let all_functions =
7474     List.filter (
7475       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7476     ) all_functions in
7477   let all_functions_sorted =
7478     List.filter (
7479       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7480     ) all_functions_sorted in
7481
7482   pr "#include <config.h>\n";
7483   pr "\n";
7484   pr "#include <stdio.h>\n";
7485   pr "#include <stdlib.h>\n";
7486   pr "#include <string.h>\n";
7487   pr "#include <inttypes.h>\n";
7488   pr "\n";
7489   pr "#include <guestfs.h>\n";
7490   pr "#include \"c-ctype.h\"\n";
7491   pr "#include \"full-write.h\"\n";
7492   pr "#include \"xstrtol.h\"\n";
7493   pr "#include \"fish.h\"\n";
7494   pr "\n";
7495   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7496   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7497   pr "\n";
7498
7499   (* list_commands function, which implements guestfish -h *)
7500   pr "void list_commands (void)\n";
7501   pr "{\n";
7502   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7503   pr "  list_builtin_commands ();\n";
7504   List.iter (
7505     fun (name, _, _, flags, _, shortdesc, _) ->
7506       let name = replace_char name '_' '-' in
7507       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7508         name shortdesc
7509   ) all_functions_sorted;
7510   pr "  printf (\"    %%s\\n\",";
7511   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7512   pr "}\n";
7513   pr "\n";
7514
7515   (* display_command function, which implements guestfish -h cmd *)
7516   pr "void display_command (const char *cmd)\n";
7517   pr "{\n";
7518   List.iter (
7519     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7520       let name2 = replace_char name '_' '-' in
7521       let alias =
7522         try find_map (function FishAlias n -> Some n | _ -> None) flags
7523         with Not_found -> name in
7524       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7525       let synopsis =
7526         match snd style with
7527         | [] -> name2
7528         | args ->
7529             sprintf "%s %s"
7530               name2 (String.concat " " (List.map name_of_argt args)) in
7531
7532       let warnings =
7533         if List.mem ProtocolLimitWarning flags then
7534           ("\n\n" ^ protocol_limit_warning)
7535         else "" in
7536
7537       (* For DangerWillRobinson commands, we should probably have
7538        * guestfish prompt before allowing you to use them (especially
7539        * in interactive mode). XXX
7540        *)
7541       let warnings =
7542         warnings ^
7543           if List.mem DangerWillRobinson flags then
7544             ("\n\n" ^ danger_will_robinson)
7545           else "" in
7546
7547       let warnings =
7548         warnings ^
7549           match deprecation_notice flags with
7550           | None -> ""
7551           | Some txt -> "\n\n" ^ txt in
7552
7553       let describe_alias =
7554         if name <> alias then
7555           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7556         else "" in
7557
7558       pr "  if (";
7559       pr "STRCASEEQ (cmd, \"%s\")" name;
7560       if name <> name2 then
7561         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7562       if name <> alias then
7563         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7564       pr ")\n";
7565       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7566         name2 shortdesc
7567         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7568          "=head1 DESCRIPTION\n\n" ^
7569          longdesc ^ warnings ^ describe_alias);
7570       pr "  else\n"
7571   ) all_functions;
7572   pr "    display_builtin_command (cmd);\n";
7573   pr "}\n";
7574   pr "\n";
7575
7576   let emit_print_list_function typ =
7577     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7578       typ typ typ;
7579     pr "{\n";
7580     pr "  unsigned int i;\n";
7581     pr "\n";
7582     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7583     pr "    printf (\"[%%d] = {\\n\", i);\n";
7584     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7585     pr "    printf (\"}\\n\");\n";
7586     pr "  }\n";
7587     pr "}\n";
7588     pr "\n";
7589   in
7590
7591   (* print_* functions *)
7592   List.iter (
7593     fun (typ, cols) ->
7594       let needs_i =
7595         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7596
7597       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7598       pr "{\n";
7599       if needs_i then (
7600         pr "  unsigned int i;\n";
7601         pr "\n"
7602       );
7603       List.iter (
7604         function
7605         | name, FString ->
7606             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7607         | name, FUUID ->
7608             pr "  printf (\"%%s%s: \", indent);\n" name;
7609             pr "  for (i = 0; i < 32; ++i)\n";
7610             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7611             pr "  printf (\"\\n\");\n"
7612         | name, FBuffer ->
7613             pr "  printf (\"%%s%s: \", indent);\n" name;
7614             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7615             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7616             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7617             pr "    else\n";
7618             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7619             pr "  printf (\"\\n\");\n"
7620         | name, (FUInt64|FBytes) ->
7621             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7622               name typ name
7623         | name, FInt64 ->
7624             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7625               name typ name
7626         | name, FUInt32 ->
7627             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7628               name typ name
7629         | name, FInt32 ->
7630             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7631               name typ name
7632         | name, FChar ->
7633             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7634               name typ name
7635         | name, FOptPercent ->
7636             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7637               typ name name typ name;
7638             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7639       ) cols;
7640       pr "}\n";
7641       pr "\n";
7642   ) structs;
7643
7644   (* Emit a print_TYPE_list function definition only if that function is used. *)
7645   List.iter (
7646     function
7647     | typ, (RStructListOnly | RStructAndList) ->
7648         (* generate the function for typ *)
7649         emit_print_list_function typ
7650     | typ, _ -> () (* empty *)
7651   ) (rstructs_used_by all_functions);
7652
7653   (* Emit a print_TYPE function definition only if that function is used. *)
7654   List.iter (
7655     function
7656     | typ, (RStructOnly | RStructAndList) ->
7657         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7658         pr "{\n";
7659         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7660         pr "}\n";
7661         pr "\n";
7662     | typ, _ -> () (* empty *)
7663   ) (rstructs_used_by all_functions);
7664
7665   (* run_<action> actions *)
7666   List.iter (
7667     fun (name, style, _, flags, _, _, _) ->
7668       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7669       pr "{\n";
7670       (match fst style with
7671        | RErr
7672        | RInt _
7673        | RBool _ -> pr "  int r;\n"
7674        | RInt64 _ -> pr "  int64_t r;\n"
7675        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7676        | RString _ -> pr "  char *r;\n"
7677        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7678        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7679        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7680        | RBufferOut _ ->
7681            pr "  char *r;\n";
7682            pr "  size_t size;\n";
7683       );
7684       List.iter (
7685         function
7686         | Device n
7687         | String n
7688         | OptString n -> pr "  const char *%s;\n" n
7689         | Pathname n
7690         | Dev_or_Path n
7691         | FileIn n
7692         | FileOut n -> pr "  char *%s;\n" n
7693         | BufferIn n ->
7694             pr "  const char *%s;\n" n;
7695             pr "  size_t %s_size;\n" n
7696         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7697         | Bool n -> pr "  int %s;\n" n
7698         | Int n -> pr "  int %s;\n" n
7699         | Int64 n -> pr "  int64_t %s;\n" n
7700       ) (snd style);
7701
7702       (* Check and convert parameters. *)
7703       let argc_expected = List.length (snd style) in
7704       pr "  if (argc != %d) {\n" argc_expected;
7705       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7706         argc_expected;
7707       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7708       pr "    return -1;\n";
7709       pr "  }\n";
7710
7711       let parse_integer fn fntyp rtyp range name i =
7712         pr "  {\n";
7713         pr "    strtol_error xerr;\n";
7714         pr "    %s r;\n" fntyp;
7715         pr "\n";
7716         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7717         pr "    if (xerr != LONGINT_OK) {\n";
7718         pr "      fprintf (stderr,\n";
7719         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7720         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7721         pr "      return -1;\n";
7722         pr "    }\n";
7723         (match range with
7724          | None -> ()
7725          | Some (min, max, comment) ->
7726              pr "    /* %s */\n" comment;
7727              pr "    if (r < %s || r > %s) {\n" min max;
7728              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7729                name;
7730              pr "      return -1;\n";
7731              pr "    }\n";
7732              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7733         );
7734         pr "    %s = r;\n" name;
7735         pr "  }\n";
7736       in
7737
7738       iteri (
7739         fun i ->
7740           function
7741           | Device name
7742           | String name ->
7743               pr "  %s = argv[%d];\n" name i
7744           | Pathname name
7745           | Dev_or_Path name ->
7746               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7747               pr "  if (%s == NULL) return -1;\n" name
7748           | OptString name ->
7749               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7750                 name i i
7751           | BufferIn name ->
7752               pr "  %s = argv[%d];\n" name i;
7753               pr "  %s_size = strlen (argv[%d]);\n" name i
7754           | FileIn name ->
7755               pr "  %s = file_in (argv[%d]);\n" name i;
7756               pr "  if (%s == NULL) return -1;\n" name
7757           | FileOut name ->
7758               pr "  %s = file_out (argv[%d]);\n" name i;
7759               pr "  if (%s == NULL) return -1;\n" name
7760           | StringList name | DeviceList name ->
7761               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7762               pr "  if (%s == NULL) return -1;\n" name;
7763           | Bool name ->
7764               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7765           | Int name ->
7766               let range =
7767                 let min = "(-(2LL<<30))"
7768                 and max = "((2LL<<30)-1)"
7769                 and comment =
7770                   "The Int type in the generator is a signed 31 bit int." in
7771                 Some (min, max, comment) in
7772               parse_integer "xstrtoll" "long long" "int" range name i
7773           | Int64 name ->
7774               parse_integer "xstrtoll" "long long" "int64_t" None name i
7775       ) (snd style);
7776
7777       (* Call C API function. *)
7778       pr "  r = guestfs_%s " name;
7779       generate_c_call_args ~handle:"g" style;
7780       pr ";\n";
7781
7782       List.iter (
7783         function
7784         | Device name | String name
7785         | OptString name | Bool name
7786         | Int name | Int64 name
7787         | BufferIn name -> ()
7788         | Pathname name | Dev_or_Path name | FileOut name ->
7789             pr "  free (%s);\n" name
7790         | FileIn name ->
7791             pr "  free_file_in (%s);\n" name
7792         | StringList name | DeviceList name ->
7793             pr "  free_strings (%s);\n" name
7794       ) (snd style);
7795
7796       (* Any output flags? *)
7797       let fish_output =
7798         let flags = filter_map (
7799           function FishOutput flag -> Some flag | _ -> None
7800         ) flags in
7801         match flags with
7802         | [] -> None
7803         | [f] -> Some f
7804         | _ ->
7805             failwithf "%s: more than one FishOutput flag is not allowed" name in
7806
7807       (* Check return value for errors and display command results. *)
7808       (match fst style with
7809        | RErr -> pr "  return r;\n"
7810        | RInt _ ->
7811            pr "  if (r == -1) return -1;\n";
7812            (match fish_output with
7813             | None ->
7814                 pr "  printf (\"%%d\\n\", r);\n";
7815             | Some FishOutputOctal ->
7816                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7817             | Some FishOutputHexadecimal ->
7818                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7819            pr "  return 0;\n"
7820        | RInt64 _ ->
7821            pr "  if (r == -1) return -1;\n";
7822            (match fish_output with
7823             | None ->
7824                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7825             | Some FishOutputOctal ->
7826                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7827             | Some FishOutputHexadecimal ->
7828                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7829            pr "  return 0;\n"
7830        | RBool _ ->
7831            pr "  if (r == -1) return -1;\n";
7832            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7833            pr "  return 0;\n"
7834        | RConstString _ ->
7835            pr "  if (r == NULL) return -1;\n";
7836            pr "  printf (\"%%s\\n\", r);\n";
7837            pr "  return 0;\n"
7838        | RConstOptString _ ->
7839            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7840            pr "  return 0;\n"
7841        | RString _ ->
7842            pr "  if (r == NULL) return -1;\n";
7843            pr "  printf (\"%%s\\n\", r);\n";
7844            pr "  free (r);\n";
7845            pr "  return 0;\n"
7846        | RStringList _ ->
7847            pr "  if (r == NULL) return -1;\n";
7848            pr "  print_strings (r);\n";
7849            pr "  free_strings (r);\n";
7850            pr "  return 0;\n"
7851        | RStruct (_, typ) ->
7852            pr "  if (r == NULL) return -1;\n";
7853            pr "  print_%s (r);\n" typ;
7854            pr "  guestfs_free_%s (r);\n" typ;
7855            pr "  return 0;\n"
7856        | RStructList (_, typ) ->
7857            pr "  if (r == NULL) return -1;\n";
7858            pr "  print_%s_list (r);\n" typ;
7859            pr "  guestfs_free_%s_list (r);\n" typ;
7860            pr "  return 0;\n"
7861        | RHashtable _ ->
7862            pr "  if (r == NULL) return -1;\n";
7863            pr "  print_table (r);\n";
7864            pr "  free_strings (r);\n";
7865            pr "  return 0;\n"
7866        | RBufferOut _ ->
7867            pr "  if (r == NULL) return -1;\n";
7868            pr "  if (full_write (1, r, size) != size) {\n";
7869            pr "    perror (\"write\");\n";
7870            pr "    free (r);\n";
7871            pr "    return -1;\n";
7872            pr "  }\n";
7873            pr "  free (r);\n";
7874            pr "  return 0;\n"
7875       );
7876       pr "}\n";
7877       pr "\n"
7878   ) all_functions;
7879
7880   (* run_action function *)
7881   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7882   pr "{\n";
7883   List.iter (
7884     fun (name, _, _, flags, _, _, _) ->
7885       let name2 = replace_char name '_' '-' in
7886       let alias =
7887         try find_map (function FishAlias n -> Some n | _ -> None) flags
7888         with Not_found -> name in
7889       pr "  if (";
7890       pr "STRCASEEQ (cmd, \"%s\")" name;
7891       if name <> name2 then
7892         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7893       if name <> alias then
7894         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7895       pr ")\n";
7896       pr "    return run_%s (cmd, argc, argv);\n" name;
7897       pr "  else\n";
7898   ) all_functions;
7899   pr "    {\n";
7900   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7901   pr "      if (command_num == 1)\n";
7902   pr "        extended_help_message ();\n";
7903   pr "      return -1;\n";
7904   pr "    }\n";
7905   pr "  return 0;\n";
7906   pr "}\n";
7907   pr "\n"
7908
7909 (* Readline completion for guestfish. *)
7910 and generate_fish_completion () =
7911   generate_header CStyle GPLv2plus;
7912
7913   let all_functions =
7914     List.filter (
7915       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7916     ) all_functions in
7917
7918   pr "\
7919 #include <config.h>
7920
7921 #include <stdio.h>
7922 #include <stdlib.h>
7923 #include <string.h>
7924
7925 #ifdef HAVE_LIBREADLINE
7926 #include <readline/readline.h>
7927 #endif
7928
7929 #include \"fish.h\"
7930
7931 #ifdef HAVE_LIBREADLINE
7932
7933 static const char *const commands[] = {
7934   BUILTIN_COMMANDS_FOR_COMPLETION,
7935 ";
7936
7937   (* Get the commands, including the aliases.  They don't need to be
7938    * sorted - the generator() function just does a dumb linear search.
7939    *)
7940   let commands =
7941     List.map (
7942       fun (name, _, _, flags, _, _, _) ->
7943         let name2 = replace_char name '_' '-' in
7944         let alias =
7945           try find_map (function FishAlias n -> Some n | _ -> None) flags
7946           with Not_found -> name in
7947
7948         if name <> alias then [name2; alias] else [name2]
7949     ) all_functions in
7950   let commands = List.flatten commands in
7951
7952   List.iter (pr "  \"%s\",\n") commands;
7953
7954   pr "  NULL
7955 };
7956
7957 static char *
7958 generator (const char *text, int state)
7959 {
7960   static int index, len;
7961   const char *name;
7962
7963   if (!state) {
7964     index = 0;
7965     len = strlen (text);
7966   }
7967
7968   rl_attempted_completion_over = 1;
7969
7970   while ((name = commands[index]) != NULL) {
7971     index++;
7972     if (STRCASEEQLEN (name, text, len))
7973       return strdup (name);
7974   }
7975
7976   return NULL;
7977 }
7978
7979 #endif /* HAVE_LIBREADLINE */
7980
7981 #ifdef HAVE_RL_COMPLETION_MATCHES
7982 #define RL_COMPLETION_MATCHES rl_completion_matches
7983 #else
7984 #ifdef HAVE_COMPLETION_MATCHES
7985 #define RL_COMPLETION_MATCHES completion_matches
7986 #endif
7987 #endif /* else just fail if we don't have either symbol */
7988
7989 char **
7990 do_completion (const char *text, int start, int end)
7991 {
7992   char **matches = NULL;
7993
7994 #ifdef HAVE_LIBREADLINE
7995   rl_completion_append_character = ' ';
7996
7997   if (start == 0)
7998     matches = RL_COMPLETION_MATCHES (text, generator);
7999   else if (complete_dest_paths)
8000     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8001 #endif
8002
8003   return matches;
8004 }
8005 ";
8006
8007 (* Generate the POD documentation for guestfish. *)
8008 and generate_fish_actions_pod () =
8009   let all_functions_sorted =
8010     List.filter (
8011       fun (_, _, _, flags, _, _, _) ->
8012         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8013     ) all_functions_sorted in
8014
8015   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8016
8017   List.iter (
8018     fun (name, style, _, flags, _, _, longdesc) ->
8019       let longdesc =
8020         Str.global_substitute rex (
8021           fun s ->
8022             let sub =
8023               try Str.matched_group 1 s
8024               with Not_found ->
8025                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8026             "C<" ^ replace_char sub '_' '-' ^ ">"
8027         ) longdesc in
8028       let name = replace_char name '_' '-' in
8029       let alias =
8030         try find_map (function FishAlias n -> Some n | _ -> None) flags
8031         with Not_found -> name in
8032
8033       pr "=head2 %s" name;
8034       if name <> alias then
8035         pr " | %s" alias;
8036       pr "\n";
8037       pr "\n";
8038       pr " %s" name;
8039       List.iter (
8040         function
8041         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8042         | OptString n -> pr " %s" n
8043         | StringList n | DeviceList n -> pr " '%s ...'" n
8044         | Bool _ -> pr " true|false"
8045         | Int n -> pr " %s" n
8046         | Int64 n -> pr " %s" n
8047         | FileIn n | FileOut n -> pr " (%s|-)" n
8048         | BufferIn n -> pr " %s" n
8049       ) (snd style);
8050       pr "\n";
8051       pr "\n";
8052       pr "%s\n\n" longdesc;
8053
8054       if List.exists (function FileIn _ | FileOut _ -> true
8055                       | _ -> false) (snd style) then
8056         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8057
8058       if List.mem ProtocolLimitWarning flags then
8059         pr "%s\n\n" protocol_limit_warning;
8060
8061       if List.mem DangerWillRobinson flags then
8062         pr "%s\n\n" danger_will_robinson;
8063
8064       match deprecation_notice flags with
8065       | None -> ()
8066       | Some txt -> pr "%s\n\n" txt
8067   ) all_functions_sorted
8068
8069 (* Generate a C function prototype. *)
8070 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8071     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8072     ?(prefix = "")
8073     ?handle name style =
8074   if extern then pr "extern ";
8075   if static then pr "static ";
8076   (match fst style with
8077    | RErr -> pr "int "
8078    | RInt _ -> pr "int "
8079    | RInt64 _ -> pr "int64_t "
8080    | RBool _ -> pr "int "
8081    | RConstString _ | RConstOptString _ -> pr "const char *"
8082    | RString _ | RBufferOut _ -> pr "char *"
8083    | RStringList _ | RHashtable _ -> pr "char **"
8084    | RStruct (_, typ) ->
8085        if not in_daemon then pr "struct guestfs_%s *" typ
8086        else pr "guestfs_int_%s *" typ
8087    | RStructList (_, typ) ->
8088        if not in_daemon then pr "struct guestfs_%s_list *" typ
8089        else pr "guestfs_int_%s_list *" typ
8090   );
8091   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8092   pr "%s%s (" prefix name;
8093   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8094     pr "void"
8095   else (
8096     let comma = ref false in
8097     (match handle with
8098      | None -> ()
8099      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8100     );
8101     let next () =
8102       if !comma then (
8103         if single_line then pr ", " else pr ",\n\t\t"
8104       );
8105       comma := true
8106     in
8107     List.iter (
8108       function
8109       | Pathname n
8110       | Device n | Dev_or_Path n
8111       | String n
8112       | OptString n ->
8113           next ();
8114           pr "const char *%s" n
8115       | StringList n | DeviceList n ->
8116           next ();
8117           pr "char *const *%s" n
8118       | Bool n -> next (); pr "int %s" n
8119       | Int n -> next (); pr "int %s" n
8120       | Int64 n -> next (); pr "int64_t %s" n
8121       | FileIn n
8122       | FileOut n ->
8123           if not in_daemon then (next (); pr "const char *%s" n)
8124       | BufferIn n ->
8125           next ();
8126           pr "const char *%s" n;
8127           next ();
8128           pr "size_t %s_size" n
8129     ) (snd style);
8130     if is_RBufferOut then (next (); pr "size_t *size_r");
8131   );
8132   pr ")";
8133   if semicolon then pr ";";
8134   if newline then pr "\n"
8135
8136 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8137 and generate_c_call_args ?handle ?(decl = false) style =
8138   pr "(";
8139   let comma = ref false in
8140   let next () =
8141     if !comma then pr ", ";
8142     comma := true
8143   in
8144   (match handle with
8145    | None -> ()
8146    | Some handle -> pr "%s" handle; comma := true
8147   );
8148   List.iter (
8149     function
8150     | BufferIn n ->
8151         next ();
8152         pr "%s, %s_size" n n
8153     | arg ->
8154         next ();
8155         pr "%s" (name_of_argt arg)
8156   ) (snd style);
8157   (* For RBufferOut calls, add implicit &size parameter. *)
8158   if not decl then (
8159     match fst style with
8160     | RBufferOut _ ->
8161         next ();
8162         pr "&size"
8163     | _ -> ()
8164   );
8165   pr ")"
8166
8167 (* Generate the OCaml bindings interface. *)
8168 and generate_ocaml_mli () =
8169   generate_header OCamlStyle LGPLv2plus;
8170
8171   pr "\
8172 (** For API documentation you should refer to the C API
8173     in the guestfs(3) manual page.  The OCaml API uses almost
8174     exactly the same calls. *)
8175
8176 type t
8177 (** A [guestfs_h] handle. *)
8178
8179 exception Error of string
8180 (** This exception is raised when there is an error. *)
8181
8182 exception Handle_closed of string
8183 (** This exception is raised if you use a {!Guestfs.t} handle
8184     after calling {!close} on it.  The string is the name of
8185     the function. *)
8186
8187 val create : unit -> t
8188 (** Create a {!Guestfs.t} handle. *)
8189
8190 val close : t -> unit
8191 (** Close the {!Guestfs.t} handle and free up all resources used
8192     by it immediately.
8193
8194     Handles are closed by the garbage collector when they become
8195     unreferenced, but callers can call this in order to provide
8196     predictable cleanup. *)
8197
8198 ";
8199   generate_ocaml_structure_decls ();
8200
8201   (* The actions. *)
8202   List.iter (
8203     fun (name, style, _, _, _, shortdesc, _) ->
8204       generate_ocaml_prototype name style;
8205       pr "(** %s *)\n" shortdesc;
8206       pr "\n"
8207   ) all_functions_sorted
8208
8209 (* Generate the OCaml bindings implementation. *)
8210 and generate_ocaml_ml () =
8211   generate_header OCamlStyle LGPLv2plus;
8212
8213   pr "\
8214 type t
8215
8216 exception Error of string
8217 exception Handle_closed of string
8218
8219 external create : unit -> t = \"ocaml_guestfs_create\"
8220 external close : t -> unit = \"ocaml_guestfs_close\"
8221
8222 (* Give the exceptions names, so they can be raised from the C code. *)
8223 let () =
8224   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8225   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8226
8227 ";
8228
8229   generate_ocaml_structure_decls ();
8230
8231   (* The actions. *)
8232   List.iter (
8233     fun (name, style, _, _, _, shortdesc, _) ->
8234       generate_ocaml_prototype ~is_external:true name style;
8235   ) all_functions_sorted
8236
8237 (* Generate the OCaml bindings C implementation. *)
8238 and generate_ocaml_c () =
8239   generate_header CStyle LGPLv2plus;
8240
8241   pr "\
8242 #include <stdio.h>
8243 #include <stdlib.h>
8244 #include <string.h>
8245
8246 #include <caml/config.h>
8247 #include <caml/alloc.h>
8248 #include <caml/callback.h>
8249 #include <caml/fail.h>
8250 #include <caml/memory.h>
8251 #include <caml/mlvalues.h>
8252 #include <caml/signals.h>
8253
8254 #include <guestfs.h>
8255
8256 #include \"guestfs_c.h\"
8257
8258 /* Copy a hashtable of string pairs into an assoc-list.  We return
8259  * the list in reverse order, but hashtables aren't supposed to be
8260  * ordered anyway.
8261  */
8262 static CAMLprim value
8263 copy_table (char * const * argv)
8264 {
8265   CAMLparam0 ();
8266   CAMLlocal5 (rv, pairv, kv, vv, cons);
8267   int i;
8268
8269   rv = Val_int (0);
8270   for (i = 0; argv[i] != NULL; i += 2) {
8271     kv = caml_copy_string (argv[i]);
8272     vv = caml_copy_string (argv[i+1]);
8273     pairv = caml_alloc (2, 0);
8274     Store_field (pairv, 0, kv);
8275     Store_field (pairv, 1, vv);
8276     cons = caml_alloc (2, 0);
8277     Store_field (cons, 1, rv);
8278     rv = cons;
8279     Store_field (cons, 0, pairv);
8280   }
8281
8282   CAMLreturn (rv);
8283 }
8284
8285 ";
8286
8287   (* Struct copy functions. *)
8288
8289   let emit_ocaml_copy_list_function typ =
8290     pr "static CAMLprim value\n";
8291     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8292     pr "{\n";
8293     pr "  CAMLparam0 ();\n";
8294     pr "  CAMLlocal2 (rv, v);\n";
8295     pr "  unsigned int i;\n";
8296     pr "\n";
8297     pr "  if (%ss->len == 0)\n" typ;
8298     pr "    CAMLreturn (Atom (0));\n";
8299     pr "  else {\n";
8300     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8301     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8302     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8303     pr "      caml_modify (&Field (rv, i), v);\n";
8304     pr "    }\n";
8305     pr "    CAMLreturn (rv);\n";
8306     pr "  }\n";
8307     pr "}\n";
8308     pr "\n";
8309   in
8310
8311   List.iter (
8312     fun (typ, cols) ->
8313       let has_optpercent_col =
8314         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8315
8316       pr "static CAMLprim value\n";
8317       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8318       pr "{\n";
8319       pr "  CAMLparam0 ();\n";
8320       if has_optpercent_col then
8321         pr "  CAMLlocal3 (rv, v, v2);\n"
8322       else
8323         pr "  CAMLlocal2 (rv, v);\n";
8324       pr "\n";
8325       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8326       iteri (
8327         fun i col ->
8328           (match col with
8329            | name, FString ->
8330                pr "  v = caml_copy_string (%s->%s);\n" typ name
8331            | name, FBuffer ->
8332                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8333                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8334                  typ name typ name
8335            | name, FUUID ->
8336                pr "  v = caml_alloc_string (32);\n";
8337                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8338            | name, (FBytes|FInt64|FUInt64) ->
8339                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8340            | name, (FInt32|FUInt32) ->
8341                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8342            | name, FOptPercent ->
8343                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8344                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8345                pr "    v = caml_alloc (1, 0);\n";
8346                pr "    Store_field (v, 0, v2);\n";
8347                pr "  } else /* None */\n";
8348                pr "    v = Val_int (0);\n";
8349            | name, FChar ->
8350                pr "  v = Val_int (%s->%s);\n" typ name
8351           );
8352           pr "  Store_field (rv, %d, v);\n" i
8353       ) cols;
8354       pr "  CAMLreturn (rv);\n";
8355       pr "}\n";
8356       pr "\n";
8357   ) structs;
8358
8359   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8360   List.iter (
8361     function
8362     | typ, (RStructListOnly | RStructAndList) ->
8363         (* generate the function for typ *)
8364         emit_ocaml_copy_list_function typ
8365     | typ, _ -> () (* empty *)
8366   ) (rstructs_used_by all_functions);
8367
8368   (* The wrappers. *)
8369   List.iter (
8370     fun (name, style, _, _, _, _, _) ->
8371       pr "/* Automatically generated wrapper for function\n";
8372       pr " * ";
8373       generate_ocaml_prototype name style;
8374       pr " */\n";
8375       pr "\n";
8376
8377       let params =
8378         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8379
8380       let needs_extra_vs =
8381         match fst style with RConstOptString _ -> true | _ -> false in
8382
8383       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8384       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8385       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8386       pr "\n";
8387
8388       pr "CAMLprim value\n";
8389       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8390       List.iter (pr ", value %s") (List.tl params);
8391       pr ")\n";
8392       pr "{\n";
8393
8394       (match params with
8395        | [p1; p2; p3; p4; p5] ->
8396            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8397        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8398            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8399            pr "  CAMLxparam%d (%s);\n"
8400              (List.length rest) (String.concat ", " rest)
8401        | ps ->
8402            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8403       );
8404       if not needs_extra_vs then
8405         pr "  CAMLlocal1 (rv);\n"
8406       else
8407         pr "  CAMLlocal3 (rv, v, v2);\n";
8408       pr "\n";
8409
8410       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8411       pr "  if (g == NULL)\n";
8412       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8413       pr "\n";
8414
8415       List.iter (
8416         function
8417         | Pathname n
8418         | Device n | Dev_or_Path n
8419         | String n
8420         | FileIn n
8421         | FileOut n ->
8422             pr "  const char *%s = String_val (%sv);\n" n n
8423         | OptString n ->
8424             pr "  const char *%s =\n" n;
8425             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8426               n n
8427         | BufferIn n ->
8428             pr "  const char *%s = String_val (%sv);\n" n n;
8429             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8430         | StringList n | DeviceList n ->
8431             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8432         | Bool n ->
8433             pr "  int %s = Bool_val (%sv);\n" n n
8434         | Int n ->
8435             pr "  int %s = Int_val (%sv);\n" n n
8436         | Int64 n ->
8437             pr "  int64_t %s = Int64_val (%sv);\n" n n
8438       ) (snd style);
8439       let error_code =
8440         match fst style with
8441         | RErr -> pr "  int r;\n"; "-1"
8442         | RInt _ -> pr "  int r;\n"; "-1"
8443         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8444         | RBool _ -> pr "  int r;\n"; "-1"
8445         | RConstString _ | RConstOptString _ ->
8446             pr "  const char *r;\n"; "NULL"
8447         | RString _ -> pr "  char *r;\n"; "NULL"
8448         | RStringList _ ->
8449             pr "  int i;\n";
8450             pr "  char **r;\n";
8451             "NULL"
8452         | RStruct (_, typ) ->
8453             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8454         | RStructList (_, typ) ->
8455             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8456         | RHashtable _ ->
8457             pr "  int i;\n";
8458             pr "  char **r;\n";
8459             "NULL"
8460         | RBufferOut _ ->
8461             pr "  char *r;\n";
8462             pr "  size_t size;\n";
8463             "NULL" in
8464       pr "\n";
8465
8466       pr "  caml_enter_blocking_section ();\n";
8467       pr "  r = guestfs_%s " name;
8468       generate_c_call_args ~handle:"g" style;
8469       pr ";\n";
8470       pr "  caml_leave_blocking_section ();\n";
8471
8472       List.iter (
8473         function
8474         | StringList n | DeviceList n ->
8475             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8476         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8477         | Bool _ | Int _ | Int64 _
8478         | FileIn _ | FileOut _ | BufferIn _ -> ()
8479       ) (snd style);
8480
8481       pr "  if (r == %s)\n" error_code;
8482       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8483       pr "\n";
8484
8485       (match fst style with
8486        | RErr -> pr "  rv = Val_unit;\n"
8487        | RInt _ -> pr "  rv = Val_int (r);\n"
8488        | RInt64 _ ->
8489            pr "  rv = caml_copy_int64 (r);\n"
8490        | RBool _ -> pr "  rv = Val_bool (r);\n"
8491        | RConstString _ ->
8492            pr "  rv = caml_copy_string (r);\n"
8493        | RConstOptString _ ->
8494            pr "  if (r) { /* Some string */\n";
8495            pr "    v = caml_alloc (1, 0);\n";
8496            pr "    v2 = caml_copy_string (r);\n";
8497            pr "    Store_field (v, 0, v2);\n";
8498            pr "  } else /* None */\n";
8499            pr "    v = Val_int (0);\n";
8500        | RString _ ->
8501            pr "  rv = caml_copy_string (r);\n";
8502            pr "  free (r);\n"
8503        | RStringList _ ->
8504            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8505            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8506            pr "  free (r);\n"
8507        | RStruct (_, typ) ->
8508            pr "  rv = copy_%s (r);\n" typ;
8509            pr "  guestfs_free_%s (r);\n" typ;
8510        | RStructList (_, typ) ->
8511            pr "  rv = copy_%s_list (r);\n" typ;
8512            pr "  guestfs_free_%s_list (r);\n" typ;
8513        | RHashtable _ ->
8514            pr "  rv = copy_table (r);\n";
8515            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8516            pr "  free (r);\n";
8517        | RBufferOut _ ->
8518            pr "  rv = caml_alloc_string (size);\n";
8519            pr "  memcpy (String_val (rv), r, size);\n";
8520       );
8521
8522       pr "  CAMLreturn (rv);\n";
8523       pr "}\n";
8524       pr "\n";
8525
8526       if List.length params > 5 then (
8527         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8528         pr "CAMLprim value ";
8529         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8530         pr "CAMLprim value\n";
8531         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8532         pr "{\n";
8533         pr "  return ocaml_guestfs_%s (argv[0]" name;
8534         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8535         pr ");\n";
8536         pr "}\n";
8537         pr "\n"
8538       )
8539   ) all_functions_sorted
8540
8541 and generate_ocaml_structure_decls () =
8542   List.iter (
8543     fun (typ, cols) ->
8544       pr "type %s = {\n" typ;
8545       List.iter (
8546         function
8547         | name, FString -> pr "  %s : string;\n" name
8548         | name, FBuffer -> pr "  %s : string;\n" name
8549         | name, FUUID -> pr "  %s : string;\n" name
8550         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8551         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8552         | name, FChar -> pr "  %s : char;\n" name
8553         | name, FOptPercent -> pr "  %s : float option;\n" name
8554       ) cols;
8555       pr "}\n";
8556       pr "\n"
8557   ) structs
8558
8559 and generate_ocaml_prototype ?(is_external = false) name style =
8560   if is_external then pr "external " else pr "val ";
8561   pr "%s : t -> " name;
8562   List.iter (
8563     function
8564     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8565     | BufferIn _ -> pr "string -> "
8566     | OptString _ -> pr "string option -> "
8567     | StringList _ | DeviceList _ -> pr "string array -> "
8568     | Bool _ -> pr "bool -> "
8569     | Int _ -> pr "int -> "
8570     | Int64 _ -> pr "int64 -> "
8571   ) (snd style);
8572   (match fst style with
8573    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8574    | RInt _ -> pr "int"
8575    | RInt64 _ -> pr "int64"
8576    | RBool _ -> pr "bool"
8577    | RConstString _ -> pr "string"
8578    | RConstOptString _ -> pr "string option"
8579    | RString _ | RBufferOut _ -> pr "string"
8580    | RStringList _ -> pr "string array"
8581    | RStruct (_, typ) -> pr "%s" typ
8582    | RStructList (_, typ) -> pr "%s array" typ
8583    | RHashtable _ -> pr "(string * string) list"
8584   );
8585   if is_external then (
8586     pr " = ";
8587     if List.length (snd style) + 1 > 5 then
8588       pr "\"ocaml_guestfs_%s_byte\" " name;
8589     pr "\"ocaml_guestfs_%s\"" name
8590   );
8591   pr "\n"
8592
8593 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8594 and generate_perl_xs () =
8595   generate_header CStyle LGPLv2plus;
8596
8597   pr "\
8598 #include \"EXTERN.h\"
8599 #include \"perl.h\"
8600 #include \"XSUB.h\"
8601
8602 #include <guestfs.h>
8603
8604 #ifndef PRId64
8605 #define PRId64 \"lld\"
8606 #endif
8607
8608 static SV *
8609 my_newSVll(long long val) {
8610 #ifdef USE_64_BIT_ALL
8611   return newSViv(val);
8612 #else
8613   char buf[100];
8614   int len;
8615   len = snprintf(buf, 100, \"%%\" PRId64, val);
8616   return newSVpv(buf, len);
8617 #endif
8618 }
8619
8620 #ifndef PRIu64
8621 #define PRIu64 \"llu\"
8622 #endif
8623
8624 static SV *
8625 my_newSVull(unsigned long long val) {
8626 #ifdef USE_64_BIT_ALL
8627   return newSVuv(val);
8628 #else
8629   char buf[100];
8630   int len;
8631   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8632   return newSVpv(buf, len);
8633 #endif
8634 }
8635
8636 /* http://www.perlmonks.org/?node_id=680842 */
8637 static char **
8638 XS_unpack_charPtrPtr (SV *arg) {
8639   char **ret;
8640   AV *av;
8641   I32 i;
8642
8643   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8644     croak (\"array reference expected\");
8645
8646   av = (AV *)SvRV (arg);
8647   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8648   if (!ret)
8649     croak (\"malloc failed\");
8650
8651   for (i = 0; i <= av_len (av); i++) {
8652     SV **elem = av_fetch (av, i, 0);
8653
8654     if (!elem || !*elem)
8655       croak (\"missing element in list\");
8656
8657     ret[i] = SvPV_nolen (*elem);
8658   }
8659
8660   ret[i] = NULL;
8661
8662   return ret;
8663 }
8664
8665 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8666
8667 PROTOTYPES: ENABLE
8668
8669 guestfs_h *
8670 _create ()
8671    CODE:
8672       RETVAL = guestfs_create ();
8673       if (!RETVAL)
8674         croak (\"could not create guestfs handle\");
8675       guestfs_set_error_handler (RETVAL, NULL, NULL);
8676  OUTPUT:
8677       RETVAL
8678
8679 void
8680 DESTROY (g)
8681       guestfs_h *g;
8682  PPCODE:
8683       guestfs_close (g);
8684
8685 ";
8686
8687   List.iter (
8688     fun (name, style, _, _, _, _, _) ->
8689       (match fst style with
8690        | RErr -> pr "void\n"
8691        | RInt _ -> pr "SV *\n"
8692        | RInt64 _ -> pr "SV *\n"
8693        | RBool _ -> pr "SV *\n"
8694        | RConstString _ -> pr "SV *\n"
8695        | RConstOptString _ -> pr "SV *\n"
8696        | RString _ -> pr "SV *\n"
8697        | RBufferOut _ -> pr "SV *\n"
8698        | RStringList _
8699        | RStruct _ | RStructList _
8700        | RHashtable _ ->
8701            pr "void\n" (* all lists returned implictly on the stack *)
8702       );
8703       (* Call and arguments. *)
8704       pr "%s (g" name;
8705       List.iter (
8706         fun arg -> pr ", %s" (name_of_argt arg)
8707       ) (snd style);
8708       pr ")\n";
8709       pr "      guestfs_h *g;\n";
8710       iteri (
8711         fun i ->
8712           function
8713           | Pathname n | Device n | Dev_or_Path n | String n
8714           | FileIn n | FileOut n ->
8715               pr "      char *%s;\n" n
8716           | BufferIn n ->
8717               pr "      char *%s;\n" n;
8718               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8719           | OptString n ->
8720               (* http://www.perlmonks.org/?node_id=554277
8721                * Note that the implicit handle argument means we have
8722                * to add 1 to the ST(x) operator.
8723                *)
8724               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8725           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8726           | Bool n -> pr "      int %s;\n" n
8727           | Int n -> pr "      int %s;\n" n
8728           | Int64 n -> pr "      int64_t %s;\n" n
8729       ) (snd style);
8730
8731       let do_cleanups () =
8732         List.iter (
8733           function
8734           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8735           | Bool _ | Int _ | Int64 _
8736           | FileIn _ | FileOut _
8737           | BufferIn _ -> ()
8738           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8739         ) (snd style)
8740       in
8741
8742       (* Code. *)
8743       (match fst style with
8744        | RErr ->
8745            pr "PREINIT:\n";
8746            pr "      int r;\n";
8747            pr " PPCODE:\n";
8748            pr "      r = guestfs_%s " name;
8749            generate_c_call_args ~handle:"g" style;
8750            pr ";\n";
8751            do_cleanups ();
8752            pr "      if (r == -1)\n";
8753            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8754        | RInt n
8755        | RBool n ->
8756            pr "PREINIT:\n";
8757            pr "      int %s;\n" n;
8758            pr "   CODE:\n";
8759            pr "      %s = guestfs_%s " n name;
8760            generate_c_call_args ~handle:"g" style;
8761            pr ";\n";
8762            do_cleanups ();
8763            pr "      if (%s == -1)\n" n;
8764            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8765            pr "      RETVAL = newSViv (%s);\n" n;
8766            pr " OUTPUT:\n";
8767            pr "      RETVAL\n"
8768        | RInt64 n ->
8769            pr "PREINIT:\n";
8770            pr "      int64_t %s;\n" n;
8771            pr "   CODE:\n";
8772            pr "      %s = guestfs_%s " n name;
8773            generate_c_call_args ~handle:"g" style;
8774            pr ";\n";
8775            do_cleanups ();
8776            pr "      if (%s == -1)\n" n;
8777            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8778            pr "      RETVAL = my_newSVll (%s);\n" n;
8779            pr " OUTPUT:\n";
8780            pr "      RETVAL\n"
8781        | RConstString n ->
8782            pr "PREINIT:\n";
8783            pr "      const char *%s;\n" n;
8784            pr "   CODE:\n";
8785            pr "      %s = guestfs_%s " n name;
8786            generate_c_call_args ~handle:"g" style;
8787            pr ";\n";
8788            do_cleanups ();
8789            pr "      if (%s == NULL)\n" n;
8790            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8791            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8792            pr " OUTPUT:\n";
8793            pr "      RETVAL\n"
8794        | RConstOptString n ->
8795            pr "PREINIT:\n";
8796            pr "      const char *%s;\n" n;
8797            pr "   CODE:\n";
8798            pr "      %s = guestfs_%s " n name;
8799            generate_c_call_args ~handle:"g" style;
8800            pr ";\n";
8801            do_cleanups ();
8802            pr "      if (%s == NULL)\n" n;
8803            pr "        RETVAL = &PL_sv_undef;\n";
8804            pr "      else\n";
8805            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8806            pr " OUTPUT:\n";
8807            pr "      RETVAL\n"
8808        | RString n ->
8809            pr "PREINIT:\n";
8810            pr "      char *%s;\n" n;
8811            pr "   CODE:\n";
8812            pr "      %s = guestfs_%s " n name;
8813            generate_c_call_args ~handle:"g" style;
8814            pr ";\n";
8815            do_cleanups ();
8816            pr "      if (%s == NULL)\n" n;
8817            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8818            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8819            pr "      free (%s);\n" n;
8820            pr " OUTPUT:\n";
8821            pr "      RETVAL\n"
8822        | RStringList n | RHashtable n ->
8823            pr "PREINIT:\n";
8824            pr "      char **%s;\n" n;
8825            pr "      int i, n;\n";
8826            pr " PPCODE:\n";
8827            pr "      %s = guestfs_%s " n name;
8828            generate_c_call_args ~handle:"g" style;
8829            pr ";\n";
8830            do_cleanups ();
8831            pr "      if (%s == NULL)\n" n;
8832            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8833            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8834            pr "      EXTEND (SP, n);\n";
8835            pr "      for (i = 0; i < n; ++i) {\n";
8836            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8837            pr "        free (%s[i]);\n" n;
8838            pr "      }\n";
8839            pr "      free (%s);\n" n;
8840        | RStruct (n, typ) ->
8841            let cols = cols_of_struct typ in
8842            generate_perl_struct_code typ cols name style n do_cleanups
8843        | RStructList (n, typ) ->
8844            let cols = cols_of_struct typ in
8845            generate_perl_struct_list_code typ cols name style n do_cleanups
8846        | RBufferOut n ->
8847            pr "PREINIT:\n";
8848            pr "      char *%s;\n" n;
8849            pr "      size_t size;\n";
8850            pr "   CODE:\n";
8851            pr "      %s = guestfs_%s " n name;
8852            generate_c_call_args ~handle:"g" style;
8853            pr ";\n";
8854            do_cleanups ();
8855            pr "      if (%s == NULL)\n" n;
8856            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8857            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8858            pr "      free (%s);\n" n;
8859            pr " OUTPUT:\n";
8860            pr "      RETVAL\n"
8861       );
8862
8863       pr "\n"
8864   ) all_functions
8865
8866 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8867   pr "PREINIT:\n";
8868   pr "      struct guestfs_%s_list *%s;\n" typ n;
8869   pr "      int i;\n";
8870   pr "      HV *hv;\n";
8871   pr " PPCODE:\n";
8872   pr "      %s = guestfs_%s " n name;
8873   generate_c_call_args ~handle:"g" style;
8874   pr ";\n";
8875   do_cleanups ();
8876   pr "      if (%s == NULL)\n" n;
8877   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8878   pr "      EXTEND (SP, %s->len);\n" n;
8879   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8880   pr "        hv = newHV ();\n";
8881   List.iter (
8882     function
8883     | name, FString ->
8884         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8885           name (String.length name) n name
8886     | name, FUUID ->
8887         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8888           name (String.length name) n name
8889     | name, FBuffer ->
8890         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8891           name (String.length name) n name n name
8892     | name, (FBytes|FUInt64) ->
8893         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8894           name (String.length name) n name
8895     | name, FInt64 ->
8896         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8897           name (String.length name) n name
8898     | name, (FInt32|FUInt32) ->
8899         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8900           name (String.length name) n name
8901     | name, FChar ->
8902         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8903           name (String.length name) n name
8904     | name, FOptPercent ->
8905         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8906           name (String.length name) n name
8907   ) cols;
8908   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8909   pr "      }\n";
8910   pr "      guestfs_free_%s_list (%s);\n" typ n
8911
8912 and generate_perl_struct_code typ cols name style n do_cleanups =
8913   pr "PREINIT:\n";
8914   pr "      struct guestfs_%s *%s;\n" typ n;
8915   pr " PPCODE:\n";
8916   pr "      %s = guestfs_%s " n name;
8917   generate_c_call_args ~handle:"g" style;
8918   pr ";\n";
8919   do_cleanups ();
8920   pr "      if (%s == NULL)\n" n;
8921   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8922   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8923   List.iter (
8924     fun ((name, _) as col) ->
8925       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8926
8927       match col with
8928       | name, FString ->
8929           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8930             n name
8931       | name, FBuffer ->
8932           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8933             n name n name
8934       | name, FUUID ->
8935           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8936             n name
8937       | name, (FBytes|FUInt64) ->
8938           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8939             n name
8940       | name, FInt64 ->
8941           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8942             n name
8943       | name, (FInt32|FUInt32) ->
8944           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8945             n name
8946       | name, FChar ->
8947           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8948             n name
8949       | name, FOptPercent ->
8950           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8951             n name
8952   ) cols;
8953   pr "      free (%s);\n" n
8954
8955 (* Generate Sys/Guestfs.pm. *)
8956 and generate_perl_pm () =
8957   generate_header HashStyle LGPLv2plus;
8958
8959   pr "\
8960 =pod
8961
8962 =head1 NAME
8963
8964 Sys::Guestfs - Perl bindings for libguestfs
8965
8966 =head1 SYNOPSIS
8967
8968  use Sys::Guestfs;
8969
8970  my $h = Sys::Guestfs->new ();
8971  $h->add_drive ('guest.img');
8972  $h->launch ();
8973  $h->mount ('/dev/sda1', '/');
8974  $h->touch ('/hello');
8975  $h->sync ();
8976
8977 =head1 DESCRIPTION
8978
8979 The C<Sys::Guestfs> module provides a Perl XS binding to the
8980 libguestfs API for examining and modifying virtual machine
8981 disk images.
8982
8983 Amongst the things this is good for: making batch configuration
8984 changes to guests, getting disk used/free statistics (see also:
8985 virt-df), migrating between virtualization systems (see also:
8986 virt-p2v), performing partial backups, performing partial guest
8987 clones, cloning guests and changing registry/UUID/hostname info, and
8988 much else besides.
8989
8990 Libguestfs uses Linux kernel and qemu code, and can access any type of
8991 guest filesystem that Linux and qemu can, including but not limited
8992 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8993 schemes, qcow, qcow2, vmdk.
8994
8995 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8996 LVs, what filesystem is in each LV, etc.).  It can also run commands
8997 in the context of the guest.  Also you can access filesystems over
8998 FUSE.
8999
9000 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9001 functions for using libguestfs from Perl, including integration
9002 with libvirt.
9003
9004 =head1 ERRORS
9005
9006 All errors turn into calls to C<croak> (see L<Carp(3)>).
9007
9008 =head1 METHODS
9009
9010 =over 4
9011
9012 =cut
9013
9014 package Sys::Guestfs;
9015
9016 use strict;
9017 use warnings;
9018
9019 # This version number changes whenever a new function
9020 # is added to the libguestfs API.  It is not directly
9021 # related to the libguestfs version number.
9022 use vars qw($VERSION);
9023 $VERSION = '0.%d';
9024
9025 require XSLoader;
9026 XSLoader::load ('Sys::Guestfs');
9027
9028 =item $h = Sys::Guestfs->new ();
9029
9030 Create a new guestfs handle.
9031
9032 =cut
9033
9034 sub new {
9035   my $proto = shift;
9036   my $class = ref ($proto) || $proto;
9037
9038   my $self = Sys::Guestfs::_create ();
9039   bless $self, $class;
9040   return $self;
9041 }
9042
9043 " max_proc_nr;
9044
9045   (* Actions.  We only need to print documentation for these as
9046    * they are pulled in from the XS code automatically.
9047    *)
9048   List.iter (
9049     fun (name, style, _, flags, _, _, longdesc) ->
9050       if not (List.mem NotInDocs flags) then (
9051         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9052         pr "=item ";
9053         generate_perl_prototype name style;
9054         pr "\n\n";
9055         pr "%s\n\n" longdesc;
9056         if List.mem ProtocolLimitWarning flags then
9057           pr "%s\n\n" protocol_limit_warning;
9058         if List.mem DangerWillRobinson flags then
9059           pr "%s\n\n" danger_will_robinson;
9060         match deprecation_notice flags with
9061         | None -> ()
9062         | Some txt -> pr "%s\n\n" txt
9063       )
9064   ) all_functions_sorted;
9065
9066   (* End of file. *)
9067   pr "\
9068 =cut
9069
9070 1;
9071
9072 =back
9073
9074 =head1 COPYRIGHT
9075
9076 Copyright (C) %s Red Hat Inc.
9077
9078 =head1 LICENSE
9079
9080 Please see the file COPYING.LIB for the full license.
9081
9082 =head1 SEE ALSO
9083
9084 L<guestfs(3)>,
9085 L<guestfish(1)>,
9086 L<http://libguestfs.org>,
9087 L<Sys::Guestfs::Lib(3)>.
9088
9089 =cut
9090 " copyright_years
9091
9092 and generate_perl_prototype name style =
9093   (match fst style with
9094    | RErr -> ()
9095    | RBool n
9096    | RInt n
9097    | RInt64 n
9098    | RConstString n
9099    | RConstOptString n
9100    | RString n
9101    | RBufferOut n -> pr "$%s = " n
9102    | RStruct (n,_)
9103    | RHashtable n -> pr "%%%s = " n
9104    | RStringList n
9105    | RStructList (n,_) -> pr "@%s = " n
9106   );
9107   pr "$h->%s (" name;
9108   let comma = ref false in
9109   List.iter (
9110     fun arg ->
9111       if !comma then pr ", ";
9112       comma := true;
9113       match arg with
9114       | Pathname n | Device n | Dev_or_Path n | String n
9115       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9116       | BufferIn n ->
9117           pr "$%s" n
9118       | StringList n | DeviceList n ->
9119           pr "\\@%s" n
9120   ) (snd style);
9121   pr ");"
9122
9123 (* Generate Python C module. *)
9124 and generate_python_c () =
9125   generate_header CStyle LGPLv2plus;
9126
9127   pr "\
9128 #define PY_SSIZE_T_CLEAN 1
9129 #include <Python.h>
9130
9131 #if PY_VERSION_HEX < 0x02050000
9132 typedef int Py_ssize_t;
9133 #define PY_SSIZE_T_MAX INT_MAX
9134 #define PY_SSIZE_T_MIN INT_MIN
9135 #endif
9136
9137 #include <stdio.h>
9138 #include <stdlib.h>
9139 #include <assert.h>
9140
9141 #include \"guestfs.h\"
9142
9143 typedef struct {
9144   PyObject_HEAD
9145   guestfs_h *g;
9146 } Pyguestfs_Object;
9147
9148 static guestfs_h *
9149 get_handle (PyObject *obj)
9150 {
9151   assert (obj);
9152   assert (obj != Py_None);
9153   return ((Pyguestfs_Object *) obj)->g;
9154 }
9155
9156 static PyObject *
9157 put_handle (guestfs_h *g)
9158 {
9159   assert (g);
9160   return
9161     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9162 }
9163
9164 /* This list should be freed (but not the strings) after use. */
9165 static char **
9166 get_string_list (PyObject *obj)
9167 {
9168   int i, len;
9169   char **r;
9170
9171   assert (obj);
9172
9173   if (!PyList_Check (obj)) {
9174     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9175     return NULL;
9176   }
9177
9178   len = PyList_Size (obj);
9179   r = malloc (sizeof (char *) * (len+1));
9180   if (r == NULL) {
9181     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9182     return NULL;
9183   }
9184
9185   for (i = 0; i < len; ++i)
9186     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9187   r[len] = NULL;
9188
9189   return r;
9190 }
9191
9192 static PyObject *
9193 put_string_list (char * const * const argv)
9194 {
9195   PyObject *list;
9196   int argc, i;
9197
9198   for (argc = 0; argv[argc] != NULL; ++argc)
9199     ;
9200
9201   list = PyList_New (argc);
9202   for (i = 0; i < argc; ++i)
9203     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9204
9205   return list;
9206 }
9207
9208 static PyObject *
9209 put_table (char * const * const argv)
9210 {
9211   PyObject *list, *item;
9212   int argc, i;
9213
9214   for (argc = 0; argv[argc] != NULL; ++argc)
9215     ;
9216
9217   list = PyList_New (argc >> 1);
9218   for (i = 0; i < argc; i += 2) {
9219     item = PyTuple_New (2);
9220     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9221     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9222     PyList_SetItem (list, i >> 1, item);
9223   }
9224
9225   return list;
9226 }
9227
9228 static void
9229 free_strings (char **argv)
9230 {
9231   int argc;
9232
9233   for (argc = 0; argv[argc] != NULL; ++argc)
9234     free (argv[argc]);
9235   free (argv);
9236 }
9237
9238 static PyObject *
9239 py_guestfs_create (PyObject *self, PyObject *args)
9240 {
9241   guestfs_h *g;
9242
9243   g = guestfs_create ();
9244   if (g == NULL) {
9245     PyErr_SetString (PyExc_RuntimeError,
9246                      \"guestfs.create: failed to allocate handle\");
9247     return NULL;
9248   }
9249   guestfs_set_error_handler (g, NULL, NULL);
9250   return put_handle (g);
9251 }
9252
9253 static PyObject *
9254 py_guestfs_close (PyObject *self, PyObject *args)
9255 {
9256   PyObject *py_g;
9257   guestfs_h *g;
9258
9259   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9260     return NULL;
9261   g = get_handle (py_g);
9262
9263   guestfs_close (g);
9264
9265   Py_INCREF (Py_None);
9266   return Py_None;
9267 }
9268
9269 ";
9270
9271   let emit_put_list_function typ =
9272     pr "static PyObject *\n";
9273     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9274     pr "{\n";
9275     pr "  PyObject *list;\n";
9276     pr "  int i;\n";
9277     pr "\n";
9278     pr "  list = PyList_New (%ss->len);\n" typ;
9279     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9280     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9281     pr "  return list;\n";
9282     pr "};\n";
9283     pr "\n"
9284   in
9285
9286   (* Structures, turned into Python dictionaries. *)
9287   List.iter (
9288     fun (typ, cols) ->
9289       pr "static PyObject *\n";
9290       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9291       pr "{\n";
9292       pr "  PyObject *dict;\n";
9293       pr "\n";
9294       pr "  dict = PyDict_New ();\n";
9295       List.iter (
9296         function
9297         | name, FString ->
9298             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9299             pr "                        PyString_FromString (%s->%s));\n"
9300               typ name
9301         | name, FBuffer ->
9302             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9303             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9304               typ name typ name
9305         | name, FUUID ->
9306             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9307             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9308               typ name
9309         | name, (FBytes|FUInt64) ->
9310             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9311             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9312               typ name
9313         | name, FInt64 ->
9314             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9315             pr "                        PyLong_FromLongLong (%s->%s));\n"
9316               typ name
9317         | name, FUInt32 ->
9318             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9319             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9320               typ name
9321         | name, FInt32 ->
9322             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9323             pr "                        PyLong_FromLong (%s->%s));\n"
9324               typ name
9325         | name, FOptPercent ->
9326             pr "  if (%s->%s >= 0)\n" typ name;
9327             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9328             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9329               typ name;
9330             pr "  else {\n";
9331             pr "    Py_INCREF (Py_None);\n";
9332             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9333             pr "  }\n"
9334         | name, FChar ->
9335             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9336             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9337       ) cols;
9338       pr "  return dict;\n";
9339       pr "};\n";
9340       pr "\n";
9341
9342   ) structs;
9343
9344   (* Emit a put_TYPE_list function definition only if that function is used. *)
9345   List.iter (
9346     function
9347     | typ, (RStructListOnly | RStructAndList) ->
9348         (* generate the function for typ *)
9349         emit_put_list_function typ
9350     | typ, _ -> () (* empty *)
9351   ) (rstructs_used_by all_functions);
9352
9353   (* Python wrapper functions. *)
9354   List.iter (
9355     fun (name, style, _, _, _, _, _) ->
9356       pr "static PyObject *\n";
9357       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9358       pr "{\n";
9359
9360       pr "  PyObject *py_g;\n";
9361       pr "  guestfs_h *g;\n";
9362       pr "  PyObject *py_r;\n";
9363
9364       let error_code =
9365         match fst style with
9366         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9367         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9368         | RConstString _ | RConstOptString _ ->
9369             pr "  const char *r;\n"; "NULL"
9370         | RString _ -> pr "  char *r;\n"; "NULL"
9371         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9372         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9373         | RStructList (_, typ) ->
9374             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9375         | RBufferOut _ ->
9376             pr "  char *r;\n";
9377             pr "  size_t size;\n";
9378             "NULL" in
9379
9380       List.iter (
9381         function
9382         | Pathname n | Device n | Dev_or_Path n | String n
9383         | FileIn n | FileOut n ->
9384             pr "  const char *%s;\n" n
9385         | OptString n -> pr "  const char *%s;\n" n
9386         | BufferIn n ->
9387             pr "  const char *%s;\n" n;
9388             pr "  Py_ssize_t %s_size;\n" n
9389         | StringList n | DeviceList n ->
9390             pr "  PyObject *py_%s;\n" n;
9391             pr "  char **%s;\n" n
9392         | Bool n -> pr "  int %s;\n" n
9393         | Int n -> pr "  int %s;\n" n
9394         | Int64 n -> pr "  long long %s;\n" n
9395       ) (snd style);
9396
9397       pr "\n";
9398
9399       (* Convert the parameters. *)
9400       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9401       List.iter (
9402         function
9403         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9404         | OptString _ -> pr "z"
9405         | StringList _ | DeviceList _ -> pr "O"
9406         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9407         | Int _ -> pr "i"
9408         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9409                              * emulate C's int/long/long long in Python?
9410                              *)
9411         | BufferIn _ -> pr "s#"
9412       ) (snd style);
9413       pr ":guestfs_%s\",\n" name;
9414       pr "                         &py_g";
9415       List.iter (
9416         function
9417         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9418         | OptString n -> pr ", &%s" n
9419         | StringList n | DeviceList n -> pr ", &py_%s" n
9420         | Bool n -> pr ", &%s" n
9421         | Int n -> pr ", &%s" n
9422         | Int64 n -> pr ", &%s" n
9423         | BufferIn n -> pr ", &%s, &%s_size" n n
9424       ) (snd style);
9425
9426       pr "))\n";
9427       pr "    return NULL;\n";
9428
9429       pr "  g = get_handle (py_g);\n";
9430       List.iter (
9431         function
9432         | Pathname _ | Device _ | Dev_or_Path _ | String _
9433         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9434         | BufferIn _ -> ()
9435         | StringList n | DeviceList n ->
9436             pr "  %s = get_string_list (py_%s);\n" n n;
9437             pr "  if (!%s) return NULL;\n" n
9438       ) (snd style);
9439
9440       pr "\n";
9441
9442       pr "  r = guestfs_%s " name;
9443       generate_c_call_args ~handle:"g" style;
9444       pr ";\n";
9445
9446       List.iter (
9447         function
9448         | Pathname _ | Device _ | Dev_or_Path _ | String _
9449         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9450         | BufferIn _ -> ()
9451         | StringList n | DeviceList n ->
9452             pr "  free (%s);\n" n
9453       ) (snd style);
9454
9455       pr "  if (r == %s) {\n" error_code;
9456       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9457       pr "    return NULL;\n";
9458       pr "  }\n";
9459       pr "\n";
9460
9461       (match fst style with
9462        | RErr ->
9463            pr "  Py_INCREF (Py_None);\n";
9464            pr "  py_r = Py_None;\n"
9465        | RInt _
9466        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9467        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9468        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9469        | RConstOptString _ ->
9470            pr "  if (r)\n";
9471            pr "    py_r = PyString_FromString (r);\n";
9472            pr "  else {\n";
9473            pr "    Py_INCREF (Py_None);\n";
9474            pr "    py_r = Py_None;\n";
9475            pr "  }\n"
9476        | RString _ ->
9477            pr "  py_r = PyString_FromString (r);\n";
9478            pr "  free (r);\n"
9479        | RStringList _ ->
9480            pr "  py_r = put_string_list (r);\n";
9481            pr "  free_strings (r);\n"
9482        | RStruct (_, typ) ->
9483            pr "  py_r = put_%s (r);\n" typ;
9484            pr "  guestfs_free_%s (r);\n" typ
9485        | RStructList (_, typ) ->
9486            pr "  py_r = put_%s_list (r);\n" typ;
9487            pr "  guestfs_free_%s_list (r);\n" typ
9488        | RHashtable n ->
9489            pr "  py_r = put_table (r);\n";
9490            pr "  free_strings (r);\n"
9491        | RBufferOut _ ->
9492            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9493            pr "  free (r);\n"
9494       );
9495
9496       pr "  return py_r;\n";
9497       pr "}\n";
9498       pr "\n"
9499   ) all_functions;
9500
9501   (* Table of functions. *)
9502   pr "static PyMethodDef methods[] = {\n";
9503   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9504   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9505   List.iter (
9506     fun (name, _, _, _, _, _, _) ->
9507       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9508         name name
9509   ) all_functions;
9510   pr "  { NULL, NULL, 0, NULL }\n";
9511   pr "};\n";
9512   pr "\n";
9513
9514   (* Init function. *)
9515   pr "\
9516 void
9517 initlibguestfsmod (void)
9518 {
9519   static int initialized = 0;
9520
9521   if (initialized) return;
9522   Py_InitModule ((char *) \"libguestfsmod\", methods);
9523   initialized = 1;
9524 }
9525 "
9526
9527 (* Generate Python module. *)
9528 and generate_python_py () =
9529   generate_header HashStyle LGPLv2plus;
9530
9531   pr "\
9532 u\"\"\"Python bindings for libguestfs
9533
9534 import guestfs
9535 g = guestfs.GuestFS ()
9536 g.add_drive (\"guest.img\")
9537 g.launch ()
9538 parts = g.list_partitions ()
9539
9540 The guestfs module provides a Python binding to the libguestfs API
9541 for examining and modifying virtual machine disk images.
9542
9543 Amongst the things this is good for: making batch configuration
9544 changes to guests, getting disk used/free statistics (see also:
9545 virt-df), migrating between virtualization systems (see also:
9546 virt-p2v), performing partial backups, performing partial guest
9547 clones, cloning guests and changing registry/UUID/hostname info, and
9548 much else besides.
9549
9550 Libguestfs uses Linux kernel and qemu code, and can access any type of
9551 guest filesystem that Linux and qemu can, including but not limited
9552 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9553 schemes, qcow, qcow2, vmdk.
9554
9555 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9556 LVs, what filesystem is in each LV, etc.).  It can also run commands
9557 in the context of the guest.  Also you can access filesystems over
9558 FUSE.
9559
9560 Errors which happen while using the API are turned into Python
9561 RuntimeError exceptions.
9562
9563 To create a guestfs handle you usually have to perform the following
9564 sequence of calls:
9565
9566 # Create the handle, call add_drive at least once, and possibly
9567 # several times if the guest has multiple block devices:
9568 g = guestfs.GuestFS ()
9569 g.add_drive (\"guest.img\")
9570
9571 # Launch the qemu subprocess and wait for it to become ready:
9572 g.launch ()
9573
9574 # Now you can issue commands, for example:
9575 logvols = g.lvs ()
9576
9577 \"\"\"
9578
9579 import libguestfsmod
9580
9581 class GuestFS:
9582     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9583
9584     def __init__ (self):
9585         \"\"\"Create a new libguestfs handle.\"\"\"
9586         self._o = libguestfsmod.create ()
9587
9588     def __del__ (self):
9589         libguestfsmod.close (self._o)
9590
9591 ";
9592
9593   List.iter (
9594     fun (name, style, _, flags, _, _, longdesc) ->
9595       pr "    def %s " name;
9596       generate_py_call_args ~handle:"self" (snd style);
9597       pr ":\n";
9598
9599       if not (List.mem NotInDocs flags) then (
9600         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9601         let doc =
9602           match fst style with
9603           | RErr | RInt _ | RInt64 _ | RBool _
9604           | RConstOptString _ | RConstString _
9605           | RString _ | RBufferOut _ -> doc
9606           | RStringList _ ->
9607               doc ^ "\n\nThis function returns a list of strings."
9608           | RStruct (_, typ) ->
9609               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9610           | RStructList (_, typ) ->
9611               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9612           | RHashtable _ ->
9613               doc ^ "\n\nThis function returns a dictionary." in
9614         let doc =
9615           if List.mem ProtocolLimitWarning flags then
9616             doc ^ "\n\n" ^ protocol_limit_warning
9617           else doc in
9618         let doc =
9619           if List.mem DangerWillRobinson flags then
9620             doc ^ "\n\n" ^ danger_will_robinson
9621           else doc in
9622         let doc =
9623           match deprecation_notice flags with
9624           | None -> doc
9625           | Some txt -> doc ^ "\n\n" ^ txt in
9626         let doc = pod2text ~width:60 name doc in
9627         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9628         let doc = String.concat "\n        " doc in
9629         pr "        u\"\"\"%s\"\"\"\n" doc;
9630       );
9631       pr "        return libguestfsmod.%s " name;
9632       generate_py_call_args ~handle:"self._o" (snd style);
9633       pr "\n";
9634       pr "\n";
9635   ) all_functions
9636
9637 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9638 and generate_py_call_args ~handle args =
9639   pr "(%s" handle;
9640   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9641   pr ")"
9642
9643 (* Useful if you need the longdesc POD text as plain text.  Returns a
9644  * list of lines.
9645  *
9646  * Because this is very slow (the slowest part of autogeneration),
9647  * we memoize the results.
9648  *)
9649 and pod2text ~width name longdesc =
9650   let key = width, name, longdesc in
9651   try Hashtbl.find pod2text_memo key
9652   with Not_found ->
9653     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9654     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9655     close_out chan;
9656     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9657     let chan = open_process_in cmd in
9658     let lines = ref [] in
9659     let rec loop i =
9660       let line = input_line chan in
9661       if i = 1 then             (* discard the first line of output *)
9662         loop (i+1)
9663       else (
9664         let line = triml line in
9665         lines := line :: !lines;
9666         loop (i+1)
9667       ) in
9668     let lines = try loop 1 with End_of_file -> List.rev !lines in
9669     unlink filename;
9670     (match close_process_in chan with
9671      | WEXITED 0 -> ()
9672      | WEXITED i ->
9673          failwithf "pod2text: process exited with non-zero status (%d)" i
9674      | WSIGNALED i | WSTOPPED i ->
9675          failwithf "pod2text: process signalled or stopped by signal %d" i
9676     );
9677     Hashtbl.add pod2text_memo key lines;
9678     pod2text_memo_updated ();
9679     lines
9680
9681 (* Generate ruby bindings. *)
9682 and generate_ruby_c () =
9683   generate_header CStyle LGPLv2plus;
9684
9685   pr "\
9686 #include <stdio.h>
9687 #include <stdlib.h>
9688
9689 #include <ruby.h>
9690
9691 #include \"guestfs.h\"
9692
9693 #include \"extconf.h\"
9694
9695 /* For Ruby < 1.9 */
9696 #ifndef RARRAY_LEN
9697 #define RARRAY_LEN(r) (RARRAY((r))->len)
9698 #endif
9699
9700 static VALUE m_guestfs;                 /* guestfs module */
9701 static VALUE c_guestfs;                 /* guestfs_h handle */
9702 static VALUE e_Error;                   /* used for all errors */
9703
9704 static void ruby_guestfs_free (void *p)
9705 {
9706   if (!p) return;
9707   guestfs_close ((guestfs_h *) p);
9708 }
9709
9710 static VALUE ruby_guestfs_create (VALUE m)
9711 {
9712   guestfs_h *g;
9713
9714   g = guestfs_create ();
9715   if (!g)
9716     rb_raise (e_Error, \"failed to create guestfs handle\");
9717
9718   /* Don't print error messages to stderr by default. */
9719   guestfs_set_error_handler (g, NULL, NULL);
9720
9721   /* Wrap it, and make sure the close function is called when the
9722    * handle goes away.
9723    */
9724   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9725 }
9726
9727 static VALUE ruby_guestfs_close (VALUE gv)
9728 {
9729   guestfs_h *g;
9730   Data_Get_Struct (gv, guestfs_h, g);
9731
9732   ruby_guestfs_free (g);
9733   DATA_PTR (gv) = NULL;
9734
9735   return Qnil;
9736 }
9737
9738 ";
9739
9740   List.iter (
9741     fun (name, style, _, _, _, _, _) ->
9742       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9743       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9744       pr ")\n";
9745       pr "{\n";
9746       pr "  guestfs_h *g;\n";
9747       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9748       pr "  if (!g)\n";
9749       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9750         name;
9751       pr "\n";
9752
9753       List.iter (
9754         function
9755         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9756             pr "  Check_Type (%sv, T_STRING);\n" n;
9757             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9758             pr "  if (!%s)\n" n;
9759             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9760             pr "              \"%s\", \"%s\");\n" n name
9761         | BufferIn n ->
9762             pr "  Check_Type (%sv, T_STRING);\n" n;
9763             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9764             pr "  if (!%s)\n" n;
9765             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9766             pr "              \"%s\", \"%s\");\n" n name;
9767             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9768         | OptString n ->
9769             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9770         | StringList n | DeviceList n ->
9771             pr "  char **%s;\n" n;
9772             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9773             pr "  {\n";
9774             pr "    int i, len;\n";
9775             pr "    len = RARRAY_LEN (%sv);\n" n;
9776             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9777               n;
9778             pr "    for (i = 0; i < len; ++i) {\n";
9779             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9780             pr "      %s[i] = StringValueCStr (v);\n" n;
9781             pr "    }\n";
9782             pr "    %s[len] = NULL;\n" n;
9783             pr "  }\n";
9784         | Bool n ->
9785             pr "  int %s = RTEST (%sv);\n" n n
9786         | Int n ->
9787             pr "  int %s = NUM2INT (%sv);\n" n n
9788         | Int64 n ->
9789             pr "  long long %s = NUM2LL (%sv);\n" n n
9790       ) (snd style);
9791       pr "\n";
9792
9793       let error_code =
9794         match fst style with
9795         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9796         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9797         | RConstString _ | RConstOptString _ ->
9798             pr "  const char *r;\n"; "NULL"
9799         | RString _ -> pr "  char *r;\n"; "NULL"
9800         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9801         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9802         | RStructList (_, typ) ->
9803             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9804         | RBufferOut _ ->
9805             pr "  char *r;\n";
9806             pr "  size_t size;\n";
9807             "NULL" in
9808       pr "\n";
9809
9810       pr "  r = guestfs_%s " name;
9811       generate_c_call_args ~handle:"g" style;
9812       pr ";\n";
9813
9814       List.iter (
9815         function
9816         | Pathname _ | Device _ | Dev_or_Path _ | String _
9817         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9818         | BufferIn _ -> ()
9819         | StringList n | DeviceList n ->
9820             pr "  free (%s);\n" n
9821       ) (snd style);
9822
9823       pr "  if (r == %s)\n" error_code;
9824       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9825       pr "\n";
9826
9827       (match fst style with
9828        | RErr ->
9829            pr "  return Qnil;\n"
9830        | RInt _ | RBool _ ->
9831            pr "  return INT2NUM (r);\n"
9832        | RInt64 _ ->
9833            pr "  return ULL2NUM (r);\n"
9834        | RConstString _ ->
9835            pr "  return rb_str_new2 (r);\n";
9836        | RConstOptString _ ->
9837            pr "  if (r)\n";
9838            pr "    return rb_str_new2 (r);\n";
9839            pr "  else\n";
9840            pr "    return Qnil;\n";
9841        | RString _ ->
9842            pr "  VALUE rv = rb_str_new2 (r);\n";
9843            pr "  free (r);\n";
9844            pr "  return rv;\n";
9845        | RStringList _ ->
9846            pr "  int i, len = 0;\n";
9847            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9848            pr "  VALUE rv = rb_ary_new2 (len);\n";
9849            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9850            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9851            pr "    free (r[i]);\n";
9852            pr "  }\n";
9853            pr "  free (r);\n";
9854            pr "  return rv;\n"
9855        | RStruct (_, typ) ->
9856            let cols = cols_of_struct typ in
9857            generate_ruby_struct_code typ cols
9858        | RStructList (_, typ) ->
9859            let cols = cols_of_struct typ in
9860            generate_ruby_struct_list_code typ cols
9861        | RHashtable _ ->
9862            pr "  VALUE rv = rb_hash_new ();\n";
9863            pr "  int i;\n";
9864            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9865            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9866            pr "    free (r[i]);\n";
9867            pr "    free (r[i+1]);\n";
9868            pr "  }\n";
9869            pr "  free (r);\n";
9870            pr "  return rv;\n"
9871        | RBufferOut _ ->
9872            pr "  VALUE rv = rb_str_new (r, size);\n";
9873            pr "  free (r);\n";
9874            pr "  return rv;\n";
9875       );
9876
9877       pr "}\n";
9878       pr "\n"
9879   ) all_functions;
9880
9881   pr "\
9882 /* Initialize the module. */
9883 void Init__guestfs ()
9884 {
9885   m_guestfs = rb_define_module (\"Guestfs\");
9886   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9887   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9888
9889   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9890   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9891
9892 ";
9893   (* Define the rest of the methods. *)
9894   List.iter (
9895     fun (name, style, _, _, _, _, _) ->
9896       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9897       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9898   ) all_functions;
9899
9900   pr "}\n"
9901
9902 (* Ruby code to return a struct. *)
9903 and generate_ruby_struct_code typ cols =
9904   pr "  VALUE rv = rb_hash_new ();\n";
9905   List.iter (
9906     function
9907     | name, FString ->
9908         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9909     | name, FBuffer ->
9910         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9911     | name, FUUID ->
9912         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9913     | name, (FBytes|FUInt64) ->
9914         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9915     | name, FInt64 ->
9916         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9917     | name, FUInt32 ->
9918         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9919     | name, FInt32 ->
9920         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9921     | name, FOptPercent ->
9922         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9923     | name, FChar -> (* XXX wrong? *)
9924         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9925   ) cols;
9926   pr "  guestfs_free_%s (r);\n" typ;
9927   pr "  return rv;\n"
9928
9929 (* Ruby code to return a struct list. *)
9930 and generate_ruby_struct_list_code typ cols =
9931   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9932   pr "  int i;\n";
9933   pr "  for (i = 0; i < r->len; ++i) {\n";
9934   pr "    VALUE hv = rb_hash_new ();\n";
9935   List.iter (
9936     function
9937     | name, FString ->
9938         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9939     | name, FBuffer ->
9940         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
9941     | name, FUUID ->
9942         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9943     | name, (FBytes|FUInt64) ->
9944         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9945     | name, FInt64 ->
9946         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9947     | name, FUInt32 ->
9948         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9949     | name, FInt32 ->
9950         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9951     | name, FOptPercent ->
9952         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9953     | name, FChar -> (* XXX wrong? *)
9954         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9955   ) cols;
9956   pr "    rb_ary_push (rv, hv);\n";
9957   pr "  }\n";
9958   pr "  guestfs_free_%s_list (r);\n" typ;
9959   pr "  return rv;\n"
9960
9961 (* Generate Java bindings GuestFS.java file. *)
9962 and generate_java_java () =
9963   generate_header CStyle LGPLv2plus;
9964
9965   pr "\
9966 package com.redhat.et.libguestfs;
9967
9968 import java.util.HashMap;
9969 import com.redhat.et.libguestfs.LibGuestFSException;
9970 import com.redhat.et.libguestfs.PV;
9971 import com.redhat.et.libguestfs.VG;
9972 import com.redhat.et.libguestfs.LV;
9973 import com.redhat.et.libguestfs.Stat;
9974 import com.redhat.et.libguestfs.StatVFS;
9975 import com.redhat.et.libguestfs.IntBool;
9976 import com.redhat.et.libguestfs.Dirent;
9977
9978 /**
9979  * The GuestFS object is a libguestfs handle.
9980  *
9981  * @author rjones
9982  */
9983 public class GuestFS {
9984   // Load the native code.
9985   static {
9986     System.loadLibrary (\"guestfs_jni\");
9987   }
9988
9989   /**
9990    * The native guestfs_h pointer.
9991    */
9992   long g;
9993
9994   /**
9995    * Create a libguestfs handle.
9996    *
9997    * @throws LibGuestFSException
9998    */
9999   public GuestFS () throws LibGuestFSException
10000   {
10001     g = _create ();
10002   }
10003   private native long _create () throws LibGuestFSException;
10004
10005   /**
10006    * Close a libguestfs handle.
10007    *
10008    * You can also leave handles to be collected by the garbage
10009    * collector, but this method ensures that the resources used
10010    * by the handle are freed up immediately.  If you call any
10011    * other methods after closing the handle, you will get an
10012    * exception.
10013    *
10014    * @throws LibGuestFSException
10015    */
10016   public void close () throws LibGuestFSException
10017   {
10018     if (g != 0)
10019       _close (g);
10020     g = 0;
10021   }
10022   private native void _close (long g) throws LibGuestFSException;
10023
10024   public void finalize () throws LibGuestFSException
10025   {
10026     close ();
10027   }
10028
10029 ";
10030
10031   List.iter (
10032     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10033       if not (List.mem NotInDocs flags); then (
10034         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10035         let doc =
10036           if List.mem ProtocolLimitWarning flags then
10037             doc ^ "\n\n" ^ protocol_limit_warning
10038           else doc in
10039         let doc =
10040           if List.mem DangerWillRobinson flags then
10041             doc ^ "\n\n" ^ danger_will_robinson
10042           else doc in
10043         let doc =
10044           match deprecation_notice flags with
10045           | None -> doc
10046           | Some txt -> doc ^ "\n\n" ^ txt in
10047         let doc = pod2text ~width:60 name doc in
10048         let doc = List.map (            (* RHBZ#501883 *)
10049           function
10050           | "" -> "<p>"
10051           | nonempty -> nonempty
10052         ) doc in
10053         let doc = String.concat "\n   * " doc in
10054
10055         pr "  /**\n";
10056         pr "   * %s\n" shortdesc;
10057         pr "   * <p>\n";
10058         pr "   * %s\n" doc;
10059         pr "   * @throws LibGuestFSException\n";
10060         pr "   */\n";
10061         pr "  ";
10062       );
10063       generate_java_prototype ~public:true ~semicolon:false name style;
10064       pr "\n";
10065       pr "  {\n";
10066       pr "    if (g == 0)\n";
10067       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10068         name;
10069       pr "    ";
10070       if fst style <> RErr then pr "return ";
10071       pr "_%s " name;
10072       generate_java_call_args ~handle:"g" (snd style);
10073       pr ";\n";
10074       pr "  }\n";
10075       pr "  ";
10076       generate_java_prototype ~privat:true ~native:true name style;
10077       pr "\n";
10078       pr "\n";
10079   ) all_functions;
10080
10081   pr "}\n"
10082
10083 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10084 and generate_java_call_args ~handle args =
10085   pr "(%s" handle;
10086   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10087   pr ")"
10088
10089 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10090     ?(semicolon=true) name style =
10091   if privat then pr "private ";
10092   if public then pr "public ";
10093   if native then pr "native ";
10094
10095   (* return type *)
10096   (match fst style with
10097    | RErr -> pr "void ";
10098    | RInt _ -> pr "int ";
10099    | RInt64 _ -> pr "long ";
10100    | RBool _ -> pr "boolean ";
10101    | RConstString _ | RConstOptString _ | RString _
10102    | RBufferOut _ -> pr "String ";
10103    | RStringList _ -> pr "String[] ";
10104    | RStruct (_, typ) ->
10105        let name = java_name_of_struct typ in
10106        pr "%s " name;
10107    | RStructList (_, typ) ->
10108        let name = java_name_of_struct typ in
10109        pr "%s[] " name;
10110    | RHashtable _ -> pr "HashMap<String,String> ";
10111   );
10112
10113   if native then pr "_%s " name else pr "%s " name;
10114   pr "(";
10115   let needs_comma = ref false in
10116   if native then (
10117     pr "long g";
10118     needs_comma := true
10119   );
10120
10121   (* args *)
10122   List.iter (
10123     fun arg ->
10124       if !needs_comma then pr ", ";
10125       needs_comma := true;
10126
10127       match arg with
10128       | Pathname n
10129       | Device n | Dev_or_Path n
10130       | String n
10131       | OptString n
10132       | FileIn n
10133       | FileOut n ->
10134           pr "String %s" n
10135       | BufferIn n ->
10136           pr "byte[] %s" n
10137       | StringList n | DeviceList n ->
10138           pr "String[] %s" n
10139       | Bool n ->
10140           pr "boolean %s" n
10141       | Int n ->
10142           pr "int %s" n
10143       | Int64 n ->
10144           pr "long %s" n
10145   ) (snd style);
10146
10147   pr ")\n";
10148   pr "    throws LibGuestFSException";
10149   if semicolon then pr ";"
10150
10151 and generate_java_struct jtyp cols () =
10152   generate_header CStyle LGPLv2plus;
10153
10154   pr "\
10155 package com.redhat.et.libguestfs;
10156
10157 /**
10158  * Libguestfs %s structure.
10159  *
10160  * @author rjones
10161  * @see GuestFS
10162  */
10163 public class %s {
10164 " jtyp jtyp;
10165
10166   List.iter (
10167     function
10168     | name, FString
10169     | name, FUUID
10170     | name, FBuffer -> pr "  public String %s;\n" name
10171     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10172     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10173     | name, FChar -> pr "  public char %s;\n" name
10174     | name, FOptPercent ->
10175         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10176         pr "  public float %s;\n" name
10177   ) cols;
10178
10179   pr "}\n"
10180
10181 and generate_java_c () =
10182   generate_header CStyle LGPLv2plus;
10183
10184   pr "\
10185 #include <stdio.h>
10186 #include <stdlib.h>
10187 #include <string.h>
10188
10189 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10190 #include \"guestfs.h\"
10191
10192 /* Note that this function returns.  The exception is not thrown
10193  * until after the wrapper function returns.
10194  */
10195 static void
10196 throw_exception (JNIEnv *env, const char *msg)
10197 {
10198   jclass cl;
10199   cl = (*env)->FindClass (env,
10200                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10201   (*env)->ThrowNew (env, cl, msg);
10202 }
10203
10204 JNIEXPORT jlong JNICALL
10205 Java_com_redhat_et_libguestfs_GuestFS__1create
10206   (JNIEnv *env, jobject obj)
10207 {
10208   guestfs_h *g;
10209
10210   g = guestfs_create ();
10211   if (g == NULL) {
10212     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10213     return 0;
10214   }
10215   guestfs_set_error_handler (g, NULL, NULL);
10216   return (jlong) (long) g;
10217 }
10218
10219 JNIEXPORT void JNICALL
10220 Java_com_redhat_et_libguestfs_GuestFS__1close
10221   (JNIEnv *env, jobject obj, jlong jg)
10222 {
10223   guestfs_h *g = (guestfs_h *) (long) jg;
10224   guestfs_close (g);
10225 }
10226
10227 ";
10228
10229   List.iter (
10230     fun (name, style, _, _, _, _, _) ->
10231       pr "JNIEXPORT ";
10232       (match fst style with
10233        | RErr -> pr "void ";
10234        | RInt _ -> pr "jint ";
10235        | RInt64 _ -> pr "jlong ";
10236        | RBool _ -> pr "jboolean ";
10237        | RConstString _ | RConstOptString _ | RString _
10238        | RBufferOut _ -> pr "jstring ";
10239        | RStruct _ | RHashtable _ ->
10240            pr "jobject ";
10241        | RStringList _ | RStructList _ ->
10242            pr "jobjectArray ";
10243       );
10244       pr "JNICALL\n";
10245       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10246       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10247       pr "\n";
10248       pr "  (JNIEnv *env, jobject obj, jlong jg";
10249       List.iter (
10250         function
10251         | Pathname n
10252         | Device n | Dev_or_Path n
10253         | String n
10254         | OptString n
10255         | FileIn n
10256         | FileOut n ->
10257             pr ", jstring j%s" n
10258         | BufferIn n ->
10259             pr ", jbyteArray j%s" n
10260         | StringList n | DeviceList n ->
10261             pr ", jobjectArray j%s" n
10262         | Bool n ->
10263             pr ", jboolean j%s" n
10264         | Int n ->
10265             pr ", jint j%s" n
10266         | Int64 n ->
10267             pr ", jlong j%s" n
10268       ) (snd style);
10269       pr ")\n";
10270       pr "{\n";
10271       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10272       let error_code, no_ret =
10273         match fst style with
10274         | RErr -> pr "  int r;\n"; "-1", ""
10275         | RBool _
10276         | RInt _ -> pr "  int r;\n"; "-1", "0"
10277         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10278         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10279         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10280         | RString _ ->
10281             pr "  jstring jr;\n";
10282             pr "  char *r;\n"; "NULL", "NULL"
10283         | RStringList _ ->
10284             pr "  jobjectArray jr;\n";
10285             pr "  int r_len;\n";
10286             pr "  jclass cl;\n";
10287             pr "  jstring jstr;\n";
10288             pr "  char **r;\n"; "NULL", "NULL"
10289         | RStruct (_, typ) ->
10290             pr "  jobject jr;\n";
10291             pr "  jclass cl;\n";
10292             pr "  jfieldID fl;\n";
10293             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10294         | RStructList (_, typ) ->
10295             pr "  jobjectArray jr;\n";
10296             pr "  jclass cl;\n";
10297             pr "  jfieldID fl;\n";
10298             pr "  jobject jfl;\n";
10299             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10300         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10301         | RBufferOut _ ->
10302             pr "  jstring jr;\n";
10303             pr "  char *r;\n";
10304             pr "  size_t size;\n";
10305             "NULL", "NULL" in
10306       List.iter (
10307         function
10308         | Pathname n
10309         | Device n | Dev_or_Path n
10310         | String n
10311         | OptString n
10312         | FileIn n
10313         | FileOut n ->
10314             pr "  const char *%s;\n" n
10315         | BufferIn n ->
10316             pr "  jbyte *%s;\n" n;
10317             pr "  size_t %s_size;\n" n
10318         | StringList n | DeviceList n ->
10319             pr "  int %s_len;\n" n;
10320             pr "  const char **%s;\n" n
10321         | Bool n
10322         | Int n ->
10323             pr "  int %s;\n" n
10324         | Int64 n ->
10325             pr "  int64_t %s;\n" n
10326       ) (snd style);
10327
10328       let needs_i =
10329         (match fst style with
10330          | RStringList _ | RStructList _ -> true
10331          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10332          | RConstOptString _
10333          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10334           List.exists (function
10335                        | StringList _ -> true
10336                        | DeviceList _ -> true
10337                        | _ -> false) (snd style) in
10338       if needs_i then
10339         pr "  int i;\n";
10340
10341       pr "\n";
10342
10343       (* Get the parameters. *)
10344       List.iter (
10345         function
10346         | Pathname n
10347         | Device n | Dev_or_Path n
10348         | String n
10349         | FileIn n
10350         | FileOut n ->
10351             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10352         | OptString n ->
10353             (* This is completely undocumented, but Java null becomes
10354              * a NULL parameter.
10355              *)
10356             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10357         | BufferIn n ->
10358             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10359             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10360         | StringList n | DeviceList n ->
10361             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10362             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10363             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10364             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10365               n;
10366             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10367             pr "  }\n";
10368             pr "  %s[%s_len] = NULL;\n" n n;
10369         | Bool n
10370         | Int n
10371         | Int64 n ->
10372             pr "  %s = j%s;\n" n n
10373       ) (snd style);
10374
10375       (* Make the call. *)
10376       pr "  r = guestfs_%s " name;
10377       generate_c_call_args ~handle:"g" style;
10378       pr ";\n";
10379
10380       (* Release the parameters. *)
10381       List.iter (
10382         function
10383         | Pathname n
10384         | Device n | Dev_or_Path n
10385         | String n
10386         | FileIn n
10387         | FileOut n ->
10388             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10389         | OptString n ->
10390             pr "  if (j%s)\n" n;
10391             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10392         | BufferIn n ->
10393             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10394         | StringList n | DeviceList n ->
10395             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10396             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10397               n;
10398             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10399             pr "  }\n";
10400             pr "  free (%s);\n" n
10401         | Bool n
10402         | Int n
10403         | Int64 n -> ()
10404       ) (snd style);
10405
10406       (* Check for errors. *)
10407       pr "  if (r == %s) {\n" error_code;
10408       pr "    throw_exception (env, guestfs_last_error (g));\n";
10409       pr "    return %s;\n" no_ret;
10410       pr "  }\n";
10411
10412       (* Return value. *)
10413       (match fst style with
10414        | RErr -> ()
10415        | RInt _ -> pr "  return (jint) r;\n"
10416        | RBool _ -> pr "  return (jboolean) r;\n"
10417        | RInt64 _ -> pr "  return (jlong) r;\n"
10418        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10419        | RConstOptString _ ->
10420            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10421        | RString _ ->
10422            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10423            pr "  free (r);\n";
10424            pr "  return jr;\n"
10425        | RStringList _ ->
10426            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10427            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10428            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10429            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10430            pr "  for (i = 0; i < r_len; ++i) {\n";
10431            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10432            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10433            pr "    free (r[i]);\n";
10434            pr "  }\n";
10435            pr "  free (r);\n";
10436            pr "  return jr;\n"
10437        | RStruct (_, typ) ->
10438            let jtyp = java_name_of_struct typ in
10439            let cols = cols_of_struct typ in
10440            generate_java_struct_return typ jtyp cols
10441        | RStructList (_, typ) ->
10442            let jtyp = java_name_of_struct typ in
10443            let cols = cols_of_struct typ in
10444            generate_java_struct_list_return typ jtyp cols
10445        | RHashtable _ ->
10446            (* XXX *)
10447            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10448            pr "  return NULL;\n"
10449        | RBufferOut _ ->
10450            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10451            pr "  free (r);\n";
10452            pr "  return jr;\n"
10453       );
10454
10455       pr "}\n";
10456       pr "\n"
10457   ) all_functions
10458
10459 and generate_java_struct_return typ jtyp cols =
10460   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10461   pr "  jr = (*env)->AllocObject (env, cl);\n";
10462   List.iter (
10463     function
10464     | name, FString ->
10465         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10466         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10467     | name, FUUID ->
10468         pr "  {\n";
10469         pr "    char s[33];\n";
10470         pr "    memcpy (s, r->%s, 32);\n" name;
10471         pr "    s[32] = 0;\n";
10472         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10473         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10474         pr "  }\n";
10475     | name, FBuffer ->
10476         pr "  {\n";
10477         pr "    int len = r->%s_len;\n" name;
10478         pr "    char s[len+1];\n";
10479         pr "    memcpy (s, r->%s, len);\n" name;
10480         pr "    s[len] = 0;\n";
10481         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10482         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10483         pr "  }\n";
10484     | name, (FBytes|FUInt64|FInt64) ->
10485         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10486         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10487     | name, (FUInt32|FInt32) ->
10488         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10489         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10490     | name, FOptPercent ->
10491         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10492         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10493     | name, FChar ->
10494         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10495         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10496   ) cols;
10497   pr "  free (r);\n";
10498   pr "  return jr;\n"
10499
10500 and generate_java_struct_list_return typ jtyp cols =
10501   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10502   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10503   pr "  for (i = 0; i < r->len; ++i) {\n";
10504   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10505   List.iter (
10506     function
10507     | name, FString ->
10508         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10509         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10510     | name, FUUID ->
10511         pr "    {\n";
10512         pr "      char s[33];\n";
10513         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10514         pr "      s[32] = 0;\n";
10515         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10516         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10517         pr "    }\n";
10518     | name, FBuffer ->
10519         pr "    {\n";
10520         pr "      int len = r->val[i].%s_len;\n" name;
10521         pr "      char s[len+1];\n";
10522         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10523         pr "      s[len] = 0;\n";
10524         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10525         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10526         pr "    }\n";
10527     | name, (FBytes|FUInt64|FInt64) ->
10528         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10529         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10530     | name, (FUInt32|FInt32) ->
10531         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10532         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10533     | name, FOptPercent ->
10534         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10535         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10536     | name, FChar ->
10537         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10538         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10539   ) cols;
10540   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10541   pr "  }\n";
10542   pr "  guestfs_free_%s_list (r);\n" typ;
10543   pr "  return jr;\n"
10544
10545 and generate_java_makefile_inc () =
10546   generate_header HashStyle GPLv2plus;
10547
10548   pr "java_built_sources = \\\n";
10549   List.iter (
10550     fun (typ, jtyp) ->
10551         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10552   ) java_structs;
10553   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10554
10555 and generate_haskell_hs () =
10556   generate_header HaskellStyle LGPLv2plus;
10557
10558   (* XXX We only know how to generate partial FFI for Haskell
10559    * at the moment.  Please help out!
10560    *)
10561   let can_generate style =
10562     match style with
10563     | RErr, _
10564     | RInt _, _
10565     | RInt64 _, _ -> true
10566     | RBool _, _
10567     | RConstString _, _
10568     | RConstOptString _, _
10569     | RString _, _
10570     | RStringList _, _
10571     | RStruct _, _
10572     | RStructList _, _
10573     | RHashtable _, _
10574     | RBufferOut _, _ -> false in
10575
10576   pr "\
10577 {-# INCLUDE <guestfs.h> #-}
10578 {-# LANGUAGE ForeignFunctionInterface #-}
10579
10580 module Guestfs (
10581   create";
10582
10583   (* List out the names of the actions we want to export. *)
10584   List.iter (
10585     fun (name, style, _, _, _, _, _) ->
10586       if can_generate style then pr ",\n  %s" name
10587   ) all_functions;
10588
10589   pr "
10590   ) where
10591
10592 -- Unfortunately some symbols duplicate ones already present
10593 -- in Prelude.  We don't know which, so we hard-code a list
10594 -- here.
10595 import Prelude hiding (truncate)
10596
10597 import Foreign
10598 import Foreign.C
10599 import Foreign.C.Types
10600 import IO
10601 import Control.Exception
10602 import Data.Typeable
10603
10604 data GuestfsS = GuestfsS            -- represents the opaque C struct
10605 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10606 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10607
10608 -- XXX define properly later XXX
10609 data PV = PV
10610 data VG = VG
10611 data LV = LV
10612 data IntBool = IntBool
10613 data Stat = Stat
10614 data StatVFS = StatVFS
10615 data Hashtable = Hashtable
10616
10617 foreign import ccall unsafe \"guestfs_create\" c_create
10618   :: IO GuestfsP
10619 foreign import ccall unsafe \"&guestfs_close\" c_close
10620   :: FunPtr (GuestfsP -> IO ())
10621 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10622   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10623
10624 create :: IO GuestfsH
10625 create = do
10626   p <- c_create
10627   c_set_error_handler p nullPtr nullPtr
10628   h <- newForeignPtr c_close p
10629   return h
10630
10631 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10632   :: GuestfsP -> IO CString
10633
10634 -- last_error :: GuestfsH -> IO (Maybe String)
10635 -- last_error h = do
10636 --   str <- withForeignPtr h (\\p -> c_last_error p)
10637 --   maybePeek peekCString str
10638
10639 last_error :: GuestfsH -> IO (String)
10640 last_error h = do
10641   str <- withForeignPtr h (\\p -> c_last_error p)
10642   if (str == nullPtr)
10643     then return \"no error\"
10644     else peekCString str
10645
10646 ";
10647
10648   (* Generate wrappers for each foreign function. *)
10649   List.iter (
10650     fun (name, style, _, _, _, _, _) ->
10651       if can_generate style then (
10652         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10653         pr "  :: ";
10654         generate_haskell_prototype ~handle:"GuestfsP" style;
10655         pr "\n";
10656         pr "\n";
10657         pr "%s :: " name;
10658         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10659         pr "\n";
10660         pr "%s %s = do\n" name
10661           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10662         pr "  r <- ";
10663         (* Convert pointer arguments using with* functions. *)
10664         List.iter (
10665           function
10666           | FileIn n
10667           | FileOut n
10668           | Pathname n | Device n | Dev_or_Path n | String n ->
10669               pr "withCString %s $ \\%s -> " n n
10670           | BufferIn n ->
10671               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10672           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10673           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10674           | Bool _ | Int _ | Int64 _ -> ()
10675         ) (snd style);
10676         (* Convert integer arguments. *)
10677         let args =
10678           List.map (
10679             function
10680             | Bool n -> sprintf "(fromBool %s)" n
10681             | Int n -> sprintf "(fromIntegral %s)" n
10682             | Int64 n -> sprintf "(fromIntegral %s)" n
10683             | FileIn n | FileOut n
10684             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10685             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10686           ) (snd style) in
10687         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10688           (String.concat " " ("p" :: args));
10689         (match fst style with
10690          | RErr | RInt _ | RInt64 _ | RBool _ ->
10691              pr "  if (r == -1)\n";
10692              pr "    then do\n";
10693              pr "      err <- last_error h\n";
10694              pr "      fail err\n";
10695          | RConstString _ | RConstOptString _ | RString _
10696          | RStringList _ | RStruct _
10697          | RStructList _ | RHashtable _ | RBufferOut _ ->
10698              pr "  if (r == nullPtr)\n";
10699              pr "    then do\n";
10700              pr "      err <- last_error h\n";
10701              pr "      fail err\n";
10702         );
10703         (match fst style with
10704          | RErr ->
10705              pr "    else return ()\n"
10706          | RInt _ ->
10707              pr "    else return (fromIntegral r)\n"
10708          | RInt64 _ ->
10709              pr "    else return (fromIntegral r)\n"
10710          | RBool _ ->
10711              pr "    else return (toBool r)\n"
10712          | RConstString _
10713          | RConstOptString _
10714          | RString _
10715          | RStringList _
10716          | RStruct _
10717          | RStructList _
10718          | RHashtable _
10719          | RBufferOut _ ->
10720              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10721         );
10722         pr "\n";
10723       )
10724   ) all_functions
10725
10726 and generate_haskell_prototype ~handle ?(hs = false) style =
10727   pr "%s -> " handle;
10728   let string = if hs then "String" else "CString" in
10729   let int = if hs then "Int" else "CInt" in
10730   let bool = if hs then "Bool" else "CInt" in
10731   let int64 = if hs then "Integer" else "Int64" in
10732   List.iter (
10733     fun arg ->
10734       (match arg with
10735        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10736        | BufferIn _ ->
10737            if hs then pr "String"
10738            else pr "CString -> CInt"
10739        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10740        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10741        | Bool _ -> pr "%s" bool
10742        | Int _ -> pr "%s" int
10743        | Int64 _ -> pr "%s" int
10744        | FileIn _ -> pr "%s" string
10745        | FileOut _ -> pr "%s" string
10746       );
10747       pr " -> ";
10748   ) (snd style);
10749   pr "IO (";
10750   (match fst style with
10751    | RErr -> if not hs then pr "CInt"
10752    | RInt _ -> pr "%s" int
10753    | RInt64 _ -> pr "%s" int64
10754    | RBool _ -> pr "%s" bool
10755    | RConstString _ -> pr "%s" string
10756    | RConstOptString _ -> pr "Maybe %s" string
10757    | RString _ -> pr "%s" string
10758    | RStringList _ -> pr "[%s]" string
10759    | RStruct (_, typ) ->
10760        let name = java_name_of_struct typ in
10761        pr "%s" name
10762    | RStructList (_, typ) ->
10763        let name = java_name_of_struct typ in
10764        pr "[%s]" name
10765    | RHashtable _ -> pr "Hashtable"
10766    | RBufferOut _ -> pr "%s" string
10767   );
10768   pr ")"
10769
10770 and generate_csharp () =
10771   generate_header CPlusPlusStyle LGPLv2plus;
10772
10773   (* XXX Make this configurable by the C# assembly users. *)
10774   let library = "libguestfs.so.0" in
10775
10776   pr "\
10777 // These C# bindings are highly experimental at present.
10778 //
10779 // Firstly they only work on Linux (ie. Mono).  In order to get them
10780 // to work on Windows (ie. .Net) you would need to port the library
10781 // itself to Windows first.
10782 //
10783 // The second issue is that some calls are known to be incorrect and
10784 // can cause Mono to segfault.  Particularly: calls which pass or
10785 // return string[], or return any structure value.  This is because
10786 // we haven't worked out the correct way to do this from C#.
10787 //
10788 // The third issue is that when compiling you get a lot of warnings.
10789 // We are not sure whether the warnings are important or not.
10790 //
10791 // Fourthly we do not routinely build or test these bindings as part
10792 // of the make && make check cycle, which means that regressions might
10793 // go unnoticed.
10794 //
10795 // Suggestions and patches are welcome.
10796
10797 // To compile:
10798 //
10799 // gmcs Libguestfs.cs
10800 // mono Libguestfs.exe
10801 //
10802 // (You'll probably want to add a Test class / static main function
10803 // otherwise this won't do anything useful).
10804
10805 using System;
10806 using System.IO;
10807 using System.Runtime.InteropServices;
10808 using System.Runtime.Serialization;
10809 using System.Collections;
10810
10811 namespace Guestfs
10812 {
10813   class Error : System.ApplicationException
10814   {
10815     public Error (string message) : base (message) {}
10816     protected Error (SerializationInfo info, StreamingContext context) {}
10817   }
10818
10819   class Guestfs
10820   {
10821     IntPtr _handle;
10822
10823     [DllImport (\"%s\")]
10824     static extern IntPtr guestfs_create ();
10825
10826     public Guestfs ()
10827     {
10828       _handle = guestfs_create ();
10829       if (_handle == IntPtr.Zero)
10830         throw new Error (\"could not create guestfs handle\");
10831     }
10832
10833     [DllImport (\"%s\")]
10834     static extern void guestfs_close (IntPtr h);
10835
10836     ~Guestfs ()
10837     {
10838       guestfs_close (_handle);
10839     }
10840
10841     [DllImport (\"%s\")]
10842     static extern string guestfs_last_error (IntPtr h);
10843
10844 " library library library;
10845
10846   (* Generate C# structure bindings.  We prefix struct names with
10847    * underscore because C# cannot have conflicting struct names and
10848    * method names (eg. "class stat" and "stat").
10849    *)
10850   List.iter (
10851     fun (typ, cols) ->
10852       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10853       pr "    public class _%s {\n" typ;
10854       List.iter (
10855         function
10856         | name, FChar -> pr "      char %s;\n" name
10857         | name, FString -> pr "      string %s;\n" name
10858         | name, FBuffer ->
10859             pr "      uint %s_len;\n" name;
10860             pr "      string %s;\n" name
10861         | name, FUUID ->
10862             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10863             pr "      string %s;\n" name
10864         | name, FUInt32 -> pr "      uint %s;\n" name
10865         | name, FInt32 -> pr "      int %s;\n" name
10866         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10867         | name, FInt64 -> pr "      long %s;\n" name
10868         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10869       ) cols;
10870       pr "    }\n";
10871       pr "\n"
10872   ) structs;
10873
10874   (* Generate C# function bindings. *)
10875   List.iter (
10876     fun (name, style, _, _, _, shortdesc, _) ->
10877       let rec csharp_return_type () =
10878         match fst style with
10879         | RErr -> "void"
10880         | RBool n -> "bool"
10881         | RInt n -> "int"
10882         | RInt64 n -> "long"
10883         | RConstString n
10884         | RConstOptString n
10885         | RString n
10886         | RBufferOut n -> "string"
10887         | RStruct (_,n) -> "_" ^ n
10888         | RHashtable n -> "Hashtable"
10889         | RStringList n -> "string[]"
10890         | RStructList (_,n) -> sprintf "_%s[]" n
10891
10892       and c_return_type () =
10893         match fst style with
10894         | RErr
10895         | RBool _
10896         | RInt _ -> "int"
10897         | RInt64 _ -> "long"
10898         | RConstString _
10899         | RConstOptString _
10900         | RString _
10901         | RBufferOut _ -> "string"
10902         | RStruct (_,n) -> "_" ^ n
10903         | RHashtable _
10904         | RStringList _ -> "string[]"
10905         | RStructList (_,n) -> sprintf "_%s[]" n
10906
10907       and c_error_comparison () =
10908         match fst style with
10909         | RErr
10910         | RBool _
10911         | RInt _
10912         | RInt64 _ -> "== -1"
10913         | RConstString _
10914         | RConstOptString _
10915         | RString _
10916         | RBufferOut _
10917         | RStruct (_,_)
10918         | RHashtable _
10919         | RStringList _
10920         | RStructList (_,_) -> "== null"
10921
10922       and generate_extern_prototype () =
10923         pr "    static extern %s guestfs_%s (IntPtr h"
10924           (c_return_type ()) name;
10925         List.iter (
10926           function
10927           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10928           | FileIn n | FileOut n
10929           | BufferIn n ->
10930               pr ", [In] string %s" n
10931           | StringList n | DeviceList n ->
10932               pr ", [In] string[] %s" n
10933           | Bool n ->
10934               pr ", bool %s" n
10935           | Int n ->
10936               pr ", int %s" n
10937           | Int64 n ->
10938               pr ", long %s" n
10939         ) (snd style);
10940         pr ");\n"
10941
10942       and generate_public_prototype () =
10943         pr "    public %s %s (" (csharp_return_type ()) name;
10944         let comma = ref false in
10945         let next () =
10946           if !comma then pr ", ";
10947           comma := true
10948         in
10949         List.iter (
10950           function
10951           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10952           | FileIn n | FileOut n
10953           | BufferIn n ->
10954               next (); pr "string %s" n
10955           | StringList n | DeviceList n ->
10956               next (); pr "string[] %s" n
10957           | Bool n ->
10958               next (); pr "bool %s" n
10959           | Int n ->
10960               next (); pr "int %s" n
10961           | Int64 n ->
10962               next (); pr "long %s" n
10963         ) (snd style);
10964         pr ")\n"
10965
10966       and generate_call () =
10967         pr "guestfs_%s (_handle" name;
10968         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10969         pr ");\n";
10970       in
10971
10972       pr "    [DllImport (\"%s\")]\n" library;
10973       generate_extern_prototype ();
10974       pr "\n";
10975       pr "    /// <summary>\n";
10976       pr "    /// %s\n" shortdesc;
10977       pr "    /// </summary>\n";
10978       generate_public_prototype ();
10979       pr "    {\n";
10980       pr "      %s r;\n" (c_return_type ());
10981       pr "      r = ";
10982       generate_call ();
10983       pr "      if (r %s)\n" (c_error_comparison ());
10984       pr "        throw new Error (guestfs_last_error (_handle));\n";
10985       (match fst style with
10986        | RErr -> ()
10987        | RBool _ ->
10988            pr "      return r != 0 ? true : false;\n"
10989        | RHashtable _ ->
10990            pr "      Hashtable rr = new Hashtable ();\n";
10991            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10992            pr "        rr.Add (r[i], r[i+1]);\n";
10993            pr "      return rr;\n"
10994        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10995        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10996        | RStructList _ ->
10997            pr "      return r;\n"
10998       );
10999       pr "    }\n";
11000       pr "\n";
11001   ) all_functions_sorted;
11002
11003   pr "  }
11004 }
11005 "
11006
11007 and generate_bindtests () =
11008   generate_header CStyle LGPLv2plus;
11009
11010   pr "\
11011 #include <stdio.h>
11012 #include <stdlib.h>
11013 #include <inttypes.h>
11014 #include <string.h>
11015
11016 #include \"guestfs.h\"
11017 #include \"guestfs-internal.h\"
11018 #include \"guestfs-internal-actions.h\"
11019 #include \"guestfs_protocol.h\"
11020
11021 #define error guestfs_error
11022 #define safe_calloc guestfs_safe_calloc
11023 #define safe_malloc guestfs_safe_malloc
11024
11025 static void
11026 print_strings (char *const *argv)
11027 {
11028   int argc;
11029
11030   printf (\"[\");
11031   for (argc = 0; argv[argc] != NULL; ++argc) {
11032     if (argc > 0) printf (\", \");
11033     printf (\"\\\"%%s\\\"\", argv[argc]);
11034   }
11035   printf (\"]\\n\");
11036 }
11037
11038 /* The test0 function prints its parameters to stdout. */
11039 ";
11040
11041   let test0, tests =
11042     match test_functions with
11043     | [] -> assert false
11044     | test0 :: tests -> test0, tests in
11045
11046   let () =
11047     let (name, style, _, _, _, _, _) = test0 in
11048     generate_prototype ~extern:false ~semicolon:false ~newline:true
11049       ~handle:"g" ~prefix:"guestfs__" name style;
11050     pr "{\n";
11051     List.iter (
11052       function
11053       | Pathname n
11054       | Device n | Dev_or_Path n
11055       | String n
11056       | FileIn n
11057       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11058       | BufferIn n ->
11059           pr "  {\n";
11060           pr "    size_t i;\n";
11061           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11062           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11063           pr "    printf (\"\\n\");\n";
11064           pr "  }\n";
11065       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11066       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11067       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11068       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11069       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11070     ) (snd style);
11071     pr "  /* Java changes stdout line buffering so we need this: */\n";
11072     pr "  fflush (stdout);\n";
11073     pr "  return 0;\n";
11074     pr "}\n";
11075     pr "\n" in
11076
11077   List.iter (
11078     fun (name, style, _, _, _, _, _) ->
11079       if String.sub name (String.length name - 3) 3 <> "err" then (
11080         pr "/* Test normal return. */\n";
11081         generate_prototype ~extern:false ~semicolon:false ~newline:true
11082           ~handle:"g" ~prefix:"guestfs__" name style;
11083         pr "{\n";
11084         (match fst style with
11085          | RErr ->
11086              pr "  return 0;\n"
11087          | RInt _ ->
11088              pr "  int r;\n";
11089              pr "  sscanf (val, \"%%d\", &r);\n";
11090              pr "  return r;\n"
11091          | RInt64 _ ->
11092              pr "  int64_t r;\n";
11093              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11094              pr "  return r;\n"
11095          | RBool _ ->
11096              pr "  return STREQ (val, \"true\");\n"
11097          | RConstString _
11098          | RConstOptString _ ->
11099              (* Can't return the input string here.  Return a static
11100               * string so we ensure we get a segfault if the caller
11101               * tries to free it.
11102               *)
11103              pr "  return \"static string\";\n"
11104          | RString _ ->
11105              pr "  return strdup (val);\n"
11106          | RStringList _ ->
11107              pr "  char **strs;\n";
11108              pr "  int n, i;\n";
11109              pr "  sscanf (val, \"%%d\", &n);\n";
11110              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11111              pr "  for (i = 0; i < n; ++i) {\n";
11112              pr "    strs[i] = safe_malloc (g, 16);\n";
11113              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11114              pr "  }\n";
11115              pr "  strs[n] = NULL;\n";
11116              pr "  return strs;\n"
11117          | RStruct (_, typ) ->
11118              pr "  struct guestfs_%s *r;\n" typ;
11119              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11120              pr "  return r;\n"
11121          | RStructList (_, typ) ->
11122              pr "  struct guestfs_%s_list *r;\n" typ;
11123              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11124              pr "  sscanf (val, \"%%d\", &r->len);\n";
11125              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11126              pr "  return r;\n"
11127          | RHashtable _ ->
11128              pr "  char **strs;\n";
11129              pr "  int n, i;\n";
11130              pr "  sscanf (val, \"%%d\", &n);\n";
11131              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11132              pr "  for (i = 0; i < n; ++i) {\n";
11133              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11134              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11135              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11136              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11137              pr "  }\n";
11138              pr "  strs[n*2] = NULL;\n";
11139              pr "  return strs;\n"
11140          | RBufferOut _ ->
11141              pr "  return strdup (val);\n"
11142         );
11143         pr "}\n";
11144         pr "\n"
11145       ) else (
11146         pr "/* Test error return. */\n";
11147         generate_prototype ~extern:false ~semicolon:false ~newline:true
11148           ~handle:"g" ~prefix:"guestfs__" name style;
11149         pr "{\n";
11150         pr "  error (g, \"error\");\n";
11151         (match fst style with
11152          | RErr | RInt _ | RInt64 _ | RBool _ ->
11153              pr "  return -1;\n"
11154          | RConstString _ | RConstOptString _
11155          | RString _ | RStringList _ | RStruct _
11156          | RStructList _
11157          | RHashtable _
11158          | RBufferOut _ ->
11159              pr "  return NULL;\n"
11160         );
11161         pr "}\n";
11162         pr "\n"
11163       )
11164   ) tests
11165
11166 and generate_ocaml_bindtests () =
11167   generate_header OCamlStyle GPLv2plus;
11168
11169   pr "\
11170 let () =
11171   let g = Guestfs.create () in
11172 ";
11173
11174   let mkargs args =
11175     String.concat " " (
11176       List.map (
11177         function
11178         | CallString s -> "\"" ^ s ^ "\""
11179         | CallOptString None -> "None"
11180         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11181         | CallStringList xs ->
11182             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11183         | CallInt i when i >= 0 -> string_of_int i
11184         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11185         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11186         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11187         | CallBool b -> string_of_bool b
11188         | CallBuffer s -> sprintf "%S" s
11189       ) args
11190     )
11191   in
11192
11193   generate_lang_bindtests (
11194     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11195   );
11196
11197   pr "print_endline \"EOF\"\n"
11198
11199 and generate_perl_bindtests () =
11200   pr "#!/usr/bin/perl -w\n";
11201   generate_header HashStyle GPLv2plus;
11202
11203   pr "\
11204 use strict;
11205
11206 use Sys::Guestfs;
11207
11208 my $g = Sys::Guestfs->new ();
11209 ";
11210
11211   let mkargs args =
11212     String.concat ", " (
11213       List.map (
11214         function
11215         | CallString s -> "\"" ^ s ^ "\""
11216         | CallOptString None -> "undef"
11217         | CallOptString (Some s) -> sprintf "\"%s\"" s
11218         | CallStringList xs ->
11219             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11220         | CallInt i -> string_of_int i
11221         | CallInt64 i -> Int64.to_string i
11222         | CallBool b -> if b then "1" else "0"
11223         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11224       ) args
11225     )
11226   in
11227
11228   generate_lang_bindtests (
11229     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11230   );
11231
11232   pr "print \"EOF\\n\"\n"
11233
11234 and generate_python_bindtests () =
11235   generate_header HashStyle GPLv2plus;
11236
11237   pr "\
11238 import guestfs
11239
11240 g = guestfs.GuestFS ()
11241 ";
11242
11243   let mkargs args =
11244     String.concat ", " (
11245       List.map (
11246         function
11247         | CallString s -> "\"" ^ s ^ "\""
11248         | CallOptString None -> "None"
11249         | CallOptString (Some s) -> sprintf "\"%s\"" s
11250         | CallStringList xs ->
11251             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11252         | CallInt i -> string_of_int i
11253         | CallInt64 i -> Int64.to_string i
11254         | CallBool b -> if b then "1" else "0"
11255         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11256       ) args
11257     )
11258   in
11259
11260   generate_lang_bindtests (
11261     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11262   );
11263
11264   pr "print \"EOF\"\n"
11265
11266 and generate_ruby_bindtests () =
11267   generate_header HashStyle GPLv2plus;
11268
11269   pr "\
11270 require 'guestfs'
11271
11272 g = Guestfs::create()
11273 ";
11274
11275   let mkargs args =
11276     String.concat ", " (
11277       List.map (
11278         function
11279         | CallString s -> "\"" ^ s ^ "\""
11280         | CallOptString None -> "nil"
11281         | CallOptString (Some s) -> sprintf "\"%s\"" s
11282         | CallStringList xs ->
11283             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11284         | CallInt i -> string_of_int i
11285         | CallInt64 i -> Int64.to_string i
11286         | CallBool b -> string_of_bool b
11287         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11288       ) args
11289     )
11290   in
11291
11292   generate_lang_bindtests (
11293     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11294   );
11295
11296   pr "print \"EOF\\n\"\n"
11297
11298 and generate_java_bindtests () =
11299   generate_header CStyle GPLv2plus;
11300
11301   pr "\
11302 import com.redhat.et.libguestfs.*;
11303
11304 public class Bindtests {
11305     public static void main (String[] argv)
11306     {
11307         try {
11308             GuestFS g = new GuestFS ();
11309 ";
11310
11311   let mkargs args =
11312     String.concat ", " (
11313       List.map (
11314         function
11315         | CallString s -> "\"" ^ s ^ "\""
11316         | CallOptString None -> "null"
11317         | CallOptString (Some s) -> sprintf "\"%s\"" s
11318         | CallStringList xs ->
11319             "new String[]{" ^
11320               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11321         | CallInt i -> string_of_int i
11322         | CallInt64 i -> Int64.to_string i
11323         | CallBool b -> string_of_bool b
11324         | CallBuffer s ->
11325             "new byte[] { " ^ String.concat "," (
11326               map_chars (fun c -> string_of_int (Char.code c)) s
11327             ) ^ " }"
11328       ) args
11329     )
11330   in
11331
11332   generate_lang_bindtests (
11333     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11334   );
11335
11336   pr "
11337             System.out.println (\"EOF\");
11338         }
11339         catch (Exception exn) {
11340             System.err.println (exn);
11341             System.exit (1);
11342         }
11343     }
11344 }
11345 "
11346
11347 and generate_haskell_bindtests () =
11348   generate_header HaskellStyle GPLv2plus;
11349
11350   pr "\
11351 module Bindtests where
11352 import qualified Guestfs
11353
11354 main = do
11355   g <- Guestfs.create
11356 ";
11357
11358   let mkargs args =
11359     String.concat " " (
11360       List.map (
11361         function
11362         | CallString s -> "\"" ^ s ^ "\""
11363         | CallOptString None -> "Nothing"
11364         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11365         | CallStringList xs ->
11366             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11367         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11368         | CallInt i -> string_of_int i
11369         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11370         | CallInt64 i -> Int64.to_string i
11371         | CallBool true -> "True"
11372         | CallBool false -> "False"
11373         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11374       ) args
11375     )
11376   in
11377
11378   generate_lang_bindtests (
11379     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11380   );
11381
11382   pr "  putStrLn \"EOF\"\n"
11383
11384 (* Language-independent bindings tests - we do it this way to
11385  * ensure there is parity in testing bindings across all languages.
11386  *)
11387 and generate_lang_bindtests call =
11388   call "test0" [CallString "abc"; CallOptString (Some "def");
11389                 CallStringList []; CallBool false;
11390                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11391                 CallBuffer "abc\000abc"];
11392   call "test0" [CallString "abc"; CallOptString None;
11393                 CallStringList []; CallBool false;
11394                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11395                 CallBuffer "abc\000abc"];
11396   call "test0" [CallString ""; CallOptString (Some "def");
11397                 CallStringList []; CallBool false;
11398                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11399                 CallBuffer "abc\000abc"];
11400   call "test0" [CallString ""; CallOptString (Some "");
11401                 CallStringList []; CallBool false;
11402                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11403                 CallBuffer "abc\000abc"];
11404   call "test0" [CallString "abc"; CallOptString (Some "def");
11405                 CallStringList ["1"]; CallBool false;
11406                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11407                 CallBuffer "abc\000abc"];
11408   call "test0" [CallString "abc"; CallOptString (Some "def");
11409                 CallStringList ["1"; "2"]; CallBool false;
11410                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11411                 CallBuffer "abc\000abc"];
11412   call "test0" [CallString "abc"; CallOptString (Some "def");
11413                 CallStringList ["1"]; CallBool true;
11414                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11415                 CallBuffer "abc\000abc"];
11416   call "test0" [CallString "abc"; CallOptString (Some "def");
11417                 CallStringList ["1"]; CallBool false;
11418                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11419                 CallBuffer "abc\000abc"];
11420   call "test0" [CallString "abc"; CallOptString (Some "def");
11421                 CallStringList ["1"]; CallBool false;
11422                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11423                 CallBuffer "abc\000abc"];
11424   call "test0" [CallString "abc"; CallOptString (Some "def");
11425                 CallStringList ["1"]; CallBool false;
11426                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11427                 CallBuffer "abc\000abc"];
11428   call "test0" [CallString "abc"; CallOptString (Some "def");
11429                 CallStringList ["1"]; CallBool false;
11430                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11431                 CallBuffer "abc\000abc"];
11432   call "test0" [CallString "abc"; CallOptString (Some "def");
11433                 CallStringList ["1"]; CallBool false;
11434                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11435                 CallBuffer "abc\000abc"];
11436   call "test0" [CallString "abc"; CallOptString (Some "def");
11437                 CallStringList ["1"]; CallBool false;
11438                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11439                 CallBuffer "abc\000abc"]
11440
11441 (* XXX Add here tests of the return and error functions. *)
11442
11443 (* Code to generator bindings for virt-inspector.  Currently only
11444  * implemented for OCaml code (for virt-p2v 2.0).
11445  *)
11446 let rng_input = "inspector/virt-inspector.rng"
11447
11448 (* Read the input file and parse it into internal structures.  This is
11449  * by no means a complete RELAX NG parser, but is just enough to be
11450  * able to parse the specific input file.
11451  *)
11452 type rng =
11453   | Element of string * rng list        (* <element name=name/> *)
11454   | Attribute of string * rng list        (* <attribute name=name/> *)
11455   | Interleave of rng list                (* <interleave/> *)
11456   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11457   | OneOrMore of rng                        (* <oneOrMore/> *)
11458   | Optional of rng                        (* <optional/> *)
11459   | Choice of string list                (* <choice><value/>*</choice> *)
11460   | Value of string                        (* <value>str</value> *)
11461   | Text                                (* <text/> *)
11462
11463 let rec string_of_rng = function
11464   | Element (name, xs) ->
11465       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11466   | Attribute (name, xs) ->
11467       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11468   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11469   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11470   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11471   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11472   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11473   | Value value -> "Value \"" ^ value ^ "\""
11474   | Text -> "Text"
11475
11476 and string_of_rng_list xs =
11477   String.concat ", " (List.map string_of_rng xs)
11478
11479 let rec parse_rng ?defines context = function
11480   | [] -> []
11481   | Xml.Element ("element", ["name", name], children) :: rest ->
11482       Element (name, parse_rng ?defines context children)
11483       :: parse_rng ?defines context rest
11484   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11485       Attribute (name, parse_rng ?defines context children)
11486       :: parse_rng ?defines context rest
11487   | Xml.Element ("interleave", [], children) :: rest ->
11488       Interleave (parse_rng ?defines context children)
11489       :: parse_rng ?defines context rest
11490   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11491       let rng = parse_rng ?defines context [child] in
11492       (match rng with
11493        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11494        | _ ->
11495            failwithf "%s: <zeroOrMore> contains more than one child element"
11496              context
11497       )
11498   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11499       let rng = parse_rng ?defines context [child] in
11500       (match rng with
11501        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11502        | _ ->
11503            failwithf "%s: <oneOrMore> contains more than one child element"
11504              context
11505       )
11506   | Xml.Element ("optional", [], [child]) :: rest ->
11507       let rng = parse_rng ?defines context [child] in
11508       (match rng with
11509        | [child] -> Optional child :: parse_rng ?defines context rest
11510        | _ ->
11511            failwithf "%s: <optional> contains more than one child element"
11512              context
11513       )
11514   | Xml.Element ("choice", [], children) :: rest ->
11515       let values = List.map (
11516         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11517         | _ ->
11518             failwithf "%s: can't handle anything except <value> in <choice>"
11519               context
11520       ) children in
11521       Choice values
11522       :: parse_rng ?defines context rest
11523   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11524       Value value :: parse_rng ?defines context rest
11525   | Xml.Element ("text", [], []) :: rest ->
11526       Text :: parse_rng ?defines context rest
11527   | Xml.Element ("ref", ["name", name], []) :: rest ->
11528       (* Look up the reference.  Because of limitations in this parser,
11529        * we can't handle arbitrarily nested <ref> yet.  You can only
11530        * use <ref> from inside <start>.
11531        *)
11532       (match defines with
11533        | None ->
11534            failwithf "%s: contains <ref>, but no refs are defined yet" context
11535        | Some map ->
11536            let rng = StringMap.find name map in
11537            rng @ parse_rng ?defines context rest
11538       )
11539   | x :: _ ->
11540       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11541
11542 let grammar =
11543   let xml = Xml.parse_file rng_input in
11544   match xml with
11545   | Xml.Element ("grammar", _,
11546                  Xml.Element ("start", _, gram) :: defines) ->
11547       (* The <define/> elements are referenced in the <start> section,
11548        * so build a map of those first.
11549        *)
11550       let defines = List.fold_left (
11551         fun map ->
11552           function Xml.Element ("define", ["name", name], defn) ->
11553             StringMap.add name defn map
11554           | _ ->
11555               failwithf "%s: expected <define name=name/>" rng_input
11556       ) StringMap.empty defines in
11557       let defines = StringMap.mapi parse_rng defines in
11558
11559       (* Parse the <start> clause, passing the defines. *)
11560       parse_rng ~defines "<start>" gram
11561   | _ ->
11562       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11563         rng_input
11564
11565 let name_of_field = function
11566   | Element (name, _) | Attribute (name, _)
11567   | ZeroOrMore (Element (name, _))
11568   | OneOrMore (Element (name, _))
11569   | Optional (Element (name, _)) -> name
11570   | Optional (Attribute (name, _)) -> name
11571   | Text -> (* an unnamed field in an element *)
11572       "data"
11573   | rng ->
11574       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11575
11576 (* At the moment this function only generates OCaml types.  However we
11577  * should parameterize it later so it can generate types/structs in a
11578  * variety of languages.
11579  *)
11580 let generate_types xs =
11581   (* A simple type is one that can be printed out directly, eg.
11582    * "string option".  A complex type is one which has a name and has
11583    * to be defined via another toplevel definition, eg. a struct.
11584    *
11585    * generate_type generates code for either simple or complex types.
11586    * In the simple case, it returns the string ("string option").  In
11587    * the complex case, it returns the name ("mountpoint").  In the
11588    * complex case it has to print out the definition before returning,
11589    * so it should only be called when we are at the beginning of a
11590    * new line (BOL context).
11591    *)
11592   let rec generate_type = function
11593     | Text ->                                (* string *)
11594         "string", true
11595     | Choice values ->                        (* [`val1|`val2|...] *)
11596         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11597     | ZeroOrMore rng ->                        (* <rng> list *)
11598         let t, is_simple = generate_type rng in
11599         t ^ " list (* 0 or more *)", is_simple
11600     | OneOrMore rng ->                        (* <rng> list *)
11601         let t, is_simple = generate_type rng in
11602         t ^ " list (* 1 or more *)", is_simple
11603                                         (* virt-inspector hack: bool *)
11604     | Optional (Attribute (name, [Value "1"])) ->
11605         "bool", true
11606     | Optional rng ->                        (* <rng> list *)
11607         let t, is_simple = generate_type rng in
11608         t ^ " option", is_simple
11609                                         (* type name = { fields ... } *)
11610     | Element (name, fields) when is_attrs_interleave fields ->
11611         generate_type_struct name (get_attrs_interleave fields)
11612     | Element (name, [field])                (* type name = field *)
11613     | Attribute (name, [field]) ->
11614         let t, is_simple = generate_type field in
11615         if is_simple then (t, true)
11616         else (
11617           pr "type %s = %s\n" name t;
11618           name, false
11619         )
11620     | Element (name, fields) ->              (* type name = { fields ... } *)
11621         generate_type_struct name fields
11622     | rng ->
11623         failwithf "generate_type failed at: %s" (string_of_rng rng)
11624
11625   and is_attrs_interleave = function
11626     | [Interleave _] -> true
11627     | Attribute _ :: fields -> is_attrs_interleave fields
11628     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11629     | _ -> false
11630
11631   and get_attrs_interleave = function
11632     | [Interleave fields] -> fields
11633     | ((Attribute _) as field) :: fields
11634     | ((Optional (Attribute _)) as field) :: fields ->
11635         field :: get_attrs_interleave fields
11636     | _ -> assert false
11637
11638   and generate_types xs =
11639     List.iter (fun x -> ignore (generate_type x)) xs
11640
11641   and generate_type_struct name fields =
11642     (* Calculate the types of the fields first.  We have to do this
11643      * before printing anything so we are still in BOL context.
11644      *)
11645     let types = List.map fst (List.map generate_type fields) in
11646
11647     (* Special case of a struct containing just a string and another
11648      * field.  Turn it into an assoc list.
11649      *)
11650     match types with
11651     | ["string"; other] ->
11652         let fname1, fname2 =
11653           match fields with
11654           | [f1; f2] -> name_of_field f1, name_of_field f2
11655           | _ -> assert false in
11656         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11657         name, false
11658
11659     | types ->
11660         pr "type %s = {\n" name;
11661         List.iter (
11662           fun (field, ftype) ->
11663             let fname = name_of_field field in
11664             pr "  %s_%s : %s;\n" name fname ftype
11665         ) (List.combine fields types);
11666         pr "}\n";
11667         (* Return the name of this type, and
11668          * false because it's not a simple type.
11669          *)
11670         name, false
11671   in
11672
11673   generate_types xs
11674
11675 let generate_parsers xs =
11676   (* As for generate_type above, generate_parser makes a parser for
11677    * some type, and returns the name of the parser it has generated.
11678    * Because it (may) need to print something, it should always be
11679    * called in BOL context.
11680    *)
11681   let rec generate_parser = function
11682     | Text ->                                (* string *)
11683         "string_child_or_empty"
11684     | Choice values ->                        (* [`val1|`val2|...] *)
11685         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11686           (String.concat "|"
11687              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11688     | ZeroOrMore rng ->                        (* <rng> list *)
11689         let pa = generate_parser rng in
11690         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11691     | OneOrMore rng ->                        (* <rng> list *)
11692         let pa = generate_parser rng in
11693         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11694                                         (* virt-inspector hack: bool *)
11695     | Optional (Attribute (name, [Value "1"])) ->
11696         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11697     | Optional rng ->                        (* <rng> list *)
11698         let pa = generate_parser rng in
11699         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11700                                         (* type name = { fields ... } *)
11701     | Element (name, fields) when is_attrs_interleave fields ->
11702         generate_parser_struct name (get_attrs_interleave fields)
11703     | Element (name, [field]) ->        (* type name = field *)
11704         let pa = generate_parser field in
11705         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11706         pr "let %s =\n" parser_name;
11707         pr "  %s\n" pa;
11708         pr "let parse_%s = %s\n" name parser_name;
11709         parser_name
11710     | Attribute (name, [field]) ->
11711         let pa = generate_parser field in
11712         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11713         pr "let %s =\n" parser_name;
11714         pr "  %s\n" pa;
11715         pr "let parse_%s = %s\n" name parser_name;
11716         parser_name
11717     | Element (name, fields) ->              (* type name = { fields ... } *)
11718         generate_parser_struct name ([], fields)
11719     | rng ->
11720         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11721
11722   and is_attrs_interleave = function
11723     | [Interleave _] -> true
11724     | Attribute _ :: fields -> is_attrs_interleave fields
11725     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11726     | _ -> false
11727
11728   and get_attrs_interleave = function
11729     | [Interleave fields] -> [], fields
11730     | ((Attribute _) as field) :: fields
11731     | ((Optional (Attribute _)) as field) :: fields ->
11732         let attrs, interleaves = get_attrs_interleave fields in
11733         (field :: attrs), interleaves
11734     | _ -> assert false
11735
11736   and generate_parsers xs =
11737     List.iter (fun x -> ignore (generate_parser x)) xs
11738
11739   and generate_parser_struct name (attrs, interleaves) =
11740     (* Generate parsers for the fields first.  We have to do this
11741      * before printing anything so we are still in BOL context.
11742      *)
11743     let fields = attrs @ interleaves in
11744     let pas = List.map generate_parser fields in
11745
11746     (* Generate an intermediate tuple from all the fields first.
11747      * If the type is just a string + another field, then we will
11748      * return this directly, otherwise it is turned into a record.
11749      *
11750      * RELAX NG note: This code treats <interleave> and plain lists of
11751      * fields the same.  In other words, it doesn't bother enforcing
11752      * any ordering of fields in the XML.
11753      *)
11754     pr "let parse_%s x =\n" name;
11755     pr "  let t = (\n    ";
11756     let comma = ref false in
11757     List.iter (
11758       fun x ->
11759         if !comma then pr ",\n    ";
11760         comma := true;
11761         match x with
11762         | Optional (Attribute (fname, [field])), pa ->
11763             pr "%s x" pa
11764         | Optional (Element (fname, [field])), pa ->
11765             pr "%s (optional_child %S x)" pa fname
11766         | Attribute (fname, [Text]), _ ->
11767             pr "attribute %S x" fname
11768         | (ZeroOrMore _ | OneOrMore _), pa ->
11769             pr "%s x" pa
11770         | Text, pa ->
11771             pr "%s x" pa
11772         | (field, pa) ->
11773             let fname = name_of_field field in
11774             pr "%s (child %S x)" pa fname
11775     ) (List.combine fields pas);
11776     pr "\n  ) in\n";
11777
11778     (match fields with
11779      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11780          pr "  t\n"
11781
11782      | _ ->
11783          pr "  (Obj.magic t : %s)\n" name
11784 (*
11785          List.iter (
11786            function
11787            | (Optional (Attribute (fname, [field])), pa) ->
11788                pr "  %s_%s =\n" name fname;
11789                pr "    %s x;\n" pa
11790            | (Optional (Element (fname, [field])), pa) ->
11791                pr "  %s_%s =\n" name fname;
11792                pr "    (let x = optional_child %S x in\n" fname;
11793                pr "     %s x);\n" pa
11794            | (field, pa) ->
11795                let fname = name_of_field field in
11796                pr "  %s_%s =\n" name fname;
11797                pr "    (let x = child %S x in\n" fname;
11798                pr "     %s x);\n" pa
11799          ) (List.combine fields pas);
11800          pr "}\n"
11801 *)
11802     );
11803     sprintf "parse_%s" name
11804   in
11805
11806   generate_parsers xs
11807
11808 (* Generate ocaml/guestfs_inspector.mli. *)
11809 let generate_ocaml_inspector_mli () =
11810   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11811
11812   pr "\
11813 (** This is an OCaml language binding to the external [virt-inspector]
11814     program.
11815
11816     For more information, please read the man page [virt-inspector(1)].
11817 *)
11818
11819 ";
11820
11821   generate_types grammar;
11822   pr "(** The nested information returned from the {!inspect} function. *)\n";
11823   pr "\n";
11824
11825   pr "\
11826 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11827 (** To inspect a libvirt domain called [name], pass a singleton
11828     list: [inspect [name]].  When using libvirt only, you may
11829     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11830
11831     To inspect a disk image or images, pass a list of the filenames
11832     of the disk images: [inspect filenames]
11833
11834     This function inspects the given guest or disk images and
11835     returns a list of operating system(s) found and a large amount
11836     of information about them.  In the vast majority of cases,
11837     a virtual machine only contains a single operating system.
11838
11839     If the optional [~xml] parameter is given, then this function
11840     skips running the external virt-inspector program and just
11841     parses the given XML directly (which is expected to be XML
11842     produced from a previous run of virt-inspector).  The list of
11843     names and connect URI are ignored in this case.
11844
11845     This function can throw a wide variety of exceptions, for example
11846     if the external virt-inspector program cannot be found, or if
11847     it doesn't generate valid XML.
11848 *)
11849 "
11850
11851 (* Generate ocaml/guestfs_inspector.ml. *)
11852 let generate_ocaml_inspector_ml () =
11853   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11854
11855   pr "open Unix\n";
11856   pr "\n";
11857
11858   generate_types grammar;
11859   pr "\n";
11860
11861   pr "\
11862 (* Misc functions which are used by the parser code below. *)
11863 let first_child = function
11864   | Xml.Element (_, _, c::_) -> c
11865   | Xml.Element (name, _, []) ->
11866       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11867   | Xml.PCData str ->
11868       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11869
11870 let string_child_or_empty = function
11871   | Xml.Element (_, _, [Xml.PCData s]) -> s
11872   | Xml.Element (_, _, []) -> \"\"
11873   | Xml.Element (x, _, _) ->
11874       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11875                 x ^ \" instead\")
11876   | Xml.PCData str ->
11877       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11878
11879 let optional_child name xml =
11880   let children = Xml.children xml in
11881   try
11882     Some (List.find (function
11883                      | Xml.Element (n, _, _) when n = name -> true
11884                      | _ -> false) children)
11885   with
11886     Not_found -> None
11887
11888 let child name xml =
11889   match optional_child name xml with
11890   | Some c -> c
11891   | None ->
11892       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11893
11894 let attribute name xml =
11895   try Xml.attrib xml name
11896   with Xml.No_attribute _ ->
11897     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11898
11899 ";
11900
11901   generate_parsers grammar;
11902   pr "\n";
11903
11904   pr "\
11905 (* Run external virt-inspector, then use parser to parse the XML. *)
11906 let inspect ?connect ?xml names =
11907   let xml =
11908     match xml with
11909     | None ->
11910         if names = [] then invalid_arg \"inspect: no names given\";
11911         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11912           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11913           names in
11914         let cmd = List.map Filename.quote cmd in
11915         let cmd = String.concat \" \" cmd in
11916         let chan = open_process_in cmd in
11917         let xml = Xml.parse_in chan in
11918         (match close_process_in chan with
11919          | WEXITED 0 -> ()
11920          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11921          | WSIGNALED i | WSTOPPED i ->
11922              failwith (\"external virt-inspector command died or stopped on sig \" ^
11923                        string_of_int i)
11924         );
11925         xml
11926     | Some doc ->
11927         Xml.parse_string doc in
11928   parse_operatingsystems xml
11929 "
11930
11931 and generate_max_proc_nr () =
11932   pr "%d\n" max_proc_nr
11933
11934 let output_to filename k =
11935   let filename_new = filename ^ ".new" in
11936   chan := open_out filename_new;
11937   k ();
11938   close_out !chan;
11939   chan := Pervasives.stdout;
11940
11941   (* Is the new file different from the current file? *)
11942   if Sys.file_exists filename && files_equal filename filename_new then
11943     unlink filename_new                 (* same, so skip it *)
11944   else (
11945     (* different, overwrite old one *)
11946     (try chmod filename 0o644 with Unix_error _ -> ());
11947     rename filename_new filename;
11948     chmod filename 0o444;
11949     printf "written %s\n%!" filename;
11950   )
11951
11952 let perror msg = function
11953   | Unix_error (err, _, _) ->
11954       eprintf "%s: %s\n" msg (error_message err)
11955   | exn ->
11956       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11957
11958 (* Main program. *)
11959 let () =
11960   let lock_fd =
11961     try openfile "HACKING" [O_RDWR] 0
11962     with
11963     | Unix_error (ENOENT, _, _) ->
11964         eprintf "\
11965 You are probably running this from the wrong directory.
11966 Run it from the top source directory using the command
11967   src/generator.ml
11968 ";
11969         exit 1
11970     | exn ->
11971         perror "open: HACKING" exn;
11972         exit 1 in
11973
11974   (* Acquire a lock so parallel builds won't try to run the generator
11975    * twice at the same time.  Subsequent builds will wait for the first
11976    * one to finish.  Note the lock is released implicitly when the
11977    * program exits.
11978    *)
11979   (try lockf lock_fd F_LOCK 1
11980    with exn ->
11981      perror "lock: HACKING" exn;
11982      exit 1);
11983
11984   check_functions ();
11985
11986   output_to "src/guestfs_protocol.x" generate_xdr;
11987   output_to "src/guestfs-structs.h" generate_structs_h;
11988   output_to "src/guestfs-actions.h" generate_actions_h;
11989   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11990   output_to "src/guestfs-actions.c" generate_client_actions;
11991   output_to "src/guestfs-bindtests.c" generate_bindtests;
11992   output_to "src/guestfs-structs.pod" generate_structs_pod;
11993   output_to "src/guestfs-actions.pod" generate_actions_pod;
11994   output_to "src/guestfs-availability.pod" generate_availability_pod;
11995   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11996   output_to "src/libguestfs.syms" generate_linker_script;
11997   output_to "daemon/actions.h" generate_daemon_actions_h;
11998   output_to "daemon/stubs.c" generate_daemon_actions;
11999   output_to "daemon/names.c" generate_daemon_names;
12000   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12001   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12002   output_to "capitests/tests.c" generate_tests;
12003   output_to "fish/cmds.c" generate_fish_cmds;
12004   output_to "fish/completion.c" generate_fish_completion;
12005   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12006   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12007   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12008   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12009   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12010   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12011   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12012   output_to "perl/Guestfs.xs" generate_perl_xs;
12013   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12014   output_to "perl/bindtests.pl" generate_perl_bindtests;
12015   output_to "python/guestfs-py.c" generate_python_c;
12016   output_to "python/guestfs.py" generate_python_py;
12017   output_to "python/bindtests.py" generate_python_bindtests;
12018   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12019   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12020   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12021
12022   List.iter (
12023     fun (typ, jtyp) ->
12024       let cols = cols_of_struct typ in
12025       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12026       output_to filename (generate_java_struct jtyp cols);
12027   ) java_structs;
12028
12029   output_to "java/Makefile.inc" generate_java_makefile_inc;
12030   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12031   output_to "java/Bindtests.java" generate_java_bindtests;
12032   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12033   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12034   output_to "csharp/Libguestfs.cs" generate_csharp;
12035
12036   (* Always generate this file last, and unconditionally.  It's used
12037    * by the Makefile to know when we must re-run the generator.
12038    *)
12039   let chan = open_out "src/stamp-generator" in
12040   fprintf chan "1\n";
12041   close_out chan;
12042
12043   printf "generated %d lines of code\n" !lines