New API: resize2fs-size to allow shrinking ext2 filesystems (RHBZ#585221).
[libguestfs.git] / src / generator.ml
1 #!/usr/bin/env ocaml
2 (* libguestfs
3  * Copyright (C) 2009-2010 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *)
19
20 (* This script generates a large amount of code and documentation for
21  * all the daemon actions.
22  *
23  * To add a new action there are only two files you need to change,
24  * this one to describe the interface (see the big table of
25  * 'daemon_functions' below), and daemon/<somefile>.c to write the
26  * implementation.
27  *
28  * After editing this file, run it (./src/generator.ml) to regenerate
29  * all the output files.  'make' will rerun this automatically when
30  * necessary.  Note that if you are using a separate build directory
31  * you must run generator.ml from the _source_ directory.
32  *
33  * IMPORTANT: This script should NOT print any warnings.  If it prints
34  * warnings, you should treat them as errors.
35  *
36  * OCaml tips:
37  * (1) In emacs, install tuareg-mode to display and format OCaml code
38  * correctly.  'vim' comes with a good OCaml editing mode by default.
39  * (2) Read the resources at http://ocaml-tutorial.org/
40  *)
41
42 #load "unix.cma";;
43 #load "str.cma";;
44 #directory "+xml-light";;
45 #directory "+../pkg-lib/xml-light";; (* for GODI users *)
46 #load "xml-light.cma";;
47
48 open Unix
49 open Printf
50
51 type style = ret * args
52 and ret =
53     (* "RErr" as a return value means an int used as a simple error
54      * indication, ie. 0 or -1.
55      *)
56   | RErr
57
58     (* "RInt" as a return value means an int which is -1 for error
59      * or any value >= 0 on success.  Only use this for smallish
60      * positive ints (0 <= i < 2^30).
61      *)
62   | RInt of string
63
64     (* "RInt64" is the same as RInt, but is guaranteed to be able
65      * to return a full 64 bit value, _except_ that -1 means error
66      * (so -1 cannot be a valid, non-error return value).
67      *)
68   | RInt64 of string
69
70     (* "RBool" is a bool return value which can be true/false or
71      * -1 for error.
72      *)
73   | RBool of string
74
75     (* "RConstString" is a string that refers to a constant value.
76      * The return value must NOT be NULL (since NULL indicates
77      * an error).
78      *
79      * Try to avoid using this.  In particular you cannot use this
80      * for values returned from the daemon, because there is no
81      * thread-safe way to return them in the C API.
82      *)
83   | RConstString of string
84
85     (* "RConstOptString" is an even more broken version of
86      * "RConstString".  The returned string may be NULL and there
87      * is no way to return an error indication.  Avoid using this!
88      *)
89   | RConstOptString of string
90
91     (* "RString" is a returned string.  It must NOT be NULL, since
92      * a NULL return indicates an error.  The caller frees this.
93      *)
94   | RString of string
95
96     (* "RStringList" is a list of strings.  No string in the list
97      * can be NULL.  The caller frees the strings and the array.
98      *)
99   | RStringList of string
100
101     (* "RStruct" is a function which returns a single named structure
102      * or an error indication (in C, a struct, and in other languages
103      * with varying representations, but usually very efficient).  See
104      * after the function list below for the structures.
105      *)
106   | RStruct of string * string          (* name of retval, name of struct *)
107
108     (* "RStructList" is a function which returns either a list/array
109      * of structures (could be zero-length), or an error indication.
110      *)
111   | RStructList of string * string      (* name of retval, name of struct *)
112
113     (* Key-value pairs of untyped strings.  Turns into a hashtable or
114      * dictionary in languages which support it.  DON'T use this as a
115      * general "bucket" for results.  Prefer a stronger typed return
116      * value if one is available, or write a custom struct.  Don't use
117      * this if the list could potentially be very long, since it is
118      * inefficient.  Keys should be unique.  NULLs are not permitted.
119      *)
120   | RHashtable of string
121
122     (* "RBufferOut" is handled almost exactly like RString, but
123      * it allows the string to contain arbitrary 8 bit data including
124      * ASCII NUL.  In the C API this causes an implicit extra parameter
125      * to be added of type <size_t *size_r>.  The extra parameter
126      * returns the actual size of the return buffer in bytes.
127      *
128      * Other programming languages support strings with arbitrary 8 bit
129      * data.
130      *
131      * At the RPC layer we have to use the opaque<> type instead of
132      * string<>.  Returned data is still limited to the max message
133      * size (ie. ~ 2 MB).
134      *)
135   | RBufferOut of string
136
137 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
138
139     (* Note in future we should allow a "variable args" parameter as
140      * the final parameter, to allow commands like
141      *   chmod mode file [file(s)...]
142      * This is not implemented yet, but many commands (such as chmod)
143      * are currently defined with the argument order keeping this future
144      * possibility in mind.
145      *)
146 and argt =
147   | String of string    (* const char *name, cannot be NULL *)
148   | Device of string    (* /dev device name, cannot be NULL *)
149   | Pathname of string  (* file name, cannot be NULL *)
150   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
151   | OptString of string (* const char *name, may be NULL *)
152   | StringList of string(* list of strings (each string cannot be NULL) *)
153   | DeviceList of string(* list of Device names (each cannot be NULL) *)
154   | Bool of string      (* boolean *)
155   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
156   | Int64 of string     (* any 64 bit int *)
157     (* These are treated as filenames (simple string parameters) in
158      * the C API and bindings.  But in the RPC protocol, we transfer
159      * the actual file content up to or down from the daemon.
160      * FileIn: local machine -> daemon (in request)
161      * FileOut: daemon -> local machine (in reply)
162      * In guestfish (only), the special name "-" means read from
163      * stdin or write to stdout.
164      *)
165   | FileIn of string
166   | FileOut of string
167     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <const char *, size_t> pair.
169      * Most other languages have a string type which can contain
170      * ASCII NUL.  We use whatever type is appropriate for each
171      * language.
172      * Buffers are limited by the total message size.  To transfer
173      * large blocks of data, use FileIn/FileOut parameters instead.
174      * To return an arbitrary buffer, use RBufferOut.
175      *)
176   | BufferIn of string
177
178 type flags =
179   | ProtocolLimitWarning  (* display warning about protocol size limits *)
180   | DangerWillRobinson    (* flags particularly dangerous commands *)
181   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
182   | FishOutput of fish_output_t (* how to display output in guestfish *)
183   | NotInFish             (* do not export via guestfish *)
184   | NotInDocs             (* do not add this function to documentation *)
185   | DeprecatedBy of string (* function is deprecated, use .. instead *)
186   | Optional of string    (* function is part of an optional group *)
187
188 and fish_output_t =
189   | FishOutputOctal       (* for int return, print in octal *)
190   | FishOutputHexadecimal (* for int return, print in hex *)
191
192 (* You can supply zero or as many tests as you want per API call.
193  *
194  * Note that the test environment has 3 block devices, of size 500MB,
195  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
196  * a fourth ISO block device with some known files on it (/dev/sdd).
197  *
198  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
199  * Number of cylinders was 63 for IDE emulated disks with precisely
200  * the same size.  How exactly this is calculated is a mystery.
201  *
202  * The ISO block device (/dev/sdd) comes from images/test.iso.
203  *
204  * To be able to run the tests in a reasonable amount of time,
205  * the virtual machine and block devices are reused between tests.
206  * So don't try testing kill_subprocess :-x
207  *
208  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
209  *
210  * Don't assume anything about the previous contents of the block
211  * devices.  Use 'Init*' to create some initial scenarios.
212  *
213  * You can add a prerequisite clause to any individual test.  This
214  * is a run-time check, which, if it fails, causes the test to be
215  * skipped.  Useful if testing a command which might not work on
216  * all variations of libguestfs builds.  A test that has prerequisite
217  * of 'Always' is run unconditionally.
218  *
219  * In addition, packagers can skip individual tests by setting the
220  * environment variables:     eg:
221  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
222  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
223  *)
224 type tests = (test_init * test_prereq * test) list
225 and test =
226     (* Run the command sequence and just expect nothing to fail. *)
227   | TestRun of seq
228
229     (* Run the command sequence and expect the output of the final
230      * command to be the string.
231      *)
232   | TestOutput of seq * string
233
234     (* Run the command sequence and expect the output of the final
235      * command to be the list of strings.
236      *)
237   | TestOutputList of seq * string list
238
239     (* Run the command sequence and expect the output of the final
240      * command to be the list of block devices (could be either
241      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
242      * character of each string).
243      *)
244   | TestOutputListOfDevices of seq * string list
245
246     (* Run the command sequence and expect the output of the final
247      * command to be the integer.
248      *)
249   | TestOutputInt of seq * int
250
251     (* Run the command sequence and expect the output of the final
252      * command to be <op> <int>, eg. ">=", "1".
253      *)
254   | TestOutputIntOp of seq * string * int
255
256     (* Run the command sequence and expect the output of the final
257      * command to be a true value (!= 0 or != NULL).
258      *)
259   | TestOutputTrue of seq
260
261     (* Run the command sequence and expect the output of the final
262      * command to be a false value (== 0 or == NULL, but not an error).
263      *)
264   | TestOutputFalse of seq
265
266     (* Run the command sequence and expect the output of the final
267      * command to be a list of the given length (but don't care about
268      * content).
269      *)
270   | TestOutputLength of seq * int
271
272     (* Run the command sequence and expect the output of the final
273      * command to be a buffer (RBufferOut), ie. string + size.
274      *)
275   | TestOutputBuffer of seq * string
276
277     (* Run the command sequence and expect the output of the final
278      * command to be a structure.
279      *)
280   | TestOutputStruct of seq * test_field_compare list
281
282     (* Run the command sequence and expect the final command (only)
283      * to fail.
284      *)
285   | TestLastFail of seq
286
287 and test_field_compare =
288   | CompareWithInt of string * int
289   | CompareWithIntOp of string * string * int
290   | CompareWithString of string * string
291   | CompareFieldsIntEq of string * string
292   | CompareFieldsStrEq of string * string
293
294 (* Test prerequisites. *)
295 and test_prereq =
296     (* Test always runs. *)
297   | Always
298
299     (* Test is currently disabled - eg. it fails, or it tests some
300      * unimplemented feature.
301      *)
302   | Disabled
303
304     (* 'string' is some C code (a function body) that should return
305      * true or false.  The test will run if the code returns true.
306      *)
307   | If of string
308
309     (* As for 'If' but the test runs _unless_ the code returns true. *)
310   | Unless of string
311
312 (* Some initial scenarios for testing. *)
313 and test_init =
314     (* Do nothing, block devices could contain random stuff including
315      * LVM PVs, and some filesystems might be mounted.  This is usually
316      * a bad idea.
317      *)
318   | InitNone
319
320     (* Block devices are empty and no filesystems are mounted. *)
321   | InitEmpty
322
323     (* /dev/sda contains a single partition /dev/sda1, with random
324      * content.  /dev/sdb and /dev/sdc may have random content.
325      * No LVM.
326      *)
327   | InitPartition
328
329     (* /dev/sda contains a single partition /dev/sda1, which is formatted
330      * as ext2, empty [except for lost+found] and mounted on /.
331      * /dev/sdb and /dev/sdc may have random content.
332      * No LVM.
333      *)
334   | InitBasicFS
335
336     (* /dev/sda:
337      *   /dev/sda1 (is a PV):
338      *     /dev/VG/LV (size 8MB):
339      *       formatted as ext2, empty [except for lost+found], mounted on /
340      * /dev/sdb and /dev/sdc may have random content.
341      *)
342   | InitBasicFSonLVM
343
344     (* /dev/sdd (the ISO, see images/ directory in source)
345      * is mounted on /
346      *)
347   | InitISOFS
348
349 (* Sequence of commands for testing. *)
350 and seq = cmd list
351 and cmd = string list
352
353 (* Note about long descriptions: When referring to another
354  * action, use the format C<guestfs_other> (ie. the full name of
355  * the C function).  This will be replaced as appropriate in other
356  * language bindings.
357  *
358  * Apart from that, long descriptions are just perldoc paragraphs.
359  *)
360
361 (* Generate a random UUID (used in tests). *)
362 let uuidgen () =
363   let chan = open_process_in "uuidgen" in
364   let uuid = input_line chan in
365   (match close_process_in chan with
366    | WEXITED 0 -> ()
367    | WEXITED _ ->
368        failwith "uuidgen: process exited with non-zero status"
369    | WSIGNALED _ | WSTOPPED _ ->
370        failwith "uuidgen: process signalled or stopped by signal"
371   );
372   uuid
373
374 (* These test functions are used in the language binding tests. *)
375
376 let test_all_args = [
377   String "str";
378   OptString "optstr";
379   StringList "strlist";
380   Bool "b";
381   Int "integer";
382   Int64 "integer64";
383   FileIn "filein";
384   FileOut "fileout";
385   BufferIn "bufferin";
386 ]
387
388 let test_all_rets = [
389   (* except for RErr, which is tested thoroughly elsewhere *)
390   "test0rint",         RInt "valout";
391   "test0rint64",       RInt64 "valout";
392   "test0rbool",        RBool "valout";
393   "test0rconststring", RConstString "valout";
394   "test0rconstoptstring", RConstOptString "valout";
395   "test0rstring",      RString "valout";
396   "test0rstringlist",  RStringList "valout";
397   "test0rstruct",      RStruct ("valout", "lvm_pv");
398   "test0rstructlist",  RStructList ("valout", "lvm_pv");
399   "test0rhashtable",   RHashtable "valout";
400 ]
401
402 let test_functions = [
403   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
404    [],
405    "internal test function - do not use",
406    "\
407 This is an internal test function which is used to test whether
408 the automatically generated bindings can handle every possible
409 parameter type correctly.
410
411 It echos the contents of each parameter to stdout.
412
413 You probably don't want to call this function.");
414 ] @ List.flatten (
415   List.map (
416     fun (name, ret) ->
417       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
418         [],
419         "internal test function - do not use",
420         "\
421 This is an internal test function which is used to test whether
422 the automatically generated bindings can handle every possible
423 return type correctly.
424
425 It converts string C<val> to the return type.
426
427 You probably don't want to call this function.");
428        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
429         [],
430         "internal test function - do not use",
431         "\
432 This is an internal test function which is used to test whether
433 the automatically generated bindings can handle every possible
434 return type correctly.
435
436 This function always returns an error.
437
438 You probably don't want to call this function.")]
439   ) test_all_rets
440 )
441
442 (* non_daemon_functions are any functions which don't get processed
443  * in the daemon, eg. functions for setting and getting local
444  * configuration values.
445  *)
446
447 let non_daemon_functions = test_functions @ [
448   ("launch", (RErr, []), -1, [FishAlias "run"],
449    [],
450    "launch the qemu subprocess",
451    "\
452 Internally libguestfs is implemented by running a virtual machine
453 using L<qemu(1)>.
454
455 You should call this after configuring the handle
456 (eg. adding drives) but before performing any actions.");
457
458   ("wait_ready", (RErr, []), -1, [NotInFish],
459    [],
460    "wait until the qemu subprocess launches (no op)",
461    "\
462 This function is a no op.
463
464 In versions of the API E<lt> 1.0.71 you had to call this function
465 just after calling C<guestfs_launch> to wait for the launch
466 to complete.  However this is no longer necessary because
467 C<guestfs_launch> now does the waiting.
468
469 If you see any calls to this function in code then you can just
470 remove them, unless you want to retain compatibility with older
471 versions of the API.");
472
473   ("kill_subprocess", (RErr, []), -1, [],
474    [],
475    "kill the qemu subprocess",
476    "\
477 This kills the qemu subprocess.  You should never need to call this.");
478
479   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
480    [],
481    "add an image to examine or modify",
482    "\
483 This function adds a virtual machine disk image C<filename> to the
484 guest.  The first time you call this function, the disk appears as IDE
485 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
486 so on.
487
488 You don't necessarily need to be root when using libguestfs.  However
489 you obviously do need sufficient permissions to access the filename
490 for whatever operations you want to perform (ie. read access if you
491 just want to read the image or write access if you want to modify the
492 image).
493
494 This is equivalent to the qemu parameter
495 C<-drive file=filename,cache=off,if=...>.
496
497 C<cache=off> is omitted in cases where it is not supported by
498 the underlying filesystem.
499
500 C<if=...> is set at compile time by the configuration option
501 C<./configure --with-drive-if=...>.  In the rare case where you
502 might need to change this at run time, use C<guestfs_add_drive_with_if>
503 or C<guestfs_add_drive_ro_with_if>.
504
505 Note that this call checks for the existence of C<filename>.  This
506 stops you from specifying other types of drive which are supported
507 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
508 the general C<guestfs_config> call instead.");
509
510   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
511    [],
512    "add a CD-ROM disk image to examine",
513    "\
514 This function adds a virtual CD-ROM disk image to the guest.
515
516 This is equivalent to the qemu parameter C<-cdrom filename>.
517
518 Notes:
519
520 =over 4
521
522 =item *
523
524 This call checks for the existence of C<filename>.  This
525 stops you from specifying other types of drive which are supported
526 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
527 the general C<guestfs_config> call instead.
528
529 =item *
530
531 If you just want to add an ISO file (often you use this as an
532 efficient way to transfer large files into the guest), then you
533 should probably use C<guestfs_add_drive_ro> instead.
534
535 =back");
536
537   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
538    [],
539    "add a drive in snapshot mode (read-only)",
540    "\
541 This adds a drive in snapshot mode, making it effectively
542 read-only.
543
544 Note that writes to the device are allowed, and will be seen for
545 the duration of the guestfs handle, but they are written
546 to a temporary file which is discarded as soon as the guestfs
547 handle is closed.  We don't currently have any method to enable
548 changes to be committed, although qemu can support this.
549
550 This is equivalent to the qemu parameter
551 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
552
553 C<if=...> is set at compile time by the configuration option
554 C<./configure --with-drive-if=...>.  In the rare case where you
555 might need to change this at run time, use C<guestfs_add_drive_with_if>
556 or C<guestfs_add_drive_ro_with_if>.
557
558 C<readonly=on> is only added where qemu supports this option.
559
560 Note that this call checks for the existence of C<filename>.  This
561 stops you from specifying other types of drive which are supported
562 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
563 the general C<guestfs_config> call instead.");
564
565   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
566    [],
567    "add qemu parameters",
568    "\
569 This can be used to add arbitrary qemu command line parameters
570 of the form C<-param value>.  Actually it's not quite arbitrary - we
571 prevent you from setting some parameters which would interfere with
572 parameters that we use.
573
574 The first character of C<param> string must be a C<-> (dash).
575
576 C<value> can be NULL.");
577
578   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
579    [],
580    "set the qemu binary",
581    "\
582 Set the qemu binary that we will use.
583
584 The default is chosen when the library was compiled by the
585 configure script.
586
587 You can also override this by setting the C<LIBGUESTFS_QEMU>
588 environment variable.
589
590 Setting C<qemu> to C<NULL> restores the default qemu binary.
591
592 Note that you should call this function as early as possible
593 after creating the handle.  This is because some pre-launch
594 operations depend on testing qemu features (by running C<qemu -help>).
595 If the qemu binary changes, we don't retest features, and
596 so you might see inconsistent results.  Using the environment
597 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
598 the qemu binary at the same time as the handle is created.");
599
600   ("get_qemu", (RConstString "qemu", []), -1, [],
601    [InitNone, Always, TestRun (
602       [["get_qemu"]])],
603    "get the qemu binary",
604    "\
605 Return the current qemu binary.
606
607 This is always non-NULL.  If it wasn't set already, then this will
608 return the default qemu binary name.");
609
610   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
611    [],
612    "set the search path",
613    "\
614 Set the path that libguestfs searches for kernel and initrd.img.
615
616 The default is C<$libdir/guestfs> unless overridden by setting
617 C<LIBGUESTFS_PATH> environment variable.
618
619 Setting C<path> to C<NULL> restores the default path.");
620
621   ("get_path", (RConstString "path", []), -1, [],
622    [InitNone, Always, TestRun (
623       [["get_path"]])],
624    "get the search path",
625    "\
626 Return the current search path.
627
628 This is always non-NULL.  If it wasn't set already, then this will
629 return the default path.");
630
631   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
632    [],
633    "add options to kernel command line",
634    "\
635 This function is used to add additional options to the
636 guest kernel command line.
637
638 The default is C<NULL> unless overridden by setting
639 C<LIBGUESTFS_APPEND> environment variable.
640
641 Setting C<append> to C<NULL> means I<no> additional options
642 are passed (libguestfs always adds a few of its own).");
643
644   ("get_append", (RConstOptString "append", []), -1, [],
645    (* This cannot be tested with the current framework.  The
646     * function can return NULL in normal operations, which the
647     * test framework interprets as an error.
648     *)
649    [],
650    "get the additional kernel options",
651    "\
652 Return the additional kernel options which are added to the
653 guest kernel command line.
654
655 If C<NULL> then no options are added.");
656
657   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
658    [],
659    "set autosync mode",
660    "\
661 If C<autosync> is true, this enables autosync.  Libguestfs will make a
662 best effort attempt to run C<guestfs_umount_all> followed by
663 C<guestfs_sync> when the handle is closed
664 (also if the program exits without closing handles).
665
666 This is disabled by default (except in guestfish where it is
667 enabled by default).");
668
669   ("get_autosync", (RBool "autosync", []), -1, [],
670    [InitNone, Always, TestRun (
671       [["get_autosync"]])],
672    "get autosync mode",
673    "\
674 Get the autosync flag.");
675
676   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
677    [],
678    "set verbose mode",
679    "\
680 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
681
682 Verbose messages are disabled unless the environment variable
683 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
684
685   ("get_verbose", (RBool "verbose", []), -1, [],
686    [],
687    "get verbose mode",
688    "\
689 This returns the verbose messages flag.");
690
691   ("is_ready", (RBool "ready", []), -1, [],
692    [InitNone, Always, TestOutputTrue (
693       [["is_ready"]])],
694    "is ready to accept commands",
695    "\
696 This returns true iff this handle is ready to accept commands
697 (in the C<READY> state).
698
699 For more information on states, see L<guestfs(3)>.");
700
701   ("is_config", (RBool "config", []), -1, [],
702    [InitNone, Always, TestOutputFalse (
703       [["is_config"]])],
704    "is in configuration state",
705    "\
706 This returns true iff this handle is being configured
707 (in the C<CONFIG> state).
708
709 For more information on states, see L<guestfs(3)>.");
710
711   ("is_launching", (RBool "launching", []), -1, [],
712    [InitNone, Always, TestOutputFalse (
713       [["is_launching"]])],
714    "is launching subprocess",
715    "\
716 This returns true iff this handle is launching the subprocess
717 (in the C<LAUNCHING> state).
718
719 For more information on states, see L<guestfs(3)>.");
720
721   ("is_busy", (RBool "busy", []), -1, [],
722    [InitNone, Always, TestOutputFalse (
723       [["is_busy"]])],
724    "is busy processing a command",
725    "\
726 This returns true iff this handle is busy processing a command
727 (in the C<BUSY> state).
728
729 For more information on states, see L<guestfs(3)>.");
730
731   ("get_state", (RInt "state", []), -1, [],
732    [],
733    "get the current state",
734    "\
735 This returns the current state as an opaque integer.  This is
736 only useful for printing debug and internal error messages.
737
738 For more information on states, see L<guestfs(3)>.");
739
740   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
741    [InitNone, Always, TestOutputInt (
742       [["set_memsize"; "500"];
743        ["get_memsize"]], 500)],
744    "set memory allocated to the qemu subprocess",
745    "\
746 This sets the memory size in megabytes allocated to the
747 qemu subprocess.  This only has any effect if called before
748 C<guestfs_launch>.
749
750 You can also change this by setting the environment
751 variable C<LIBGUESTFS_MEMSIZE> before the handle is
752 created.
753
754 For more information on the architecture of libguestfs,
755 see L<guestfs(3)>.");
756
757   ("get_memsize", (RInt "memsize", []), -1, [],
758    [InitNone, Always, TestOutputIntOp (
759       [["get_memsize"]], ">=", 256)],
760    "get memory allocated to the qemu subprocess",
761    "\
762 This gets the memory size in megabytes allocated to the
763 qemu subprocess.
764
765 If C<guestfs_set_memsize> was not called
766 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
767 then this returns the compiled-in default value for memsize.
768
769 For more information on the architecture of libguestfs,
770 see L<guestfs(3)>.");
771
772   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
773    [InitNone, Always, TestOutputIntOp (
774       [["get_pid"]], ">=", 1)],
775    "get PID of qemu subprocess",
776    "\
777 Return the process ID of the qemu subprocess.  If there is no
778 qemu subprocess, then this will return an error.
779
780 This is an internal call used for debugging and testing.");
781
782   ("version", (RStruct ("version", "version"), []), -1, [],
783    [InitNone, Always, TestOutputStruct (
784       [["version"]], [CompareWithInt ("major", 1)])],
785    "get the library version number",
786    "\
787 Return the libguestfs version number that the program is linked
788 against.
789
790 Note that because of dynamic linking this is not necessarily
791 the version of libguestfs that you compiled against.  You can
792 compile the program, and then at runtime dynamically link
793 against a completely different C<libguestfs.so> library.
794
795 This call was added in version C<1.0.58>.  In previous
796 versions of libguestfs there was no way to get the version
797 number.  From C code you can use ELF weak linking tricks to find out if
798 this symbol exists (if it doesn't, then it's an earlier version).
799
800 The call returns a structure with four elements.  The first
801 three (C<major>, C<minor> and C<release>) are numbers and
802 correspond to the usual version triplet.  The fourth element
803 (C<extra>) is a string and is normally empty, but may be
804 used for distro-specific information.
805
806 To construct the original version string:
807 C<$major.$minor.$release$extra>
808
809 I<Note:> Don't use this call to test for availability
810 of features.  Distro backports makes this unreliable.  Use
811 C<guestfs_available> instead.");
812
813   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
814    [InitNone, Always, TestOutputTrue (
815       [["set_selinux"; "true"];
816        ["get_selinux"]])],
817    "set SELinux enabled or disabled at appliance boot",
818    "\
819 This sets the selinux flag that is passed to the appliance
820 at boot time.  The default is C<selinux=0> (disabled).
821
822 Note that if SELinux is enabled, it is always in
823 Permissive mode (C<enforcing=0>).
824
825 For more information on the architecture of libguestfs,
826 see L<guestfs(3)>.");
827
828   ("get_selinux", (RBool "selinux", []), -1, [],
829    [],
830    "get SELinux enabled flag",
831    "\
832 This returns the current setting of the selinux flag which
833 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
834
835 For more information on the architecture of libguestfs,
836 see L<guestfs(3)>.");
837
838   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
839    [InitNone, Always, TestOutputFalse (
840       [["set_trace"; "false"];
841        ["get_trace"]])],
842    "enable or disable command traces",
843    "\
844 If the command trace flag is set to 1, then commands are
845 printed on stdout before they are executed in a format
846 which is very similar to the one used by guestfish.  In
847 other words, you can run a program with this enabled, and
848 you will get out a script which you can feed to guestfish
849 to perform the same set of actions.
850
851 If you want to trace C API calls into libguestfs (and
852 other libraries) then possibly a better way is to use
853 the external ltrace(1) command.
854
855 Command traces are disabled unless the environment variable
856 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
857
858   ("get_trace", (RBool "trace", []), -1, [],
859    [],
860    "get command trace enabled flag",
861    "\
862 Return the command trace flag.");
863
864   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
865    [InitNone, Always, TestOutputFalse (
866       [["set_direct"; "false"];
867        ["get_direct"]])],
868    "enable or disable direct appliance mode",
869    "\
870 If the direct appliance mode flag is enabled, then stdin and
871 stdout are passed directly through to the appliance once it
872 is launched.
873
874 One consequence of this is that log messages aren't caught
875 by the library and handled by C<guestfs_set_log_message_callback>,
876 but go straight to stdout.
877
878 You probably don't want to use this unless you know what you
879 are doing.
880
881 The default is disabled.");
882
883   ("get_direct", (RBool "direct", []), -1, [],
884    [],
885    "get direct appliance mode flag",
886    "\
887 Return the direct appliance mode flag.");
888
889   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
890    [InitNone, Always, TestOutputTrue (
891       [["set_recovery_proc"; "true"];
892        ["get_recovery_proc"]])],
893    "enable or disable the recovery process",
894    "\
895 If this is called with the parameter C<false> then
896 C<guestfs_launch> does not create a recovery process.  The
897 purpose of the recovery process is to stop runaway qemu
898 processes in the case where the main program aborts abruptly.
899
900 This only has any effect if called before C<guestfs_launch>,
901 and the default is true.
902
903 About the only time when you would want to disable this is
904 if the main process will fork itself into the background
905 (\"daemonize\" itself).  In this case the recovery process
906 thinks that the main program has disappeared and so kills
907 qemu, which is not very helpful.");
908
909   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
910    [],
911    "get recovery process enabled flag",
912    "\
913 Return the recovery process enabled flag.");
914
915   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
916    [],
917    "add a drive specifying the QEMU block emulation to use",
918    "\
919 This is the same as C<guestfs_add_drive> but it allows you
920 to specify the QEMU interface emulation to use at run time.");
921
922   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
923    [],
924    "add a drive read-only specifying the QEMU block emulation to use",
925    "\
926 This is the same as C<guestfs_add_drive_ro> but it allows you
927 to specify the QEMU interface emulation to use at run time.");
928
929 ]
930
931 (* daemon_functions are any functions which cause some action
932  * to take place in the daemon.
933  *)
934
935 let daemon_functions = [
936   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
937    [InitEmpty, Always, TestOutput (
938       [["part_disk"; "/dev/sda"; "mbr"];
939        ["mkfs"; "ext2"; "/dev/sda1"];
940        ["mount"; "/dev/sda1"; "/"];
941        ["write"; "/new"; "new file contents"];
942        ["cat"; "/new"]], "new file contents")],
943    "mount a guest disk at a position in the filesystem",
944    "\
945 Mount a guest disk at a position in the filesystem.  Block devices
946 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
947 the guest.  If those block devices contain partitions, they will have
948 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
949 names can be used.
950
951 The rules are the same as for L<mount(2)>:  A filesystem must
952 first be mounted on C</> before others can be mounted.  Other
953 filesystems can only be mounted on directories which already
954 exist.
955
956 The mounted filesystem is writable, if we have sufficient permissions
957 on the underlying device.
958
959 B<Important note:>
960 When you use this call, the filesystem options C<sync> and C<noatime>
961 are set implicitly.  This was originally done because we thought it
962 would improve reliability, but it turns out that I<-o sync> has a
963 very large negative performance impact and negligible effect on
964 reliability.  Therefore we recommend that you avoid using
965 C<guestfs_mount> in any code that needs performance, and instead
966 use C<guestfs_mount_options> (use an empty string for the first
967 parameter if you don't want any options).");
968
969   ("sync", (RErr, []), 2, [],
970    [ InitEmpty, Always, TestRun [["sync"]]],
971    "sync disks, writes are flushed through to the disk image",
972    "\
973 This syncs the disk, so that any writes are flushed through to the
974 underlying disk image.
975
976 You should always call this if you have modified a disk image, before
977 closing the handle.");
978
979   ("touch", (RErr, [Pathname "path"]), 3, [],
980    [InitBasicFS, Always, TestOutputTrue (
981       [["touch"; "/new"];
982        ["exists"; "/new"]])],
983    "update file timestamps or create a new file",
984    "\
985 Touch acts like the L<touch(1)> command.  It can be used to
986 update the timestamps on a file, or, if the file does not exist,
987 to create a new zero-length file.");
988
989   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
990    [InitISOFS, Always, TestOutput (
991       [["cat"; "/known-2"]], "abcdef\n")],
992    "list the contents of a file",
993    "\
994 Return the contents of the file named C<path>.
995
996 Note that this function cannot correctly handle binary files
997 (specifically, files containing C<\\0> character which is treated
998 as end of string).  For those you need to use the C<guestfs_read_file>
999 or C<guestfs_download> functions which have a more complex interface.");
1000
1001   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1002    [], (* XXX Tricky to test because it depends on the exact format
1003         * of the 'ls -l' command, which changes between F10 and F11.
1004         *)
1005    "list the files in a directory (long format)",
1006    "\
1007 List the files in C<directory> (relative to the root directory,
1008 there is no cwd) in the format of 'ls -la'.
1009
1010 This command is mostly useful for interactive sessions.  It
1011 is I<not> intended that you try to parse the output string.");
1012
1013   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1014    [InitBasicFS, Always, TestOutputList (
1015       [["touch"; "/new"];
1016        ["touch"; "/newer"];
1017        ["touch"; "/newest"];
1018        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1019    "list the files in a directory",
1020    "\
1021 List the files in C<directory> (relative to the root directory,
1022 there is no cwd).  The '.' and '..' entries are not returned, but
1023 hidden files are shown.
1024
1025 This command is mostly useful for interactive sessions.  Programs
1026 should probably use C<guestfs_readdir> instead.");
1027
1028   ("list_devices", (RStringList "devices", []), 7, [],
1029    [InitEmpty, Always, TestOutputListOfDevices (
1030       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1031    "list the block devices",
1032    "\
1033 List all the block devices.
1034
1035 The full block device names are returned, eg. C</dev/sda>");
1036
1037   ("list_partitions", (RStringList "partitions", []), 8, [],
1038    [InitBasicFS, Always, TestOutputListOfDevices (
1039       [["list_partitions"]], ["/dev/sda1"]);
1040     InitEmpty, Always, TestOutputListOfDevices (
1041       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1042        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1043    "list the partitions",
1044    "\
1045 List all the partitions detected on all block devices.
1046
1047 The full partition device names are returned, eg. C</dev/sda1>
1048
1049 This does not return logical volumes.  For that you will need to
1050 call C<guestfs_lvs>.");
1051
1052   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1053    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1054       [["pvs"]], ["/dev/sda1"]);
1055     InitEmpty, Always, TestOutputListOfDevices (
1056       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1057        ["pvcreate"; "/dev/sda1"];
1058        ["pvcreate"; "/dev/sda2"];
1059        ["pvcreate"; "/dev/sda3"];
1060        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1061    "list the LVM physical volumes (PVs)",
1062    "\
1063 List all the physical volumes detected.  This is the equivalent
1064 of the L<pvs(8)> command.
1065
1066 This returns a list of just the device names that contain
1067 PVs (eg. C</dev/sda2>).
1068
1069 See also C<guestfs_pvs_full>.");
1070
1071   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1072    [InitBasicFSonLVM, Always, TestOutputList (
1073       [["vgs"]], ["VG"]);
1074     InitEmpty, Always, TestOutputList (
1075       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1076        ["pvcreate"; "/dev/sda1"];
1077        ["pvcreate"; "/dev/sda2"];
1078        ["pvcreate"; "/dev/sda3"];
1079        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1080        ["vgcreate"; "VG2"; "/dev/sda3"];
1081        ["vgs"]], ["VG1"; "VG2"])],
1082    "list the LVM volume groups (VGs)",
1083    "\
1084 List all the volumes groups detected.  This is the equivalent
1085 of the L<vgs(8)> command.
1086
1087 This returns a list of just the volume group names that were
1088 detected (eg. C<VolGroup00>).
1089
1090 See also C<guestfs_vgs_full>.");
1091
1092   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1093    [InitBasicFSonLVM, Always, TestOutputList (
1094       [["lvs"]], ["/dev/VG/LV"]);
1095     InitEmpty, Always, TestOutputList (
1096       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1097        ["pvcreate"; "/dev/sda1"];
1098        ["pvcreate"; "/dev/sda2"];
1099        ["pvcreate"; "/dev/sda3"];
1100        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1101        ["vgcreate"; "VG2"; "/dev/sda3"];
1102        ["lvcreate"; "LV1"; "VG1"; "50"];
1103        ["lvcreate"; "LV2"; "VG1"; "50"];
1104        ["lvcreate"; "LV3"; "VG2"; "50"];
1105        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1106    "list the LVM logical volumes (LVs)",
1107    "\
1108 List all the logical volumes detected.  This is the equivalent
1109 of the L<lvs(8)> command.
1110
1111 This returns a list of the logical volume device names
1112 (eg. C</dev/VolGroup00/LogVol00>).
1113
1114 See also C<guestfs_lvs_full>.");
1115
1116   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1117    [], (* XXX how to test? *)
1118    "list the LVM physical volumes (PVs)",
1119    "\
1120 List all the physical volumes detected.  This is the equivalent
1121 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1122
1123   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1124    [], (* XXX how to test? *)
1125    "list the LVM volume groups (VGs)",
1126    "\
1127 List all the volumes groups detected.  This is the equivalent
1128 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1129
1130   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1131    [], (* XXX how to test? *)
1132    "list the LVM logical volumes (LVs)",
1133    "\
1134 List all the logical volumes detected.  This is the equivalent
1135 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1136
1137   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1138    [InitISOFS, Always, TestOutputList (
1139       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1140     InitISOFS, Always, TestOutputList (
1141       [["read_lines"; "/empty"]], [])],
1142    "read file as lines",
1143    "\
1144 Return the contents of the file named C<path>.
1145
1146 The file contents are returned as a list of lines.  Trailing
1147 C<LF> and C<CRLF> character sequences are I<not> returned.
1148
1149 Note that this function cannot correctly handle binary files
1150 (specifically, files containing C<\\0> character which is treated
1151 as end of line).  For those you need to use the C<guestfs_read_file>
1152 function which has a more complex interface.");
1153
1154   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1155    [], (* XXX Augeas code needs tests. *)
1156    "create a new Augeas handle",
1157    "\
1158 Create a new Augeas handle for editing configuration files.
1159 If there was any previous Augeas handle associated with this
1160 guestfs session, then it is closed.
1161
1162 You must call this before using any other C<guestfs_aug_*>
1163 commands.
1164
1165 C<root> is the filesystem root.  C<root> must not be NULL,
1166 use C</> instead.
1167
1168 The flags are the same as the flags defined in
1169 E<lt>augeas.hE<gt>, the logical I<or> of the following
1170 integers:
1171
1172 =over 4
1173
1174 =item C<AUG_SAVE_BACKUP> = 1
1175
1176 Keep the original file with a C<.augsave> extension.
1177
1178 =item C<AUG_SAVE_NEWFILE> = 2
1179
1180 Save changes into a file with extension C<.augnew>, and
1181 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1182
1183 =item C<AUG_TYPE_CHECK> = 4
1184
1185 Typecheck lenses (can be expensive).
1186
1187 =item C<AUG_NO_STDINC> = 8
1188
1189 Do not use standard load path for modules.
1190
1191 =item C<AUG_SAVE_NOOP> = 16
1192
1193 Make save a no-op, just record what would have been changed.
1194
1195 =item C<AUG_NO_LOAD> = 32
1196
1197 Do not load the tree in C<guestfs_aug_init>.
1198
1199 =back
1200
1201 To close the handle, you can call C<guestfs_aug_close>.
1202
1203 To find out more about Augeas, see L<http://augeas.net/>.");
1204
1205   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1206    [], (* XXX Augeas code needs tests. *)
1207    "close the current Augeas handle",
1208    "\
1209 Close the current Augeas handle and free up any resources
1210 used by it.  After calling this, you have to call
1211 C<guestfs_aug_init> again before you can use any other
1212 Augeas functions.");
1213
1214   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1215    [], (* XXX Augeas code needs tests. *)
1216    "define an Augeas variable",
1217    "\
1218 Defines an Augeas variable C<name> whose value is the result
1219 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1220 undefined.
1221
1222 On success this returns the number of nodes in C<expr>, or
1223 C<0> if C<expr> evaluates to something which is not a nodeset.");
1224
1225   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1226    [], (* XXX Augeas code needs tests. *)
1227    "define an Augeas node",
1228    "\
1229 Defines a variable C<name> whose value is the result of
1230 evaluating C<expr>.
1231
1232 If C<expr> evaluates to an empty nodeset, a node is created,
1233 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1234 C<name> will be the nodeset containing that single node.
1235
1236 On success this returns a pair containing the
1237 number of nodes in the nodeset, and a boolean flag
1238 if a node was created.");
1239
1240   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1241    [], (* XXX Augeas code needs tests. *)
1242    "look up the value of an Augeas path",
1243    "\
1244 Look up the value associated with C<path>.  If C<path>
1245 matches exactly one node, the C<value> is returned.");
1246
1247   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1248    [], (* XXX Augeas code needs tests. *)
1249    "set Augeas path to value",
1250    "\
1251 Set the value associated with C<path> to C<val>.
1252
1253 In the Augeas API, it is possible to clear a node by setting
1254 the value to NULL.  Due to an oversight in the libguestfs API
1255 you cannot do that with this call.  Instead you must use the
1256 C<guestfs_aug_clear> call.");
1257
1258   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1259    [], (* XXX Augeas code needs tests. *)
1260    "insert a sibling Augeas node",
1261    "\
1262 Create a new sibling C<label> for C<path>, inserting it into
1263 the tree before or after C<path> (depending on the boolean
1264 flag C<before>).
1265
1266 C<path> must match exactly one existing node in the tree, and
1267 C<label> must be a label, ie. not contain C</>, C<*> or end
1268 with a bracketed index C<[N]>.");
1269
1270   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1271    [], (* XXX Augeas code needs tests. *)
1272    "remove an Augeas path",
1273    "\
1274 Remove C<path> and all of its children.
1275
1276 On success this returns the number of entries which were removed.");
1277
1278   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1279    [], (* XXX Augeas code needs tests. *)
1280    "move Augeas node",
1281    "\
1282 Move the node C<src> to C<dest>.  C<src> must match exactly
1283 one node.  C<dest> is overwritten if it exists.");
1284
1285   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1286    [], (* XXX Augeas code needs tests. *)
1287    "return Augeas nodes which match augpath",
1288    "\
1289 Returns a list of paths which match the path expression C<path>.
1290 The returned paths are sufficiently qualified so that they match
1291 exactly one node in the current tree.");
1292
1293   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1294    [], (* XXX Augeas code needs tests. *)
1295    "write all pending Augeas changes to disk",
1296    "\
1297 This writes all pending changes to disk.
1298
1299 The flags which were passed to C<guestfs_aug_init> affect exactly
1300 how files are saved.");
1301
1302   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1303    [], (* XXX Augeas code needs tests. *)
1304    "load files into the tree",
1305    "\
1306 Load files into the tree.
1307
1308 See C<aug_load> in the Augeas documentation for the full gory
1309 details.");
1310
1311   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1312    [], (* XXX Augeas code needs tests. *)
1313    "list Augeas nodes under augpath",
1314    "\
1315 This is just a shortcut for listing C<guestfs_aug_match>
1316 C<path/*> and sorting the resulting nodes into alphabetical order.");
1317
1318   ("rm", (RErr, [Pathname "path"]), 29, [],
1319    [InitBasicFS, Always, TestRun
1320       [["touch"; "/new"];
1321        ["rm"; "/new"]];
1322     InitBasicFS, Always, TestLastFail
1323       [["rm"; "/new"]];
1324     InitBasicFS, Always, TestLastFail
1325       [["mkdir"; "/new"];
1326        ["rm"; "/new"]]],
1327    "remove a file",
1328    "\
1329 Remove the single file C<path>.");
1330
1331   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1332    [InitBasicFS, Always, TestRun
1333       [["mkdir"; "/new"];
1334        ["rmdir"; "/new"]];
1335     InitBasicFS, Always, TestLastFail
1336       [["rmdir"; "/new"]];
1337     InitBasicFS, Always, TestLastFail
1338       [["touch"; "/new"];
1339        ["rmdir"; "/new"]]],
1340    "remove a directory",
1341    "\
1342 Remove the single directory C<path>.");
1343
1344   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1345    [InitBasicFS, Always, TestOutputFalse
1346       [["mkdir"; "/new"];
1347        ["mkdir"; "/new/foo"];
1348        ["touch"; "/new/foo/bar"];
1349        ["rm_rf"; "/new"];
1350        ["exists"; "/new"]]],
1351    "remove a file or directory recursively",
1352    "\
1353 Remove the file or directory C<path>, recursively removing the
1354 contents if its a directory.  This is like the C<rm -rf> shell
1355 command.");
1356
1357   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1358    [InitBasicFS, Always, TestOutputTrue
1359       [["mkdir"; "/new"];
1360        ["is_dir"; "/new"]];
1361     InitBasicFS, Always, TestLastFail
1362       [["mkdir"; "/new/foo/bar"]]],
1363    "create a directory",
1364    "\
1365 Create a directory named C<path>.");
1366
1367   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1368    [InitBasicFS, Always, TestOutputTrue
1369       [["mkdir_p"; "/new/foo/bar"];
1370        ["is_dir"; "/new/foo/bar"]];
1371     InitBasicFS, Always, TestOutputTrue
1372       [["mkdir_p"; "/new/foo/bar"];
1373        ["is_dir"; "/new/foo"]];
1374     InitBasicFS, Always, TestOutputTrue
1375       [["mkdir_p"; "/new/foo/bar"];
1376        ["is_dir"; "/new"]];
1377     (* Regression tests for RHBZ#503133: *)
1378     InitBasicFS, Always, TestRun
1379       [["mkdir"; "/new"];
1380        ["mkdir_p"; "/new"]];
1381     InitBasicFS, Always, TestLastFail
1382       [["touch"; "/new"];
1383        ["mkdir_p"; "/new"]]],
1384    "create a directory and parents",
1385    "\
1386 Create a directory named C<path>, creating any parent directories
1387 as necessary.  This is like the C<mkdir -p> shell command.");
1388
1389   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1390    [], (* XXX Need stat command to test *)
1391    "change file mode",
1392    "\
1393 Change the mode (permissions) of C<path> to C<mode>.  Only
1394 numeric modes are supported.
1395
1396 I<Note>: When using this command from guestfish, C<mode>
1397 by default would be decimal, unless you prefix it with
1398 C<0> to get octal, ie. use C<0700> not C<700>.
1399
1400 The mode actually set is affected by the umask.");
1401
1402   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1403    [], (* XXX Need stat command to test *)
1404    "change file owner and group",
1405    "\
1406 Change the file owner to C<owner> and group to C<group>.
1407
1408 Only numeric uid and gid are supported.  If you want to use
1409 names, you will need to locate and parse the password file
1410 yourself (Augeas support makes this relatively easy).");
1411
1412   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1413    [InitISOFS, Always, TestOutputTrue (
1414       [["exists"; "/empty"]]);
1415     InitISOFS, Always, TestOutputTrue (
1416       [["exists"; "/directory"]])],
1417    "test if file or directory exists",
1418    "\
1419 This returns C<true> if and only if there is a file, directory
1420 (or anything) with the given C<path> name.
1421
1422 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1423
1424   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1425    [InitISOFS, Always, TestOutputTrue (
1426       [["is_file"; "/known-1"]]);
1427     InitISOFS, Always, TestOutputFalse (
1428       [["is_file"; "/directory"]])],
1429    "test if file exists",
1430    "\
1431 This returns C<true> if and only if there is a file
1432 with the given C<path> name.  Note that it returns false for
1433 other objects like directories.
1434
1435 See also C<guestfs_stat>.");
1436
1437   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1438    [InitISOFS, Always, TestOutputFalse (
1439       [["is_dir"; "/known-3"]]);
1440     InitISOFS, Always, TestOutputTrue (
1441       [["is_dir"; "/directory"]])],
1442    "test if file exists",
1443    "\
1444 This returns C<true> if and only if there is a directory
1445 with the given C<path> name.  Note that it returns false for
1446 other objects like files.
1447
1448 See also C<guestfs_stat>.");
1449
1450   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1451    [InitEmpty, Always, TestOutputListOfDevices (
1452       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1453        ["pvcreate"; "/dev/sda1"];
1454        ["pvcreate"; "/dev/sda2"];
1455        ["pvcreate"; "/dev/sda3"];
1456        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1457    "create an LVM physical volume",
1458    "\
1459 This creates an LVM physical volume on the named C<device>,
1460 where C<device> should usually be a partition name such
1461 as C</dev/sda1>.");
1462
1463   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1464    [InitEmpty, Always, TestOutputList (
1465       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1466        ["pvcreate"; "/dev/sda1"];
1467        ["pvcreate"; "/dev/sda2"];
1468        ["pvcreate"; "/dev/sda3"];
1469        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1470        ["vgcreate"; "VG2"; "/dev/sda3"];
1471        ["vgs"]], ["VG1"; "VG2"])],
1472    "create an LVM volume group",
1473    "\
1474 This creates an LVM volume group called C<volgroup>
1475 from the non-empty list of physical volumes C<physvols>.");
1476
1477   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1478    [InitEmpty, Always, TestOutputList (
1479       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1480        ["pvcreate"; "/dev/sda1"];
1481        ["pvcreate"; "/dev/sda2"];
1482        ["pvcreate"; "/dev/sda3"];
1483        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1484        ["vgcreate"; "VG2"; "/dev/sda3"];
1485        ["lvcreate"; "LV1"; "VG1"; "50"];
1486        ["lvcreate"; "LV2"; "VG1"; "50"];
1487        ["lvcreate"; "LV3"; "VG2"; "50"];
1488        ["lvcreate"; "LV4"; "VG2"; "50"];
1489        ["lvcreate"; "LV5"; "VG2"; "50"];
1490        ["lvs"]],
1491       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1492        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1493    "create an LVM logical volume",
1494    "\
1495 This creates an LVM logical volume called C<logvol>
1496 on the volume group C<volgroup>, with C<size> megabytes.");
1497
1498   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1499    [InitEmpty, Always, TestOutput (
1500       [["part_disk"; "/dev/sda"; "mbr"];
1501        ["mkfs"; "ext2"; "/dev/sda1"];
1502        ["mount_options"; ""; "/dev/sda1"; "/"];
1503        ["write"; "/new"; "new file contents"];
1504        ["cat"; "/new"]], "new file contents")],
1505    "make a filesystem",
1506    "\
1507 This creates a filesystem on C<device> (usually a partition
1508 or LVM logical volume).  The filesystem type is C<fstype>, for
1509 example C<ext3>.");
1510
1511   ("sfdisk", (RErr, [Device "device";
1512                      Int "cyls"; Int "heads"; Int "sectors";
1513                      StringList "lines"]), 43, [DangerWillRobinson],
1514    [],
1515    "create partitions on a block device",
1516    "\
1517 This is a direct interface to the L<sfdisk(8)> program for creating
1518 partitions on block devices.
1519
1520 C<device> should be a block device, for example C</dev/sda>.
1521
1522 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1523 and sectors on the device, which are passed directly to sfdisk as
1524 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1525 of these, then the corresponding parameter is omitted.  Usually for
1526 'large' disks, you can just pass C<0> for these, but for small
1527 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1528 out the right geometry and you will need to tell it.
1529
1530 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1531 information refer to the L<sfdisk(8)> manpage.
1532
1533 To create a single partition occupying the whole disk, you would
1534 pass C<lines> as a single element list, when the single element being
1535 the string C<,> (comma).
1536
1537 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1538 C<guestfs_part_init>");
1539
1540   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1541    [],
1542    "create a file",
1543    "\
1544 This call creates a file called C<path>.  The contents of the
1545 file is the string C<content> (which can contain any 8 bit data),
1546 with length C<size>.
1547
1548 As a special case, if C<size> is C<0>
1549 then the length is calculated using C<strlen> (so in this case
1550 the content cannot contain embedded ASCII NULs).
1551
1552 I<NB.> Owing to a bug, writing content containing ASCII NUL
1553 characters does I<not> work, even if the length is specified.");
1554
1555   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1556    [InitEmpty, Always, TestOutputListOfDevices (
1557       [["part_disk"; "/dev/sda"; "mbr"];
1558        ["mkfs"; "ext2"; "/dev/sda1"];
1559        ["mount_options"; ""; "/dev/sda1"; "/"];
1560        ["mounts"]], ["/dev/sda1"]);
1561     InitEmpty, Always, TestOutputList (
1562       [["part_disk"; "/dev/sda"; "mbr"];
1563        ["mkfs"; "ext2"; "/dev/sda1"];
1564        ["mount_options"; ""; "/dev/sda1"; "/"];
1565        ["umount"; "/"];
1566        ["mounts"]], [])],
1567    "unmount a filesystem",
1568    "\
1569 This unmounts the given filesystem.  The filesystem may be
1570 specified either by its mountpoint (path) or the device which
1571 contains the filesystem.");
1572
1573   ("mounts", (RStringList "devices", []), 46, [],
1574    [InitBasicFS, Always, TestOutputListOfDevices (
1575       [["mounts"]], ["/dev/sda1"])],
1576    "show mounted filesystems",
1577    "\
1578 This returns the list of currently mounted filesystems.  It returns
1579 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1580
1581 Some internal mounts are not shown.
1582
1583 See also: C<guestfs_mountpoints>");
1584
1585   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1586    [InitBasicFS, Always, TestOutputList (
1587       [["umount_all"];
1588        ["mounts"]], []);
1589     (* check that umount_all can unmount nested mounts correctly: *)
1590     InitEmpty, Always, TestOutputList (
1591       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1592        ["mkfs"; "ext2"; "/dev/sda1"];
1593        ["mkfs"; "ext2"; "/dev/sda2"];
1594        ["mkfs"; "ext2"; "/dev/sda3"];
1595        ["mount_options"; ""; "/dev/sda1"; "/"];
1596        ["mkdir"; "/mp1"];
1597        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1598        ["mkdir"; "/mp1/mp2"];
1599        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1600        ["mkdir"; "/mp1/mp2/mp3"];
1601        ["umount_all"];
1602        ["mounts"]], [])],
1603    "unmount all filesystems",
1604    "\
1605 This unmounts all mounted filesystems.
1606
1607 Some internal mounts are not unmounted by this call.");
1608
1609   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1610    [],
1611    "remove all LVM LVs, VGs and PVs",
1612    "\
1613 This command removes all LVM logical volumes, volume groups
1614 and physical volumes.");
1615
1616   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1617    [InitISOFS, Always, TestOutput (
1618       [["file"; "/empty"]], "empty");
1619     InitISOFS, Always, TestOutput (
1620       [["file"; "/known-1"]], "ASCII text");
1621     InitISOFS, Always, TestLastFail (
1622       [["file"; "/notexists"]])],
1623    "determine file type",
1624    "\
1625 This call uses the standard L<file(1)> command to determine
1626 the type or contents of the file.  This also works on devices,
1627 for example to find out whether a partition contains a filesystem.
1628
1629 This call will also transparently look inside various types
1630 of compressed file.
1631
1632 The exact command which runs is C<file -zbsL path>.  Note in
1633 particular that the filename is not prepended to the output
1634 (the C<-b> option).");
1635
1636   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1637    [InitBasicFS, Always, TestOutput (
1638       [["upload"; "test-command"; "/test-command"];
1639        ["chmod"; "0o755"; "/test-command"];
1640        ["command"; "/test-command 1"]], "Result1");
1641     InitBasicFS, Always, TestOutput (
1642       [["upload"; "test-command"; "/test-command"];
1643        ["chmod"; "0o755"; "/test-command"];
1644        ["command"; "/test-command 2"]], "Result2\n");
1645     InitBasicFS, Always, TestOutput (
1646       [["upload"; "test-command"; "/test-command"];
1647        ["chmod"; "0o755"; "/test-command"];
1648        ["command"; "/test-command 3"]], "\nResult3");
1649     InitBasicFS, Always, TestOutput (
1650       [["upload"; "test-command"; "/test-command"];
1651        ["chmod"; "0o755"; "/test-command"];
1652        ["command"; "/test-command 4"]], "\nResult4\n");
1653     InitBasicFS, Always, TestOutput (
1654       [["upload"; "test-command"; "/test-command"];
1655        ["chmod"; "0o755"; "/test-command"];
1656        ["command"; "/test-command 5"]], "\nResult5\n\n");
1657     InitBasicFS, Always, TestOutput (
1658       [["upload"; "test-command"; "/test-command"];
1659        ["chmod"; "0o755"; "/test-command"];
1660        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1661     InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 7"]], "");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 8"]], "\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 9"]], "\n\n");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1681     InitBasicFS, Always, TestLastFail (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command"]])],
1685    "run a command from the guest filesystem",
1686    "\
1687 This call runs a command from the guest filesystem.  The
1688 filesystem must be mounted, and must contain a compatible
1689 operating system (ie. something Linux, with the same
1690 or compatible processor architecture).
1691
1692 The single parameter is an argv-style list of arguments.
1693 The first element is the name of the program to run.
1694 Subsequent elements are parameters.  The list must be
1695 non-empty (ie. must contain a program name).  Note that
1696 the command runs directly, and is I<not> invoked via
1697 the shell (see C<guestfs_sh>).
1698
1699 The return value is anything printed to I<stdout> by
1700 the command.
1701
1702 If the command returns a non-zero exit status, then
1703 this function returns an error message.  The error message
1704 string is the content of I<stderr> from the command.
1705
1706 The C<$PATH> environment variable will contain at least
1707 C</usr/bin> and C</bin>.  If you require a program from
1708 another location, you should provide the full path in the
1709 first parameter.
1710
1711 Shared libraries and data files required by the program
1712 must be available on filesystems which are mounted in the
1713 correct places.  It is the caller's responsibility to ensure
1714 all filesystems that are needed are mounted at the right
1715 locations.");
1716
1717   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1718    [InitBasicFS, Always, TestOutputList (
1719       [["upload"; "test-command"; "/test-command"];
1720        ["chmod"; "0o755"; "/test-command"];
1721        ["command_lines"; "/test-command 1"]], ["Result1"]);
1722     InitBasicFS, Always, TestOutputList (
1723       [["upload"; "test-command"; "/test-command"];
1724        ["chmod"; "0o755"; "/test-command"];
1725        ["command_lines"; "/test-command 2"]], ["Result2"]);
1726     InitBasicFS, Always, TestOutputList (
1727       [["upload"; "test-command"; "/test-command"];
1728        ["chmod"; "0o755"; "/test-command"];
1729        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1730     InitBasicFS, Always, TestOutputList (
1731       [["upload"; "test-command"; "/test-command"];
1732        ["chmod"; "0o755"; "/test-command"];
1733        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1734     InitBasicFS, Always, TestOutputList (
1735       [["upload"; "test-command"; "/test-command"];
1736        ["chmod"; "0o755"; "/test-command"];
1737        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1738     InitBasicFS, Always, TestOutputList (
1739       [["upload"; "test-command"; "/test-command"];
1740        ["chmod"; "0o755"; "/test-command"];
1741        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1742     InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 7"]], []);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 8"]], [""]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 9"]], ["";""]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1762    "run a command, returning lines",
1763    "\
1764 This is the same as C<guestfs_command>, but splits the
1765 result into a list of lines.
1766
1767 See also: C<guestfs_sh_lines>");
1768
1769   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1770    [InitISOFS, Always, TestOutputStruct (
1771       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1772    "get file information",
1773    "\
1774 Returns file information for the given C<path>.
1775
1776 This is the same as the C<stat(2)> system call.");
1777
1778   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1779    [InitISOFS, Always, TestOutputStruct (
1780       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1781    "get file information for a symbolic link",
1782    "\
1783 Returns file information for the given C<path>.
1784
1785 This is the same as C<guestfs_stat> except that if C<path>
1786 is a symbolic link, then the link is stat-ed, not the file it
1787 refers to.
1788
1789 This is the same as the C<lstat(2)> system call.");
1790
1791   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1792    [InitISOFS, Always, TestOutputStruct (
1793       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1794    "get file system statistics",
1795    "\
1796 Returns file system statistics for any mounted file system.
1797 C<path> should be a file or directory in the mounted file system
1798 (typically it is the mount point itself, but it doesn't need to be).
1799
1800 This is the same as the C<statvfs(2)> system call.");
1801
1802   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1803    [], (* XXX test *)
1804    "get ext2/ext3/ext4 superblock details",
1805    "\
1806 This returns the contents of the ext2, ext3 or ext4 filesystem
1807 superblock on C<device>.
1808
1809 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1810 manpage for more details.  The list of fields returned isn't
1811 clearly defined, and depends on both the version of C<tune2fs>
1812 that libguestfs was built against, and the filesystem itself.");
1813
1814   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1815    [InitEmpty, Always, TestOutputTrue (
1816       [["blockdev_setro"; "/dev/sda"];
1817        ["blockdev_getro"; "/dev/sda"]])],
1818    "set block device to read-only",
1819    "\
1820 Sets the block device named C<device> to read-only.
1821
1822 This uses the L<blockdev(8)> command.");
1823
1824   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1825    [InitEmpty, Always, TestOutputFalse (
1826       [["blockdev_setrw"; "/dev/sda"];
1827        ["blockdev_getro"; "/dev/sda"]])],
1828    "set block device to read-write",
1829    "\
1830 Sets the block device named C<device> to read-write.
1831
1832 This uses the L<blockdev(8)> command.");
1833
1834   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1835    [InitEmpty, Always, TestOutputTrue (
1836       [["blockdev_setro"; "/dev/sda"];
1837        ["blockdev_getro"; "/dev/sda"]])],
1838    "is block device set to read-only",
1839    "\
1840 Returns a boolean indicating if the block device is read-only
1841 (true if read-only, false if not).
1842
1843 This uses the L<blockdev(8)> command.");
1844
1845   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1846    [InitEmpty, Always, TestOutputInt (
1847       [["blockdev_getss"; "/dev/sda"]], 512)],
1848    "get sectorsize of block device",
1849    "\
1850 This returns the size of sectors on a block device.
1851 Usually 512, but can be larger for modern devices.
1852
1853 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1854 for that).
1855
1856 This uses the L<blockdev(8)> command.");
1857
1858   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1859    [InitEmpty, Always, TestOutputInt (
1860       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1861    "get blocksize of block device",
1862    "\
1863 This returns the block size of a device.
1864
1865 (Note this is different from both I<size in blocks> and
1866 I<filesystem block size>).
1867
1868 This uses the L<blockdev(8)> command.");
1869
1870   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1871    [], (* XXX test *)
1872    "set blocksize of block device",
1873    "\
1874 This sets the block size of a device.
1875
1876 (Note this is different from both I<size in blocks> and
1877 I<filesystem block size>).
1878
1879 This uses the L<blockdev(8)> command.");
1880
1881   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1882    [InitEmpty, Always, TestOutputInt (
1883       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1884    "get total size of device in 512-byte sectors",
1885    "\
1886 This returns the size of the device in units of 512-byte sectors
1887 (even if the sectorsize isn't 512 bytes ... weird).
1888
1889 See also C<guestfs_blockdev_getss> for the real sector size of
1890 the device, and C<guestfs_blockdev_getsize64> for the more
1891 useful I<size in bytes>.
1892
1893 This uses the L<blockdev(8)> command.");
1894
1895   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1896    [InitEmpty, Always, TestOutputInt (
1897       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1898    "get total size of device in bytes",
1899    "\
1900 This returns the size of the device in bytes.
1901
1902 See also C<guestfs_blockdev_getsz>.
1903
1904 This uses the L<blockdev(8)> command.");
1905
1906   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1907    [InitEmpty, Always, TestRun
1908       [["blockdev_flushbufs"; "/dev/sda"]]],
1909    "flush device buffers",
1910    "\
1911 This tells the kernel to flush internal buffers associated
1912 with C<device>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1917    [InitEmpty, Always, TestRun
1918       [["blockdev_rereadpt"; "/dev/sda"]]],
1919    "reread partition table",
1920    "\
1921 Reread the partition table on C<device>.
1922
1923 This uses the L<blockdev(8)> command.");
1924
1925   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1926    [InitBasicFS, Always, TestOutput (
1927       (* Pick a file from cwd which isn't likely to change. *)
1928       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1929        ["checksum"; "md5"; "/COPYING.LIB"]],
1930       Digest.to_hex (Digest.file "COPYING.LIB"))],
1931    "upload a file from the local machine",
1932    "\
1933 Upload local file C<filename> to C<remotefilename> on the
1934 filesystem.
1935
1936 C<filename> can also be a named pipe.
1937
1938 See also C<guestfs_download>.");
1939
1940   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1941    [InitBasicFS, Always, TestOutput (
1942       (* Pick a file from cwd which isn't likely to change. *)
1943       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1944        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1945        ["upload"; "testdownload.tmp"; "/upload"];
1946        ["checksum"; "md5"; "/upload"]],
1947       Digest.to_hex (Digest.file "COPYING.LIB"))],
1948    "download a file to the local machine",
1949    "\
1950 Download file C<remotefilename> and save it as C<filename>
1951 on the local machine.
1952
1953 C<filename> can also be a named pipe.
1954
1955 See also C<guestfs_upload>, C<guestfs_cat>.");
1956
1957   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1958    [InitISOFS, Always, TestOutput (
1959       [["checksum"; "crc"; "/known-3"]], "2891671662");
1960     InitISOFS, Always, TestLastFail (
1961       [["checksum"; "crc"; "/notexists"]]);
1962     InitISOFS, Always, TestOutput (
1963       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1964     InitISOFS, Always, TestOutput (
1965       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1966     InitISOFS, Always, TestOutput (
1967       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1968     InitISOFS, Always, TestOutput (
1969       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1970     InitISOFS, Always, TestOutput (
1971       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1972     InitISOFS, Always, TestOutput (
1973       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1974     (* Test for RHBZ#579608, absolute symbolic links. *)
1975     InitISOFS, Always, TestOutput (
1976       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
1977    "compute MD5, SHAx or CRC checksum of file",
1978    "\
1979 This call computes the MD5, SHAx or CRC checksum of the
1980 file named C<path>.
1981
1982 The type of checksum to compute is given by the C<csumtype>
1983 parameter which must have one of the following values:
1984
1985 =over 4
1986
1987 =item C<crc>
1988
1989 Compute the cyclic redundancy check (CRC) specified by POSIX
1990 for the C<cksum> command.
1991
1992 =item C<md5>
1993
1994 Compute the MD5 hash (using the C<md5sum> program).
1995
1996 =item C<sha1>
1997
1998 Compute the SHA1 hash (using the C<sha1sum> program).
1999
2000 =item C<sha224>
2001
2002 Compute the SHA224 hash (using the C<sha224sum> program).
2003
2004 =item C<sha256>
2005
2006 Compute the SHA256 hash (using the C<sha256sum> program).
2007
2008 =item C<sha384>
2009
2010 Compute the SHA384 hash (using the C<sha384sum> program).
2011
2012 =item C<sha512>
2013
2014 Compute the SHA512 hash (using the C<sha512sum> program).
2015
2016 =back
2017
2018 The checksum is returned as a printable string.
2019
2020 To get the checksum for a device, use C<guestfs_checksum_device>.
2021
2022 To get the checksums for many files, use C<guestfs_checksums_out>.");
2023
2024   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2025    [InitBasicFS, Always, TestOutput (
2026       [["tar_in"; "../images/helloworld.tar"; "/"];
2027        ["cat"; "/hello"]], "hello\n")],
2028    "unpack tarfile to directory",
2029    "\
2030 This command uploads and unpacks local file C<tarfile> (an
2031 I<uncompressed> tar file) into C<directory>.
2032
2033 To upload a compressed tarball, use C<guestfs_tgz_in>
2034 or C<guestfs_txz_in>.");
2035
2036   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2037    [],
2038    "pack directory into tarfile",
2039    "\
2040 This command packs the contents of C<directory> and downloads
2041 it to local file C<tarfile>.
2042
2043 To download a compressed tarball, use C<guestfs_tgz_out>
2044 or C<guestfs_txz_out>.");
2045
2046   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2047    [InitBasicFS, Always, TestOutput (
2048       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2049        ["cat"; "/hello"]], "hello\n")],
2050    "unpack compressed tarball to directory",
2051    "\
2052 This command uploads and unpacks local file C<tarball> (a
2053 I<gzip compressed> tar file) into C<directory>.
2054
2055 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2056
2057   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2058    [],
2059    "pack directory into compressed tarball",
2060    "\
2061 This command packs the contents of C<directory> and downloads
2062 it to local file C<tarball>.
2063
2064 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2065
2066   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2067    [InitBasicFS, Always, TestLastFail (
2068       [["umount"; "/"];
2069        ["mount_ro"; "/dev/sda1"; "/"];
2070        ["touch"; "/new"]]);
2071     InitBasicFS, Always, TestOutput (
2072       [["write"; "/new"; "data"];
2073        ["umount"; "/"];
2074        ["mount_ro"; "/dev/sda1"; "/"];
2075        ["cat"; "/new"]], "data")],
2076    "mount a guest disk, read-only",
2077    "\
2078 This is the same as the C<guestfs_mount> command, but it
2079 mounts the filesystem with the read-only (I<-o ro>) flag.");
2080
2081   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2082    [],
2083    "mount a guest disk with mount options",
2084    "\
2085 This is the same as the C<guestfs_mount> command, but it
2086 allows you to set the mount options as for the
2087 L<mount(8)> I<-o> flag.
2088
2089 If the C<options> parameter is an empty string, then
2090 no options are passed (all options default to whatever
2091 the filesystem uses).");
2092
2093   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2094    [],
2095    "mount a guest disk with mount options and vfstype",
2096    "\
2097 This is the same as the C<guestfs_mount> command, but it
2098 allows you to set both the mount options and the vfstype
2099 as for the L<mount(8)> I<-o> and I<-t> flags.");
2100
2101   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2102    [],
2103    "debugging and internals",
2104    "\
2105 The C<guestfs_debug> command exposes some internals of
2106 C<guestfsd> (the guestfs daemon) that runs inside the
2107 qemu subprocess.
2108
2109 There is no comprehensive help for this command.  You have
2110 to look at the file C<daemon/debug.c> in the libguestfs source
2111 to find out what you can do.");
2112
2113   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2114    [InitEmpty, Always, TestOutputList (
2115       [["part_disk"; "/dev/sda"; "mbr"];
2116        ["pvcreate"; "/dev/sda1"];
2117        ["vgcreate"; "VG"; "/dev/sda1"];
2118        ["lvcreate"; "LV1"; "VG"; "50"];
2119        ["lvcreate"; "LV2"; "VG"; "50"];
2120        ["lvremove"; "/dev/VG/LV1"];
2121        ["lvs"]], ["/dev/VG/LV2"]);
2122     InitEmpty, Always, TestOutputList (
2123       [["part_disk"; "/dev/sda"; "mbr"];
2124        ["pvcreate"; "/dev/sda1"];
2125        ["vgcreate"; "VG"; "/dev/sda1"];
2126        ["lvcreate"; "LV1"; "VG"; "50"];
2127        ["lvcreate"; "LV2"; "VG"; "50"];
2128        ["lvremove"; "/dev/VG"];
2129        ["lvs"]], []);
2130     InitEmpty, Always, TestOutputList (
2131       [["part_disk"; "/dev/sda"; "mbr"];
2132        ["pvcreate"; "/dev/sda1"];
2133        ["vgcreate"; "VG"; "/dev/sda1"];
2134        ["lvcreate"; "LV1"; "VG"; "50"];
2135        ["lvcreate"; "LV2"; "VG"; "50"];
2136        ["lvremove"; "/dev/VG"];
2137        ["vgs"]], ["VG"])],
2138    "remove an LVM logical volume",
2139    "\
2140 Remove an LVM logical volume C<device>, where C<device> is
2141 the path to the LV, such as C</dev/VG/LV>.
2142
2143 You can also remove all LVs in a volume group by specifying
2144 the VG name, C</dev/VG>.");
2145
2146   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2147    [InitEmpty, Always, TestOutputList (
2148       [["part_disk"; "/dev/sda"; "mbr"];
2149        ["pvcreate"; "/dev/sda1"];
2150        ["vgcreate"; "VG"; "/dev/sda1"];
2151        ["lvcreate"; "LV1"; "VG"; "50"];
2152        ["lvcreate"; "LV2"; "VG"; "50"];
2153        ["vgremove"; "VG"];
2154        ["lvs"]], []);
2155     InitEmpty, Always, TestOutputList (
2156       [["part_disk"; "/dev/sda"; "mbr"];
2157        ["pvcreate"; "/dev/sda1"];
2158        ["vgcreate"; "VG"; "/dev/sda1"];
2159        ["lvcreate"; "LV1"; "VG"; "50"];
2160        ["lvcreate"; "LV2"; "VG"; "50"];
2161        ["vgremove"; "VG"];
2162        ["vgs"]], [])],
2163    "remove an LVM volume group",
2164    "\
2165 Remove an LVM volume group C<vgname>, (for example C<VG>).
2166
2167 This also forcibly removes all logical volumes in the volume
2168 group (if any).");
2169
2170   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2171    [InitEmpty, Always, TestOutputListOfDevices (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["pvremove"; "/dev/sda1"];
2179        ["lvs"]], []);
2180     InitEmpty, Always, TestOutputListOfDevices (
2181       [["part_disk"; "/dev/sda"; "mbr"];
2182        ["pvcreate"; "/dev/sda1"];
2183        ["vgcreate"; "VG"; "/dev/sda1"];
2184        ["lvcreate"; "LV1"; "VG"; "50"];
2185        ["lvcreate"; "LV2"; "VG"; "50"];
2186        ["vgremove"; "VG"];
2187        ["pvremove"; "/dev/sda1"];
2188        ["vgs"]], []);
2189     InitEmpty, Always, TestOutputListOfDevices (
2190       [["part_disk"; "/dev/sda"; "mbr"];
2191        ["pvcreate"; "/dev/sda1"];
2192        ["vgcreate"; "VG"; "/dev/sda1"];
2193        ["lvcreate"; "LV1"; "VG"; "50"];
2194        ["lvcreate"; "LV2"; "VG"; "50"];
2195        ["vgremove"; "VG"];
2196        ["pvremove"; "/dev/sda1"];
2197        ["pvs"]], [])],
2198    "remove an LVM physical volume",
2199    "\
2200 This wipes a physical volume C<device> so that LVM will no longer
2201 recognise it.
2202
2203 The implementation uses the C<pvremove> command which refuses to
2204 wipe physical volumes that contain any volume groups, so you have
2205 to remove those first.");
2206
2207   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2208    [InitBasicFS, Always, TestOutput (
2209       [["set_e2label"; "/dev/sda1"; "testlabel"];
2210        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2211    "set the ext2/3/4 filesystem label",
2212    "\
2213 This sets the ext2/3/4 filesystem label of the filesystem on
2214 C<device> to C<label>.  Filesystem labels are limited to
2215 16 characters.
2216
2217 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2218 to return the existing label on a filesystem.");
2219
2220   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2221    [],
2222    "get the ext2/3/4 filesystem label",
2223    "\
2224 This returns the ext2/3/4 filesystem label of the filesystem on
2225 C<device>.");
2226
2227   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2228    (let uuid = uuidgen () in
2229     [InitBasicFS, Always, TestOutput (
2230        [["set_e2uuid"; "/dev/sda1"; uuid];
2231         ["get_e2uuid"; "/dev/sda1"]], uuid);
2232      InitBasicFS, Always, TestOutput (
2233        [["set_e2uuid"; "/dev/sda1"; "clear"];
2234         ["get_e2uuid"; "/dev/sda1"]], "");
2235      (* We can't predict what UUIDs will be, so just check the commands run. *)
2236      InitBasicFS, Always, TestRun (
2237        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2238      InitBasicFS, Always, TestRun (
2239        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2240    "set the ext2/3/4 filesystem UUID",
2241    "\
2242 This sets the ext2/3/4 filesystem UUID of the filesystem on
2243 C<device> to C<uuid>.  The format of the UUID and alternatives
2244 such as C<clear>, C<random> and C<time> are described in the
2245 L<tune2fs(8)> manpage.
2246
2247 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2248 to return the existing UUID of a filesystem.");
2249
2250   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2251    [],
2252    "get the ext2/3/4 filesystem UUID",
2253    "\
2254 This returns the ext2/3/4 filesystem UUID of the filesystem on
2255 C<device>.");
2256
2257   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2258    [InitBasicFS, Always, TestOutputInt (
2259       [["umount"; "/dev/sda1"];
2260        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2261     InitBasicFS, Always, TestOutputInt (
2262       [["umount"; "/dev/sda1"];
2263        ["zero"; "/dev/sda1"];
2264        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2265    "run the filesystem checker",
2266    "\
2267 This runs the filesystem checker (fsck) on C<device> which
2268 should have filesystem type C<fstype>.
2269
2270 The returned integer is the status.  See L<fsck(8)> for the
2271 list of status codes from C<fsck>.
2272
2273 Notes:
2274
2275 =over 4
2276
2277 =item *
2278
2279 Multiple status codes can be summed together.
2280
2281 =item *
2282
2283 A non-zero return code can mean \"success\", for example if
2284 errors have been corrected on the filesystem.
2285
2286 =item *
2287
2288 Checking or repairing NTFS volumes is not supported
2289 (by linux-ntfs).
2290
2291 =back
2292
2293 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2294
2295   ("zero", (RErr, [Device "device"]), 85, [],
2296    [InitBasicFS, Always, TestOutput (
2297       [["umount"; "/dev/sda1"];
2298        ["zero"; "/dev/sda1"];
2299        ["file"; "/dev/sda1"]], "data")],
2300    "write zeroes to the device",
2301    "\
2302 This command writes zeroes over the first few blocks of C<device>.
2303
2304 How many blocks are zeroed isn't specified (but it's I<not> enough
2305 to securely wipe the device).  It should be sufficient to remove
2306 any partition tables, filesystem superblocks and so on.
2307
2308 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2309
2310   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2311    (* Test disabled because grub-install incompatible with virtio-blk driver.
2312     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2313     *)
2314    [InitBasicFS, Disabled, TestOutputTrue (
2315       [["grub_install"; "/"; "/dev/sda1"];
2316        ["is_dir"; "/boot"]])],
2317    "install GRUB",
2318    "\
2319 This command installs GRUB (the Grand Unified Bootloader) on
2320 C<device>, with the root directory being C<root>.");
2321
2322   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2323    [InitBasicFS, Always, TestOutput (
2324       [["write"; "/old"; "file content"];
2325        ["cp"; "/old"; "/new"];
2326        ["cat"; "/new"]], "file content");
2327     InitBasicFS, Always, TestOutputTrue (
2328       [["write"; "/old"; "file content"];
2329        ["cp"; "/old"; "/new"];
2330        ["is_file"; "/old"]]);
2331     InitBasicFS, Always, TestOutput (
2332       [["write"; "/old"; "file content"];
2333        ["mkdir"; "/dir"];
2334        ["cp"; "/old"; "/dir/new"];
2335        ["cat"; "/dir/new"]], "file content")],
2336    "copy a file",
2337    "\
2338 This copies a file from C<src> to C<dest> where C<dest> is
2339 either a destination filename or destination directory.");
2340
2341   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2342    [InitBasicFS, Always, TestOutput (
2343       [["mkdir"; "/olddir"];
2344        ["mkdir"; "/newdir"];
2345        ["write"; "/olddir/file"; "file content"];
2346        ["cp_a"; "/olddir"; "/newdir"];
2347        ["cat"; "/newdir/olddir/file"]], "file content")],
2348    "copy a file or directory recursively",
2349    "\
2350 This copies a file or directory from C<src> to C<dest>
2351 recursively using the C<cp -a> command.");
2352
2353   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2354    [InitBasicFS, Always, TestOutput (
2355       [["write"; "/old"; "file content"];
2356        ["mv"; "/old"; "/new"];
2357        ["cat"; "/new"]], "file content");
2358     InitBasicFS, Always, TestOutputFalse (
2359       [["write"; "/old"; "file content"];
2360        ["mv"; "/old"; "/new"];
2361        ["is_file"; "/old"]])],
2362    "move a file",
2363    "\
2364 This moves a file from C<src> to C<dest> where C<dest> is
2365 either a destination filename or destination directory.");
2366
2367   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2368    [InitEmpty, Always, TestRun (
2369       [["drop_caches"; "3"]])],
2370    "drop kernel page cache, dentries and inodes",
2371    "\
2372 This instructs the guest kernel to drop its page cache,
2373 and/or dentries and inode caches.  The parameter C<whattodrop>
2374 tells the kernel what precisely to drop, see
2375 L<http://linux-mm.org/Drop_Caches>
2376
2377 Setting C<whattodrop> to 3 should drop everything.
2378
2379 This automatically calls L<sync(2)> before the operation,
2380 so that the maximum guest memory is freed.");
2381
2382   ("dmesg", (RString "kmsgs", []), 91, [],
2383    [InitEmpty, Always, TestRun (
2384       [["dmesg"]])],
2385    "return kernel messages",
2386    "\
2387 This returns the kernel messages (C<dmesg> output) from
2388 the guest kernel.  This is sometimes useful for extended
2389 debugging of problems.
2390
2391 Another way to get the same information is to enable
2392 verbose messages with C<guestfs_set_verbose> or by setting
2393 the environment variable C<LIBGUESTFS_DEBUG=1> before
2394 running the program.");
2395
2396   ("ping_daemon", (RErr, []), 92, [],
2397    [InitEmpty, Always, TestRun (
2398       [["ping_daemon"]])],
2399    "ping the guest daemon",
2400    "\
2401 This is a test probe into the guestfs daemon running inside
2402 the qemu subprocess.  Calling this function checks that the
2403 daemon responds to the ping message, without affecting the daemon
2404 or attached block device(s) in any other way.");
2405
2406   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2407    [InitBasicFS, Always, TestOutputTrue (
2408       [["write"; "/file1"; "contents of a file"];
2409        ["cp"; "/file1"; "/file2"];
2410        ["equal"; "/file1"; "/file2"]]);
2411     InitBasicFS, Always, TestOutputFalse (
2412       [["write"; "/file1"; "contents of a file"];
2413        ["write"; "/file2"; "contents of another file"];
2414        ["equal"; "/file1"; "/file2"]]);
2415     InitBasicFS, Always, TestLastFail (
2416       [["equal"; "/file1"; "/file2"]])],
2417    "test if two files have equal contents",
2418    "\
2419 This compares the two files C<file1> and C<file2> and returns
2420 true if their content is exactly equal, or false otherwise.
2421
2422 The external L<cmp(1)> program is used for the comparison.");
2423
2424   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2425    [InitISOFS, Always, TestOutputList (
2426       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2427     InitISOFS, Always, TestOutputList (
2428       [["strings"; "/empty"]], []);
2429     (* Test for RHBZ#579608, absolute symbolic links. *)
2430     InitISOFS, Always, TestRun (
2431       [["strings"; "/abssymlink"]])],
2432    "print the printable strings in a file",
2433    "\
2434 This runs the L<strings(1)> command on a file and returns
2435 the list of printable strings found.");
2436
2437   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2438    [InitISOFS, Always, TestOutputList (
2439       [["strings_e"; "b"; "/known-5"]], []);
2440     InitBasicFS, Always, TestOutputList (
2441       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2442        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2443    "print the printable strings in a file",
2444    "\
2445 This is like the C<guestfs_strings> command, but allows you to
2446 specify the encoding of strings that are looked for in
2447 the source file C<path>.
2448
2449 Allowed encodings are:
2450
2451 =over 4
2452
2453 =item s
2454
2455 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2456 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2457
2458 =item S
2459
2460 Single 8-bit-byte characters.
2461
2462 =item b
2463
2464 16-bit big endian strings such as those encoded in
2465 UTF-16BE or UCS-2BE.
2466
2467 =item l (lower case letter L)
2468
2469 16-bit little endian such as UTF-16LE and UCS-2LE.
2470 This is useful for examining binaries in Windows guests.
2471
2472 =item B
2473
2474 32-bit big endian such as UCS-4BE.
2475
2476 =item L
2477
2478 32-bit little endian such as UCS-4LE.
2479
2480 =back
2481
2482 The returned strings are transcoded to UTF-8.");
2483
2484   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2485    [InitISOFS, Always, TestOutput (
2486       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2487     (* Test for RHBZ#501888c2 regression which caused large hexdump
2488      * commands to segfault.
2489      *)
2490     InitISOFS, Always, TestRun (
2491       [["hexdump"; "/100krandom"]]);
2492     (* Test for RHBZ#579608, absolute symbolic links. *)
2493     InitISOFS, Always, TestRun (
2494       [["hexdump"; "/abssymlink"]])],
2495    "dump a file in hexadecimal",
2496    "\
2497 This runs C<hexdump -C> on the given C<path>.  The result is
2498 the human-readable, canonical hex dump of the file.");
2499
2500   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2501    [InitNone, Always, TestOutput (
2502       [["part_disk"; "/dev/sda"; "mbr"];
2503        ["mkfs"; "ext3"; "/dev/sda1"];
2504        ["mount_options"; ""; "/dev/sda1"; "/"];
2505        ["write"; "/new"; "test file"];
2506        ["umount"; "/dev/sda1"];
2507        ["zerofree"; "/dev/sda1"];
2508        ["mount_options"; ""; "/dev/sda1"; "/"];
2509        ["cat"; "/new"]], "test file")],
2510    "zero unused inodes and disk blocks on ext2/3 filesystem",
2511    "\
2512 This runs the I<zerofree> program on C<device>.  This program
2513 claims to zero unused inodes and disk blocks on an ext2/3
2514 filesystem, thus making it possible to compress the filesystem
2515 more effectively.
2516
2517 You should B<not> run this program if the filesystem is
2518 mounted.
2519
2520 It is possible that using this program can damage the filesystem
2521 or data on the filesystem.");
2522
2523   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2524    [],
2525    "resize an LVM physical volume",
2526    "\
2527 This resizes (expands or shrinks) an existing LVM physical
2528 volume to match the new size of the underlying device.");
2529
2530   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2531                        Int "cyls"; Int "heads"; Int "sectors";
2532                        String "line"]), 99, [DangerWillRobinson],
2533    [],
2534    "modify a single partition on a block device",
2535    "\
2536 This runs L<sfdisk(8)> option to modify just the single
2537 partition C<n> (note: C<n> counts from 1).
2538
2539 For other parameters, see C<guestfs_sfdisk>.  You should usually
2540 pass C<0> for the cyls/heads/sectors parameters.
2541
2542 See also: C<guestfs_part_add>");
2543
2544   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2545    [],
2546    "display the partition table",
2547    "\
2548 This displays the partition table on C<device>, in the
2549 human-readable output of the L<sfdisk(8)> command.  It is
2550 not intended to be parsed.
2551
2552 See also: C<guestfs_part_list>");
2553
2554   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2555    [],
2556    "display the kernel geometry",
2557    "\
2558 This displays the kernel's idea of the geometry of C<device>.
2559
2560 The result is in human-readable format, and not designed to
2561 be parsed.");
2562
2563   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2564    [],
2565    "display the disk geometry from the partition table",
2566    "\
2567 This displays the disk geometry of C<device> read from the
2568 partition table.  Especially in the case where the underlying
2569 block device has been resized, this can be different from the
2570 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2571
2572 The result is in human-readable format, and not designed to
2573 be parsed.");
2574
2575   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2576    [],
2577    "activate or deactivate all volume groups",
2578    "\
2579 This command activates or (if C<activate> is false) deactivates
2580 all logical volumes in all volume groups.
2581 If activated, then they are made known to the
2582 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2583 then those devices disappear.
2584
2585 This command is the same as running C<vgchange -a y|n>");
2586
2587   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2588    [],
2589    "activate or deactivate some volume groups",
2590    "\
2591 This command activates or (if C<activate> is false) deactivates
2592 all logical volumes in the listed volume groups C<volgroups>.
2593 If activated, then they are made known to the
2594 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2595 then those devices disappear.
2596
2597 This command is the same as running C<vgchange -a y|n volgroups...>
2598
2599 Note that if C<volgroups> is an empty list then B<all> volume groups
2600 are activated or deactivated.");
2601
2602   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2603    [InitNone, Always, TestOutput (
2604       [["part_disk"; "/dev/sda"; "mbr"];
2605        ["pvcreate"; "/dev/sda1"];
2606        ["vgcreate"; "VG"; "/dev/sda1"];
2607        ["lvcreate"; "LV"; "VG"; "10"];
2608        ["mkfs"; "ext2"; "/dev/VG/LV"];
2609        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2610        ["write"; "/new"; "test content"];
2611        ["umount"; "/"];
2612        ["lvresize"; "/dev/VG/LV"; "20"];
2613        ["e2fsck_f"; "/dev/VG/LV"];
2614        ["resize2fs"; "/dev/VG/LV"];
2615        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2616        ["cat"; "/new"]], "test content");
2617     InitNone, Always, TestRun (
2618       (* Make an LV smaller to test RHBZ#587484. *)
2619       [["part_disk"; "/dev/sda"; "mbr"];
2620        ["pvcreate"; "/dev/sda1"];
2621        ["vgcreate"; "VG"; "/dev/sda1"];
2622        ["lvcreate"; "LV"; "VG"; "20"];
2623        ["lvresize"; "/dev/VG/LV"; "10"]])],
2624    "resize an LVM logical volume",
2625    "\
2626 This resizes (expands or shrinks) an existing LVM logical
2627 volume to C<mbytes>.  When reducing, data in the reduced part
2628 is lost.");
2629
2630   ("resize2fs", (RErr, [Device "device"]), 106, [],
2631    [], (* lvresize tests this *)
2632    "resize an ext2/ext3 filesystem",
2633    "\
2634 This resizes an ext2 or ext3 filesystem to match the size of
2635 the underlying device.
2636
2637 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2638 on the C<device> before calling this command.  For unknown reasons
2639 C<resize2fs> sometimes gives an error about this and sometimes not.
2640 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2641 calling this function.");
2642
2643   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2644    [InitBasicFS, Always, TestOutputList (
2645       [["find"; "/"]], ["lost+found"]);
2646     InitBasicFS, Always, TestOutputList (
2647       [["touch"; "/a"];
2648        ["mkdir"; "/b"];
2649        ["touch"; "/b/c"];
2650        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2651     InitBasicFS, Always, TestOutputList (
2652       [["mkdir_p"; "/a/b/c"];
2653        ["touch"; "/a/b/c/d"];
2654        ["find"; "/a/b/"]], ["c"; "c/d"])],
2655    "find all files and directories",
2656    "\
2657 This command lists out all files and directories, recursively,
2658 starting at C<directory>.  It is essentially equivalent to
2659 running the shell command C<find directory -print> but some
2660 post-processing happens on the output, described below.
2661
2662 This returns a list of strings I<without any prefix>.  Thus
2663 if the directory structure was:
2664
2665  /tmp/a
2666  /tmp/b
2667  /tmp/c/d
2668
2669 then the returned list from C<guestfs_find> C</tmp> would be
2670 4 elements:
2671
2672  a
2673  b
2674  c
2675  c/d
2676
2677 If C<directory> is not a directory, then this command returns
2678 an error.
2679
2680 The returned list is sorted.
2681
2682 See also C<guestfs_find0>.");
2683
2684   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2685    [], (* lvresize tests this *)
2686    "check an ext2/ext3 filesystem",
2687    "\
2688 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2689 filesystem checker on C<device>, noninteractively (C<-p>),
2690 even if the filesystem appears to be clean (C<-f>).
2691
2692 This command is only needed because of C<guestfs_resize2fs>
2693 (q.v.).  Normally you should use C<guestfs_fsck>.");
2694
2695   ("sleep", (RErr, [Int "secs"]), 109, [],
2696    [InitNone, Always, TestRun (
2697       [["sleep"; "1"]])],
2698    "sleep for some seconds",
2699    "\
2700 Sleep for C<secs> seconds.");
2701
2702   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2703    [InitNone, Always, TestOutputInt (
2704       [["part_disk"; "/dev/sda"; "mbr"];
2705        ["mkfs"; "ntfs"; "/dev/sda1"];
2706        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2707     InitNone, Always, TestOutputInt (
2708       [["part_disk"; "/dev/sda"; "mbr"];
2709        ["mkfs"; "ext2"; "/dev/sda1"];
2710        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2711    "probe NTFS volume",
2712    "\
2713 This command runs the L<ntfs-3g.probe(8)> command which probes
2714 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2715 be mounted read-write, and some cannot be mounted at all).
2716
2717 C<rw> is a boolean flag.  Set it to true if you want to test
2718 if the volume can be mounted read-write.  Set it to false if
2719 you want to test if the volume can be mounted read-only.
2720
2721 The return value is an integer which C<0> if the operation
2722 would succeed, or some non-zero value documented in the
2723 L<ntfs-3g.probe(8)> manual page.");
2724
2725   ("sh", (RString "output", [String "command"]), 111, [],
2726    [], (* XXX needs tests *)
2727    "run a command via the shell",
2728    "\
2729 This call runs a command from the guest filesystem via the
2730 guest's C</bin/sh>.
2731
2732 This is like C<guestfs_command>, but passes the command to:
2733
2734  /bin/sh -c \"command\"
2735
2736 Depending on the guest's shell, this usually results in
2737 wildcards being expanded, shell expressions being interpolated
2738 and so on.
2739
2740 All the provisos about C<guestfs_command> apply to this call.");
2741
2742   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2743    [], (* XXX needs tests *)
2744    "run a command via the shell returning lines",
2745    "\
2746 This is the same as C<guestfs_sh>, but splits the result
2747 into a list of lines.
2748
2749 See also: C<guestfs_command_lines>");
2750
2751   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2752    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2753     * code in stubs.c, since all valid glob patterns must start with "/".
2754     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2755     *)
2756    [InitBasicFS, Always, TestOutputList (
2757       [["mkdir_p"; "/a/b/c"];
2758        ["touch"; "/a/b/c/d"];
2759        ["touch"; "/a/b/c/e"];
2760        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2761     InitBasicFS, Always, TestOutputList (
2762       [["mkdir_p"; "/a/b/c"];
2763        ["touch"; "/a/b/c/d"];
2764        ["touch"; "/a/b/c/e"];
2765        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2766     InitBasicFS, Always, TestOutputList (
2767       [["mkdir_p"; "/a/b/c"];
2768        ["touch"; "/a/b/c/d"];
2769        ["touch"; "/a/b/c/e"];
2770        ["glob_expand"; "/a/*/x/*"]], [])],
2771    "expand a wildcard path",
2772    "\
2773 This command searches for all the pathnames matching
2774 C<pattern> according to the wildcard expansion rules
2775 used by the shell.
2776
2777 If no paths match, then this returns an empty list
2778 (note: not an error).
2779
2780 It is just a wrapper around the C L<glob(3)> function
2781 with flags C<GLOB_MARK|GLOB_BRACE>.
2782 See that manual page for more details.");
2783
2784   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2785    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2786       [["scrub_device"; "/dev/sdc"]])],
2787    "scrub (securely wipe) a device",
2788    "\
2789 This command writes patterns over C<device> to make data retrieval
2790 more difficult.
2791
2792 It is an interface to the L<scrub(1)> program.  See that
2793 manual page for more details.");
2794
2795   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2796    [InitBasicFS, Always, TestRun (
2797       [["write"; "/file"; "content"];
2798        ["scrub_file"; "/file"]])],
2799    "scrub (securely wipe) a file",
2800    "\
2801 This command writes patterns over a file to make data retrieval
2802 more difficult.
2803
2804 The file is I<removed> after scrubbing.
2805
2806 It is an interface to the L<scrub(1)> program.  See that
2807 manual page for more details.");
2808
2809   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2810    [], (* XXX needs testing *)
2811    "scrub (securely wipe) free space",
2812    "\
2813 This command creates the directory C<dir> and then fills it
2814 with files until the filesystem is full, and scrubs the files
2815 as for C<guestfs_scrub_file>, and deletes them.
2816 The intention is to scrub any free space on the partition
2817 containing C<dir>.
2818
2819 It is an interface to the L<scrub(1)> program.  See that
2820 manual page for more details.");
2821
2822   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2823    [InitBasicFS, Always, TestRun (
2824       [["mkdir"; "/tmp"];
2825        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2826    "create a temporary directory",
2827    "\
2828 This command creates a temporary directory.  The
2829 C<template> parameter should be a full pathname for the
2830 temporary directory name with the final six characters being
2831 \"XXXXXX\".
2832
2833 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2834 the second one being suitable for Windows filesystems.
2835
2836 The name of the temporary directory that was created
2837 is returned.
2838
2839 The temporary directory is created with mode 0700
2840 and is owned by root.
2841
2842 The caller is responsible for deleting the temporary
2843 directory and its contents after use.
2844
2845 See also: L<mkdtemp(3)>");
2846
2847   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2848    [InitISOFS, Always, TestOutputInt (
2849       [["wc_l"; "/10klines"]], 10000);
2850     (* Test for RHBZ#579608, absolute symbolic links. *)
2851     InitISOFS, Always, TestOutputInt (
2852       [["wc_l"; "/abssymlink"]], 10000)],
2853    "count lines in a file",
2854    "\
2855 This command counts the lines in a file, using the
2856 C<wc -l> external command.");
2857
2858   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2859    [InitISOFS, Always, TestOutputInt (
2860       [["wc_w"; "/10klines"]], 10000)],
2861    "count words in a file",
2862    "\
2863 This command counts the words in a file, using the
2864 C<wc -w> external command.");
2865
2866   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2867    [InitISOFS, Always, TestOutputInt (
2868       [["wc_c"; "/100kallspaces"]], 102400)],
2869    "count characters in a file",
2870    "\
2871 This command counts the characters in a file, using the
2872 C<wc -c> external command.");
2873
2874   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2875    [InitISOFS, Always, TestOutputList (
2876       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2877     (* Test for RHBZ#579608, absolute symbolic links. *)
2878     InitISOFS, Always, TestOutputList (
2879       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2880    "return first 10 lines of a file",
2881    "\
2882 This command returns up to the first 10 lines of a file as
2883 a list of strings.");
2884
2885   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2886    [InitISOFS, Always, TestOutputList (
2887       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2888     InitISOFS, Always, TestOutputList (
2889       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2890     InitISOFS, Always, TestOutputList (
2891       [["head_n"; "0"; "/10klines"]], [])],
2892    "return first N lines of a file",
2893    "\
2894 If the parameter C<nrlines> is a positive number, this returns the first
2895 C<nrlines> lines of the file C<path>.
2896
2897 If the parameter C<nrlines> is a negative number, this returns lines
2898 from the file C<path>, excluding the last C<nrlines> lines.
2899
2900 If the parameter C<nrlines> is zero, this returns an empty list.");
2901
2902   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2903    [InitISOFS, Always, TestOutputList (
2904       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2905    "return last 10 lines of a file",
2906    "\
2907 This command returns up to the last 10 lines of a file as
2908 a list of strings.");
2909
2910   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2911    [InitISOFS, Always, TestOutputList (
2912       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2913     InitISOFS, Always, TestOutputList (
2914       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2915     InitISOFS, Always, TestOutputList (
2916       [["tail_n"; "0"; "/10klines"]], [])],
2917    "return last N lines of a file",
2918    "\
2919 If the parameter C<nrlines> is a positive number, this returns the last
2920 C<nrlines> lines of the file C<path>.
2921
2922 If the parameter C<nrlines> is a negative number, this returns lines
2923 from the file C<path>, starting with the C<-nrlines>th line.
2924
2925 If the parameter C<nrlines> is zero, this returns an empty list.");
2926
2927   ("df", (RString "output", []), 125, [],
2928    [], (* XXX Tricky to test because it depends on the exact format
2929         * of the 'df' command and other imponderables.
2930         *)
2931    "report file system disk space usage",
2932    "\
2933 This command runs the C<df> command to report disk space used.
2934
2935 This command is mostly useful for interactive sessions.  It
2936 is I<not> intended that you try to parse the output string.
2937 Use C<statvfs> from programs.");
2938
2939   ("df_h", (RString "output", []), 126, [],
2940    [], (* XXX Tricky to test because it depends on the exact format
2941         * of the 'df' command and other imponderables.
2942         *)
2943    "report file system disk space usage (human readable)",
2944    "\
2945 This command runs the C<df -h> command to report disk space used
2946 in human-readable format.
2947
2948 This command is mostly useful for interactive sessions.  It
2949 is I<not> intended that you try to parse the output string.
2950 Use C<statvfs> from programs.");
2951
2952   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2953    [InitISOFS, Always, TestOutputInt (
2954       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2955    "estimate file space usage",
2956    "\
2957 This command runs the C<du -s> command to estimate file space
2958 usage for C<path>.
2959
2960 C<path> can be a file or a directory.  If C<path> is a directory
2961 then the estimate includes the contents of the directory and all
2962 subdirectories (recursively).
2963
2964 The result is the estimated size in I<kilobytes>
2965 (ie. units of 1024 bytes).");
2966
2967   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2968    [InitISOFS, Always, TestOutputList (
2969       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2970    "list files in an initrd",
2971    "\
2972 This command lists out files contained in an initrd.
2973
2974 The files are listed without any initial C</> character.  The
2975 files are listed in the order they appear (not necessarily
2976 alphabetical).  Directory names are listed as separate items.
2977
2978 Old Linux kernels (2.4 and earlier) used a compressed ext2
2979 filesystem as initrd.  We I<only> support the newer initramfs
2980 format (compressed cpio files).");
2981
2982   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2983    [],
2984    "mount a file using the loop device",
2985    "\
2986 This command lets you mount C<file> (a filesystem image
2987 in a file) on a mount point.  It is entirely equivalent to
2988 the command C<mount -o loop file mountpoint>.");
2989
2990   ("mkswap", (RErr, [Device "device"]), 130, [],
2991    [InitEmpty, Always, TestRun (
2992       [["part_disk"; "/dev/sda"; "mbr"];
2993        ["mkswap"; "/dev/sda1"]])],
2994    "create a swap partition",
2995    "\
2996 Create a swap partition on C<device>.");
2997
2998   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2999    [InitEmpty, Always, TestRun (
3000       [["part_disk"; "/dev/sda"; "mbr"];
3001        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3002    "create a swap partition with a label",
3003    "\
3004 Create a swap partition on C<device> with label C<label>.
3005
3006 Note that you cannot attach a swap label to a block device
3007 (eg. C</dev/sda>), just to a partition.  This appears to be
3008 a limitation of the kernel or swap tools.");
3009
3010   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3011    (let uuid = uuidgen () in
3012     [InitEmpty, Always, TestRun (
3013        [["part_disk"; "/dev/sda"; "mbr"];
3014         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3015    "create a swap partition with an explicit UUID",
3016    "\
3017 Create a swap partition on C<device> with UUID C<uuid>.");
3018
3019   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3020    [InitBasicFS, Always, TestOutputStruct (
3021       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3022        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3023        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3024     InitBasicFS, Always, TestOutputStruct (
3025       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3026        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3027    "make block, character or FIFO devices",
3028    "\
3029 This call creates block or character special devices, or
3030 named pipes (FIFOs).
3031
3032 The C<mode> parameter should be the mode, using the standard
3033 constants.  C<devmajor> and C<devminor> are the
3034 device major and minor numbers, only used when creating block
3035 and character special devices.
3036
3037 Note that, just like L<mknod(2)>, the mode must be bitwise
3038 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3039 just creates a regular file).  These constants are
3040 available in the standard Linux header files, or you can use
3041 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3042 which are wrappers around this command which bitwise OR
3043 in the appropriate constant for you.
3044
3045 The mode actually set is affected by the umask.");
3046
3047   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3048    [InitBasicFS, Always, TestOutputStruct (
3049       [["mkfifo"; "0o777"; "/node"];
3050        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3051    "make FIFO (named pipe)",
3052    "\
3053 This call creates a FIFO (named pipe) called C<path> with
3054 mode C<mode>.  It is just a convenient wrapper around
3055 C<guestfs_mknod>.
3056
3057 The mode actually set is affected by the umask.");
3058
3059   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3060    [InitBasicFS, Always, TestOutputStruct (
3061       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3062        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3063    "make block device node",
3064    "\
3065 This call creates a block device node called C<path> with
3066 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3067 It is just a convenient wrapper around C<guestfs_mknod>.
3068
3069 The mode actually set is affected by the umask.");
3070
3071   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3072    [InitBasicFS, Always, TestOutputStruct (
3073       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3074        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3075    "make char device node",
3076    "\
3077 This call creates a char device node called C<path> with
3078 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3079 It is just a convenient wrapper around C<guestfs_mknod>.
3080
3081 The mode actually set is affected by the umask.");
3082
3083   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3084    [InitEmpty, Always, TestOutputInt (
3085       [["umask"; "0o22"]], 0o22)],
3086    "set file mode creation mask (umask)",
3087    "\
3088 This function sets the mask used for creating new files and
3089 device nodes to C<mask & 0777>.
3090
3091 Typical umask values would be C<022> which creates new files
3092 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3093 C<002> which creates new files with permissions like
3094 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3095
3096 The default umask is C<022>.  This is important because it
3097 means that directories and device nodes will be created with
3098 C<0644> or C<0755> mode even if you specify C<0777>.
3099
3100 See also C<guestfs_get_umask>,
3101 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3102
3103 This call returns the previous umask.");
3104
3105   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3106    [],
3107    "read directories entries",
3108    "\
3109 This returns the list of directory entries in directory C<dir>.
3110
3111 All entries in the directory are returned, including C<.> and
3112 C<..>.  The entries are I<not> sorted, but returned in the same
3113 order as the underlying filesystem.
3114
3115 Also this call returns basic file type information about each
3116 file.  The C<ftyp> field will contain one of the following characters:
3117
3118 =over 4
3119
3120 =item 'b'
3121
3122 Block special
3123
3124 =item 'c'
3125
3126 Char special
3127
3128 =item 'd'
3129
3130 Directory
3131
3132 =item 'f'
3133
3134 FIFO (named pipe)
3135
3136 =item 'l'
3137
3138 Symbolic link
3139
3140 =item 'r'
3141
3142 Regular file
3143
3144 =item 's'
3145
3146 Socket
3147
3148 =item 'u'
3149
3150 Unknown file type
3151
3152 =item '?'
3153
3154 The L<readdir(3)> returned a C<d_type> field with an
3155 unexpected value
3156
3157 =back
3158
3159 This function is primarily intended for use by programs.  To
3160 get a simple list of names, use C<guestfs_ls>.  To get a printable
3161 directory for human consumption, use C<guestfs_ll>.");
3162
3163   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3164    [],
3165    "create partitions on a block device",
3166    "\
3167 This is a simplified interface to the C<guestfs_sfdisk>
3168 command, where partition sizes are specified in megabytes
3169 only (rounded to the nearest cylinder) and you don't need
3170 to specify the cyls, heads and sectors parameters which
3171 were rarely if ever used anyway.
3172
3173 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3174 and C<guestfs_part_disk>");
3175
3176   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3177    [],
3178    "determine file type inside a compressed file",
3179    "\
3180 This command runs C<file> after first decompressing C<path>
3181 using C<method>.
3182
3183 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3184
3185 Since 1.0.63, use C<guestfs_file> instead which can now
3186 process compressed files.");
3187
3188   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3189    [],
3190    "list extended attributes of a file or directory",
3191    "\
3192 This call lists the extended attributes of the file or directory
3193 C<path>.
3194
3195 At the system call level, this is a combination of the
3196 L<listxattr(2)> and L<getxattr(2)> calls.
3197
3198 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3199
3200   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3201    [],
3202    "list extended attributes of a file or directory",
3203    "\
3204 This is the same as C<guestfs_getxattrs>, but if C<path>
3205 is a symbolic link, then it returns the extended attributes
3206 of the link itself.");
3207
3208   ("setxattr", (RErr, [String "xattr";
3209                        String "val"; Int "vallen"; (* will be BufferIn *)
3210                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3211    [],
3212    "set extended attribute of a file or directory",
3213    "\
3214 This call sets the extended attribute named C<xattr>
3215 of the file C<path> to the value C<val> (of length C<vallen>).
3216 The value is arbitrary 8 bit data.
3217
3218 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3219
3220   ("lsetxattr", (RErr, [String "xattr";
3221                         String "val"; Int "vallen"; (* will be BufferIn *)
3222                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3223    [],
3224    "set extended attribute of a file or directory",
3225    "\
3226 This is the same as C<guestfs_setxattr>, but if C<path>
3227 is a symbolic link, then it sets an extended attribute
3228 of the link itself.");
3229
3230   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3231    [],
3232    "remove extended attribute of a file or directory",
3233    "\
3234 This call removes the extended attribute named C<xattr>
3235 of the file C<path>.
3236
3237 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3238
3239   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3240    [],
3241    "remove extended attribute of a file or directory",
3242    "\
3243 This is the same as C<guestfs_removexattr>, but if C<path>
3244 is a symbolic link, then it removes an extended attribute
3245 of the link itself.");
3246
3247   ("mountpoints", (RHashtable "mps", []), 147, [],
3248    [],
3249    "show mountpoints",
3250    "\
3251 This call is similar to C<guestfs_mounts>.  That call returns
3252 a list of devices.  This one returns a hash table (map) of
3253 device name to directory where the device is mounted.");
3254
3255   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3256    (* This is a special case: while you would expect a parameter
3257     * of type "Pathname", that doesn't work, because it implies
3258     * NEED_ROOT in the generated calling code in stubs.c, and
3259     * this function cannot use NEED_ROOT.
3260     *)
3261    [],
3262    "create a mountpoint",
3263    "\
3264 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3265 specialized calls that can be used to create extra mountpoints
3266 before mounting the first filesystem.
3267
3268 These calls are I<only> necessary in some very limited circumstances,
3269 mainly the case where you want to mount a mix of unrelated and/or
3270 read-only filesystems together.
3271
3272 For example, live CDs often contain a \"Russian doll\" nest of
3273 filesystems, an ISO outer layer, with a squashfs image inside, with
3274 an ext2/3 image inside that.  You can unpack this as follows
3275 in guestfish:
3276
3277  add-ro Fedora-11-i686-Live.iso
3278  run
3279  mkmountpoint /cd
3280  mkmountpoint /squash
3281  mkmountpoint /ext3
3282  mount /dev/sda /cd
3283  mount-loop /cd/LiveOS/squashfs.img /squash
3284  mount-loop /squash/LiveOS/ext3fs.img /ext3
3285
3286 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3287
3288   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3289    [],
3290    "remove a mountpoint",
3291    "\
3292 This calls removes a mountpoint that was previously created
3293 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3294 for full details.");
3295
3296   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3297    [InitISOFS, Always, TestOutputBuffer (
3298       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3299     (* Test various near large, large and too large files (RHBZ#589039). *)
3300     InitBasicFS, Always, TestLastFail (
3301       [["touch"; "/a"];
3302        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3303        ["read_file"; "/a"]]);
3304     InitBasicFS, Always, TestLastFail (
3305       [["touch"; "/a"];
3306        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3307        ["read_file"; "/a"]]);
3308     InitBasicFS, Always, TestLastFail (
3309       [["touch"; "/a"];
3310        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3311        ["read_file"; "/a"]])],
3312    "read a file",
3313    "\
3314 This calls returns the contents of the file C<path> as a
3315 buffer.
3316
3317 Unlike C<guestfs_cat>, this function can correctly
3318 handle files that contain embedded ASCII NUL characters.
3319 However unlike C<guestfs_download>, this function is limited
3320 in the total size of file that can be handled.");
3321
3322   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3323    [InitISOFS, Always, TestOutputList (
3324       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3325     InitISOFS, Always, TestOutputList (
3326       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3327     (* Test for RHBZ#579608, absolute symbolic links. *)
3328     InitISOFS, Always, TestOutputList (
3329       [["grep"; "nomatch"; "/abssymlink"]], [])],
3330    "return lines matching a pattern",
3331    "\
3332 This calls the external C<grep> program and returns the
3333 matching lines.");
3334
3335   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3336    [InitISOFS, Always, TestOutputList (
3337       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3338    "return lines matching a pattern",
3339    "\
3340 This calls the external C<egrep> program and returns the
3341 matching lines.");
3342
3343   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3344    [InitISOFS, Always, TestOutputList (
3345       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3346    "return lines matching a pattern",
3347    "\
3348 This calls the external C<fgrep> program and returns the
3349 matching lines.");
3350
3351   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3352    [InitISOFS, Always, TestOutputList (
3353       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3354    "return lines matching a pattern",
3355    "\
3356 This calls the external C<grep -i> program and returns the
3357 matching lines.");
3358
3359   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3360    [InitISOFS, Always, TestOutputList (
3361       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3362    "return lines matching a pattern",
3363    "\
3364 This calls the external C<egrep -i> program and returns the
3365 matching lines.");
3366
3367   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3368    [InitISOFS, Always, TestOutputList (
3369       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3370    "return lines matching a pattern",
3371    "\
3372 This calls the external C<fgrep -i> program and returns the
3373 matching lines.");
3374
3375   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3376    [InitISOFS, Always, TestOutputList (
3377       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3378    "return lines matching a pattern",
3379    "\
3380 This calls the external C<zgrep> program and returns the
3381 matching lines.");
3382
3383   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3384    [InitISOFS, Always, TestOutputList (
3385       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3386    "return lines matching a pattern",
3387    "\
3388 This calls the external C<zegrep> program and returns the
3389 matching lines.");
3390
3391   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3392    [InitISOFS, Always, TestOutputList (
3393       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3394    "return lines matching a pattern",
3395    "\
3396 This calls the external C<zfgrep> program and returns the
3397 matching lines.");
3398
3399   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3400    [InitISOFS, Always, TestOutputList (
3401       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3402    "return lines matching a pattern",
3403    "\
3404 This calls the external C<zgrep -i> program and returns the
3405 matching lines.");
3406
3407   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3408    [InitISOFS, Always, TestOutputList (
3409       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3410    "return lines matching a pattern",
3411    "\
3412 This calls the external C<zegrep -i> program and returns the
3413 matching lines.");
3414
3415   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3416    [InitISOFS, Always, TestOutputList (
3417       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3418    "return lines matching a pattern",
3419    "\
3420 This calls the external C<zfgrep -i> program and returns the
3421 matching lines.");
3422
3423   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3424    [InitISOFS, Always, TestOutput (
3425       [["realpath"; "/../directory"]], "/directory")],
3426    "canonicalized absolute pathname",
3427    "\
3428 Return the canonicalized absolute pathname of C<path>.  The
3429 returned path has no C<.>, C<..> or symbolic link path elements.");
3430
3431   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3432    [InitBasicFS, Always, TestOutputStruct (
3433       [["touch"; "/a"];
3434        ["ln"; "/a"; "/b"];
3435        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3436    "create a hard link",
3437    "\
3438 This command creates a hard link using the C<ln> command.");
3439
3440   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3441    [InitBasicFS, Always, TestOutputStruct (
3442       [["touch"; "/a"];
3443        ["touch"; "/b"];
3444        ["ln_f"; "/a"; "/b"];
3445        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3446    "create a hard link",
3447    "\
3448 This command creates a hard link using the C<ln -f> command.
3449 The C<-f> option removes the link (C<linkname>) if it exists already.");
3450
3451   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3452    [InitBasicFS, Always, TestOutputStruct (
3453       [["touch"; "/a"];
3454        ["ln_s"; "a"; "/b"];
3455        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3456    "create a symbolic link",
3457    "\
3458 This command creates a symbolic link using the C<ln -s> command.");
3459
3460   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3461    [InitBasicFS, Always, TestOutput (
3462       [["mkdir_p"; "/a/b"];
3463        ["touch"; "/a/b/c"];
3464        ["ln_sf"; "../d"; "/a/b/c"];
3465        ["readlink"; "/a/b/c"]], "../d")],
3466    "create a symbolic link",
3467    "\
3468 This command creates a symbolic link using the C<ln -sf> command,
3469 The C<-f> option removes the link (C<linkname>) if it exists already.");
3470
3471   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3472    [] (* XXX tested above *),
3473    "read the target of a symbolic link",
3474    "\
3475 This command reads the target of a symbolic link.");
3476
3477   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3478    [InitBasicFS, Always, TestOutputStruct (
3479       [["fallocate"; "/a"; "1000000"];
3480        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3481    "preallocate a file in the guest filesystem",
3482    "\
3483 This command preallocates a file (containing zero bytes) named
3484 C<path> of size C<len> bytes.  If the file exists already, it
3485 is overwritten.
3486
3487 Do not confuse this with the guestfish-specific
3488 C<alloc> command which allocates a file in the host and
3489 attaches it as a device.");
3490
3491   ("swapon_device", (RErr, [Device "device"]), 170, [],
3492    [InitPartition, Always, TestRun (
3493       [["mkswap"; "/dev/sda1"];
3494        ["swapon_device"; "/dev/sda1"];
3495        ["swapoff_device"; "/dev/sda1"]])],
3496    "enable swap on device",
3497    "\
3498 This command enables the libguestfs appliance to use the
3499 swap device or partition named C<device>.  The increased
3500 memory is made available for all commands, for example
3501 those run using C<guestfs_command> or C<guestfs_sh>.
3502
3503 Note that you should not swap to existing guest swap
3504 partitions unless you know what you are doing.  They may
3505 contain hibernation information, or other information that
3506 the guest doesn't want you to trash.  You also risk leaking
3507 information about the host to the guest this way.  Instead,
3508 attach a new host device to the guest and swap on that.");
3509
3510   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3511    [], (* XXX tested by swapon_device *)
3512    "disable swap on device",
3513    "\
3514 This command disables the libguestfs appliance swap
3515 device or partition named C<device>.
3516 See C<guestfs_swapon_device>.");
3517
3518   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3519    [InitBasicFS, Always, TestRun (
3520       [["fallocate"; "/swap"; "8388608"];
3521        ["mkswap_file"; "/swap"];
3522        ["swapon_file"; "/swap"];
3523        ["swapoff_file"; "/swap"]])],
3524    "enable swap on file",
3525    "\
3526 This command enables swap to a file.
3527 See C<guestfs_swapon_device> for other notes.");
3528
3529   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3530    [], (* XXX tested by swapon_file *)
3531    "disable swap on file",
3532    "\
3533 This command disables the libguestfs appliance swap on file.");
3534
3535   ("swapon_label", (RErr, [String "label"]), 174, [],
3536    [InitEmpty, Always, TestRun (
3537       [["part_disk"; "/dev/sdb"; "mbr"];
3538        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3539        ["swapon_label"; "swapit"];
3540        ["swapoff_label"; "swapit"];
3541        ["zero"; "/dev/sdb"];
3542        ["blockdev_rereadpt"; "/dev/sdb"]])],
3543    "enable swap on labeled swap partition",
3544    "\
3545 This command enables swap to a labeled swap partition.
3546 See C<guestfs_swapon_device> for other notes.");
3547
3548   ("swapoff_label", (RErr, [String "label"]), 175, [],
3549    [], (* XXX tested by swapon_label *)
3550    "disable swap on labeled swap partition",
3551    "\
3552 This command disables the libguestfs appliance swap on
3553 labeled swap partition.");
3554
3555   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3556    (let uuid = uuidgen () in
3557     [InitEmpty, Always, TestRun (
3558        [["mkswap_U"; uuid; "/dev/sdb"];
3559         ["swapon_uuid"; uuid];
3560         ["swapoff_uuid"; uuid]])]),
3561    "enable swap on swap partition by UUID",
3562    "\
3563 This command enables swap to a swap partition with the given UUID.
3564 See C<guestfs_swapon_device> for other notes.");
3565
3566   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3567    [], (* XXX tested by swapon_uuid *)
3568    "disable swap on swap partition by UUID",
3569    "\
3570 This command disables the libguestfs appliance swap partition
3571 with the given UUID.");
3572
3573   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3574    [InitBasicFS, Always, TestRun (
3575       [["fallocate"; "/swap"; "8388608"];
3576        ["mkswap_file"; "/swap"]])],
3577    "create a swap file",
3578    "\
3579 Create a swap file.
3580
3581 This command just writes a swap file signature to an existing
3582 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3583
3584   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3585    [InitISOFS, Always, TestRun (
3586       [["inotify_init"; "0"]])],
3587    "create an inotify handle",
3588    "\
3589 This command creates a new inotify handle.
3590 The inotify subsystem can be used to notify events which happen to
3591 objects in the guest filesystem.
3592
3593 C<maxevents> is the maximum number of events which will be
3594 queued up between calls to C<guestfs_inotify_read> or
3595 C<guestfs_inotify_files>.
3596 If this is passed as C<0>, then the kernel (or previously set)
3597 default is used.  For Linux 2.6.29 the default was 16384 events.
3598 Beyond this limit, the kernel throws away events, but records
3599 the fact that it threw them away by setting a flag
3600 C<IN_Q_OVERFLOW> in the returned structure list (see
3601 C<guestfs_inotify_read>).
3602
3603 Before any events are generated, you have to add some
3604 watches to the internal watch list.  See:
3605 C<guestfs_inotify_add_watch>,
3606 C<guestfs_inotify_rm_watch> and
3607 C<guestfs_inotify_watch_all>.
3608
3609 Queued up events should be read periodically by calling
3610 C<guestfs_inotify_read>
3611 (or C<guestfs_inotify_files> which is just a helpful
3612 wrapper around C<guestfs_inotify_read>).  If you don't
3613 read the events out often enough then you risk the internal
3614 queue overflowing.
3615
3616 The handle should be closed after use by calling
3617 C<guestfs_inotify_close>.  This also removes any
3618 watches automatically.
3619
3620 See also L<inotify(7)> for an overview of the inotify interface
3621 as exposed by the Linux kernel, which is roughly what we expose
3622 via libguestfs.  Note that there is one global inotify handle
3623 per libguestfs instance.");
3624
3625   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3626    [InitBasicFS, Always, TestOutputList (
3627       [["inotify_init"; "0"];
3628        ["inotify_add_watch"; "/"; "1073741823"];
3629        ["touch"; "/a"];
3630        ["touch"; "/b"];
3631        ["inotify_files"]], ["a"; "b"])],
3632    "add an inotify watch",
3633    "\
3634 Watch C<path> for the events listed in C<mask>.
3635
3636 Note that if C<path> is a directory then events within that
3637 directory are watched, but this does I<not> happen recursively
3638 (in subdirectories).
3639
3640 Note for non-C or non-Linux callers: the inotify events are
3641 defined by the Linux kernel ABI and are listed in
3642 C</usr/include/sys/inotify.h>.");
3643
3644   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3645    [],
3646    "remove an inotify watch",
3647    "\
3648 Remove a previously defined inotify watch.
3649 See C<guestfs_inotify_add_watch>.");
3650
3651   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3652    [],
3653    "return list of inotify events",
3654    "\
3655 Return the complete queue of events that have happened
3656 since the previous read call.
3657
3658 If no events have happened, this returns an empty list.
3659
3660 I<Note>: In order to make sure that all events have been
3661 read, you must call this function repeatedly until it
3662 returns an empty list.  The reason is that the call will
3663 read events up to the maximum appliance-to-host message
3664 size and leave remaining events in the queue.");
3665
3666   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3667    [],
3668    "return list of watched files that had events",
3669    "\
3670 This function is a helpful wrapper around C<guestfs_inotify_read>
3671 which just returns a list of pathnames of objects that were
3672 touched.  The returned pathnames are sorted and deduplicated.");
3673
3674   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3675    [],
3676    "close the inotify handle",
3677    "\
3678 This closes the inotify handle which was previously
3679 opened by inotify_init.  It removes all watches, throws
3680 away any pending events, and deallocates all resources.");
3681
3682   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3683    [],
3684    "set SELinux security context",
3685    "\
3686 This sets the SELinux security context of the daemon
3687 to the string C<context>.
3688
3689 See the documentation about SELINUX in L<guestfs(3)>.");
3690
3691   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3692    [],
3693    "get SELinux security context",
3694    "\
3695 This gets the SELinux security context of the daemon.
3696
3697 See the documentation about SELINUX in L<guestfs(3)>,
3698 and C<guestfs_setcon>");
3699
3700   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3701    [InitEmpty, Always, TestOutput (
3702       [["part_disk"; "/dev/sda"; "mbr"];
3703        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3704        ["mount_options"; ""; "/dev/sda1"; "/"];
3705        ["write"; "/new"; "new file contents"];
3706        ["cat"; "/new"]], "new file contents")],
3707    "make a filesystem with block size",
3708    "\
3709 This call is similar to C<guestfs_mkfs>, but it allows you to
3710 control the block size of the resulting filesystem.  Supported
3711 block sizes depend on the filesystem type, but typically they
3712 are C<1024>, C<2048> or C<4096> only.");
3713
3714   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3715    [InitEmpty, Always, TestOutput (
3716       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3717        ["mke2journal"; "4096"; "/dev/sda1"];
3718        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3719        ["mount_options"; ""; "/dev/sda2"; "/"];
3720        ["write"; "/new"; "new file contents"];
3721        ["cat"; "/new"]], "new file contents")],
3722    "make ext2/3/4 external journal",
3723    "\
3724 This creates an ext2 external journal on C<device>.  It is equivalent
3725 to the command:
3726
3727  mke2fs -O journal_dev -b blocksize device");
3728
3729   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3730    [InitEmpty, Always, TestOutput (
3731       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3732        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3733        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3734        ["mount_options"; ""; "/dev/sda2"; "/"];
3735        ["write"; "/new"; "new file contents"];
3736        ["cat"; "/new"]], "new file contents")],
3737    "make ext2/3/4 external journal with label",
3738    "\
3739 This creates an ext2 external journal on C<device> with label C<label>.");
3740
3741   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3742    (let uuid = uuidgen () in
3743     [InitEmpty, Always, TestOutput (
3744        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3745         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3746         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3747         ["mount_options"; ""; "/dev/sda2"; "/"];
3748         ["write"; "/new"; "new file contents"];
3749         ["cat"; "/new"]], "new file contents")]),
3750    "make ext2/3/4 external journal with UUID",
3751    "\
3752 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3753
3754   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3755    [],
3756    "make ext2/3/4 filesystem with external journal",
3757    "\
3758 This creates an ext2/3/4 filesystem on C<device> with
3759 an external journal on C<journal>.  It is equivalent
3760 to the command:
3761
3762  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3763
3764 See also C<guestfs_mke2journal>.");
3765
3766   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3767    [],
3768    "make ext2/3/4 filesystem with external journal",
3769    "\
3770 This creates an ext2/3/4 filesystem on C<device> with
3771 an external journal on the journal labeled C<label>.
3772
3773 See also C<guestfs_mke2journal_L>.");
3774
3775   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3776    [],
3777    "make ext2/3/4 filesystem with external journal",
3778    "\
3779 This creates an ext2/3/4 filesystem on C<device> with
3780 an external journal on the journal with UUID C<uuid>.
3781
3782 See also C<guestfs_mke2journal_U>.");
3783
3784   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3785    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3786    "load a kernel module",
3787    "\
3788 This loads a kernel module in the appliance.
3789
3790 The kernel module must have been whitelisted when libguestfs
3791 was built (see C<appliance/kmod.whitelist.in> in the source).");
3792
3793   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3794    [InitNone, Always, TestOutput (
3795       [["echo_daemon"; "This is a test"]], "This is a test"
3796     )],
3797    "echo arguments back to the client",
3798    "\
3799 This command concatenate the list of C<words> passed with single spaces between
3800 them and returns the resulting string.
3801
3802 You can use this command to test the connection through to the daemon.
3803
3804 See also C<guestfs_ping_daemon>.");
3805
3806   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3807    [], (* There is a regression test for this. *)
3808    "find all files and directories, returning NUL-separated list",
3809    "\
3810 This command lists out all files and directories, recursively,
3811 starting at C<directory>, placing the resulting list in the
3812 external file called C<files>.
3813
3814 This command works the same way as C<guestfs_find> with the
3815 following exceptions:
3816
3817 =over 4
3818
3819 =item *
3820
3821 The resulting list is written to an external file.
3822
3823 =item *
3824
3825 Items (filenames) in the result are separated
3826 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3827
3828 =item *
3829
3830 This command is not limited in the number of names that it
3831 can return.
3832
3833 =item *
3834
3835 The result list is not sorted.
3836
3837 =back");
3838
3839   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3840    [InitISOFS, Always, TestOutput (
3841       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3842     InitISOFS, Always, TestOutput (
3843       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3844     InitISOFS, Always, TestOutput (
3845       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3846     InitISOFS, Always, TestLastFail (
3847       [["case_sensitive_path"; "/Known-1/"]]);
3848     InitBasicFS, Always, TestOutput (
3849       [["mkdir"; "/a"];
3850        ["mkdir"; "/a/bbb"];
3851        ["touch"; "/a/bbb/c"];
3852        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3853     InitBasicFS, Always, TestOutput (
3854       [["mkdir"; "/a"];
3855        ["mkdir"; "/a/bbb"];
3856        ["touch"; "/a/bbb/c"];
3857        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3858     InitBasicFS, Always, TestLastFail (
3859       [["mkdir"; "/a"];
3860        ["mkdir"; "/a/bbb"];
3861        ["touch"; "/a/bbb/c"];
3862        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3863    "return true path on case-insensitive filesystem",
3864    "\
3865 This can be used to resolve case insensitive paths on
3866 a filesystem which is case sensitive.  The use case is
3867 to resolve paths which you have read from Windows configuration
3868 files or the Windows Registry, to the true path.
3869
3870 The command handles a peculiarity of the Linux ntfs-3g
3871 filesystem driver (and probably others), which is that although
3872 the underlying filesystem is case-insensitive, the driver
3873 exports the filesystem to Linux as case-sensitive.
3874
3875 One consequence of this is that special directories such
3876 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3877 (or other things) depending on the precise details of how
3878 they were created.  In Windows itself this would not be
3879 a problem.
3880
3881 Bug or feature?  You decide:
3882 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3883
3884 This function resolves the true case of each element in the
3885 path and returns the case-sensitive path.
3886
3887 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3888 might return C<\"/WINDOWS/system32\"> (the exact return value
3889 would depend on details of how the directories were originally
3890 created under Windows).
3891
3892 I<Note>:
3893 This function does not handle drive names, backslashes etc.
3894
3895 See also C<guestfs_realpath>.");
3896
3897   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3898    [InitBasicFS, Always, TestOutput (
3899       [["vfs_type"; "/dev/sda1"]], "ext2")],
3900    "get the Linux VFS type corresponding to a mounted device",
3901    "\
3902 This command gets the block device type corresponding to
3903 a mounted device called C<device>.
3904
3905 Usually the result is the name of the Linux VFS module that
3906 is used to mount this device (probably determined automatically
3907 if you used the C<guestfs_mount> call).");
3908
3909   ("truncate", (RErr, [Pathname "path"]), 199, [],
3910    [InitBasicFS, Always, TestOutputStruct (
3911       [["write"; "/test"; "some stuff so size is not zero"];
3912        ["truncate"; "/test"];
3913        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3914    "truncate a file to zero size",
3915    "\
3916 This command truncates C<path> to a zero-length file.  The
3917 file must exist already.");
3918
3919   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3920    [InitBasicFS, Always, TestOutputStruct (
3921       [["touch"; "/test"];
3922        ["truncate_size"; "/test"; "1000"];
3923        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3924    "truncate a file to a particular size",
3925    "\
3926 This command truncates C<path> to size C<size> bytes.  The file
3927 must exist already.  If the file is smaller than C<size> then
3928 the file is extended to the required size with null bytes.");
3929
3930   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3931    [InitBasicFS, Always, TestOutputStruct (
3932       [["touch"; "/test"];
3933        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3934        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3935    "set timestamp of a file with nanosecond precision",
3936    "\
3937 This command sets the timestamps of a file with nanosecond
3938 precision.
3939
3940 C<atsecs, atnsecs> are the last access time (atime) in secs and
3941 nanoseconds from the epoch.
3942
3943 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3944 secs and nanoseconds from the epoch.
3945
3946 If the C<*nsecs> field contains the special value C<-1> then
3947 the corresponding timestamp is set to the current time.  (The
3948 C<*secs> field is ignored in this case).
3949
3950 If the C<*nsecs> field contains the special value C<-2> then
3951 the corresponding timestamp is left unchanged.  (The
3952 C<*secs> field is ignored in this case).");
3953
3954   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3955    [InitBasicFS, Always, TestOutputStruct (
3956       [["mkdir_mode"; "/test"; "0o111"];
3957        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3958    "create a directory with a particular mode",
3959    "\
3960 This command creates a directory, setting the initial permissions
3961 of the directory to C<mode>.
3962
3963 For common Linux filesystems, the actual mode which is set will
3964 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
3965 interpret the mode in other ways.
3966
3967 See also C<guestfs_mkdir>, C<guestfs_umask>");
3968
3969   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3970    [], (* XXX *)
3971    "change file owner and group",
3972    "\
3973 Change the file owner to C<owner> and group to C<group>.
3974 This is like C<guestfs_chown> but if C<path> is a symlink then
3975 the link itself is changed, not the target.
3976
3977 Only numeric uid and gid are supported.  If you want to use
3978 names, you will need to locate and parse the password file
3979 yourself (Augeas support makes this relatively easy).");
3980
3981   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3982    [], (* XXX *)
3983    "lstat on multiple files",
3984    "\
3985 This call allows you to perform the C<guestfs_lstat> operation
3986 on multiple files, where all files are in the directory C<path>.
3987 C<names> is the list of files from this directory.
3988
3989 On return you get a list of stat structs, with a one-to-one
3990 correspondence to the C<names> list.  If any name did not exist
3991 or could not be lstat'd, then the C<ino> field of that structure
3992 is set to C<-1>.
3993
3994 This call is intended for programs that want to efficiently
3995 list a directory contents without making many round-trips.
3996 See also C<guestfs_lxattrlist> for a similarly efficient call
3997 for getting extended attributes.  Very long directory listings
3998 might cause the protocol message size to be exceeded, causing
3999 this call to fail.  The caller must split up such requests
4000 into smaller groups of names.");
4001
4002   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4003    [], (* XXX *)
4004    "lgetxattr on multiple files",
4005    "\
4006 This call allows you to get the extended attributes
4007 of multiple files, where all files are in the directory C<path>.
4008 C<names> is the list of files from this directory.
4009
4010 On return you get a flat list of xattr structs which must be
4011 interpreted sequentially.  The first xattr struct always has a zero-length
4012 C<attrname>.  C<attrval> in this struct is zero-length
4013 to indicate there was an error doing C<lgetxattr> for this
4014 file, I<or> is a C string which is a decimal number
4015 (the number of following attributes for this file, which could
4016 be C<\"0\">).  Then after the first xattr struct are the
4017 zero or more attributes for the first named file.
4018 This repeats for the second and subsequent files.
4019
4020 This call is intended for programs that want to efficiently
4021 list a directory contents without making many round-trips.
4022 See also C<guestfs_lstatlist> for a similarly efficient call
4023 for getting standard stats.  Very long directory listings
4024 might cause the protocol message size to be exceeded, causing
4025 this call to fail.  The caller must split up such requests
4026 into smaller groups of names.");
4027
4028   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4029    [], (* XXX *)
4030    "readlink on multiple files",
4031    "\
4032 This call allows you to do a C<readlink> operation
4033 on multiple files, where all files are in the directory C<path>.
4034 C<names> is the list of files from this directory.
4035
4036 On return you get a list of strings, with a one-to-one
4037 correspondence to the C<names> list.  Each string is the
4038 value of the symbol link.
4039
4040 If the C<readlink(2)> operation fails on any name, then
4041 the corresponding result string is the empty string C<\"\">.
4042 However the whole operation is completed even if there
4043 were C<readlink(2)> errors, and so you can call this
4044 function with names where you don't know if they are
4045 symbolic links already (albeit slightly less efficient).
4046
4047 This call is intended for programs that want to efficiently
4048 list a directory contents without making many round-trips.
4049 Very long directory listings might cause the protocol
4050 message size to be exceeded, causing
4051 this call to fail.  The caller must split up such requests
4052 into smaller groups of names.");
4053
4054   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4055    [InitISOFS, Always, TestOutputBuffer (
4056       [["pread"; "/known-4"; "1"; "3"]], "\n");
4057     InitISOFS, Always, TestOutputBuffer (
4058       [["pread"; "/empty"; "0"; "100"]], "")],
4059    "read part of a file",
4060    "\
4061 This command lets you read part of a file.  It reads C<count>
4062 bytes of the file, starting at C<offset>, from file C<path>.
4063
4064 This may read fewer bytes than requested.  For further details
4065 see the L<pread(2)> system call.
4066
4067 See also C<guestfs_pwrite>.");
4068
4069   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4070    [InitEmpty, Always, TestRun (
4071       [["part_init"; "/dev/sda"; "gpt"]])],
4072    "create an empty partition table",
4073    "\
4074 This creates an empty partition table on C<device> of one of the
4075 partition types listed below.  Usually C<parttype> should be
4076 either C<msdos> or C<gpt> (for large disks).
4077
4078 Initially there are no partitions.  Following this, you should
4079 call C<guestfs_part_add> for each partition required.
4080
4081 Possible values for C<parttype> are:
4082
4083 =over 4
4084
4085 =item B<efi> | B<gpt>
4086
4087 Intel EFI / GPT partition table.
4088
4089 This is recommended for >= 2 TB partitions that will be accessed
4090 from Linux and Intel-based Mac OS X.  It also has limited backwards
4091 compatibility with the C<mbr> format.
4092
4093 =item B<mbr> | B<msdos>
4094
4095 The standard PC \"Master Boot Record\" (MBR) format used
4096 by MS-DOS and Windows.  This partition type will B<only> work
4097 for device sizes up to 2 TB.  For large disks we recommend
4098 using C<gpt>.
4099
4100 =back
4101
4102 Other partition table types that may work but are not
4103 supported include:
4104
4105 =over 4
4106
4107 =item B<aix>
4108
4109 AIX disk labels.
4110
4111 =item B<amiga> | B<rdb>
4112
4113 Amiga \"Rigid Disk Block\" format.
4114
4115 =item B<bsd>
4116
4117 BSD disk labels.
4118
4119 =item B<dasd>
4120
4121 DASD, used on IBM mainframes.
4122
4123 =item B<dvh>
4124
4125 MIPS/SGI volumes.
4126
4127 =item B<mac>
4128
4129 Old Mac partition format.  Modern Macs use C<gpt>.
4130
4131 =item B<pc98>
4132
4133 NEC PC-98 format, common in Japan apparently.
4134
4135 =item B<sun>
4136
4137 Sun disk labels.
4138
4139 =back");
4140
4141   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4142    [InitEmpty, Always, TestRun (
4143       [["part_init"; "/dev/sda"; "mbr"];
4144        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4145     InitEmpty, Always, TestRun (
4146       [["part_init"; "/dev/sda"; "gpt"];
4147        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4148        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4149     InitEmpty, Always, TestRun (
4150       [["part_init"; "/dev/sda"; "mbr"];
4151        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4152        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4153        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4154        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4155    "add a partition to the device",
4156    "\
4157 This command adds a partition to C<device>.  If there is no partition
4158 table on the device, call C<guestfs_part_init> first.
4159
4160 The C<prlogex> parameter is the type of partition.  Normally you
4161 should pass C<p> or C<primary> here, but MBR partition tables also
4162 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4163 types.
4164
4165 C<startsect> and C<endsect> are the start and end of the partition
4166 in I<sectors>.  C<endsect> may be negative, which means it counts
4167 backwards from the end of the disk (C<-1> is the last sector).
4168
4169 Creating a partition which covers the whole disk is not so easy.
4170 Use C<guestfs_part_disk> to do that.");
4171
4172   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4173    [InitEmpty, Always, TestRun (
4174       [["part_disk"; "/dev/sda"; "mbr"]]);
4175     InitEmpty, Always, TestRun (
4176       [["part_disk"; "/dev/sda"; "gpt"]])],
4177    "partition whole disk with a single primary partition",
4178    "\
4179 This command is simply a combination of C<guestfs_part_init>
4180 followed by C<guestfs_part_add> to create a single primary partition
4181 covering the whole disk.
4182
4183 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4184 but other possible values are described in C<guestfs_part_init>.");
4185
4186   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4187    [InitEmpty, Always, TestRun (
4188       [["part_disk"; "/dev/sda"; "mbr"];
4189        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4190    "make a partition bootable",
4191    "\
4192 This sets the bootable flag on partition numbered C<partnum> on
4193 device C<device>.  Note that partitions are numbered from 1.
4194
4195 The bootable flag is used by some operating systems (notably
4196 Windows) to determine which partition to boot from.  It is by
4197 no means universally recognized.");
4198
4199   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4200    [InitEmpty, Always, TestRun (
4201       [["part_disk"; "/dev/sda"; "gpt"];
4202        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4203    "set partition name",
4204    "\
4205 This sets the partition name on partition numbered C<partnum> on
4206 device C<device>.  Note that partitions are numbered from 1.
4207
4208 The partition name can only be set on certain types of partition
4209 table.  This works on C<gpt> but not on C<mbr> partitions.");
4210
4211   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4212    [], (* XXX Add a regression test for this. *)
4213    "list partitions on a device",
4214    "\
4215 This command parses the partition table on C<device> and
4216 returns the list of partitions found.
4217
4218 The fields in the returned structure are:
4219
4220 =over 4
4221
4222 =item B<part_num>
4223
4224 Partition number, counting from 1.
4225
4226 =item B<part_start>
4227
4228 Start of the partition I<in bytes>.  To get sectors you have to
4229 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4230
4231 =item B<part_end>
4232
4233 End of the partition in bytes.
4234
4235 =item B<part_size>
4236
4237 Size of the partition in bytes.
4238
4239 =back");
4240
4241   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4242    [InitEmpty, Always, TestOutput (
4243       [["part_disk"; "/dev/sda"; "gpt"];
4244        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4245    "get the partition table type",
4246    "\
4247 This command examines the partition table on C<device> and
4248 returns the partition table type (format) being used.
4249
4250 Common return values include: C<msdos> (a DOS/Windows style MBR
4251 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4252 values are possible, although unusual.  See C<guestfs_part_init>
4253 for a full list.");
4254
4255   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4256    [InitBasicFS, Always, TestOutputBuffer (
4257       [["fill"; "0x63"; "10"; "/test"];
4258        ["read_file"; "/test"]], "cccccccccc")],
4259    "fill a file with octets",
4260    "\
4261 This command creates a new file called C<path>.  The initial
4262 content of the file is C<len> octets of C<c>, where C<c>
4263 must be a number in the range C<[0..255]>.
4264
4265 To fill a file with zero bytes (sparsely), it is
4266 much more efficient to use C<guestfs_truncate_size>.
4267 To create a file with a pattern of repeating bytes
4268 use C<guestfs_fill_pattern>.");
4269
4270   ("available", (RErr, [StringList "groups"]), 216, [],
4271    [InitNone, Always, TestRun [["available"; ""]]],
4272    "test availability of some parts of the API",
4273    "\
4274 This command is used to check the availability of some
4275 groups of functionality in the appliance, which not all builds of
4276 the libguestfs appliance will be able to provide.
4277
4278 The libguestfs groups, and the functions that those
4279 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4280
4281 The argument C<groups> is a list of group names, eg:
4282 C<[\"inotify\", \"augeas\"]> would check for the availability of
4283 the Linux inotify functions and Augeas (configuration file
4284 editing) functions.
4285
4286 The command returns no error if I<all> requested groups are available.
4287
4288 It fails with an error if one or more of the requested
4289 groups is unavailable in the appliance.
4290
4291 If an unknown group name is included in the
4292 list of groups then an error is always returned.
4293
4294 I<Notes:>
4295
4296 =over 4
4297
4298 =item *
4299
4300 You must call C<guestfs_launch> before calling this function.
4301
4302 The reason is because we don't know what groups are
4303 supported by the appliance/daemon until it is running and can
4304 be queried.
4305
4306 =item *
4307
4308 If a group of functions is available, this does not necessarily
4309 mean that they will work.  You still have to check for errors
4310 when calling individual API functions even if they are
4311 available.
4312
4313 =item *
4314
4315 It is usually the job of distro packagers to build
4316 complete functionality into the libguestfs appliance.
4317 Upstream libguestfs, if built from source with all
4318 requirements satisfied, will support everything.
4319
4320 =item *
4321
4322 This call was added in version C<1.0.80>.  In previous
4323 versions of libguestfs all you could do would be to speculatively
4324 execute a command to find out if the daemon implemented it.
4325 See also C<guestfs_version>.
4326
4327 =back");
4328
4329   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4330    [InitBasicFS, Always, TestOutputBuffer (
4331       [["write"; "/src"; "hello, world"];
4332        ["dd"; "/src"; "/dest"];
4333        ["read_file"; "/dest"]], "hello, world")],
4334    "copy from source to destination using dd",
4335    "\
4336 This command copies from one source device or file C<src>
4337 to another destination device or file C<dest>.  Normally you
4338 would use this to copy to or from a device or partition, for
4339 example to duplicate a filesystem.
4340
4341 If the destination is a device, it must be as large or larger
4342 than the source file or device, otherwise the copy will fail.
4343 This command cannot do partial copies (see C<guestfs_copy_size>).");
4344
4345   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4346    [InitBasicFS, Always, TestOutputInt (
4347       [["write"; "/file"; "hello, world"];
4348        ["filesize"; "/file"]], 12)],
4349    "return the size of the file in bytes",
4350    "\
4351 This command returns the size of C<file> in bytes.
4352
4353 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4354 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4355 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4356
4357   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4358    [InitBasicFSonLVM, Always, TestOutputList (
4359       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4360        ["lvs"]], ["/dev/VG/LV2"])],
4361    "rename an LVM logical volume",
4362    "\
4363 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4364
4365   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4366    [InitBasicFSonLVM, Always, TestOutputList (
4367       [["umount"; "/"];
4368        ["vg_activate"; "false"; "VG"];
4369        ["vgrename"; "VG"; "VG2"];
4370        ["vg_activate"; "true"; "VG2"];
4371        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4372        ["vgs"]], ["VG2"])],
4373    "rename an LVM volume group",
4374    "\
4375 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4376
4377   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4378    [InitISOFS, Always, TestOutputBuffer (
4379       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4380    "list the contents of a single file in an initrd",
4381    "\
4382 This command unpacks the file C<filename> from the initrd file
4383 called C<initrdpath>.  The filename must be given I<without> the
4384 initial C</> character.
4385
4386 For example, in guestfish you could use the following command
4387 to examine the boot script (usually called C</init>)
4388 contained in a Linux initrd or initramfs image:
4389
4390  initrd-cat /boot/initrd-<version>.img init
4391
4392 See also C<guestfs_initrd_list>.");
4393
4394   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4395    [],
4396    "get the UUID of a physical volume",
4397    "\
4398 This command returns the UUID of the LVM PV C<device>.");
4399
4400   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4401    [],
4402    "get the UUID of a volume group",
4403    "\
4404 This command returns the UUID of the LVM VG named C<vgname>.");
4405
4406   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4407    [],
4408    "get the UUID of a logical volume",
4409    "\
4410 This command returns the UUID of the LVM LV C<device>.");
4411
4412   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4413    [],
4414    "get the PV UUIDs containing the volume group",
4415    "\
4416 Given a VG called C<vgname>, this returns the UUIDs of all
4417 the physical volumes that this volume group resides on.
4418
4419 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4420 calls to associate physical volumes and volume groups.
4421
4422 See also C<guestfs_vglvuuids>.");
4423
4424   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4425    [],
4426    "get the LV UUIDs of all LVs in the volume group",
4427    "\
4428 Given a VG called C<vgname>, this returns the UUIDs of all
4429 the logical volumes created in this volume group.
4430
4431 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4432 calls to associate logical volumes and volume groups.
4433
4434 See also C<guestfs_vgpvuuids>.");
4435
4436   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4437    [InitBasicFS, Always, TestOutputBuffer (
4438       [["write"; "/src"; "hello, world"];
4439        ["copy_size"; "/src"; "/dest"; "5"];
4440        ["read_file"; "/dest"]], "hello")],
4441    "copy size bytes from source to destination using dd",
4442    "\
4443 This command copies exactly C<size> bytes from one source device
4444 or file C<src> to another destination device or file C<dest>.
4445
4446 Note this will fail if the source is too short or if the destination
4447 is not large enough.");
4448
4449   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4450    [InitBasicFSonLVM, Always, TestRun (
4451       [["zero_device"; "/dev/VG/LV"]])],
4452    "write zeroes to an entire device",
4453    "\
4454 This command writes zeroes over the entire C<device>.  Compare
4455 with C<guestfs_zero> which just zeroes the first few blocks of
4456 a device.");
4457
4458   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4459    [InitBasicFS, Always, TestOutput (
4460       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4461        ["cat"; "/hello"]], "hello\n")],
4462    "unpack compressed tarball to directory",
4463    "\
4464 This command uploads and unpacks local file C<tarball> (an
4465 I<xz compressed> tar file) into C<directory>.");
4466
4467   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4468    [],
4469    "pack directory into compressed tarball",
4470    "\
4471 This command packs the contents of C<directory> and downloads
4472 it to local file C<tarball> (as an xz compressed tar archive).");
4473
4474   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4475    [],
4476    "resize an NTFS filesystem",
4477    "\
4478 This command resizes an NTFS filesystem, expanding or
4479 shrinking it to the size of the underlying device.
4480 See also L<ntfsresize(8)>.");
4481
4482   ("vgscan", (RErr, []), 232, [],
4483    [InitEmpty, Always, TestRun (
4484       [["vgscan"]])],
4485    "rescan for LVM physical volumes, volume groups and logical volumes",
4486    "\
4487 This rescans all block devices and rebuilds the list of LVM
4488 physical volumes, volume groups and logical volumes.");
4489
4490   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4491    [InitEmpty, Always, TestRun (
4492       [["part_init"; "/dev/sda"; "mbr"];
4493        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4494        ["part_del"; "/dev/sda"; "1"]])],
4495    "delete a partition",
4496    "\
4497 This command deletes the partition numbered C<partnum> on C<device>.
4498
4499 Note that in the case of MBR partitioning, deleting an
4500 extended partition also deletes any logical partitions
4501 it contains.");
4502
4503   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4504    [InitEmpty, Always, TestOutputTrue (
4505       [["part_init"; "/dev/sda"; "mbr"];
4506        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4507        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4508        ["part_get_bootable"; "/dev/sda"; "1"]])],
4509    "return true if a partition is bootable",
4510    "\
4511 This command returns true if the partition C<partnum> on
4512 C<device> has the bootable flag set.
4513
4514 See also C<guestfs_part_set_bootable>.");
4515
4516   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4517    [InitEmpty, Always, TestOutputInt (
4518       [["part_init"; "/dev/sda"; "mbr"];
4519        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4520        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4521        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4522    "get the MBR type byte (ID byte) from a partition",
4523    "\
4524 Returns the MBR type byte (also known as the ID byte) from
4525 the numbered partition C<partnum>.
4526
4527 Note that only MBR (old DOS-style) partitions have type bytes.
4528 You will get undefined results for other partition table
4529 types (see C<guestfs_part_get_parttype>).");
4530
4531   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4532    [], (* tested by part_get_mbr_id *)
4533    "set the MBR type byte (ID byte) of a partition",
4534    "\
4535 Sets the MBR type byte (also known as the ID byte) of
4536 the numbered partition C<partnum> to C<idbyte>.  Note
4537 that the type bytes quoted in most documentation are
4538 in fact hexadecimal numbers, but usually documented
4539 without any leading \"0x\" which might be confusing.
4540
4541 Note that only MBR (old DOS-style) partitions have type bytes.
4542 You will get undefined results for other partition table
4543 types (see C<guestfs_part_get_parttype>).");
4544
4545   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4546    [InitISOFS, Always, TestOutput (
4547       [["checksum_device"; "md5"; "/dev/sdd"]],
4548       (Digest.to_hex (Digest.file "images/test.iso")))],
4549    "compute MD5, SHAx or CRC checksum of the contents of a device",
4550    "\
4551 This call computes the MD5, SHAx or CRC checksum of the
4552 contents of the device named C<device>.  For the types of
4553 checksums supported see the C<guestfs_checksum> command.");
4554
4555   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4556    [InitNone, Always, TestRun (
4557       [["part_disk"; "/dev/sda"; "mbr"];
4558        ["pvcreate"; "/dev/sda1"];
4559        ["vgcreate"; "VG"; "/dev/sda1"];
4560        ["lvcreate"; "LV"; "VG"; "10"];
4561        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4562    "expand an LV to fill free space",
4563    "\
4564 This expands an existing logical volume C<lv> so that it fills
4565 C<pc>% of the remaining free space in the volume group.  Commonly
4566 you would call this with pc = 100 which expands the logical volume
4567 as much as possible, using all remaining free space in the volume
4568 group.");
4569
4570   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4571    [], (* XXX Augeas code needs tests. *)
4572    "clear Augeas path",
4573    "\
4574 Set the value associated with C<path> to C<NULL>.  This
4575 is the same as the L<augtool(1)> C<clear> command.");
4576
4577   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4578    [InitEmpty, Always, TestOutputInt (
4579       [["get_umask"]], 0o22)],
4580    "get the current umask",
4581    "\
4582 Return the current umask.  By default the umask is C<022>
4583 unless it has been set by calling C<guestfs_umask>.");
4584
4585   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4586    [],
4587    "upload a file to the appliance (internal use only)",
4588    "\
4589 The C<guestfs_debug_upload> command uploads a file to
4590 the libguestfs appliance.
4591
4592 There is no comprehensive help for this command.  You have
4593 to look at the file C<daemon/debug.c> in the libguestfs source
4594 to find out what it is for.");
4595
4596   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4597    [InitBasicFS, Always, TestOutput (
4598       [["base64_in"; "../images/hello.b64"; "/hello"];
4599        ["cat"; "/hello"]], "hello\n")],
4600    "upload base64-encoded data to file",
4601    "\
4602 This command uploads base64-encoded data from C<base64file>
4603 to C<filename>.");
4604
4605   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4606    [],
4607    "download file and encode as base64",
4608    "\
4609 This command downloads the contents of C<filename>, writing
4610 it out to local file C<base64file> encoded as base64.");
4611
4612   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4613    [],
4614    "compute MD5, SHAx or CRC checksum of files in a directory",
4615    "\
4616 This command computes the checksums of all regular files in
4617 C<directory> and then emits a list of those checksums to
4618 the local output file C<sumsfile>.
4619
4620 This can be used for verifying the integrity of a virtual
4621 machine.  However to be properly secure you should pay
4622 attention to the output of the checksum command (it uses
4623 the ones from GNU coreutils).  In particular when the
4624 filename is not printable, coreutils uses a special
4625 backslash syntax.  For more information, see the GNU
4626 coreutils info file.");
4627
4628   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4629    [InitBasicFS, Always, TestOutputBuffer (
4630       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4631        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4632    "fill a file with a repeating pattern of bytes",
4633    "\
4634 This function is like C<guestfs_fill> except that it creates
4635 a new file of length C<len> containing the repeating pattern
4636 of bytes in C<pattern>.  The pattern is truncated if necessary
4637 to ensure the length of the file is exactly C<len> bytes.");
4638
4639   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4640    [InitBasicFS, Always, TestOutput (
4641       [["write"; "/new"; "new file contents"];
4642        ["cat"; "/new"]], "new file contents");
4643     InitBasicFS, Always, TestOutput (
4644       [["write"; "/new"; "\nnew file contents\n"];
4645        ["cat"; "/new"]], "\nnew file contents\n");
4646     InitBasicFS, Always, TestOutput (
4647       [["write"; "/new"; "\n\n"];
4648        ["cat"; "/new"]], "\n\n");
4649     InitBasicFS, Always, TestOutput (
4650       [["write"; "/new"; ""];
4651        ["cat"; "/new"]], "");
4652     InitBasicFS, Always, TestOutput (
4653       [["write"; "/new"; "\n\n\n"];
4654        ["cat"; "/new"]], "\n\n\n");
4655     InitBasicFS, Always, TestOutput (
4656       [["write"; "/new"; "\n"];
4657        ["cat"; "/new"]], "\n")],
4658    "create a new file",
4659    "\
4660 This call creates a file called C<path>.  The content of the
4661 file is the string C<content> (which can contain any 8 bit data).");
4662
4663   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4664    [InitBasicFS, Always, TestOutput (
4665       [["write"; "/new"; "new file contents"];
4666        ["pwrite"; "/new"; "data"; "4"];
4667        ["cat"; "/new"]], "new data contents");
4668     InitBasicFS, Always, TestOutput (
4669       [["write"; "/new"; "new file contents"];
4670        ["pwrite"; "/new"; "is extended"; "9"];
4671        ["cat"; "/new"]], "new file is extended");
4672     InitBasicFS, Always, TestOutput (
4673       [["write"; "/new"; "new file contents"];
4674        ["pwrite"; "/new"; ""; "4"];
4675        ["cat"; "/new"]], "new file contents")],
4676    "write to part of a file",
4677    "\
4678 This command writes to part of a file.  It writes the data
4679 buffer C<content> to the file C<path> starting at offset C<offset>.
4680
4681 This command implements the L<pwrite(2)> system call, and like
4682 that system call it may not write the full data requested.  The
4683 return value is the number of bytes that were actually written
4684 to the file.  This could even be 0, although short writes are
4685 unlikely for regular files in ordinary circumstances.
4686
4687 See also C<guestfs_pread>.");
4688
4689   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4690    [],
4691    "resize an ext2/ext3 filesystem (with size)",
4692    "\
4693 This command is the same as C<guestfs_resize2fs> except that it
4694 allows you to specify the new size (in bytes) explicitly.");
4695
4696 ]
4697
4698 let all_functions = non_daemon_functions @ daemon_functions
4699
4700 (* In some places we want the functions to be displayed sorted
4701  * alphabetically, so this is useful:
4702  *)
4703 let all_functions_sorted =
4704   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4705                compare n1 n2) all_functions
4706
4707 (* This is used to generate the src/MAX_PROC_NR file which
4708  * contains the maximum procedure number, a surrogate for the
4709  * ABI version number.  See src/Makefile.am for the details.
4710  *)
4711 let max_proc_nr =
4712   let proc_nrs = List.map (
4713     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4714   ) daemon_functions in
4715   List.fold_left max 0 proc_nrs
4716
4717 (* Field types for structures. *)
4718 type field =
4719   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4720   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4721   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4722   | FUInt32
4723   | FInt32
4724   | FUInt64
4725   | FInt64
4726   | FBytes                      (* Any int measure that counts bytes. *)
4727   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4728   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4729
4730 (* Because we generate extra parsing code for LVM command line tools,
4731  * we have to pull out the LVM columns separately here.
4732  *)
4733 let lvm_pv_cols = [
4734   "pv_name", FString;
4735   "pv_uuid", FUUID;
4736   "pv_fmt", FString;
4737   "pv_size", FBytes;
4738   "dev_size", FBytes;
4739   "pv_free", FBytes;
4740   "pv_used", FBytes;
4741   "pv_attr", FString (* XXX *);
4742   "pv_pe_count", FInt64;
4743   "pv_pe_alloc_count", FInt64;
4744   "pv_tags", FString;
4745   "pe_start", FBytes;
4746   "pv_mda_count", FInt64;
4747   "pv_mda_free", FBytes;
4748   (* Not in Fedora 10:
4749      "pv_mda_size", FBytes;
4750   *)
4751 ]
4752 let lvm_vg_cols = [
4753   "vg_name", FString;
4754   "vg_uuid", FUUID;
4755   "vg_fmt", FString;
4756   "vg_attr", FString (* XXX *);
4757   "vg_size", FBytes;
4758   "vg_free", FBytes;
4759   "vg_sysid", FString;
4760   "vg_extent_size", FBytes;
4761   "vg_extent_count", FInt64;
4762   "vg_free_count", FInt64;
4763   "max_lv", FInt64;
4764   "max_pv", FInt64;
4765   "pv_count", FInt64;
4766   "lv_count", FInt64;
4767   "snap_count", FInt64;
4768   "vg_seqno", FInt64;
4769   "vg_tags", FString;
4770   "vg_mda_count", FInt64;
4771   "vg_mda_free", FBytes;
4772   (* Not in Fedora 10:
4773      "vg_mda_size", FBytes;
4774   *)
4775 ]
4776 let lvm_lv_cols = [
4777   "lv_name", FString;
4778   "lv_uuid", FUUID;
4779   "lv_attr", FString (* XXX *);
4780   "lv_major", FInt64;
4781   "lv_minor", FInt64;
4782   "lv_kernel_major", FInt64;
4783   "lv_kernel_minor", FInt64;
4784   "lv_size", FBytes;
4785   "seg_count", FInt64;
4786   "origin", FString;
4787   "snap_percent", FOptPercent;
4788   "copy_percent", FOptPercent;
4789   "move_pv", FString;
4790   "lv_tags", FString;
4791   "mirror_log", FString;
4792   "modules", FString;
4793 ]
4794
4795 (* Names and fields in all structures (in RStruct and RStructList)
4796  * that we support.
4797  *)
4798 let structs = [
4799   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4800    * not use this struct in any new code.
4801    *)
4802   "int_bool", [
4803     "i", FInt32;                (* for historical compatibility *)
4804     "b", FInt32;                (* for historical compatibility *)
4805   ];
4806
4807   (* LVM PVs, VGs, LVs. *)
4808   "lvm_pv", lvm_pv_cols;
4809   "lvm_vg", lvm_vg_cols;
4810   "lvm_lv", lvm_lv_cols;
4811
4812   (* Column names and types from stat structures.
4813    * NB. Can't use things like 'st_atime' because glibc header files
4814    * define some of these as macros.  Ugh.
4815    *)
4816   "stat", [
4817     "dev", FInt64;
4818     "ino", FInt64;
4819     "mode", FInt64;
4820     "nlink", FInt64;
4821     "uid", FInt64;
4822     "gid", FInt64;
4823     "rdev", FInt64;
4824     "size", FInt64;
4825     "blksize", FInt64;
4826     "blocks", FInt64;
4827     "atime", FInt64;
4828     "mtime", FInt64;
4829     "ctime", FInt64;
4830   ];
4831   "statvfs", [
4832     "bsize", FInt64;
4833     "frsize", FInt64;
4834     "blocks", FInt64;
4835     "bfree", FInt64;
4836     "bavail", FInt64;
4837     "files", FInt64;
4838     "ffree", FInt64;
4839     "favail", FInt64;
4840     "fsid", FInt64;
4841     "flag", FInt64;
4842     "namemax", FInt64;
4843   ];
4844
4845   (* Column names in dirent structure. *)
4846   "dirent", [
4847     "ino", FInt64;
4848     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4849     "ftyp", FChar;
4850     "name", FString;
4851   ];
4852
4853   (* Version numbers. *)
4854   "version", [
4855     "major", FInt64;
4856     "minor", FInt64;
4857     "release", FInt64;
4858     "extra", FString;
4859   ];
4860
4861   (* Extended attribute. *)
4862   "xattr", [
4863     "attrname", FString;
4864     "attrval", FBuffer;
4865   ];
4866
4867   (* Inotify events. *)
4868   "inotify_event", [
4869     "in_wd", FInt64;
4870     "in_mask", FUInt32;
4871     "in_cookie", FUInt32;
4872     "in_name", FString;
4873   ];
4874
4875   (* Partition table entry. *)
4876   "partition", [
4877     "part_num", FInt32;
4878     "part_start", FBytes;
4879     "part_end", FBytes;
4880     "part_size", FBytes;
4881   ];
4882 ] (* end of structs *)
4883
4884 (* Ugh, Java has to be different ..
4885  * These names are also used by the Haskell bindings.
4886  *)
4887 let java_structs = [
4888   "int_bool", "IntBool";
4889   "lvm_pv", "PV";
4890   "lvm_vg", "VG";
4891   "lvm_lv", "LV";
4892   "stat", "Stat";
4893   "statvfs", "StatVFS";
4894   "dirent", "Dirent";
4895   "version", "Version";
4896   "xattr", "XAttr";
4897   "inotify_event", "INotifyEvent";
4898   "partition", "Partition";
4899 ]
4900
4901 (* What structs are actually returned. *)
4902 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4903
4904 (* Returns a list of RStruct/RStructList structs that are returned
4905  * by any function.  Each element of returned list is a pair:
4906  *
4907  * (structname, RStructOnly)
4908  *    == there exists function which returns RStruct (_, structname)
4909  * (structname, RStructListOnly)
4910  *    == there exists function which returns RStructList (_, structname)
4911  * (structname, RStructAndList)
4912  *    == there are functions returning both RStruct (_, structname)
4913  *                                      and RStructList (_, structname)
4914  *)
4915 let rstructs_used_by functions =
4916   (* ||| is a "logical OR" for rstructs_used_t *)
4917   let (|||) a b =
4918     match a, b with
4919     | RStructAndList, _
4920     | _, RStructAndList -> RStructAndList
4921     | RStructOnly, RStructListOnly
4922     | RStructListOnly, RStructOnly -> RStructAndList
4923     | RStructOnly, RStructOnly -> RStructOnly
4924     | RStructListOnly, RStructListOnly -> RStructListOnly
4925   in
4926
4927   let h = Hashtbl.create 13 in
4928
4929   (* if elem->oldv exists, update entry using ||| operator,
4930    * else just add elem->newv to the hash
4931    *)
4932   let update elem newv =
4933     try  let oldv = Hashtbl.find h elem in
4934          Hashtbl.replace h elem (newv ||| oldv)
4935     with Not_found -> Hashtbl.add h elem newv
4936   in
4937
4938   List.iter (
4939     fun (_, style, _, _, _, _, _) ->
4940       match fst style with
4941       | RStruct (_, structname) -> update structname RStructOnly
4942       | RStructList (_, structname) -> update structname RStructListOnly
4943       | _ -> ()
4944   ) functions;
4945
4946   (* return key->values as a list of (key,value) *)
4947   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4948
4949 (* Used for testing language bindings. *)
4950 type callt =
4951   | CallString of string
4952   | CallOptString of string option
4953   | CallStringList of string list
4954   | CallInt of int
4955   | CallInt64 of int64
4956   | CallBool of bool
4957   | CallBuffer of string
4958
4959 (* Used to memoize the result of pod2text. *)
4960 let pod2text_memo_filename = "src/.pod2text.data"
4961 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4962   try
4963     let chan = open_in pod2text_memo_filename in
4964     let v = input_value chan in
4965     close_in chan;
4966     v
4967   with
4968     _ -> Hashtbl.create 13
4969 let pod2text_memo_updated () =
4970   let chan = open_out pod2text_memo_filename in
4971   output_value chan pod2text_memo;
4972   close_out chan
4973
4974 (* Useful functions.
4975  * Note we don't want to use any external OCaml libraries which
4976  * makes this a bit harder than it should be.
4977  *)
4978 module StringMap = Map.Make (String)
4979
4980 let failwithf fs = ksprintf failwith fs
4981
4982 let unique = let i = ref 0 in fun () -> incr i; !i
4983
4984 let replace_char s c1 c2 =
4985   let s2 = String.copy s in
4986   let r = ref false in
4987   for i = 0 to String.length s2 - 1 do
4988     if String.unsafe_get s2 i = c1 then (
4989       String.unsafe_set s2 i c2;
4990       r := true
4991     )
4992   done;
4993   if not !r then s else s2
4994
4995 let isspace c =
4996   c = ' '
4997   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4998
4999 let triml ?(test = isspace) str =
5000   let i = ref 0 in
5001   let n = ref (String.length str) in
5002   while !n > 0 && test str.[!i]; do
5003     decr n;
5004     incr i
5005   done;
5006   if !i = 0 then str
5007   else String.sub str !i !n
5008
5009 let trimr ?(test = isspace) str =
5010   let n = ref (String.length str) in
5011   while !n > 0 && test str.[!n-1]; do
5012     decr n
5013   done;
5014   if !n = String.length str then str
5015   else String.sub str 0 !n
5016
5017 let trim ?(test = isspace) str =
5018   trimr ~test (triml ~test str)
5019
5020 let rec find s sub =
5021   let len = String.length s in
5022   let sublen = String.length sub in
5023   let rec loop i =
5024     if i <= len-sublen then (
5025       let rec loop2 j =
5026         if j < sublen then (
5027           if s.[i+j] = sub.[j] then loop2 (j+1)
5028           else -1
5029         ) else
5030           i (* found *)
5031       in
5032       let r = loop2 0 in
5033       if r = -1 then loop (i+1) else r
5034     ) else
5035       -1 (* not found *)
5036   in
5037   loop 0
5038
5039 let rec replace_str s s1 s2 =
5040   let len = String.length s in
5041   let sublen = String.length s1 in
5042   let i = find s s1 in
5043   if i = -1 then s
5044   else (
5045     let s' = String.sub s 0 i in
5046     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5047     s' ^ s2 ^ replace_str s'' s1 s2
5048   )
5049
5050 let rec string_split sep str =
5051   let len = String.length str in
5052   let seplen = String.length sep in
5053   let i = find str sep in
5054   if i = -1 then [str]
5055   else (
5056     let s' = String.sub str 0 i in
5057     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5058     s' :: string_split sep s''
5059   )
5060
5061 let files_equal n1 n2 =
5062   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5063   match Sys.command cmd with
5064   | 0 -> true
5065   | 1 -> false
5066   | i -> failwithf "%s: failed with error code %d" cmd i
5067
5068 let rec filter_map f = function
5069   | [] -> []
5070   | x :: xs ->
5071       match f x with
5072       | Some y -> y :: filter_map f xs
5073       | None -> filter_map f xs
5074
5075 let rec find_map f = function
5076   | [] -> raise Not_found
5077   | x :: xs ->
5078       match f x with
5079       | Some y -> y
5080       | None -> find_map f xs
5081
5082 let iteri f xs =
5083   let rec loop i = function
5084     | [] -> ()
5085     | x :: xs -> f i x; loop (i+1) xs
5086   in
5087   loop 0 xs
5088
5089 let mapi f xs =
5090   let rec loop i = function
5091     | [] -> []
5092     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5093   in
5094   loop 0 xs
5095
5096 let count_chars c str =
5097   let count = ref 0 in
5098   for i = 0 to String.length str - 1 do
5099     if c = String.unsafe_get str i then incr count
5100   done;
5101   !count
5102
5103 let explode str =
5104   let r = ref [] in
5105   for i = 0 to String.length str - 1 do
5106     let c = String.unsafe_get str i in
5107     r := c :: !r;
5108   done;
5109   List.rev !r
5110
5111 let map_chars f str =
5112   List.map f (explode str)
5113
5114 let name_of_argt = function
5115   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5116   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5117   | FileIn n | FileOut n | BufferIn n -> n
5118
5119 let java_name_of_struct typ =
5120   try List.assoc typ java_structs
5121   with Not_found ->
5122     failwithf
5123       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5124
5125 let cols_of_struct typ =
5126   try List.assoc typ structs
5127   with Not_found ->
5128     failwithf "cols_of_struct: unknown struct %s" typ
5129
5130 let seq_of_test = function
5131   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5132   | TestOutputListOfDevices (s, _)
5133   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5134   | TestOutputTrue s | TestOutputFalse s
5135   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5136   | TestOutputStruct (s, _)
5137   | TestLastFail s -> s
5138
5139 (* Handling for function flags. *)
5140 let protocol_limit_warning =
5141   "Because of the message protocol, there is a transfer limit
5142 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5143
5144 let danger_will_robinson =
5145   "B<This command is dangerous.  Without careful use you
5146 can easily destroy all your data>."
5147
5148 let deprecation_notice flags =
5149   try
5150     let alt =
5151       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5152     let txt =
5153       sprintf "This function is deprecated.
5154 In new code, use the C<%s> call instead.
5155
5156 Deprecated functions will not be removed from the API, but the
5157 fact that they are deprecated indicates that there are problems
5158 with correct use of these functions." alt in
5159     Some txt
5160   with
5161     Not_found -> None
5162
5163 (* Create list of optional groups. *)
5164 let optgroups =
5165   let h = Hashtbl.create 13 in
5166   List.iter (
5167     fun (name, _, _, flags, _, _, _) ->
5168       List.iter (
5169         function
5170         | Optional group ->
5171             let names = try Hashtbl.find h group with Not_found -> [] in
5172             Hashtbl.replace h group (name :: names)
5173         | _ -> ()
5174       ) flags
5175   ) daemon_functions;
5176   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5177   let groups =
5178     List.map (
5179       fun group -> group, List.sort compare (Hashtbl.find h group)
5180     ) groups in
5181   List.sort (fun x y -> compare (fst x) (fst y)) groups
5182
5183 (* Check function names etc. for consistency. *)
5184 let check_functions () =
5185   let contains_uppercase str =
5186     let len = String.length str in
5187     let rec loop i =
5188       if i >= len then false
5189       else (
5190         let c = str.[i] in
5191         if c >= 'A' && c <= 'Z' then true
5192         else loop (i+1)
5193       )
5194     in
5195     loop 0
5196   in
5197
5198   (* Check function names. *)
5199   List.iter (
5200     fun (name, _, _, _, _, _, _) ->
5201       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5202         failwithf "function name %s does not need 'guestfs' prefix" name;
5203       if name = "" then
5204         failwithf "function name is empty";
5205       if name.[0] < 'a' || name.[0] > 'z' then
5206         failwithf "function name %s must start with lowercase a-z" name;
5207       if String.contains name '-' then
5208         failwithf "function name %s should not contain '-', use '_' instead."
5209           name
5210   ) all_functions;
5211
5212   (* Check function parameter/return names. *)
5213   List.iter (
5214     fun (name, style, _, _, _, _, _) ->
5215       let check_arg_ret_name n =
5216         if contains_uppercase n then
5217           failwithf "%s param/ret %s should not contain uppercase chars"
5218             name n;
5219         if String.contains n '-' || String.contains n '_' then
5220           failwithf "%s param/ret %s should not contain '-' or '_'"
5221             name n;
5222         if n = "value" then
5223           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;
5224         if n = "int" || n = "char" || n = "short" || n = "long" then
5225           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5226         if n = "i" || n = "n" then
5227           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5228         if n = "argv" || n = "args" then
5229           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5230
5231         (* List Haskell, OCaml and C keywords here.
5232          * http://www.haskell.org/haskellwiki/Keywords
5233          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5234          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5235          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5236          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5237          * Omitting _-containing words, since they're handled above.
5238          * Omitting the OCaml reserved word, "val", is ok,
5239          * and saves us from renaming several parameters.
5240          *)
5241         let reserved = [
5242           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5243           "char"; "class"; "const"; "constraint"; "continue"; "data";
5244           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5245           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5246           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5247           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5248           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5249           "interface";
5250           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5251           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5252           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5253           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5254           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5255           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5256           "volatile"; "when"; "where"; "while";
5257           ] in
5258         if List.mem n reserved then
5259           failwithf "%s has param/ret using reserved word %s" name n;
5260       in
5261
5262       (match fst style with
5263        | RErr -> ()
5264        | RInt n | RInt64 n | RBool n
5265        | RConstString n | RConstOptString n | RString n
5266        | RStringList n | RStruct (n, _) | RStructList (n, _)
5267        | RHashtable n | RBufferOut n ->
5268            check_arg_ret_name n
5269       );
5270       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5271   ) all_functions;
5272
5273   (* Check short descriptions. *)
5274   List.iter (
5275     fun (name, _, _, _, _, shortdesc, _) ->
5276       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5277         failwithf "short description of %s should begin with lowercase." name;
5278       let c = shortdesc.[String.length shortdesc-1] in
5279       if c = '\n' || c = '.' then
5280         failwithf "short description of %s should not end with . or \\n." name
5281   ) all_functions;
5282
5283   (* Check long descriptions. *)
5284   List.iter (
5285     fun (name, _, _, _, _, _, longdesc) ->
5286       if longdesc.[String.length longdesc-1] = '\n' then
5287         failwithf "long description of %s should not end with \\n." name
5288   ) all_functions;
5289
5290   (* Check proc_nrs. *)
5291   List.iter (
5292     fun (name, _, proc_nr, _, _, _, _) ->
5293       if proc_nr <= 0 then
5294         failwithf "daemon function %s should have proc_nr > 0" name
5295   ) daemon_functions;
5296
5297   List.iter (
5298     fun (name, _, proc_nr, _, _, _, _) ->
5299       if proc_nr <> -1 then
5300         failwithf "non-daemon function %s should have proc_nr -1" name
5301   ) non_daemon_functions;
5302
5303   let proc_nrs =
5304     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5305       daemon_functions in
5306   let proc_nrs =
5307     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5308   let rec loop = function
5309     | [] -> ()
5310     | [_] -> ()
5311     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5312         loop rest
5313     | (name1,nr1) :: (name2,nr2) :: _ ->
5314         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5315           name1 name2 nr1 nr2
5316   in
5317   loop proc_nrs;
5318
5319   (* Check tests. *)
5320   List.iter (
5321     function
5322       (* Ignore functions that have no tests.  We generate a
5323        * warning when the user does 'make check' instead.
5324        *)
5325     | name, _, _, _, [], _, _ -> ()
5326     | name, _, _, _, tests, _, _ ->
5327         let funcs =
5328           List.map (
5329             fun (_, _, test) ->
5330               match seq_of_test test with
5331               | [] ->
5332                   failwithf "%s has a test containing an empty sequence" name
5333               | cmds -> List.map List.hd cmds
5334           ) tests in
5335         let funcs = List.flatten funcs in
5336
5337         let tested = List.mem name funcs in
5338
5339         if not tested then
5340           failwithf "function %s has tests but does not test itself" name
5341   ) all_functions
5342
5343 (* 'pr' prints to the current output file. *)
5344 let chan = ref Pervasives.stdout
5345 let lines = ref 0
5346 let pr fs =
5347   ksprintf
5348     (fun str ->
5349        let i = count_chars '\n' str in
5350        lines := !lines + i;
5351        output_string !chan str
5352     ) fs
5353
5354 let copyright_years =
5355   let this_year = 1900 + (localtime (time ())).tm_year in
5356   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5357
5358 (* Generate a header block in a number of standard styles. *)
5359 type comment_style =
5360     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5361 type license = GPLv2plus | LGPLv2plus
5362
5363 let generate_header ?(extra_inputs = []) comment license =
5364   let inputs = "src/generator.ml" :: extra_inputs in
5365   let c = match comment with
5366     | CStyle ->         pr "/* "; " *"
5367     | CPlusPlusStyle -> pr "// "; "//"
5368     | HashStyle ->      pr "# ";  "#"
5369     | OCamlStyle ->     pr "(* "; " *"
5370     | HaskellStyle ->   pr "{- "; "  " in
5371   pr "libguestfs generated file\n";
5372   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5373   List.iter (pr "%s   %s\n" c) inputs;
5374   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5375   pr "%s\n" c;
5376   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5377   pr "%s\n" c;
5378   (match license with
5379    | GPLv2plus ->
5380        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5381        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5382        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5383        pr "%s (at your option) any later version.\n" c;
5384        pr "%s\n" c;
5385        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5386        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5387        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5388        pr "%s GNU General Public License for more details.\n" c;
5389        pr "%s\n" c;
5390        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5391        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5392        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5393
5394    | LGPLv2plus ->
5395        pr "%s This library is free software; you can redistribute it and/or\n" c;
5396        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5397        pr "%s License as published by the Free Software Foundation; either\n" c;
5398        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5399        pr "%s\n" c;
5400        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5401        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5402        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5403        pr "%s Lesser General Public License for more details.\n" c;
5404        pr "%s\n" c;
5405        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5406        pr "%s License along with this library; if not, write to the Free Software\n" c;
5407        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5408   );
5409   (match comment with
5410    | CStyle -> pr " */\n"
5411    | CPlusPlusStyle
5412    | HashStyle -> ()
5413    | OCamlStyle -> pr " *)\n"
5414    | HaskellStyle -> pr "-}\n"
5415   );
5416   pr "\n"
5417
5418 (* Start of main code generation functions below this line. *)
5419
5420 (* Generate the pod documentation for the C API. *)
5421 let rec generate_actions_pod () =
5422   List.iter (
5423     fun (shortname, style, _, flags, _, _, longdesc) ->
5424       if not (List.mem NotInDocs flags) then (
5425         let name = "guestfs_" ^ shortname in
5426         pr "=head2 %s\n\n" name;
5427         pr " ";
5428         generate_prototype ~extern:false ~handle:"g" name style;
5429         pr "\n\n";
5430         pr "%s\n\n" longdesc;
5431         (match fst style with
5432          | RErr ->
5433              pr "This function returns 0 on success or -1 on error.\n\n"
5434          | RInt _ ->
5435              pr "On error this function returns -1.\n\n"
5436          | RInt64 _ ->
5437              pr "On error this function returns -1.\n\n"
5438          | RBool _ ->
5439              pr "This function returns a C truth value on success or -1 on error.\n\n"
5440          | RConstString _ ->
5441              pr "This function returns a string, or NULL on error.
5442 The string is owned by the guest handle and must I<not> be freed.\n\n"
5443          | RConstOptString _ ->
5444              pr "This function returns a string which may be NULL.
5445 There is way to return an error from this function.
5446 The string is owned by the guest handle and must I<not> be freed.\n\n"
5447          | RString _ ->
5448              pr "This function returns a string, or NULL on error.
5449 I<The caller must free the returned string after use>.\n\n"
5450          | RStringList _ ->
5451              pr "This function returns a NULL-terminated array of strings
5452 (like L<environ(3)>), or NULL if there was an error.
5453 I<The caller must free the strings and the array after use>.\n\n"
5454          | RStruct (_, typ) ->
5455              pr "This function returns a C<struct guestfs_%s *>,
5456 or NULL if there was an error.
5457 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5458          | RStructList (_, typ) ->
5459              pr "This function returns a C<struct guestfs_%s_list *>
5460 (see E<lt>guestfs-structs.hE<gt>),
5461 or NULL if there was an error.
5462 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5463          | RHashtable _ ->
5464              pr "This function returns a NULL-terminated array of
5465 strings, or NULL if there was an error.
5466 The array of strings will always have length C<2n+1>, where
5467 C<n> keys and values alternate, followed by the trailing NULL entry.
5468 I<The caller must free the strings and the array after use>.\n\n"
5469          | RBufferOut _ ->
5470              pr "This function returns a buffer, or NULL on error.
5471 The size of the returned buffer is written to C<*size_r>.
5472 I<The caller must free the returned buffer after use>.\n\n"
5473         );
5474         if List.mem ProtocolLimitWarning flags then
5475           pr "%s\n\n" protocol_limit_warning;
5476         if List.mem DangerWillRobinson flags then
5477           pr "%s\n\n" danger_will_robinson;
5478         match deprecation_notice flags with
5479         | None -> ()
5480         | Some txt -> pr "%s\n\n" txt
5481       )
5482   ) all_functions_sorted
5483
5484 and generate_structs_pod () =
5485   (* Structs documentation. *)
5486   List.iter (
5487     fun (typ, cols) ->
5488       pr "=head2 guestfs_%s\n" typ;
5489       pr "\n";
5490       pr " struct guestfs_%s {\n" typ;
5491       List.iter (
5492         function
5493         | name, FChar -> pr "   char %s;\n" name
5494         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5495         | name, FInt32 -> pr "   int32_t %s;\n" name
5496         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5497         | name, FInt64 -> pr "   int64_t %s;\n" name
5498         | name, FString -> pr "   char *%s;\n" name
5499         | name, FBuffer ->
5500             pr "   /* The next two fields describe a byte array. */\n";
5501             pr "   uint32_t %s_len;\n" name;
5502             pr "   char *%s;\n" name
5503         | name, FUUID ->
5504             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5505             pr "   char %s[32];\n" name
5506         | name, FOptPercent ->
5507             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5508             pr "   float %s;\n" name
5509       ) cols;
5510       pr " };\n";
5511       pr " \n";
5512       pr " struct guestfs_%s_list {\n" typ;
5513       pr "   uint32_t len; /* Number of elements in list. */\n";
5514       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5515       pr " };\n";
5516       pr " \n";
5517       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5518       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5519         typ typ;
5520       pr "\n"
5521   ) structs
5522
5523 and generate_availability_pod () =
5524   (* Availability documentation. *)
5525   pr "=over 4\n";
5526   pr "\n";
5527   List.iter (
5528     fun (group, functions) ->
5529       pr "=item B<%s>\n" group;
5530       pr "\n";
5531       pr "The following functions:\n";
5532       List.iter (pr "L</guestfs_%s>\n") functions;
5533       pr "\n"
5534   ) optgroups;
5535   pr "=back\n";
5536   pr "\n"
5537
5538 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5539  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5540  *
5541  * We have to use an underscore instead of a dash because otherwise
5542  * rpcgen generates incorrect code.
5543  *
5544  * This header is NOT exported to clients, but see also generate_structs_h.
5545  *)
5546 and generate_xdr () =
5547   generate_header CStyle LGPLv2plus;
5548
5549   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5550   pr "typedef string str<>;\n";
5551   pr "\n";
5552
5553   (* Internal structures. *)
5554   List.iter (
5555     function
5556     | typ, cols ->
5557         pr "struct guestfs_int_%s {\n" typ;
5558         List.iter (function
5559                    | name, FChar -> pr "  char %s;\n" name
5560                    | name, FString -> pr "  string %s<>;\n" name
5561                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5562                    | name, FUUID -> pr "  opaque %s[32];\n" name
5563                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5564                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5565                    | name, FOptPercent -> pr "  float %s;\n" name
5566                   ) cols;
5567         pr "};\n";
5568         pr "\n";
5569         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5570         pr "\n";
5571   ) structs;
5572
5573   List.iter (
5574     fun (shortname, style, _, _, _, _, _) ->
5575       let name = "guestfs_" ^ shortname in
5576
5577       (match snd style with
5578        | [] -> ()
5579        | args ->
5580            pr "struct %s_args {\n" name;
5581            List.iter (
5582              function
5583              | Pathname n | Device n | Dev_or_Path n | String n ->
5584                  pr "  string %s<>;\n" n
5585              | OptString n -> pr "  str *%s;\n" n
5586              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5587              | Bool n -> pr "  bool %s;\n" n
5588              | Int n -> pr "  int %s;\n" n
5589              | Int64 n -> pr "  hyper %s;\n" n
5590              | BufferIn n ->
5591                  pr "  opaque %s<>;\n" n
5592              | FileIn _ | FileOut _ -> ()
5593            ) args;
5594            pr "};\n\n"
5595       );
5596       (match fst style with
5597        | RErr -> ()
5598        | RInt n ->
5599            pr "struct %s_ret {\n" name;
5600            pr "  int %s;\n" n;
5601            pr "};\n\n"
5602        | RInt64 n ->
5603            pr "struct %s_ret {\n" name;
5604            pr "  hyper %s;\n" n;
5605            pr "};\n\n"
5606        | RBool n ->
5607            pr "struct %s_ret {\n" name;
5608            pr "  bool %s;\n" n;
5609            pr "};\n\n"
5610        | RConstString _ | RConstOptString _ ->
5611            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5612        | RString n ->
5613            pr "struct %s_ret {\n" name;
5614            pr "  string %s<>;\n" n;
5615            pr "};\n\n"
5616        | RStringList n ->
5617            pr "struct %s_ret {\n" name;
5618            pr "  str %s<>;\n" n;
5619            pr "};\n\n"
5620        | RStruct (n, typ) ->
5621            pr "struct %s_ret {\n" name;
5622            pr "  guestfs_int_%s %s;\n" typ n;
5623            pr "};\n\n"
5624        | RStructList (n, typ) ->
5625            pr "struct %s_ret {\n" name;
5626            pr "  guestfs_int_%s_list %s;\n" typ n;
5627            pr "};\n\n"
5628        | RHashtable n ->
5629            pr "struct %s_ret {\n" name;
5630            pr "  str %s<>;\n" n;
5631            pr "};\n\n"
5632        | RBufferOut n ->
5633            pr "struct %s_ret {\n" name;
5634            pr "  opaque %s<>;\n" n;
5635            pr "};\n\n"
5636       );
5637   ) daemon_functions;
5638
5639   (* Table of procedure numbers. *)
5640   pr "enum guestfs_procedure {\n";
5641   List.iter (
5642     fun (shortname, _, proc_nr, _, _, _, _) ->
5643       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5644   ) daemon_functions;
5645   pr "  GUESTFS_PROC_NR_PROCS\n";
5646   pr "};\n";
5647   pr "\n";
5648
5649   (* Having to choose a maximum message size is annoying for several
5650    * reasons (it limits what we can do in the API), but it (a) makes
5651    * the protocol a lot simpler, and (b) provides a bound on the size
5652    * of the daemon which operates in limited memory space.
5653    *)
5654   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5655   pr "\n";
5656
5657   (* Message header, etc. *)
5658   pr "\
5659 /* The communication protocol is now documented in the guestfs(3)
5660  * manpage.
5661  */
5662
5663 const GUESTFS_PROGRAM = 0x2000F5F5;
5664 const GUESTFS_PROTOCOL_VERSION = 1;
5665
5666 /* These constants must be larger than any possible message length. */
5667 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5668 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5669
5670 enum guestfs_message_direction {
5671   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5672   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5673 };
5674
5675 enum guestfs_message_status {
5676   GUESTFS_STATUS_OK = 0,
5677   GUESTFS_STATUS_ERROR = 1
5678 };
5679
5680 const GUESTFS_ERROR_LEN = 256;
5681
5682 struct guestfs_message_error {
5683   string error_message<GUESTFS_ERROR_LEN>;
5684 };
5685
5686 struct guestfs_message_header {
5687   unsigned prog;                     /* GUESTFS_PROGRAM */
5688   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5689   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5690   guestfs_message_direction direction;
5691   unsigned serial;                   /* message serial number */
5692   guestfs_message_status status;
5693 };
5694
5695 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5696
5697 struct guestfs_chunk {
5698   int cancel;                        /* if non-zero, transfer is cancelled */
5699   /* data size is 0 bytes if the transfer has finished successfully */
5700   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5701 };
5702 "
5703
5704 (* Generate the guestfs-structs.h file. *)
5705 and generate_structs_h () =
5706   generate_header CStyle LGPLv2plus;
5707
5708   (* This is a public exported header file containing various
5709    * structures.  The structures are carefully written to have
5710    * exactly the same in-memory format as the XDR structures that
5711    * we use on the wire to the daemon.  The reason for creating
5712    * copies of these structures here is just so we don't have to
5713    * export the whole of guestfs_protocol.h (which includes much
5714    * unrelated and XDR-dependent stuff that we don't want to be
5715    * public, or required by clients).
5716    *
5717    * To reiterate, we will pass these structures to and from the
5718    * client with a simple assignment or memcpy, so the format
5719    * must be identical to what rpcgen / the RFC defines.
5720    *)
5721
5722   (* Public structures. *)
5723   List.iter (
5724     fun (typ, cols) ->
5725       pr "struct guestfs_%s {\n" typ;
5726       List.iter (
5727         function
5728         | name, FChar -> pr "  char %s;\n" name
5729         | name, FString -> pr "  char *%s;\n" name
5730         | name, FBuffer ->
5731             pr "  uint32_t %s_len;\n" name;
5732             pr "  char *%s;\n" name
5733         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5734         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5735         | name, FInt32 -> pr "  int32_t %s;\n" name
5736         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5737         | name, FInt64 -> pr "  int64_t %s;\n" name
5738         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5739       ) cols;
5740       pr "};\n";
5741       pr "\n";
5742       pr "struct guestfs_%s_list {\n" typ;
5743       pr "  uint32_t len;\n";
5744       pr "  struct guestfs_%s *val;\n" typ;
5745       pr "};\n";
5746       pr "\n";
5747       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5748       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5749       pr "\n"
5750   ) structs
5751
5752 (* Generate the guestfs-actions.h file. *)
5753 and generate_actions_h () =
5754   generate_header CStyle LGPLv2plus;
5755   List.iter (
5756     fun (shortname, style, _, _, _, _, _) ->
5757       let name = "guestfs_" ^ shortname in
5758       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5759         name style
5760   ) all_functions
5761
5762 (* Generate the guestfs-internal-actions.h file. *)
5763 and generate_internal_actions_h () =
5764   generate_header CStyle LGPLv2plus;
5765   List.iter (
5766     fun (shortname, style, _, _, _, _, _) ->
5767       let name = "guestfs__" ^ shortname in
5768       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5769         name style
5770   ) non_daemon_functions
5771
5772 (* Generate the client-side dispatch stubs. *)
5773 and generate_client_actions () =
5774   generate_header CStyle LGPLv2plus;
5775
5776   pr "\
5777 #include <stdio.h>
5778 #include <stdlib.h>
5779 #include <stdint.h>
5780 #include <string.h>
5781 #include <inttypes.h>
5782
5783 #include \"guestfs.h\"
5784 #include \"guestfs-internal.h\"
5785 #include \"guestfs-internal-actions.h\"
5786 #include \"guestfs_protocol.h\"
5787
5788 #define error guestfs_error
5789 //#define perrorf guestfs_perrorf
5790 #define safe_malloc guestfs_safe_malloc
5791 #define safe_realloc guestfs_safe_realloc
5792 //#define safe_strdup guestfs_safe_strdup
5793 #define safe_memdup guestfs_safe_memdup
5794
5795 /* Check the return message from a call for validity. */
5796 static int
5797 check_reply_header (guestfs_h *g,
5798                     const struct guestfs_message_header *hdr,
5799                     unsigned int proc_nr, unsigned int serial)
5800 {
5801   if (hdr->prog != GUESTFS_PROGRAM) {
5802     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5803     return -1;
5804   }
5805   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5806     error (g, \"wrong protocol version (%%d/%%d)\",
5807            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5808     return -1;
5809   }
5810   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5811     error (g, \"unexpected message direction (%%d/%%d)\",
5812            hdr->direction, GUESTFS_DIRECTION_REPLY);
5813     return -1;
5814   }
5815   if (hdr->proc != proc_nr) {
5816     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5817     return -1;
5818   }
5819   if (hdr->serial != serial) {
5820     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5821     return -1;
5822   }
5823
5824   return 0;
5825 }
5826
5827 /* Check we are in the right state to run a high-level action. */
5828 static int
5829 check_state (guestfs_h *g, const char *caller)
5830 {
5831   if (!guestfs__is_ready (g)) {
5832     if (guestfs__is_config (g) || guestfs__is_launching (g))
5833       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5834         caller);
5835     else
5836       error (g, \"%%s called from the wrong state, %%d != READY\",
5837         caller, guestfs__get_state (g));
5838     return -1;
5839   }
5840   return 0;
5841 }
5842
5843 ";
5844
5845   let error_code_of = function
5846     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5847     | RConstString _ | RConstOptString _
5848     | RString _ | RStringList _
5849     | RStruct _ | RStructList _
5850     | RHashtable _ | RBufferOut _ -> "NULL"
5851   in
5852
5853   (* Generate code to check String-like parameters are not passed in
5854    * as NULL (returning an error if they are).
5855    *)
5856   let check_null_strings shortname style =
5857     let pr_newline = ref false in
5858     List.iter (
5859       function
5860       (* parameters which should not be NULL *)
5861       | String n
5862       | Device n
5863       | Pathname n
5864       | Dev_or_Path n
5865       | FileIn n
5866       | FileOut n
5867       | BufferIn n
5868       | StringList n
5869       | DeviceList n ->
5870           pr "  if (%s == NULL) {\n" n;
5871           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
5872           pr "           \"%s\", \"%s\");\n" shortname n;
5873           pr "    return %s;\n" (error_code_of (fst style));
5874           pr "  }\n";
5875           pr_newline := true
5876
5877       (* can be NULL *)
5878       | OptString _
5879
5880       (* not applicable *)
5881       | Bool _
5882       | Int _
5883       | Int64 _ -> ()
5884     ) (snd style);
5885
5886     if !pr_newline then pr "\n";
5887   in
5888
5889   (* Generate code to generate guestfish call traces. *)
5890   let trace_call shortname style =
5891     pr "  if (guestfs__get_trace (g)) {\n";
5892
5893     let needs_i =
5894       List.exists (function
5895                    | StringList _ | DeviceList _ -> true
5896                    | _ -> false) (snd style) in
5897     if needs_i then (
5898       pr "    int i;\n";
5899       pr "\n"
5900     );
5901
5902     pr "    printf (\"%s\");\n" shortname;
5903     List.iter (
5904       function
5905       | String n                        (* strings *)
5906       | Device n
5907       | Pathname n
5908       | Dev_or_Path n
5909       | FileIn n
5910       | FileOut n
5911       | BufferIn n ->
5912           (* guestfish doesn't support string escaping, so neither do we *)
5913           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5914       | OptString n ->                  (* string option *)
5915           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5916           pr "    else printf (\" null\");\n"
5917       | StringList n
5918       | DeviceList n ->                 (* string list *)
5919           pr "    putchar (' ');\n";
5920           pr "    putchar ('\"');\n";
5921           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5922           pr "      if (i > 0) putchar (' ');\n";
5923           pr "      fputs (%s[i], stdout);\n" n;
5924           pr "    }\n";
5925           pr "    putchar ('\"');\n";
5926       | Bool n ->                       (* boolean *)
5927           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5928       | Int n ->                        (* int *)
5929           pr "    printf (\" %%d\", %s);\n" n
5930       | Int64 n ->
5931           pr "    printf (\" %%\" PRIi64, %s);\n" n
5932     ) (snd style);
5933     pr "    putchar ('\\n');\n";
5934     pr "  }\n";
5935     pr "\n";
5936   in
5937
5938   (* For non-daemon functions, generate a wrapper around each function. *)
5939   List.iter (
5940     fun (shortname, style, _, _, _, _, _) ->
5941       let name = "guestfs_" ^ shortname in
5942
5943       generate_prototype ~extern:false ~semicolon:false ~newline:true
5944         ~handle:"g" name style;
5945       pr "{\n";
5946       check_null_strings shortname style;
5947       trace_call shortname style;
5948       pr "  return guestfs__%s " shortname;
5949       generate_c_call_args ~handle:"g" style;
5950       pr ";\n";
5951       pr "}\n";
5952       pr "\n"
5953   ) non_daemon_functions;
5954
5955   (* Client-side stubs for each function. *)
5956   List.iter (
5957     fun (shortname, style, _, _, _, _, _) ->
5958       let name = "guestfs_" ^ shortname in
5959       let error_code = error_code_of (fst style) in
5960
5961       (* Generate the action stub. *)
5962       generate_prototype ~extern:false ~semicolon:false ~newline:true
5963         ~handle:"g" name style;
5964
5965       pr "{\n";
5966
5967       (match snd style with
5968        | [] -> ()
5969        | _ -> pr "  struct %s_args args;\n" name
5970       );
5971
5972       pr "  guestfs_message_header hdr;\n";
5973       pr "  guestfs_message_error err;\n";
5974       let has_ret =
5975         match fst style with
5976         | RErr -> false
5977         | RConstString _ | RConstOptString _ ->
5978             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5979         | RInt _ | RInt64 _
5980         | RBool _ | RString _ | RStringList _
5981         | RStruct _ | RStructList _
5982         | RHashtable _ | RBufferOut _ ->
5983             pr "  struct %s_ret ret;\n" name;
5984             true in
5985
5986       pr "  int serial;\n";
5987       pr "  int r;\n";
5988       pr "\n";
5989       check_null_strings shortname style;
5990       trace_call shortname style;
5991       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
5992         shortname error_code;
5993       pr "  guestfs___set_busy (g);\n";
5994       pr "\n";
5995
5996       (* Send the main header and arguments. *)
5997       (match snd style with
5998        | [] ->
5999            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6000              (String.uppercase shortname)
6001        | args ->
6002            List.iter (
6003              function
6004              | Pathname n | Device n | Dev_or_Path n | String n ->
6005                  pr "  args.%s = (char *) %s;\n" n n
6006              | OptString n ->
6007                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6008              | StringList n | DeviceList n ->
6009                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6010                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6011              | Bool n ->
6012                  pr "  args.%s = %s;\n" n n
6013              | Int n ->
6014                  pr "  args.%s = %s;\n" n n
6015              | Int64 n ->
6016                  pr "  args.%s = %s;\n" n n
6017              | FileIn _ | FileOut _ -> ()
6018              | BufferIn n ->
6019                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6020                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6021                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6022                    shortname;
6023                  pr "    guestfs___end_busy (g);\n";
6024                  pr "    return %s;\n" error_code;
6025                  pr "  }\n";
6026                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6027                  pr "  args.%s.%s_len = %s_size;\n" n n n
6028            ) args;
6029            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6030              (String.uppercase shortname);
6031            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6032              name;
6033       );
6034       pr "  if (serial == -1) {\n";
6035       pr "    guestfs___end_busy (g);\n";
6036       pr "    return %s;\n" error_code;
6037       pr "  }\n";
6038       pr "\n";
6039
6040       (* Send any additional files (FileIn) requested. *)
6041       let need_read_reply_label = ref false in
6042       List.iter (
6043         function
6044         | FileIn n ->
6045             pr "  r = guestfs___send_file (g, %s);\n" n;
6046             pr "  if (r == -1) {\n";
6047             pr "    guestfs___end_busy (g);\n";
6048             pr "    return %s;\n" error_code;
6049             pr "  }\n";
6050             pr "  if (r == -2) /* daemon cancelled */\n";
6051             pr "    goto read_reply;\n";
6052             need_read_reply_label := true;
6053             pr "\n";
6054         | _ -> ()
6055       ) (snd style);
6056
6057       (* Wait for the reply from the remote end. *)
6058       if !need_read_reply_label then pr " read_reply:\n";
6059       pr "  memset (&hdr, 0, sizeof hdr);\n";
6060       pr "  memset (&err, 0, sizeof err);\n";
6061       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6062       pr "\n";
6063       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6064       if not has_ret then
6065         pr "NULL, NULL"
6066       else
6067         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6068       pr ");\n";
6069
6070       pr "  if (r == -1) {\n";
6071       pr "    guestfs___end_busy (g);\n";
6072       pr "    return %s;\n" error_code;
6073       pr "  }\n";
6074       pr "\n";
6075
6076       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6077         (String.uppercase shortname);
6078       pr "    guestfs___end_busy (g);\n";
6079       pr "    return %s;\n" error_code;
6080       pr "  }\n";
6081       pr "\n";
6082
6083       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6084       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6085       pr "    free (err.error_message);\n";
6086       pr "    guestfs___end_busy (g);\n";
6087       pr "    return %s;\n" error_code;
6088       pr "  }\n";
6089       pr "\n";
6090
6091       (* Expecting to receive further files (FileOut)? *)
6092       List.iter (
6093         function
6094         | FileOut n ->
6095             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6096             pr "    guestfs___end_busy (g);\n";
6097             pr "    return %s;\n" error_code;
6098             pr "  }\n";
6099             pr "\n";
6100         | _ -> ()
6101       ) (snd style);
6102
6103       pr "  guestfs___end_busy (g);\n";
6104
6105       (match fst style with
6106        | RErr -> pr "  return 0;\n"
6107        | RInt n | RInt64 n | RBool n ->
6108            pr "  return ret.%s;\n" n
6109        | RConstString _ | RConstOptString _ ->
6110            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6111        | RString n ->
6112            pr "  return ret.%s; /* caller will free */\n" n
6113        | RStringList n | RHashtable n ->
6114            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6115            pr "  ret.%s.%s_val =\n" n n;
6116            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6117            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6118              n n;
6119            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6120            pr "  return ret.%s.%s_val;\n" n n
6121        | RStruct (n, _) ->
6122            pr "  /* caller will free this */\n";
6123            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6124        | RStructList (n, _) ->
6125            pr "  /* caller will free this */\n";
6126            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6127        | RBufferOut n ->
6128            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6129            pr "   * _val might be NULL here.  To make the API saner for\n";
6130            pr "   * callers, we turn this case into a unique pointer (using\n";
6131            pr "   * malloc(1)).\n";
6132            pr "   */\n";
6133            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6134            pr "    *size_r = ret.%s.%s_len;\n" n n;
6135            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6136            pr "  } else {\n";
6137            pr "    free (ret.%s.%s_val);\n" n n;
6138            pr "    char *p = safe_malloc (g, 1);\n";
6139            pr "    *size_r = ret.%s.%s_len;\n" n n;
6140            pr "    return p;\n";
6141            pr "  }\n";
6142       );
6143
6144       pr "}\n\n"
6145   ) daemon_functions;
6146
6147   (* Functions to free structures. *)
6148   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6149   pr " * structure format is identical to the XDR format.  See note in\n";
6150   pr " * generator.ml.\n";
6151   pr " */\n";
6152   pr "\n";
6153
6154   List.iter (
6155     fun (typ, _) ->
6156       pr "void\n";
6157       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6158       pr "{\n";
6159       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6160       pr "  free (x);\n";
6161       pr "}\n";
6162       pr "\n";
6163
6164       pr "void\n";
6165       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6166       pr "{\n";
6167       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6168       pr "  free (x);\n";
6169       pr "}\n";
6170       pr "\n";
6171
6172   ) structs;
6173
6174 (* Generate daemon/actions.h. *)
6175 and generate_daemon_actions_h () =
6176   generate_header CStyle GPLv2plus;
6177
6178   pr "#include \"../src/guestfs_protocol.h\"\n";
6179   pr "\n";
6180
6181   List.iter (
6182     fun (name, style, _, _, _, _, _) ->
6183       generate_prototype
6184         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6185         name style;
6186   ) daemon_functions
6187
6188 (* Generate the linker script which controls the visibility of
6189  * symbols in the public ABI and ensures no other symbols get
6190  * exported accidentally.
6191  *)
6192 and generate_linker_script () =
6193   generate_header HashStyle GPLv2plus;
6194
6195   let globals = [
6196     "guestfs_create";
6197     "guestfs_close";
6198     "guestfs_get_error_handler";
6199     "guestfs_get_out_of_memory_handler";
6200     "guestfs_last_error";
6201     "guestfs_set_error_handler";
6202     "guestfs_set_launch_done_callback";
6203     "guestfs_set_log_message_callback";
6204     "guestfs_set_out_of_memory_handler";
6205     "guestfs_set_subprocess_quit_callback";
6206
6207     (* Unofficial parts of the API: the bindings code use these
6208      * functions, so it is useful to export them.
6209      *)
6210     "guestfs_safe_calloc";
6211     "guestfs_safe_malloc";
6212   ] in
6213   let functions =
6214     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6215       all_functions in
6216   let structs =
6217     List.concat (
6218       List.map (fun (typ, _) ->
6219                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6220         structs
6221     ) in
6222   let globals = List.sort compare (globals @ functions @ structs) in
6223
6224   pr "{\n";
6225   pr "    global:\n";
6226   List.iter (pr "        %s;\n") globals;
6227   pr "\n";
6228
6229   pr "    local:\n";
6230   pr "        *;\n";
6231   pr "};\n"
6232
6233 (* Generate the server-side stubs. *)
6234 and generate_daemon_actions () =
6235   generate_header CStyle GPLv2plus;
6236
6237   pr "#include <config.h>\n";
6238   pr "\n";
6239   pr "#include <stdio.h>\n";
6240   pr "#include <stdlib.h>\n";
6241   pr "#include <string.h>\n";
6242   pr "#include <inttypes.h>\n";
6243   pr "#include <rpc/types.h>\n";
6244   pr "#include <rpc/xdr.h>\n";
6245   pr "\n";
6246   pr "#include \"daemon.h\"\n";
6247   pr "#include \"c-ctype.h\"\n";
6248   pr "#include \"../src/guestfs_protocol.h\"\n";
6249   pr "#include \"actions.h\"\n";
6250   pr "\n";
6251
6252   List.iter (
6253     fun (name, style, _, _, _, _, _) ->
6254       (* Generate server-side stubs. *)
6255       pr "static void %s_stub (XDR *xdr_in)\n" name;
6256       pr "{\n";
6257       let error_code =
6258         match fst style with
6259         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6260         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6261         | RBool _ -> pr "  int r;\n"; "-1"
6262         | RConstString _ | RConstOptString _ ->
6263             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6264         | RString _ -> pr "  char *r;\n"; "NULL"
6265         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6266         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6267         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6268         | RBufferOut _ ->
6269             pr "  size_t size = 1;\n";
6270             pr "  char *r;\n";
6271             "NULL" in
6272
6273       (match snd style with
6274        | [] -> ()
6275        | args ->
6276            pr "  struct guestfs_%s_args args;\n" name;
6277            List.iter (
6278              function
6279              | Device n | Dev_or_Path n
6280              | Pathname n
6281              | String n -> ()
6282              | OptString n -> pr "  char *%s;\n" n
6283              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6284              | Bool n -> pr "  int %s;\n" n
6285              | Int n -> pr "  int %s;\n" n
6286              | Int64 n -> pr "  int64_t %s;\n" n
6287              | FileIn _ | FileOut _ -> ()
6288              | BufferIn n ->
6289                  pr "  const char *%s;\n" n;
6290                  pr "  size_t %s_size;\n" n
6291            ) args
6292       );
6293       pr "\n";
6294
6295       let is_filein =
6296         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6297
6298       (match snd style with
6299        | [] -> ()
6300        | args ->
6301            pr "  memset (&args, 0, sizeof args);\n";
6302            pr "\n";
6303            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6304            if is_filein then
6305              pr "    if (cancel_receive () != -2)\n";
6306            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6307            pr "    goto done;\n";
6308            pr "  }\n";
6309            let pr_args n =
6310              pr "  char *%s = args.%s;\n" n n
6311            in
6312            let pr_list_handling_code n =
6313              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6314              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6315              pr "  if (%s == NULL) {\n" n;
6316              if is_filein then
6317                pr "    if (cancel_receive () != -2)\n";
6318              pr "      reply_with_perror (\"realloc\");\n";
6319              pr "    goto done;\n";
6320              pr "  }\n";
6321              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6322              pr "  args.%s.%s_val = %s;\n" n n n;
6323            in
6324            List.iter (
6325              function
6326              | Pathname n ->
6327                  pr_args n;
6328                  pr "  ABS_PATH (%s, %s, goto done);\n"
6329                    n (if is_filein then "cancel_receive ()" else "0");
6330              | Device n ->
6331                  pr_args n;
6332                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6333                    n (if is_filein then "cancel_receive ()" else "0");
6334              | Dev_or_Path n ->
6335                  pr_args n;
6336                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6337                    n (if is_filein then "cancel_receive ()" else "0");
6338              | String n -> pr_args n
6339              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6340              | StringList n ->
6341                  pr_list_handling_code n;
6342              | DeviceList n ->
6343                  pr_list_handling_code n;
6344                  pr "  /* Ensure that each is a device,\n";
6345                  pr "   * and perform device name translation. */\n";
6346                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
6347                  pr "    RESOLVE_DEVICE (physvols[pvi], %s, goto done);\n"
6348                    (if is_filein then "cancel_receive ()" else "0");
6349                  pr "  }\n";
6350              | Bool n -> pr "  %s = args.%s;\n" n n
6351              | Int n -> pr "  %s = args.%s;\n" n n
6352              | Int64 n -> pr "  %s = args.%s;\n" n n
6353              | FileIn _ | FileOut _ -> ()
6354              | BufferIn n ->
6355                  pr "  %s = args.%s.%s_val;\n" n n n;
6356                  pr "  %s_size = args.%s.%s_len;\n" n n n
6357            ) args;
6358            pr "\n"
6359       );
6360
6361       (* this is used at least for do_equal *)
6362       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6363         (* Emit NEED_ROOT just once, even when there are two or
6364            more Pathname args *)
6365         pr "  NEED_ROOT (%s, goto done);\n"
6366           (if is_filein then "cancel_receive ()" else "0");
6367       );
6368
6369       (* Don't want to call the impl with any FileIn or FileOut
6370        * parameters, since these go "outside" the RPC protocol.
6371        *)
6372       let args' =
6373         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6374           (snd style) in
6375       pr "  r = do_%s " name;
6376       generate_c_call_args (fst style, args');
6377       pr ";\n";
6378
6379       (match fst style with
6380        | RErr | RInt _ | RInt64 _ | RBool _
6381        | RConstString _ | RConstOptString _
6382        | RString _ | RStringList _ | RHashtable _
6383        | RStruct (_, _) | RStructList (_, _) ->
6384            pr "  if (r == %s)\n" error_code;
6385            pr "    /* do_%s has already called reply_with_error */\n" name;
6386            pr "    goto done;\n";
6387            pr "\n"
6388        | RBufferOut _ ->
6389            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6390            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6391            pr "   */\n";
6392            pr "  if (size == 1 && r == %s)\n" error_code;
6393            pr "    /* do_%s has already called reply_with_error */\n" name;
6394            pr "    goto done;\n";
6395            pr "\n"
6396       );
6397
6398       (* If there are any FileOut parameters, then the impl must
6399        * send its own reply.
6400        *)
6401       let no_reply =
6402         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6403       if no_reply then
6404         pr "  /* do_%s has already sent a reply */\n" name
6405       else (
6406         match fst style with
6407         | RErr -> pr "  reply (NULL, NULL);\n"
6408         | RInt n | RInt64 n | RBool n ->
6409             pr "  struct guestfs_%s_ret ret;\n" name;
6410             pr "  ret.%s = r;\n" n;
6411             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6412               name
6413         | RConstString _ | RConstOptString _ ->
6414             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6415         | RString n ->
6416             pr "  struct guestfs_%s_ret ret;\n" name;
6417             pr "  ret.%s = r;\n" n;
6418             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6419               name;
6420             pr "  free (r);\n"
6421         | RStringList n | RHashtable n ->
6422             pr "  struct guestfs_%s_ret ret;\n" name;
6423             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6424             pr "  ret.%s.%s_val = r;\n" n n;
6425             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6426               name;
6427             pr "  free_strings (r);\n"
6428         | RStruct (n, _) ->
6429             pr "  struct guestfs_%s_ret ret;\n" name;
6430             pr "  ret.%s = *r;\n" n;
6431             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6432               name;
6433             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6434               name
6435         | RStructList (n, _) ->
6436             pr "  struct guestfs_%s_ret ret;\n" name;
6437             pr "  ret.%s = *r;\n" n;
6438             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6439               name;
6440             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6441               name
6442         | RBufferOut n ->
6443             pr "  struct guestfs_%s_ret ret;\n" name;
6444             pr "  ret.%s.%s_val = r;\n" n n;
6445             pr "  ret.%s.%s_len = size;\n" n n;
6446             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6447               name;
6448             pr "  free (r);\n"
6449       );
6450
6451       (* Free the args. *)
6452       pr "done:\n";
6453       (match snd style with
6454        | [] -> ()
6455        | _ ->
6456            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6457              name
6458       );
6459       pr "  return;\n";
6460       pr "}\n\n";
6461   ) daemon_functions;
6462
6463   (* Dispatch function. *)
6464   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6465   pr "{\n";
6466   pr "  switch (proc_nr) {\n";
6467
6468   List.iter (
6469     fun (name, style, _, _, _, _, _) ->
6470       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6471       pr "      %s_stub (xdr_in);\n" name;
6472       pr "      break;\n"
6473   ) daemon_functions;
6474
6475   pr "    default:\n";
6476   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";
6477   pr "  }\n";
6478   pr "}\n";
6479   pr "\n";
6480
6481   (* LVM columns and tokenization functions. *)
6482   (* XXX This generates crap code.  We should rethink how we
6483    * do this parsing.
6484    *)
6485   List.iter (
6486     function
6487     | typ, cols ->
6488         pr "static const char *lvm_%s_cols = \"%s\";\n"
6489           typ (String.concat "," (List.map fst cols));
6490         pr "\n";
6491
6492         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6493         pr "{\n";
6494         pr "  char *tok, *p, *next;\n";
6495         pr "  int i, j;\n";
6496         pr "\n";
6497         (*
6498           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6499           pr "\n";
6500         *)
6501         pr "  if (!str) {\n";
6502         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6503         pr "    return -1;\n";
6504         pr "  }\n";
6505         pr "  if (!*str || c_isspace (*str)) {\n";
6506         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6507         pr "    return -1;\n";
6508         pr "  }\n";
6509         pr "  tok = str;\n";
6510         List.iter (
6511           fun (name, coltype) ->
6512             pr "  if (!tok) {\n";
6513             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6514             pr "    return -1;\n";
6515             pr "  }\n";
6516             pr "  p = strchrnul (tok, ',');\n";
6517             pr "  if (*p) next = p+1; else next = NULL;\n";
6518             pr "  *p = '\\0';\n";
6519             (match coltype with
6520              | FString ->
6521                  pr "  r->%s = strdup (tok);\n" name;
6522                  pr "  if (r->%s == NULL) {\n" name;
6523                  pr "    perror (\"strdup\");\n";
6524                  pr "    return -1;\n";
6525                  pr "  }\n"
6526              | FUUID ->
6527                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6528                  pr "    if (tok[j] == '\\0') {\n";
6529                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6530                  pr "      return -1;\n";
6531                  pr "    } else if (tok[j] != '-')\n";
6532                  pr "      r->%s[i++] = tok[j];\n" name;
6533                  pr "  }\n";
6534              | FBytes ->
6535                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6536                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6537                  pr "    return -1;\n";
6538                  pr "  }\n";
6539              | FInt64 ->
6540                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6541                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6542                  pr "    return -1;\n";
6543                  pr "  }\n";
6544              | FOptPercent ->
6545                  pr "  if (tok[0] == '\\0')\n";
6546                  pr "    r->%s = -1;\n" name;
6547                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6548                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6549                  pr "    return -1;\n";
6550                  pr "  }\n";
6551              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6552                  assert false (* can never be an LVM column *)
6553             );
6554             pr "  tok = next;\n";
6555         ) cols;
6556
6557         pr "  if (tok != NULL) {\n";
6558         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6559         pr "    return -1;\n";
6560         pr "  }\n";
6561         pr "  return 0;\n";
6562         pr "}\n";
6563         pr "\n";
6564
6565         pr "guestfs_int_lvm_%s_list *\n" typ;
6566         pr "parse_command_line_%ss (void)\n" typ;
6567         pr "{\n";
6568         pr "  char *out, *err;\n";
6569         pr "  char *p, *pend;\n";
6570         pr "  int r, i;\n";
6571         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6572         pr "  void *newp;\n";
6573         pr "\n";
6574         pr "  ret = malloc (sizeof *ret);\n";
6575         pr "  if (!ret) {\n";
6576         pr "    reply_with_perror (\"malloc\");\n";
6577         pr "    return NULL;\n";
6578         pr "  }\n";
6579         pr "\n";
6580         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6581         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6582         pr "\n";
6583         pr "  r = command (&out, &err,\n";
6584         pr "           \"lvm\", \"%ss\",\n" typ;
6585         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6586         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6587         pr "  if (r == -1) {\n";
6588         pr "    reply_with_error (\"%%s\", err);\n";
6589         pr "    free (out);\n";
6590         pr "    free (err);\n";
6591         pr "    free (ret);\n";
6592         pr "    return NULL;\n";
6593         pr "  }\n";
6594         pr "\n";
6595         pr "  free (err);\n";
6596         pr "\n";
6597         pr "  /* Tokenize each line of the output. */\n";
6598         pr "  p = out;\n";
6599         pr "  i = 0;\n";
6600         pr "  while (p) {\n";
6601         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6602         pr "    if (pend) {\n";
6603         pr "      *pend = '\\0';\n";
6604         pr "      pend++;\n";
6605         pr "    }\n";
6606         pr "\n";
6607         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6608         pr "      p++;\n";
6609         pr "\n";
6610         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6611         pr "      p = pend;\n";
6612         pr "      continue;\n";
6613         pr "    }\n";
6614         pr "\n";
6615         pr "    /* Allocate some space to store this next entry. */\n";
6616         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6617         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6618         pr "    if (newp == NULL) {\n";
6619         pr "      reply_with_perror (\"realloc\");\n";
6620         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6621         pr "      free (ret);\n";
6622         pr "      free (out);\n";
6623         pr "      return NULL;\n";
6624         pr "    }\n";
6625         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6626         pr "\n";
6627         pr "    /* Tokenize the next entry. */\n";
6628         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6629         pr "    if (r == -1) {\n";
6630         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6631         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6632         pr "      free (ret);\n";
6633         pr "      free (out);\n";
6634         pr "      return NULL;\n";
6635         pr "    }\n";
6636         pr "\n";
6637         pr "    ++i;\n";
6638         pr "    p = pend;\n";
6639         pr "  }\n";
6640         pr "\n";
6641         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6642         pr "\n";
6643         pr "  free (out);\n";
6644         pr "  return ret;\n";
6645         pr "}\n"
6646
6647   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6648
6649 (* Generate a list of function names, for debugging in the daemon.. *)
6650 and generate_daemon_names () =
6651   generate_header CStyle GPLv2plus;
6652
6653   pr "#include <config.h>\n";
6654   pr "\n";
6655   pr "#include \"daemon.h\"\n";
6656   pr "\n";
6657
6658   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6659   pr "const char *function_names[] = {\n";
6660   List.iter (
6661     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6662   ) daemon_functions;
6663   pr "};\n";
6664
6665 (* Generate the optional groups for the daemon to implement
6666  * guestfs_available.
6667  *)
6668 and generate_daemon_optgroups_c () =
6669   generate_header CStyle GPLv2plus;
6670
6671   pr "#include <config.h>\n";
6672   pr "\n";
6673   pr "#include \"daemon.h\"\n";
6674   pr "#include \"optgroups.h\"\n";
6675   pr "\n";
6676
6677   pr "struct optgroup optgroups[] = {\n";
6678   List.iter (
6679     fun (group, _) ->
6680       pr "  { \"%s\", optgroup_%s_available },\n" group group
6681   ) optgroups;
6682   pr "  { NULL, NULL }\n";
6683   pr "};\n"
6684
6685 and generate_daemon_optgroups_h () =
6686   generate_header CStyle GPLv2plus;
6687
6688   List.iter (
6689     fun (group, _) ->
6690       pr "extern int optgroup_%s_available (void);\n" group
6691   ) optgroups
6692
6693 (* Generate the tests. *)
6694 and generate_tests () =
6695   generate_header CStyle GPLv2plus;
6696
6697   pr "\
6698 #include <stdio.h>
6699 #include <stdlib.h>
6700 #include <string.h>
6701 #include <unistd.h>
6702 #include <sys/types.h>
6703 #include <fcntl.h>
6704
6705 #include \"guestfs.h\"
6706 #include \"guestfs-internal.h\"
6707
6708 static guestfs_h *g;
6709 static int suppress_error = 0;
6710
6711 static void print_error (guestfs_h *g, void *data, const char *msg)
6712 {
6713   if (!suppress_error)
6714     fprintf (stderr, \"%%s\\n\", msg);
6715 }
6716
6717 /* FIXME: nearly identical code appears in fish.c */
6718 static void print_strings (char *const *argv)
6719 {
6720   int argc;
6721
6722   for (argc = 0; argv[argc] != NULL; ++argc)
6723     printf (\"\\t%%s\\n\", argv[argc]);
6724 }
6725
6726 /*
6727 static void print_table (char const *const *argv)
6728 {
6729   int i;
6730
6731   for (i = 0; argv[i] != NULL; i += 2)
6732     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6733 }
6734 */
6735
6736 ";
6737
6738   (* Generate a list of commands which are not tested anywhere. *)
6739   pr "static void no_test_warnings (void)\n";
6740   pr "{\n";
6741
6742   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6743   List.iter (
6744     fun (_, _, _, _, tests, _, _) ->
6745       let tests = filter_map (
6746         function
6747         | (_, (Always|If _|Unless _), test) -> Some test
6748         | (_, Disabled, _) -> None
6749       ) tests in
6750       let seq = List.concat (List.map seq_of_test tests) in
6751       let cmds_tested = List.map List.hd seq in
6752       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6753   ) all_functions;
6754
6755   List.iter (
6756     fun (name, _, _, _, _, _, _) ->
6757       if not (Hashtbl.mem hash name) then
6758         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6759   ) all_functions;
6760
6761   pr "}\n";
6762   pr "\n";
6763
6764   (* Generate the actual tests.  Note that we generate the tests
6765    * in reverse order, deliberately, so that (in general) the
6766    * newest tests run first.  This makes it quicker and easier to
6767    * debug them.
6768    *)
6769   let test_names =
6770     List.map (
6771       fun (name, _, _, flags, tests, _, _) ->
6772         mapi (generate_one_test name flags) tests
6773     ) (List.rev all_functions) in
6774   let test_names = List.concat test_names in
6775   let nr_tests = List.length test_names in
6776
6777   pr "\
6778 int main (int argc, char *argv[])
6779 {
6780   char c = 0;
6781   unsigned long int n_failed = 0;
6782   const char *filename;
6783   int fd;
6784   int nr_tests, test_num = 0;
6785
6786   setbuf (stdout, NULL);
6787
6788   no_test_warnings ();
6789
6790   g = guestfs_create ();
6791   if (g == NULL) {
6792     printf (\"guestfs_create FAILED\\n\");
6793     exit (EXIT_FAILURE);
6794   }
6795
6796   guestfs_set_error_handler (g, print_error, NULL);
6797
6798   guestfs_set_path (g, \"../appliance\");
6799
6800   filename = \"test1.img\";
6801   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6802   if (fd == -1) {
6803     perror (filename);
6804     exit (EXIT_FAILURE);
6805   }
6806   if (lseek (fd, %d, SEEK_SET) == -1) {
6807     perror (\"lseek\");
6808     close (fd);
6809     unlink (filename);
6810     exit (EXIT_FAILURE);
6811   }
6812   if (write (fd, &c, 1) == -1) {
6813     perror (\"write\");
6814     close (fd);
6815     unlink (filename);
6816     exit (EXIT_FAILURE);
6817   }
6818   if (close (fd) == -1) {
6819     perror (filename);
6820     unlink (filename);
6821     exit (EXIT_FAILURE);
6822   }
6823   if (guestfs_add_drive (g, filename) == -1) {
6824     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6825     exit (EXIT_FAILURE);
6826   }
6827
6828   filename = \"test2.img\";
6829   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6830   if (fd == -1) {
6831     perror (filename);
6832     exit (EXIT_FAILURE);
6833   }
6834   if (lseek (fd, %d, SEEK_SET) == -1) {
6835     perror (\"lseek\");
6836     close (fd);
6837     unlink (filename);
6838     exit (EXIT_FAILURE);
6839   }
6840   if (write (fd, &c, 1) == -1) {
6841     perror (\"write\");
6842     close (fd);
6843     unlink (filename);
6844     exit (EXIT_FAILURE);
6845   }
6846   if (close (fd) == -1) {
6847     perror (filename);
6848     unlink (filename);
6849     exit (EXIT_FAILURE);
6850   }
6851   if (guestfs_add_drive (g, filename) == -1) {
6852     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6853     exit (EXIT_FAILURE);
6854   }
6855
6856   filename = \"test3.img\";
6857   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6858   if (fd == -1) {
6859     perror (filename);
6860     exit (EXIT_FAILURE);
6861   }
6862   if (lseek (fd, %d, SEEK_SET) == -1) {
6863     perror (\"lseek\");
6864     close (fd);
6865     unlink (filename);
6866     exit (EXIT_FAILURE);
6867   }
6868   if (write (fd, &c, 1) == -1) {
6869     perror (\"write\");
6870     close (fd);
6871     unlink (filename);
6872     exit (EXIT_FAILURE);
6873   }
6874   if (close (fd) == -1) {
6875     perror (filename);
6876     unlink (filename);
6877     exit (EXIT_FAILURE);
6878   }
6879   if (guestfs_add_drive (g, filename) == -1) {
6880     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6881     exit (EXIT_FAILURE);
6882   }
6883
6884   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6885     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6886     exit (EXIT_FAILURE);
6887   }
6888
6889   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6890   alarm (600);
6891
6892   if (guestfs_launch (g) == -1) {
6893     printf (\"guestfs_launch FAILED\\n\");
6894     exit (EXIT_FAILURE);
6895   }
6896
6897   /* Cancel previous alarm. */
6898   alarm (0);
6899
6900   nr_tests = %d;
6901
6902 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6903
6904   iteri (
6905     fun i test_name ->
6906       pr "  test_num++;\n";
6907       pr "  if (guestfs_get_verbose (g))\n";
6908       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
6909       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6910       pr "  if (%s () == -1) {\n" test_name;
6911       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6912       pr "    n_failed++;\n";
6913       pr "  }\n";
6914   ) test_names;
6915   pr "\n";
6916
6917   pr "  guestfs_close (g);\n";
6918   pr "  unlink (\"test1.img\");\n";
6919   pr "  unlink (\"test2.img\");\n";
6920   pr "  unlink (\"test3.img\");\n";
6921   pr "\n";
6922
6923   pr "  if (n_failed > 0) {\n";
6924   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6925   pr "    exit (EXIT_FAILURE);\n";
6926   pr "  }\n";
6927   pr "\n";
6928
6929   pr "  exit (EXIT_SUCCESS);\n";
6930   pr "}\n"
6931
6932 and generate_one_test name flags i (init, prereq, test) =
6933   let test_name = sprintf "test_%s_%d" name i in
6934
6935   pr "\
6936 static int %s_skip (void)
6937 {
6938   const char *str;
6939
6940   str = getenv (\"TEST_ONLY\");
6941   if (str)
6942     return strstr (str, \"%s\") == NULL;
6943   str = getenv (\"SKIP_%s\");
6944   if (str && STREQ (str, \"1\")) return 1;
6945   str = getenv (\"SKIP_TEST_%s\");
6946   if (str && STREQ (str, \"1\")) return 1;
6947   return 0;
6948 }
6949
6950 " test_name name (String.uppercase test_name) (String.uppercase name);
6951
6952   (match prereq with
6953    | Disabled | Always -> ()
6954    | If code | Unless code ->
6955        pr "static int %s_prereq (void)\n" test_name;
6956        pr "{\n";
6957        pr "  %s\n" code;
6958        pr "}\n";
6959        pr "\n";
6960   );
6961
6962   pr "\
6963 static int %s (void)
6964 {
6965   if (%s_skip ()) {
6966     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6967     return 0;
6968   }
6969
6970 " test_name test_name test_name;
6971
6972   (* Optional functions should only be tested if the relevant
6973    * support is available in the daemon.
6974    *)
6975   List.iter (
6976     function
6977     | Optional group ->
6978         pr "  {\n";
6979         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6980         pr "    int r;\n";
6981         pr "    suppress_error = 1;\n";
6982         pr "    r = guestfs_available (g, (char **) groups);\n";
6983         pr "    suppress_error = 0;\n";
6984         pr "    if (r == -1) {\n";
6985         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6986         pr "      return 0;\n";
6987         pr "    }\n";
6988         pr "  }\n";
6989     | _ -> ()
6990   ) flags;
6991
6992   (match prereq with
6993    | Disabled ->
6994        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6995    | If _ ->
6996        pr "  if (! %s_prereq ()) {\n" test_name;
6997        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6998        pr "    return 0;\n";
6999        pr "  }\n";
7000        pr "\n";
7001        generate_one_test_body name i test_name init test;
7002    | Unless _ ->
7003        pr "  if (%s_prereq ()) {\n" test_name;
7004        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7005        pr "    return 0;\n";
7006        pr "  }\n";
7007        pr "\n";
7008        generate_one_test_body name i test_name init test;
7009    | Always ->
7010        generate_one_test_body name i test_name init test
7011   );
7012
7013   pr "  return 0;\n";
7014   pr "}\n";
7015   pr "\n";
7016   test_name
7017
7018 and generate_one_test_body name i test_name init test =
7019   (match init with
7020    | InitNone (* XXX at some point, InitNone and InitEmpty became
7021                * folded together as the same thing.  Really we should
7022                * make InitNone do nothing at all, but the tests may
7023                * need to be checked to make sure this is OK.
7024                *)
7025    | InitEmpty ->
7026        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7027        List.iter (generate_test_command_call test_name)
7028          [["blockdev_setrw"; "/dev/sda"];
7029           ["umount_all"];
7030           ["lvm_remove_all"]]
7031    | InitPartition ->
7032        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7033        List.iter (generate_test_command_call test_name)
7034          [["blockdev_setrw"; "/dev/sda"];
7035           ["umount_all"];
7036           ["lvm_remove_all"];
7037           ["part_disk"; "/dev/sda"; "mbr"]]
7038    | InitBasicFS ->
7039        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7040        List.iter (generate_test_command_call test_name)
7041          [["blockdev_setrw"; "/dev/sda"];
7042           ["umount_all"];
7043           ["lvm_remove_all"];
7044           ["part_disk"; "/dev/sda"; "mbr"];
7045           ["mkfs"; "ext2"; "/dev/sda1"];
7046           ["mount_options"; ""; "/dev/sda1"; "/"]]
7047    | InitBasicFSonLVM ->
7048        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7049          test_name;
7050        List.iter (generate_test_command_call test_name)
7051          [["blockdev_setrw"; "/dev/sda"];
7052           ["umount_all"];
7053           ["lvm_remove_all"];
7054           ["part_disk"; "/dev/sda"; "mbr"];
7055           ["pvcreate"; "/dev/sda1"];
7056           ["vgcreate"; "VG"; "/dev/sda1"];
7057           ["lvcreate"; "LV"; "VG"; "8"];
7058           ["mkfs"; "ext2"; "/dev/VG/LV"];
7059           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7060    | InitISOFS ->
7061        pr "  /* InitISOFS for %s */\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           ["mount_ro"; "/dev/sdd"; "/"]]
7067   );
7068
7069   let get_seq_last = function
7070     | [] ->
7071         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7072           test_name
7073     | seq ->
7074         let seq = List.rev seq in
7075         List.rev (List.tl seq), List.hd seq
7076   in
7077
7078   match test with
7079   | TestRun seq ->
7080       pr "  /* TestRun for %s (%d) */\n" name i;
7081       List.iter (generate_test_command_call test_name) seq
7082   | TestOutput (seq, expected) ->
7083       pr "  /* TestOutput for %s (%d) */\n" name i;
7084       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7085       let seq, last = get_seq_last seq in
7086       let test () =
7087         pr "    if (STRNEQ (r, expected)) {\n";
7088         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7089         pr "      return -1;\n";
7090         pr "    }\n"
7091       in
7092       List.iter (generate_test_command_call test_name) seq;
7093       generate_test_command_call ~test test_name last
7094   | TestOutputList (seq, expected) ->
7095       pr "  /* TestOutputList for %s (%d) */\n" name i;
7096       let seq, last = get_seq_last seq in
7097       let test () =
7098         iteri (
7099           fun i str ->
7100             pr "    if (!r[%d]) {\n" i;
7101             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7102             pr "      print_strings (r);\n";
7103             pr "      return -1;\n";
7104             pr "    }\n";
7105             pr "    {\n";
7106             pr "      const char *expected = \"%s\";\n" (c_quote str);
7107             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7108             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7109             pr "        return -1;\n";
7110             pr "      }\n";
7111             pr "    }\n"
7112         ) expected;
7113         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7114         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7115           test_name;
7116         pr "      print_strings (r);\n";
7117         pr "      return -1;\n";
7118         pr "    }\n"
7119       in
7120       List.iter (generate_test_command_call test_name) seq;
7121       generate_test_command_call ~test test_name last
7122   | TestOutputListOfDevices (seq, expected) ->
7123       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7124       let seq, last = get_seq_last seq in
7125       let test () =
7126         iteri (
7127           fun i str ->
7128             pr "    if (!r[%d]) {\n" i;
7129             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7130             pr "      print_strings (r);\n";
7131             pr "      return -1;\n";
7132             pr "    }\n";
7133             pr "    {\n";
7134             pr "      const char *expected = \"%s\";\n" (c_quote str);
7135             pr "      r[%d][5] = 's';\n" i;
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   | TestOutputInt (seq, expected) ->
7152       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7153       let seq, last = get_seq_last seq in
7154       let test () =
7155         pr "    if (r != %d) {\n" expected;
7156         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7157           test_name expected;
7158         pr "               (int) r);\n";
7159         pr "      return -1;\n";
7160         pr "    }\n"
7161       in
7162       List.iter (generate_test_command_call test_name) seq;
7163       generate_test_command_call ~test test_name last
7164   | TestOutputIntOp (seq, op, expected) ->
7165       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7166       let seq, last = get_seq_last seq in
7167       let test () =
7168         pr "    if (! (r %s %d)) {\n" op expected;
7169         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7170           test_name op expected;
7171         pr "               (int) r);\n";
7172         pr "      return -1;\n";
7173         pr "    }\n"
7174       in
7175       List.iter (generate_test_command_call test_name) seq;
7176       generate_test_command_call ~test test_name last
7177   | TestOutputTrue seq ->
7178       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7179       let seq, last = get_seq_last seq in
7180       let test () =
7181         pr "    if (!r) {\n";
7182         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7183           test_name;
7184         pr "      return -1;\n";
7185         pr "    }\n"
7186       in
7187       List.iter (generate_test_command_call test_name) seq;
7188       generate_test_command_call ~test test_name last
7189   | TestOutputFalse seq ->
7190       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7191       let seq, last = get_seq_last seq in
7192       let test () =
7193         pr "    if (r) {\n";
7194         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7195           test_name;
7196         pr "      return -1;\n";
7197         pr "    }\n"
7198       in
7199       List.iter (generate_test_command_call test_name) seq;
7200       generate_test_command_call ~test test_name last
7201   | TestOutputLength (seq, expected) ->
7202       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7203       let seq, last = get_seq_last seq in
7204       let test () =
7205         pr "    int j;\n";
7206         pr "    for (j = 0; j < %d; ++j)\n" expected;
7207         pr "      if (r[j] == NULL) {\n";
7208         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7209           test_name;
7210         pr "        print_strings (r);\n";
7211         pr "        return -1;\n";
7212         pr "      }\n";
7213         pr "    if (r[j] != NULL) {\n";
7214         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7215           test_name;
7216         pr "      print_strings (r);\n";
7217         pr "      return -1;\n";
7218         pr "    }\n"
7219       in
7220       List.iter (generate_test_command_call test_name) seq;
7221       generate_test_command_call ~test test_name last
7222   | TestOutputBuffer (seq, expected) ->
7223       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7224       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7225       let seq, last = get_seq_last seq in
7226       let len = String.length expected in
7227       let test () =
7228         pr "    if (size != %d) {\n" len;
7229         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7230         pr "      return -1;\n";
7231         pr "    }\n";
7232         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7233         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7234         pr "      return -1;\n";
7235         pr "    }\n"
7236       in
7237       List.iter (generate_test_command_call test_name) seq;
7238       generate_test_command_call ~test test_name last
7239   | TestOutputStruct (seq, checks) ->
7240       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7241       let seq, last = get_seq_last seq in
7242       let test () =
7243         List.iter (
7244           function
7245           | CompareWithInt (field, expected) ->
7246               pr "    if (r->%s != %d) {\n" field expected;
7247               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7248                 test_name field expected;
7249               pr "               (int) r->%s);\n" field;
7250               pr "      return -1;\n";
7251               pr "    }\n"
7252           | CompareWithIntOp (field, op, expected) ->
7253               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7254               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7255                 test_name field op expected;
7256               pr "               (int) r->%s);\n" field;
7257               pr "      return -1;\n";
7258               pr "    }\n"
7259           | CompareWithString (field, expected) ->
7260               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7261               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7262                 test_name field expected;
7263               pr "               r->%s);\n" field;
7264               pr "      return -1;\n";
7265               pr "    }\n"
7266           | CompareFieldsIntEq (field1, field2) ->
7267               pr "    if (r->%s != r->%s) {\n" field1 field2;
7268               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7269                 test_name field1 field2;
7270               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7271               pr "      return -1;\n";
7272               pr "    }\n"
7273           | CompareFieldsStrEq (field1, field2) ->
7274               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7275               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7276                 test_name field1 field2;
7277               pr "               r->%s, r->%s);\n" field1 field2;
7278               pr "      return -1;\n";
7279               pr "    }\n"
7280         ) checks
7281       in
7282       List.iter (generate_test_command_call test_name) seq;
7283       generate_test_command_call ~test test_name last
7284   | TestLastFail seq ->
7285       pr "  /* TestLastFail for %s (%d) */\n" name i;
7286       let seq, last = get_seq_last seq in
7287       List.iter (generate_test_command_call test_name) seq;
7288       generate_test_command_call test_name ~expect_error:true last
7289
7290 (* Generate the code to run a command, leaving the result in 'r'.
7291  * If you expect to get an error then you should set expect_error:true.
7292  *)
7293 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7294   match cmd with
7295   | [] -> assert false
7296   | name :: args ->
7297       (* Look up the command to find out what args/ret it has. *)
7298       let style =
7299         try
7300           let _, style, _, _, _, _, _ =
7301             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7302           style
7303         with Not_found ->
7304           failwithf "%s: in test, command %s was not found" test_name name in
7305
7306       if List.length (snd style) <> List.length args then
7307         failwithf "%s: in test, wrong number of args given to %s"
7308           test_name name;
7309
7310       pr "  {\n";
7311
7312       List.iter (
7313         function
7314         | OptString n, "NULL" -> ()
7315         | Pathname n, arg
7316         | Device n, arg
7317         | Dev_or_Path n, arg
7318         | String n, arg
7319         | OptString n, arg ->
7320             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7321         | BufferIn n, arg ->
7322             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7323             pr "    size_t %s_size = %d;\n" n (String.length arg)
7324         | Int _, _
7325         | Int64 _, _
7326         | Bool _, _
7327         | FileIn _, _ | FileOut _, _ -> ()
7328         | StringList n, "" | DeviceList n, "" ->
7329             pr "    const char *const %s[1] = { NULL };\n" n
7330         | StringList n, arg | DeviceList n, arg ->
7331             let strs = string_split " " arg in
7332             iteri (
7333               fun i str ->
7334                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7335             ) strs;
7336             pr "    const char *const %s[] = {\n" n;
7337             iteri (
7338               fun i _ -> pr "      %s_%d,\n" n i
7339             ) strs;
7340             pr "      NULL\n";
7341             pr "    };\n";
7342       ) (List.combine (snd style) args);
7343
7344       let error_code =
7345         match fst style with
7346         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7347         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7348         | RConstString _ | RConstOptString _ ->
7349             pr "    const char *r;\n"; "NULL"
7350         | RString _ -> pr "    char *r;\n"; "NULL"
7351         | RStringList _ | RHashtable _ ->
7352             pr "    char **r;\n";
7353             pr "    int i;\n";
7354             "NULL"
7355         | RStruct (_, typ) ->
7356             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7357         | RStructList (_, typ) ->
7358             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7359         | RBufferOut _ ->
7360             pr "    char *r;\n";
7361             pr "    size_t size;\n";
7362             "NULL" in
7363
7364       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7365       pr "    r = guestfs_%s (g" name;
7366
7367       (* Generate the parameters. *)
7368       List.iter (
7369         function
7370         | OptString _, "NULL" -> pr ", NULL"
7371         | Pathname n, _
7372         | Device n, _ | Dev_or_Path n, _
7373         | String n, _
7374         | OptString n, _ ->
7375             pr ", %s" n
7376         | BufferIn n, _ ->
7377             pr ", %s, %s_size" n n
7378         | FileIn _, arg | FileOut _, arg ->
7379             pr ", \"%s\"" (c_quote arg)
7380         | StringList n, _ | DeviceList n, _ ->
7381             pr ", (char **) %s" n
7382         | Int _, arg ->
7383             let i =
7384               try int_of_string arg
7385               with Failure "int_of_string" ->
7386                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7387             pr ", %d" i
7388         | Int64 _, arg ->
7389             let i =
7390               try Int64.of_string arg
7391               with Failure "int_of_string" ->
7392                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7393             pr ", %Ld" i
7394         | Bool _, arg ->
7395             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7396       ) (List.combine (snd style) args);
7397
7398       (match fst style with
7399        | RBufferOut _ -> pr ", &size"
7400        | _ -> ()
7401       );
7402
7403       pr ");\n";
7404
7405       if not expect_error then
7406         pr "    if (r == %s)\n" error_code
7407       else
7408         pr "    if (r != %s)\n" error_code;
7409       pr "      return -1;\n";
7410
7411       (* Insert the test code. *)
7412       (match test with
7413        | None -> ()
7414        | Some f -> f ()
7415       );
7416
7417       (match fst style with
7418        | RErr | RInt _ | RInt64 _ | RBool _
7419        | RConstString _ | RConstOptString _ -> ()
7420        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7421        | RStringList _ | RHashtable _ ->
7422            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7423            pr "      free (r[i]);\n";
7424            pr "    free (r);\n"
7425        | RStruct (_, typ) ->
7426            pr "    guestfs_free_%s (r);\n" typ
7427        | RStructList (_, typ) ->
7428            pr "    guestfs_free_%s_list (r);\n" typ
7429       );
7430
7431       pr "  }\n"
7432
7433 and c_quote str =
7434   let str = replace_str str "\r" "\\r" in
7435   let str = replace_str str "\n" "\\n" in
7436   let str = replace_str str "\t" "\\t" in
7437   let str = replace_str str "\000" "\\0" in
7438   str
7439
7440 (* Generate a lot of different functions for guestfish. *)
7441 and generate_fish_cmds () =
7442   generate_header CStyle GPLv2plus;
7443
7444   let all_functions =
7445     List.filter (
7446       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7447     ) all_functions in
7448   let all_functions_sorted =
7449     List.filter (
7450       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7451     ) all_functions_sorted in
7452
7453   pr "#include <config.h>\n";
7454   pr "\n";
7455   pr "#include <stdio.h>\n";
7456   pr "#include <stdlib.h>\n";
7457   pr "#include <string.h>\n";
7458   pr "#include <inttypes.h>\n";
7459   pr "\n";
7460   pr "#include <guestfs.h>\n";
7461   pr "#include \"c-ctype.h\"\n";
7462   pr "#include \"full-write.h\"\n";
7463   pr "#include \"xstrtol.h\"\n";
7464   pr "#include \"fish.h\"\n";
7465   pr "\n";
7466   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7467   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7468   pr "\n";
7469
7470   (* list_commands function, which implements guestfish -h *)
7471   pr "void list_commands (void)\n";
7472   pr "{\n";
7473   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7474   pr "  list_builtin_commands ();\n";
7475   List.iter (
7476     fun (name, _, _, flags, _, shortdesc, _) ->
7477       let name = replace_char name '_' '-' in
7478       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7479         name shortdesc
7480   ) all_functions_sorted;
7481   pr "  printf (\"    %%s\\n\",";
7482   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7483   pr "}\n";
7484   pr "\n";
7485
7486   (* display_command function, which implements guestfish -h cmd *)
7487   pr "void display_command (const char *cmd)\n";
7488   pr "{\n";
7489   List.iter (
7490     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7491       let name2 = replace_char name '_' '-' in
7492       let alias =
7493         try find_map (function FishAlias n -> Some n | _ -> None) flags
7494         with Not_found -> name in
7495       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7496       let synopsis =
7497         match snd style with
7498         | [] -> name2
7499         | args ->
7500             sprintf "%s %s"
7501               name2 (String.concat " " (List.map name_of_argt args)) in
7502
7503       let warnings =
7504         if List.mem ProtocolLimitWarning flags then
7505           ("\n\n" ^ protocol_limit_warning)
7506         else "" in
7507
7508       (* For DangerWillRobinson commands, we should probably have
7509        * guestfish prompt before allowing you to use them (especially
7510        * in interactive mode). XXX
7511        *)
7512       let warnings =
7513         warnings ^
7514           if List.mem DangerWillRobinson flags then
7515             ("\n\n" ^ danger_will_robinson)
7516           else "" in
7517
7518       let warnings =
7519         warnings ^
7520           match deprecation_notice flags with
7521           | None -> ""
7522           | Some txt -> "\n\n" ^ txt in
7523
7524       let describe_alias =
7525         if name <> alias then
7526           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7527         else "" in
7528
7529       pr "  if (";
7530       pr "STRCASEEQ (cmd, \"%s\")" name;
7531       if name <> name2 then
7532         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7533       if name <> alias then
7534         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7535       pr ")\n";
7536       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7537         name2 shortdesc
7538         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7539          "=head1 DESCRIPTION\n\n" ^
7540          longdesc ^ warnings ^ describe_alias);
7541       pr "  else\n"
7542   ) all_functions;
7543   pr "    display_builtin_command (cmd);\n";
7544   pr "}\n";
7545   pr "\n";
7546
7547   let emit_print_list_function typ =
7548     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7549       typ typ typ;
7550     pr "{\n";
7551     pr "  unsigned int i;\n";
7552     pr "\n";
7553     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7554     pr "    printf (\"[%%d] = {\\n\", i);\n";
7555     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7556     pr "    printf (\"}\\n\");\n";
7557     pr "  }\n";
7558     pr "}\n";
7559     pr "\n";
7560   in
7561
7562   (* print_* functions *)
7563   List.iter (
7564     fun (typ, cols) ->
7565       let needs_i =
7566         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7567
7568       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7569       pr "{\n";
7570       if needs_i then (
7571         pr "  unsigned int i;\n";
7572         pr "\n"
7573       );
7574       List.iter (
7575         function
7576         | name, FString ->
7577             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7578         | name, FUUID ->
7579             pr "  printf (\"%%s%s: \", indent);\n" name;
7580             pr "  for (i = 0; i < 32; ++i)\n";
7581             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7582             pr "  printf (\"\\n\");\n"
7583         | name, FBuffer ->
7584             pr "  printf (\"%%s%s: \", indent);\n" name;
7585             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7586             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7587             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7588             pr "    else\n";
7589             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7590             pr "  printf (\"\\n\");\n"
7591         | name, (FUInt64|FBytes) ->
7592             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7593               name typ name
7594         | name, FInt64 ->
7595             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7596               name typ name
7597         | name, FUInt32 ->
7598             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7599               name typ name
7600         | name, FInt32 ->
7601             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7602               name typ name
7603         | name, FChar ->
7604             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7605               name typ name
7606         | name, FOptPercent ->
7607             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7608               typ name name typ name;
7609             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7610       ) cols;
7611       pr "}\n";
7612       pr "\n";
7613   ) structs;
7614
7615   (* Emit a print_TYPE_list function definition only if that function is used. *)
7616   List.iter (
7617     function
7618     | typ, (RStructListOnly | RStructAndList) ->
7619         (* generate the function for typ *)
7620         emit_print_list_function typ
7621     | typ, _ -> () (* empty *)
7622   ) (rstructs_used_by all_functions);
7623
7624   (* Emit a print_TYPE function definition only if that function is used. *)
7625   List.iter (
7626     function
7627     | typ, (RStructOnly | RStructAndList) ->
7628         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7629         pr "{\n";
7630         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7631         pr "}\n";
7632         pr "\n";
7633     | typ, _ -> () (* empty *)
7634   ) (rstructs_used_by all_functions);
7635
7636   (* run_<action> actions *)
7637   List.iter (
7638     fun (name, style, _, flags, _, _, _) ->
7639       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7640       pr "{\n";
7641       (match fst style with
7642        | RErr
7643        | RInt _
7644        | RBool _ -> pr "  int r;\n"
7645        | RInt64 _ -> pr "  int64_t r;\n"
7646        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7647        | RString _ -> pr "  char *r;\n"
7648        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7649        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7650        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7651        | RBufferOut _ ->
7652            pr "  char *r;\n";
7653            pr "  size_t size;\n";
7654       );
7655       List.iter (
7656         function
7657         | Device n
7658         | String n
7659         | OptString n -> pr "  const char *%s;\n" n
7660         | Pathname n
7661         | Dev_or_Path n
7662         | FileIn n
7663         | FileOut n -> pr "  char *%s;\n" n
7664         | BufferIn n ->
7665             pr "  const char *%s;\n" n;
7666             pr "  size_t %s_size;\n" n
7667         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7668         | Bool n -> pr "  int %s;\n" n
7669         | Int n -> pr "  int %s;\n" n
7670         | Int64 n -> pr "  int64_t %s;\n" n
7671       ) (snd style);
7672
7673       (* Check and convert parameters. *)
7674       let argc_expected = List.length (snd style) in
7675       pr "  if (argc != %d) {\n" argc_expected;
7676       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7677         argc_expected;
7678       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7679       pr "    return -1;\n";
7680       pr "  }\n";
7681
7682       let parse_integer fn fntyp rtyp range name i =
7683         pr "  {\n";
7684         pr "    strtol_error xerr;\n";
7685         pr "    %s r;\n" fntyp;
7686         pr "\n";
7687         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7688         pr "    if (xerr != LONGINT_OK) {\n";
7689         pr "      fprintf (stderr,\n";
7690         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7691         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7692         pr "      return -1;\n";
7693         pr "    }\n";
7694         (match range with
7695          | None -> ()
7696          | Some (min, max, comment) ->
7697              pr "    /* %s */\n" comment;
7698              pr "    if (r < %s || r > %s) {\n" min max;
7699              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7700                name;
7701              pr "      return -1;\n";
7702              pr "    }\n";
7703              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7704         );
7705         pr "    %s = r;\n" name;
7706         pr "  }\n";
7707       in
7708
7709       iteri (
7710         fun i ->
7711           function
7712           | Device name
7713           | String name ->
7714               pr "  %s = argv[%d];\n" name i
7715           | Pathname name
7716           | Dev_or_Path name ->
7717               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7718               pr "  if (%s == NULL) return -1;\n" name
7719           | OptString name ->
7720               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7721                 name i i
7722           | BufferIn name ->
7723               pr "  %s = argv[%d];\n" name i;
7724               pr "  %s_size = strlen (argv[%d]);\n" name i
7725           | FileIn name ->
7726               pr "  %s = file_in (argv[%d]);\n" name i;
7727               pr "  if (%s == NULL) return -1;\n" name
7728           | FileOut name ->
7729               pr "  %s = file_out (argv[%d]);\n" name i;
7730               pr "  if (%s == NULL) return -1;\n" name
7731           | StringList name | DeviceList name ->
7732               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7733               pr "  if (%s == NULL) return -1;\n" name;
7734           | Bool name ->
7735               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7736           | Int name ->
7737               let range =
7738                 let min = "(-(2LL<<30))"
7739                 and max = "((2LL<<30)-1)"
7740                 and comment =
7741                   "The Int type in the generator is a signed 31 bit int." in
7742                 Some (min, max, comment) in
7743               parse_integer "xstrtoll" "long long" "int" range name i
7744           | Int64 name ->
7745               parse_integer "xstrtoll" "long long" "int64_t" None name i
7746       ) (snd style);
7747
7748       (* Call C API function. *)
7749       pr "  r = guestfs_%s " name;
7750       generate_c_call_args ~handle:"g" style;
7751       pr ";\n";
7752
7753       List.iter (
7754         function
7755         | Device name | String name
7756         | OptString name | Bool name
7757         | Int name | Int64 name
7758         | BufferIn name -> ()
7759         | Pathname name | Dev_or_Path name | FileOut name ->
7760             pr "  free (%s);\n" name
7761         | FileIn name ->
7762             pr "  free_file_in (%s);\n" name
7763         | StringList name | DeviceList name ->
7764             pr "  free_strings (%s);\n" name
7765       ) (snd style);
7766
7767       (* Any output flags? *)
7768       let fish_output =
7769         let flags = filter_map (
7770           function FishOutput flag -> Some flag | _ -> None
7771         ) flags in
7772         match flags with
7773         | [] -> None
7774         | [f] -> Some f
7775         | _ ->
7776             failwithf "%s: more than one FishOutput flag is not allowed" name in
7777
7778       (* Check return value for errors and display command results. *)
7779       (match fst style with
7780        | RErr -> pr "  return r;\n"
7781        | RInt _ ->
7782            pr "  if (r == -1) return -1;\n";
7783            (match fish_output with
7784             | None ->
7785                 pr "  printf (\"%%d\\n\", r);\n";
7786             | Some FishOutputOctal ->
7787                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7788             | Some FishOutputHexadecimal ->
7789                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7790            pr "  return 0;\n"
7791        | RInt64 _ ->
7792            pr "  if (r == -1) return -1;\n";
7793            (match fish_output with
7794             | None ->
7795                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7796             | Some FishOutputOctal ->
7797                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
7798             | Some FishOutputHexadecimal ->
7799                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7800            pr "  return 0;\n"
7801        | RBool _ ->
7802            pr "  if (r == -1) return -1;\n";
7803            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7804            pr "  return 0;\n"
7805        | RConstString _ ->
7806            pr "  if (r == NULL) return -1;\n";
7807            pr "  printf (\"%%s\\n\", r);\n";
7808            pr "  return 0;\n"
7809        | RConstOptString _ ->
7810            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7811            pr "  return 0;\n"
7812        | RString _ ->
7813            pr "  if (r == NULL) return -1;\n";
7814            pr "  printf (\"%%s\\n\", r);\n";
7815            pr "  free (r);\n";
7816            pr "  return 0;\n"
7817        | RStringList _ ->
7818            pr "  if (r == NULL) return -1;\n";
7819            pr "  print_strings (r);\n";
7820            pr "  free_strings (r);\n";
7821            pr "  return 0;\n"
7822        | RStruct (_, typ) ->
7823            pr "  if (r == NULL) return -1;\n";
7824            pr "  print_%s (r);\n" typ;
7825            pr "  guestfs_free_%s (r);\n" typ;
7826            pr "  return 0;\n"
7827        | RStructList (_, typ) ->
7828            pr "  if (r == NULL) return -1;\n";
7829            pr "  print_%s_list (r);\n" typ;
7830            pr "  guestfs_free_%s_list (r);\n" typ;
7831            pr "  return 0;\n"
7832        | RHashtable _ ->
7833            pr "  if (r == NULL) return -1;\n";
7834            pr "  print_table (r);\n";
7835            pr "  free_strings (r);\n";
7836            pr "  return 0;\n"
7837        | RBufferOut _ ->
7838            pr "  if (r == NULL) return -1;\n";
7839            pr "  if (full_write (1, r, size) != size) {\n";
7840            pr "    perror (\"write\");\n";
7841            pr "    free (r);\n";
7842            pr "    return -1;\n";
7843            pr "  }\n";
7844            pr "  free (r);\n";
7845            pr "  return 0;\n"
7846       );
7847       pr "}\n";
7848       pr "\n"
7849   ) all_functions;
7850
7851   (* run_action function *)
7852   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7853   pr "{\n";
7854   List.iter (
7855     fun (name, _, _, flags, _, _, _) ->
7856       let name2 = replace_char name '_' '-' in
7857       let alias =
7858         try find_map (function FishAlias n -> Some n | _ -> None) flags
7859         with Not_found -> name in
7860       pr "  if (";
7861       pr "STRCASEEQ (cmd, \"%s\")" name;
7862       if name <> name2 then
7863         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7864       if name <> alias then
7865         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7866       pr ")\n";
7867       pr "    return run_%s (cmd, argc, argv);\n" name;
7868       pr "  else\n";
7869   ) all_functions;
7870   pr "    {\n";
7871   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7872   pr "      if (command_num == 1)\n";
7873   pr "        extended_help_message ();\n";
7874   pr "      return -1;\n";
7875   pr "    }\n";
7876   pr "  return 0;\n";
7877   pr "}\n";
7878   pr "\n"
7879
7880 (* Readline completion for guestfish. *)
7881 and generate_fish_completion () =
7882   generate_header CStyle GPLv2plus;
7883
7884   let all_functions =
7885     List.filter (
7886       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7887     ) all_functions in
7888
7889   pr "\
7890 #include <config.h>
7891
7892 #include <stdio.h>
7893 #include <stdlib.h>
7894 #include <string.h>
7895
7896 #ifdef HAVE_LIBREADLINE
7897 #include <readline/readline.h>
7898 #endif
7899
7900 #include \"fish.h\"
7901
7902 #ifdef HAVE_LIBREADLINE
7903
7904 static const char *const commands[] = {
7905   BUILTIN_COMMANDS_FOR_COMPLETION,
7906 ";
7907
7908   (* Get the commands, including the aliases.  They don't need to be
7909    * sorted - the generator() function just does a dumb linear search.
7910    *)
7911   let commands =
7912     List.map (
7913       fun (name, _, _, flags, _, _, _) ->
7914         let name2 = replace_char name '_' '-' in
7915         let alias =
7916           try find_map (function FishAlias n -> Some n | _ -> None) flags
7917           with Not_found -> name in
7918
7919         if name <> alias then [name2; alias] else [name2]
7920     ) all_functions in
7921   let commands = List.flatten commands in
7922
7923   List.iter (pr "  \"%s\",\n") commands;
7924
7925   pr "  NULL
7926 };
7927
7928 static char *
7929 generator (const char *text, int state)
7930 {
7931   static int index, len;
7932   const char *name;
7933
7934   if (!state) {
7935     index = 0;
7936     len = strlen (text);
7937   }
7938
7939   rl_attempted_completion_over = 1;
7940
7941   while ((name = commands[index]) != NULL) {
7942     index++;
7943     if (STRCASEEQLEN (name, text, len))
7944       return strdup (name);
7945   }
7946
7947   return NULL;
7948 }
7949
7950 #endif /* HAVE_LIBREADLINE */
7951
7952 #ifdef HAVE_RL_COMPLETION_MATCHES
7953 #define RL_COMPLETION_MATCHES rl_completion_matches
7954 #else
7955 #ifdef HAVE_COMPLETION_MATCHES
7956 #define RL_COMPLETION_MATCHES completion_matches
7957 #endif
7958 #endif /* else just fail if we don't have either symbol */
7959
7960 char **
7961 do_completion (const char *text, int start, int end)
7962 {
7963   char **matches = NULL;
7964
7965 #ifdef HAVE_LIBREADLINE
7966   rl_completion_append_character = ' ';
7967
7968   if (start == 0)
7969     matches = RL_COMPLETION_MATCHES (text, generator);
7970   else if (complete_dest_paths)
7971     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
7972 #endif
7973
7974   return matches;
7975 }
7976 ";
7977
7978 (* Generate the POD documentation for guestfish. *)
7979 and generate_fish_actions_pod () =
7980   let all_functions_sorted =
7981     List.filter (
7982       fun (_, _, _, flags, _, _, _) ->
7983         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7984     ) all_functions_sorted in
7985
7986   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7987
7988   List.iter (
7989     fun (name, style, _, flags, _, _, longdesc) ->
7990       let longdesc =
7991         Str.global_substitute rex (
7992           fun s ->
7993             let sub =
7994               try Str.matched_group 1 s
7995               with Not_found ->
7996                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7997             "C<" ^ replace_char sub '_' '-' ^ ">"
7998         ) longdesc in
7999       let name = replace_char name '_' '-' in
8000       let alias =
8001         try find_map (function FishAlias n -> Some n | _ -> None) flags
8002         with Not_found -> name in
8003
8004       pr "=head2 %s" name;
8005       if name <> alias then
8006         pr " | %s" alias;
8007       pr "\n";
8008       pr "\n";
8009       pr " %s" name;
8010       List.iter (
8011         function
8012         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8013         | OptString n -> pr " %s" n
8014         | StringList n | DeviceList n -> pr " '%s ...'" n
8015         | Bool _ -> pr " true|false"
8016         | Int n -> pr " %s" n
8017         | Int64 n -> pr " %s" n
8018         | FileIn n | FileOut n -> pr " (%s|-)" n
8019         | BufferIn n -> pr " %s" n
8020       ) (snd style);
8021       pr "\n";
8022       pr "\n";
8023       pr "%s\n\n" longdesc;
8024
8025       if List.exists (function FileIn _ | FileOut _ -> true
8026                       | _ -> false) (snd style) then
8027         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8028
8029       if List.mem ProtocolLimitWarning flags then
8030         pr "%s\n\n" protocol_limit_warning;
8031
8032       if List.mem DangerWillRobinson flags then
8033         pr "%s\n\n" danger_will_robinson;
8034
8035       match deprecation_notice flags with
8036       | None -> ()
8037       | Some txt -> pr "%s\n\n" txt
8038   ) all_functions_sorted
8039
8040 (* Generate a C function prototype. *)
8041 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8042     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8043     ?(prefix = "")
8044     ?handle name style =
8045   if extern then pr "extern ";
8046   if static then pr "static ";
8047   (match fst style with
8048    | RErr -> pr "int "
8049    | RInt _ -> pr "int "
8050    | RInt64 _ -> pr "int64_t "
8051    | RBool _ -> pr "int "
8052    | RConstString _ | RConstOptString _ -> pr "const char *"
8053    | RString _ | RBufferOut _ -> pr "char *"
8054    | RStringList _ | RHashtable _ -> pr "char **"
8055    | RStruct (_, typ) ->
8056        if not in_daemon then pr "struct guestfs_%s *" typ
8057        else pr "guestfs_int_%s *" typ
8058    | RStructList (_, typ) ->
8059        if not in_daemon then pr "struct guestfs_%s_list *" typ
8060        else pr "guestfs_int_%s_list *" typ
8061   );
8062   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8063   pr "%s%s (" prefix name;
8064   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8065     pr "void"
8066   else (
8067     let comma = ref false in
8068     (match handle with
8069      | None -> ()
8070      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8071     );
8072     let next () =
8073       if !comma then (
8074         if single_line then pr ", " else pr ",\n\t\t"
8075       );
8076       comma := true
8077     in
8078     List.iter (
8079       function
8080       | Pathname n
8081       | Device n | Dev_or_Path n
8082       | String n
8083       | OptString n ->
8084           next ();
8085           pr "const char *%s" n
8086       | StringList n | DeviceList n ->
8087           next ();
8088           pr "char *const *%s" n
8089       | Bool n -> next (); pr "int %s" n
8090       | Int n -> next (); pr "int %s" n
8091       | Int64 n -> next (); pr "int64_t %s" n
8092       | FileIn n
8093       | FileOut n ->
8094           if not in_daemon then (next (); pr "const char *%s" n)
8095       | BufferIn n ->
8096           next ();
8097           pr "const char *%s" n;
8098           next ();
8099           pr "size_t %s_size" n
8100     ) (snd style);
8101     if is_RBufferOut then (next (); pr "size_t *size_r");
8102   );
8103   pr ")";
8104   if semicolon then pr ";";
8105   if newline then pr "\n"
8106
8107 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8108 and generate_c_call_args ?handle ?(decl = false) style =
8109   pr "(";
8110   let comma = ref false in
8111   let next () =
8112     if !comma then pr ", ";
8113     comma := true
8114   in
8115   (match handle with
8116    | None -> ()
8117    | Some handle -> pr "%s" handle; comma := true
8118   );
8119   List.iter (
8120     function
8121     | BufferIn n ->
8122         next ();
8123         pr "%s, %s_size" n n
8124     | arg ->
8125         next ();
8126         pr "%s" (name_of_argt arg)
8127   ) (snd style);
8128   (* For RBufferOut calls, add implicit &size parameter. *)
8129   if not decl then (
8130     match fst style with
8131     | RBufferOut _ ->
8132         next ();
8133         pr "&size"
8134     | _ -> ()
8135   );
8136   pr ")"
8137
8138 (* Generate the OCaml bindings interface. *)
8139 and generate_ocaml_mli () =
8140   generate_header OCamlStyle LGPLv2plus;
8141
8142   pr "\
8143 (** For API documentation you should refer to the C API
8144     in the guestfs(3) manual page.  The OCaml API uses almost
8145     exactly the same calls. *)
8146
8147 type t
8148 (** A [guestfs_h] handle. *)
8149
8150 exception Error of string
8151 (** This exception is raised when there is an error. *)
8152
8153 exception Handle_closed of string
8154 (** This exception is raised if you use a {!Guestfs.t} handle
8155     after calling {!close} on it.  The string is the name of
8156     the function. *)
8157
8158 val create : unit -> t
8159 (** Create a {!Guestfs.t} handle. *)
8160
8161 val close : t -> unit
8162 (** Close the {!Guestfs.t} handle and free up all resources used
8163     by it immediately.
8164
8165     Handles are closed by the garbage collector when they become
8166     unreferenced, but callers can call this in order to provide
8167     predictable cleanup. *)
8168
8169 ";
8170   generate_ocaml_structure_decls ();
8171
8172   (* The actions. *)
8173   List.iter (
8174     fun (name, style, _, _, _, shortdesc, _) ->
8175       generate_ocaml_prototype name style;
8176       pr "(** %s *)\n" shortdesc;
8177       pr "\n"
8178   ) all_functions_sorted
8179
8180 (* Generate the OCaml bindings implementation. *)
8181 and generate_ocaml_ml () =
8182   generate_header OCamlStyle LGPLv2plus;
8183
8184   pr "\
8185 type t
8186
8187 exception Error of string
8188 exception Handle_closed of string
8189
8190 external create : unit -> t = \"ocaml_guestfs_create\"
8191 external close : t -> unit = \"ocaml_guestfs_close\"
8192
8193 (* Give the exceptions names, so they can be raised from the C code. *)
8194 let () =
8195   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8196   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8197
8198 ";
8199
8200   generate_ocaml_structure_decls ();
8201
8202   (* The actions. *)
8203   List.iter (
8204     fun (name, style, _, _, _, shortdesc, _) ->
8205       generate_ocaml_prototype ~is_external:true name style;
8206   ) all_functions_sorted
8207
8208 (* Generate the OCaml bindings C implementation. *)
8209 and generate_ocaml_c () =
8210   generate_header CStyle LGPLv2plus;
8211
8212   pr "\
8213 #include <stdio.h>
8214 #include <stdlib.h>
8215 #include <string.h>
8216
8217 #include <caml/config.h>
8218 #include <caml/alloc.h>
8219 #include <caml/callback.h>
8220 #include <caml/fail.h>
8221 #include <caml/memory.h>
8222 #include <caml/mlvalues.h>
8223 #include <caml/signals.h>
8224
8225 #include <guestfs.h>
8226
8227 #include \"guestfs_c.h\"
8228
8229 /* Copy a hashtable of string pairs into an assoc-list.  We return
8230  * the list in reverse order, but hashtables aren't supposed to be
8231  * ordered anyway.
8232  */
8233 static CAMLprim value
8234 copy_table (char * const * argv)
8235 {
8236   CAMLparam0 ();
8237   CAMLlocal5 (rv, pairv, kv, vv, cons);
8238   int i;
8239
8240   rv = Val_int (0);
8241   for (i = 0; argv[i] != NULL; i += 2) {
8242     kv = caml_copy_string (argv[i]);
8243     vv = caml_copy_string (argv[i+1]);
8244     pairv = caml_alloc (2, 0);
8245     Store_field (pairv, 0, kv);
8246     Store_field (pairv, 1, vv);
8247     cons = caml_alloc (2, 0);
8248     Store_field (cons, 1, rv);
8249     rv = cons;
8250     Store_field (cons, 0, pairv);
8251   }
8252
8253   CAMLreturn (rv);
8254 }
8255
8256 ";
8257
8258   (* Struct copy functions. *)
8259
8260   let emit_ocaml_copy_list_function typ =
8261     pr "static CAMLprim value\n";
8262     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8263     pr "{\n";
8264     pr "  CAMLparam0 ();\n";
8265     pr "  CAMLlocal2 (rv, v);\n";
8266     pr "  unsigned int i;\n";
8267     pr "\n";
8268     pr "  if (%ss->len == 0)\n" typ;
8269     pr "    CAMLreturn (Atom (0));\n";
8270     pr "  else {\n";
8271     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8272     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8273     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8274     pr "      caml_modify (&Field (rv, i), v);\n";
8275     pr "    }\n";
8276     pr "    CAMLreturn (rv);\n";
8277     pr "  }\n";
8278     pr "}\n";
8279     pr "\n";
8280   in
8281
8282   List.iter (
8283     fun (typ, cols) ->
8284       let has_optpercent_col =
8285         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8286
8287       pr "static CAMLprim value\n";
8288       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8289       pr "{\n";
8290       pr "  CAMLparam0 ();\n";
8291       if has_optpercent_col then
8292         pr "  CAMLlocal3 (rv, v, v2);\n"
8293       else
8294         pr "  CAMLlocal2 (rv, v);\n";
8295       pr "\n";
8296       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8297       iteri (
8298         fun i col ->
8299           (match col with
8300            | name, FString ->
8301                pr "  v = caml_copy_string (%s->%s);\n" typ name
8302            | name, FBuffer ->
8303                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8304                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8305                  typ name typ name
8306            | name, FUUID ->
8307                pr "  v = caml_alloc_string (32);\n";
8308                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8309            | name, (FBytes|FInt64|FUInt64) ->
8310                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8311            | name, (FInt32|FUInt32) ->
8312                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8313            | name, FOptPercent ->
8314                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8315                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8316                pr "    v = caml_alloc (1, 0);\n";
8317                pr "    Store_field (v, 0, v2);\n";
8318                pr "  } else /* None */\n";
8319                pr "    v = Val_int (0);\n";
8320            | name, FChar ->
8321                pr "  v = Val_int (%s->%s);\n" typ name
8322           );
8323           pr "  Store_field (rv, %d, v);\n" i
8324       ) cols;
8325       pr "  CAMLreturn (rv);\n";
8326       pr "}\n";
8327       pr "\n";
8328   ) structs;
8329
8330   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8331   List.iter (
8332     function
8333     | typ, (RStructListOnly | RStructAndList) ->
8334         (* generate the function for typ *)
8335         emit_ocaml_copy_list_function typ
8336     | typ, _ -> () (* empty *)
8337   ) (rstructs_used_by all_functions);
8338
8339   (* The wrappers. *)
8340   List.iter (
8341     fun (name, style, _, _, _, _, _) ->
8342       pr "/* Automatically generated wrapper for function\n";
8343       pr " * ";
8344       generate_ocaml_prototype name style;
8345       pr " */\n";
8346       pr "\n";
8347
8348       let params =
8349         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8350
8351       let needs_extra_vs =
8352         match fst style with RConstOptString _ -> true | _ -> false in
8353
8354       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8355       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8356       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8357       pr "\n";
8358
8359       pr "CAMLprim value\n";
8360       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8361       List.iter (pr ", value %s") (List.tl params);
8362       pr ")\n";
8363       pr "{\n";
8364
8365       (match params with
8366        | [p1; p2; p3; p4; p5] ->
8367            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8368        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8369            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8370            pr "  CAMLxparam%d (%s);\n"
8371              (List.length rest) (String.concat ", " rest)
8372        | ps ->
8373            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8374       );
8375       if not needs_extra_vs then
8376         pr "  CAMLlocal1 (rv);\n"
8377       else
8378         pr "  CAMLlocal3 (rv, v, v2);\n";
8379       pr "\n";
8380
8381       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8382       pr "  if (g == NULL)\n";
8383       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8384       pr "\n";
8385
8386       List.iter (
8387         function
8388         | Pathname n
8389         | Device n | Dev_or_Path n
8390         | String n
8391         | FileIn n
8392         | FileOut n ->
8393             pr "  const char *%s = String_val (%sv);\n" n n
8394         | OptString n ->
8395             pr "  const char *%s =\n" n;
8396             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
8397               n n
8398         | BufferIn n ->
8399             pr "  const char *%s = String_val (%sv);\n" n n;
8400             pr "  size_t %s_size = caml_string_length (%sv);\n" n n
8401         | StringList n | DeviceList n ->
8402             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8403         | Bool n ->
8404             pr "  int %s = Bool_val (%sv);\n" n n
8405         | Int n ->
8406             pr "  int %s = Int_val (%sv);\n" n n
8407         | Int64 n ->
8408             pr "  int64_t %s = Int64_val (%sv);\n" n n
8409       ) (snd style);
8410       let error_code =
8411         match fst style with
8412         | RErr -> pr "  int r;\n"; "-1"
8413         | RInt _ -> pr "  int r;\n"; "-1"
8414         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8415         | RBool _ -> pr "  int r;\n"; "-1"
8416         | RConstString _ | RConstOptString _ ->
8417             pr "  const char *r;\n"; "NULL"
8418         | RString _ -> pr "  char *r;\n"; "NULL"
8419         | RStringList _ ->
8420             pr "  int i;\n";
8421             pr "  char **r;\n";
8422             "NULL"
8423         | RStruct (_, typ) ->
8424             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8425         | RStructList (_, typ) ->
8426             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8427         | RHashtable _ ->
8428             pr "  int i;\n";
8429             pr "  char **r;\n";
8430             "NULL"
8431         | RBufferOut _ ->
8432             pr "  char *r;\n";
8433             pr "  size_t size;\n";
8434             "NULL" in
8435       pr "\n";
8436
8437       pr "  caml_enter_blocking_section ();\n";
8438       pr "  r = guestfs_%s " name;
8439       generate_c_call_args ~handle:"g" style;
8440       pr ";\n";
8441       pr "  caml_leave_blocking_section ();\n";
8442
8443       List.iter (
8444         function
8445         | StringList n | DeviceList n ->
8446             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8447         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8448         | Bool _ | Int _ | Int64 _
8449         | FileIn _ | FileOut _ | BufferIn _ -> ()
8450       ) (snd style);
8451
8452       pr "  if (r == %s)\n" error_code;
8453       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8454       pr "\n";
8455
8456       (match fst style with
8457        | RErr -> pr "  rv = Val_unit;\n"
8458        | RInt _ -> pr "  rv = Val_int (r);\n"
8459        | RInt64 _ ->
8460            pr "  rv = caml_copy_int64 (r);\n"
8461        | RBool _ -> pr "  rv = Val_bool (r);\n"
8462        | RConstString _ ->
8463            pr "  rv = caml_copy_string (r);\n"
8464        | RConstOptString _ ->
8465            pr "  if (r) { /* Some string */\n";
8466            pr "    v = caml_alloc (1, 0);\n";
8467            pr "    v2 = caml_copy_string (r);\n";
8468            pr "    Store_field (v, 0, v2);\n";
8469            pr "  } else /* None */\n";
8470            pr "    v = Val_int (0);\n";
8471        | RString _ ->
8472            pr "  rv = caml_copy_string (r);\n";
8473            pr "  free (r);\n"
8474        | RStringList _ ->
8475            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8476            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8477            pr "  free (r);\n"
8478        | RStruct (_, typ) ->
8479            pr "  rv = copy_%s (r);\n" typ;
8480            pr "  guestfs_free_%s (r);\n" typ;
8481        | RStructList (_, typ) ->
8482            pr "  rv = copy_%s_list (r);\n" typ;
8483            pr "  guestfs_free_%s_list (r);\n" typ;
8484        | RHashtable _ ->
8485            pr "  rv = copy_table (r);\n";
8486            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8487            pr "  free (r);\n";
8488        | RBufferOut _ ->
8489            pr "  rv = caml_alloc_string (size);\n";
8490            pr "  memcpy (String_val (rv), r, size);\n";
8491       );
8492
8493       pr "  CAMLreturn (rv);\n";
8494       pr "}\n";
8495       pr "\n";
8496
8497       if List.length params > 5 then (
8498         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8499         pr "CAMLprim value ";
8500         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8501         pr "CAMLprim value\n";
8502         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8503         pr "{\n";
8504         pr "  return ocaml_guestfs_%s (argv[0]" name;
8505         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8506         pr ");\n";
8507         pr "}\n";
8508         pr "\n"
8509       )
8510   ) all_functions_sorted
8511
8512 and generate_ocaml_structure_decls () =
8513   List.iter (
8514     fun (typ, cols) ->
8515       pr "type %s = {\n" typ;
8516       List.iter (
8517         function
8518         | name, FString -> pr "  %s : string;\n" name
8519         | name, FBuffer -> pr "  %s : string;\n" name
8520         | name, FUUID -> pr "  %s : string;\n" name
8521         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8522         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8523         | name, FChar -> pr "  %s : char;\n" name
8524         | name, FOptPercent -> pr "  %s : float option;\n" name
8525       ) cols;
8526       pr "}\n";
8527       pr "\n"
8528   ) structs
8529
8530 and generate_ocaml_prototype ?(is_external = false) name style =
8531   if is_external then pr "external " else pr "val ";
8532   pr "%s : t -> " name;
8533   List.iter (
8534     function
8535     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8536     | BufferIn _ -> pr "string -> "
8537     | OptString _ -> pr "string option -> "
8538     | StringList _ | DeviceList _ -> pr "string array -> "
8539     | Bool _ -> pr "bool -> "
8540     | Int _ -> pr "int -> "
8541     | Int64 _ -> pr "int64 -> "
8542   ) (snd style);
8543   (match fst style with
8544    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8545    | RInt _ -> pr "int"
8546    | RInt64 _ -> pr "int64"
8547    | RBool _ -> pr "bool"
8548    | RConstString _ -> pr "string"
8549    | RConstOptString _ -> pr "string option"
8550    | RString _ | RBufferOut _ -> pr "string"
8551    | RStringList _ -> pr "string array"
8552    | RStruct (_, typ) -> pr "%s" typ
8553    | RStructList (_, typ) -> pr "%s array" typ
8554    | RHashtable _ -> pr "(string * string) list"
8555   );
8556   if is_external then (
8557     pr " = ";
8558     if List.length (snd style) + 1 > 5 then
8559       pr "\"ocaml_guestfs_%s_byte\" " name;
8560     pr "\"ocaml_guestfs_%s\"" name
8561   );
8562   pr "\n"
8563
8564 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8565 and generate_perl_xs () =
8566   generate_header CStyle LGPLv2plus;
8567
8568   pr "\
8569 #include \"EXTERN.h\"
8570 #include \"perl.h\"
8571 #include \"XSUB.h\"
8572
8573 #include <guestfs.h>
8574
8575 #ifndef PRId64
8576 #define PRId64 \"lld\"
8577 #endif
8578
8579 static SV *
8580 my_newSVll(long long val) {
8581 #ifdef USE_64_BIT_ALL
8582   return newSViv(val);
8583 #else
8584   char buf[100];
8585   int len;
8586   len = snprintf(buf, 100, \"%%\" PRId64, val);
8587   return newSVpv(buf, len);
8588 #endif
8589 }
8590
8591 #ifndef PRIu64
8592 #define PRIu64 \"llu\"
8593 #endif
8594
8595 static SV *
8596 my_newSVull(unsigned long long val) {
8597 #ifdef USE_64_BIT_ALL
8598   return newSVuv(val);
8599 #else
8600   char buf[100];
8601   int len;
8602   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8603   return newSVpv(buf, len);
8604 #endif
8605 }
8606
8607 /* http://www.perlmonks.org/?node_id=680842 */
8608 static char **
8609 XS_unpack_charPtrPtr (SV *arg) {
8610   char **ret;
8611   AV *av;
8612   I32 i;
8613
8614   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8615     croak (\"array reference expected\");
8616
8617   av = (AV *)SvRV (arg);
8618   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8619   if (!ret)
8620     croak (\"malloc failed\");
8621
8622   for (i = 0; i <= av_len (av); i++) {
8623     SV **elem = av_fetch (av, i, 0);
8624
8625     if (!elem || !*elem)
8626       croak (\"missing element in list\");
8627
8628     ret[i] = SvPV_nolen (*elem);
8629   }
8630
8631   ret[i] = NULL;
8632
8633   return ret;
8634 }
8635
8636 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8637
8638 PROTOTYPES: ENABLE
8639
8640 guestfs_h *
8641 _create ()
8642    CODE:
8643       RETVAL = guestfs_create ();
8644       if (!RETVAL)
8645         croak (\"could not create guestfs handle\");
8646       guestfs_set_error_handler (RETVAL, NULL, NULL);
8647  OUTPUT:
8648       RETVAL
8649
8650 void
8651 DESTROY (g)
8652       guestfs_h *g;
8653  PPCODE:
8654       guestfs_close (g);
8655
8656 ";
8657
8658   List.iter (
8659     fun (name, style, _, _, _, _, _) ->
8660       (match fst style with
8661        | RErr -> pr "void\n"
8662        | RInt _ -> pr "SV *\n"
8663        | RInt64 _ -> pr "SV *\n"
8664        | RBool _ -> pr "SV *\n"
8665        | RConstString _ -> pr "SV *\n"
8666        | RConstOptString _ -> pr "SV *\n"
8667        | RString _ -> pr "SV *\n"
8668        | RBufferOut _ -> pr "SV *\n"
8669        | RStringList _
8670        | RStruct _ | RStructList _
8671        | RHashtable _ ->
8672            pr "void\n" (* all lists returned implictly on the stack *)
8673       );
8674       (* Call and arguments. *)
8675       pr "%s (g" name;
8676       List.iter (
8677         fun arg -> pr ", %s" (name_of_argt arg)
8678       ) (snd style);
8679       pr ")\n";
8680       pr "      guestfs_h *g;\n";
8681       iteri (
8682         fun i ->
8683           function
8684           | Pathname n | Device n | Dev_or_Path n | String n
8685           | FileIn n | FileOut n ->
8686               pr "      char *%s;\n" n
8687           | BufferIn n ->
8688               pr "      char *%s;\n" n;
8689               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8690           | OptString n ->
8691               (* http://www.perlmonks.org/?node_id=554277
8692                * Note that the implicit handle argument means we have
8693                * to add 1 to the ST(x) operator.
8694                *)
8695               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8696           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8697           | Bool n -> pr "      int %s;\n" n
8698           | Int n -> pr "      int %s;\n" n
8699           | Int64 n -> pr "      int64_t %s;\n" n
8700       ) (snd style);
8701
8702       let do_cleanups () =
8703         List.iter (
8704           function
8705           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8706           | Bool _ | Int _ | Int64 _
8707           | FileIn _ | FileOut _
8708           | BufferIn _ -> ()
8709           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8710         ) (snd style)
8711       in
8712
8713       (* Code. *)
8714       (match fst style with
8715        | RErr ->
8716            pr "PREINIT:\n";
8717            pr "      int r;\n";
8718            pr " PPCODE:\n";
8719            pr "      r = guestfs_%s " name;
8720            generate_c_call_args ~handle:"g" style;
8721            pr ";\n";
8722            do_cleanups ();
8723            pr "      if (r == -1)\n";
8724            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8725        | RInt n
8726        | RBool n ->
8727            pr "PREINIT:\n";
8728            pr "      int %s;\n" n;
8729            pr "   CODE:\n";
8730            pr "      %s = guestfs_%s " n name;
8731            generate_c_call_args ~handle:"g" style;
8732            pr ";\n";
8733            do_cleanups ();
8734            pr "      if (%s == -1)\n" n;
8735            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8736            pr "      RETVAL = newSViv (%s);\n" n;
8737            pr " OUTPUT:\n";
8738            pr "      RETVAL\n"
8739        | RInt64 n ->
8740            pr "PREINIT:\n";
8741            pr "      int64_t %s;\n" n;
8742            pr "   CODE:\n";
8743            pr "      %s = guestfs_%s " n name;
8744            generate_c_call_args ~handle:"g" style;
8745            pr ";\n";
8746            do_cleanups ();
8747            pr "      if (%s == -1)\n" n;
8748            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8749            pr "      RETVAL = my_newSVll (%s);\n" n;
8750            pr " OUTPUT:\n";
8751            pr "      RETVAL\n"
8752        | RConstString n ->
8753            pr "PREINIT:\n";
8754            pr "      const char *%s;\n" n;
8755            pr "   CODE:\n";
8756            pr "      %s = guestfs_%s " n name;
8757            generate_c_call_args ~handle:"g" style;
8758            pr ";\n";
8759            do_cleanups ();
8760            pr "      if (%s == NULL)\n" n;
8761            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8762            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8763            pr " OUTPUT:\n";
8764            pr "      RETVAL\n"
8765        | RConstOptString n ->
8766            pr "PREINIT:\n";
8767            pr "      const char *%s;\n" n;
8768            pr "   CODE:\n";
8769            pr "      %s = guestfs_%s " n name;
8770            generate_c_call_args ~handle:"g" style;
8771            pr ";\n";
8772            do_cleanups ();
8773            pr "      if (%s == NULL)\n" n;
8774            pr "        RETVAL = &PL_sv_undef;\n";
8775            pr "      else\n";
8776            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8777            pr " OUTPUT:\n";
8778            pr "      RETVAL\n"
8779        | RString n ->
8780            pr "PREINIT:\n";
8781            pr "      char *%s;\n" n;
8782            pr "   CODE:\n";
8783            pr "      %s = guestfs_%s " n name;
8784            generate_c_call_args ~handle:"g" style;
8785            pr ";\n";
8786            do_cleanups ();
8787            pr "      if (%s == NULL)\n" n;
8788            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8789            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8790            pr "      free (%s);\n" n;
8791            pr " OUTPUT:\n";
8792            pr "      RETVAL\n"
8793        | RStringList n | RHashtable n ->
8794            pr "PREINIT:\n";
8795            pr "      char **%s;\n" n;
8796            pr "      int i, n;\n";
8797            pr " PPCODE:\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 "        croak (\"%%s\", guestfs_last_error (g));\n";
8804            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8805            pr "      EXTEND (SP, n);\n";
8806            pr "      for (i = 0; i < n; ++i) {\n";
8807            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8808            pr "        free (%s[i]);\n" n;
8809            pr "      }\n";
8810            pr "      free (%s);\n" n;
8811        | RStruct (n, typ) ->
8812            let cols = cols_of_struct typ in
8813            generate_perl_struct_code typ cols name style n do_cleanups
8814        | RStructList (n, typ) ->
8815            let cols = cols_of_struct typ in
8816            generate_perl_struct_list_code typ cols name style n do_cleanups
8817        | RBufferOut n ->
8818            pr "PREINIT:\n";
8819            pr "      char *%s;\n" n;
8820            pr "      size_t size;\n";
8821            pr "   CODE:\n";
8822            pr "      %s = guestfs_%s " n name;
8823            generate_c_call_args ~handle:"g" style;
8824            pr ";\n";
8825            do_cleanups ();
8826            pr "      if (%s == NULL)\n" n;
8827            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8828            pr "      RETVAL = newSVpvn (%s, size);\n" n;
8829            pr "      free (%s);\n" n;
8830            pr " OUTPUT:\n";
8831            pr "      RETVAL\n"
8832       );
8833
8834       pr "\n"
8835   ) all_functions
8836
8837 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8838   pr "PREINIT:\n";
8839   pr "      struct guestfs_%s_list *%s;\n" typ n;
8840   pr "      int i;\n";
8841   pr "      HV *hv;\n";
8842   pr " PPCODE:\n";
8843   pr "      %s = guestfs_%s " n name;
8844   generate_c_call_args ~handle:"g" style;
8845   pr ";\n";
8846   do_cleanups ();
8847   pr "      if (%s == NULL)\n" n;
8848   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8849   pr "      EXTEND (SP, %s->len);\n" n;
8850   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8851   pr "        hv = newHV ();\n";
8852   List.iter (
8853     function
8854     | name, FString ->
8855         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8856           name (String.length name) n name
8857     | name, FUUID ->
8858         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8859           name (String.length name) n name
8860     | name, FBuffer ->
8861         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8862           name (String.length name) n name n name
8863     | name, (FBytes|FUInt64) ->
8864         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8865           name (String.length name) n name
8866     | name, FInt64 ->
8867         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8868           name (String.length name) n name
8869     | name, (FInt32|FUInt32) ->
8870         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8871           name (String.length name) n name
8872     | name, FChar ->
8873         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8874           name (String.length name) n name
8875     | name, FOptPercent ->
8876         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8877           name (String.length name) n name
8878   ) cols;
8879   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8880   pr "      }\n";
8881   pr "      guestfs_free_%s_list (%s);\n" typ n
8882
8883 and generate_perl_struct_code typ cols name style n do_cleanups =
8884   pr "PREINIT:\n";
8885   pr "      struct guestfs_%s *%s;\n" typ n;
8886   pr " PPCODE:\n";
8887   pr "      %s = guestfs_%s " n name;
8888   generate_c_call_args ~handle:"g" style;
8889   pr ";\n";
8890   do_cleanups ();
8891   pr "      if (%s == NULL)\n" n;
8892   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8893   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8894   List.iter (
8895     fun ((name, _) as col) ->
8896       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8897
8898       match col with
8899       | name, FString ->
8900           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8901             n name
8902       | name, FBuffer ->
8903           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
8904             n name n name
8905       | name, FUUID ->
8906           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8907             n name
8908       | name, (FBytes|FUInt64) ->
8909           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8910             n name
8911       | name, FInt64 ->
8912           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8913             n name
8914       | name, (FInt32|FUInt32) ->
8915           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8916             n name
8917       | name, FChar ->
8918           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8919             n name
8920       | name, FOptPercent ->
8921           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8922             n name
8923   ) cols;
8924   pr "      free (%s);\n" n
8925
8926 (* Generate Sys/Guestfs.pm. *)
8927 and generate_perl_pm () =
8928   generate_header HashStyle LGPLv2plus;
8929
8930   pr "\
8931 =pod
8932
8933 =head1 NAME
8934
8935 Sys::Guestfs - Perl bindings for libguestfs
8936
8937 =head1 SYNOPSIS
8938
8939  use Sys::Guestfs;
8940
8941  my $h = Sys::Guestfs->new ();
8942  $h->add_drive ('guest.img');
8943  $h->launch ();
8944  $h->mount ('/dev/sda1', '/');
8945  $h->touch ('/hello');
8946  $h->sync ();
8947
8948 =head1 DESCRIPTION
8949
8950 The C<Sys::Guestfs> module provides a Perl XS binding to the
8951 libguestfs API for examining and modifying virtual machine
8952 disk images.
8953
8954 Amongst the things this is good for: making batch configuration
8955 changes to guests, getting disk used/free statistics (see also:
8956 virt-df), migrating between virtualization systems (see also:
8957 virt-p2v), performing partial backups, performing partial guest
8958 clones, cloning guests and changing registry/UUID/hostname info, and
8959 much else besides.
8960
8961 Libguestfs uses Linux kernel and qemu code, and can access any type of
8962 guest filesystem that Linux and qemu can, including but not limited
8963 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8964 schemes, qcow, qcow2, vmdk.
8965
8966 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8967 LVs, what filesystem is in each LV, etc.).  It can also run commands
8968 in the context of the guest.  Also you can access filesystems over
8969 FUSE.
8970
8971 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8972 functions for using libguestfs from Perl, including integration
8973 with libvirt.
8974
8975 =head1 ERRORS
8976
8977 All errors turn into calls to C<croak> (see L<Carp(3)>).
8978
8979 =head1 METHODS
8980
8981 =over 4
8982
8983 =cut
8984
8985 package Sys::Guestfs;
8986
8987 use strict;
8988 use warnings;
8989
8990 # This version number changes whenever a new function
8991 # is added to the libguestfs API.  It is not directly
8992 # related to the libguestfs version number.
8993 use vars qw($VERSION);
8994 $VERSION = '0.%d';
8995
8996 require XSLoader;
8997 XSLoader::load ('Sys::Guestfs');
8998
8999 =item $h = Sys::Guestfs->new ();
9000
9001 Create a new guestfs handle.
9002
9003 =cut
9004
9005 sub new {
9006   my $proto = shift;
9007   my $class = ref ($proto) || $proto;
9008
9009   my $self = Sys::Guestfs::_create ();
9010   bless $self, $class;
9011   return $self;
9012 }
9013
9014 " max_proc_nr;
9015
9016   (* Actions.  We only need to print documentation for these as
9017    * they are pulled in from the XS code automatically.
9018    *)
9019   List.iter (
9020     fun (name, style, _, flags, _, _, longdesc) ->
9021       if not (List.mem NotInDocs flags) then (
9022         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9023         pr "=item ";
9024         generate_perl_prototype name style;
9025         pr "\n\n";
9026         pr "%s\n\n" longdesc;
9027         if List.mem ProtocolLimitWarning flags then
9028           pr "%s\n\n" protocol_limit_warning;
9029         if List.mem DangerWillRobinson flags then
9030           pr "%s\n\n" danger_will_robinson;
9031         match deprecation_notice flags with
9032         | None -> ()
9033         | Some txt -> pr "%s\n\n" txt
9034       )
9035   ) all_functions_sorted;
9036
9037   (* End of file. *)
9038   pr "\
9039 =cut
9040
9041 1;
9042
9043 =back
9044
9045 =head1 COPYRIGHT
9046
9047 Copyright (C) %s Red Hat Inc.
9048
9049 =head1 LICENSE
9050
9051 Please see the file COPYING.LIB for the full license.
9052
9053 =head1 SEE ALSO
9054
9055 L<guestfs(3)>,
9056 L<guestfish(1)>,
9057 L<http://libguestfs.org>,
9058 L<Sys::Guestfs::Lib(3)>.
9059
9060 =cut
9061 " copyright_years
9062
9063 and generate_perl_prototype name style =
9064   (match fst style with
9065    | RErr -> ()
9066    | RBool n
9067    | RInt n
9068    | RInt64 n
9069    | RConstString n
9070    | RConstOptString n
9071    | RString n
9072    | RBufferOut n -> pr "$%s = " n
9073    | RStruct (n,_)
9074    | RHashtable n -> pr "%%%s = " n
9075    | RStringList n
9076    | RStructList (n,_) -> pr "@%s = " n
9077   );
9078   pr "$h->%s (" name;
9079   let comma = ref false in
9080   List.iter (
9081     fun arg ->
9082       if !comma then pr ", ";
9083       comma := true;
9084       match arg with
9085       | Pathname n | Device n | Dev_or_Path n | String n
9086       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9087       | BufferIn n ->
9088           pr "$%s" n
9089       | StringList n | DeviceList n ->
9090           pr "\\@%s" n
9091   ) (snd style);
9092   pr ");"
9093
9094 (* Generate Python C module. *)
9095 and generate_python_c () =
9096   generate_header CStyle LGPLv2plus;
9097
9098   pr "\
9099 #define PY_SSIZE_T_CLEAN 1
9100 #include <Python.h>
9101
9102 #include <stdio.h>
9103 #include <stdlib.h>
9104 #include <assert.h>
9105
9106 #include \"guestfs.h\"
9107
9108 typedef struct {
9109   PyObject_HEAD
9110   guestfs_h *g;
9111 } Pyguestfs_Object;
9112
9113 static guestfs_h *
9114 get_handle (PyObject *obj)
9115 {
9116   assert (obj);
9117   assert (obj != Py_None);
9118   return ((Pyguestfs_Object *) obj)->g;
9119 }
9120
9121 static PyObject *
9122 put_handle (guestfs_h *g)
9123 {
9124   assert (g);
9125   return
9126     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9127 }
9128
9129 /* This list should be freed (but not the strings) after use. */
9130 static char **
9131 get_string_list (PyObject *obj)
9132 {
9133   int i, len;
9134   char **r;
9135
9136   assert (obj);
9137
9138   if (!PyList_Check (obj)) {
9139     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9140     return NULL;
9141   }
9142
9143   len = PyList_Size (obj);
9144   r = malloc (sizeof (char *) * (len+1));
9145   if (r == NULL) {
9146     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9147     return NULL;
9148   }
9149
9150   for (i = 0; i < len; ++i)
9151     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9152   r[len] = NULL;
9153
9154   return r;
9155 }
9156
9157 static PyObject *
9158 put_string_list (char * const * const argv)
9159 {
9160   PyObject *list;
9161   int argc, i;
9162
9163   for (argc = 0; argv[argc] != NULL; ++argc)
9164     ;
9165
9166   list = PyList_New (argc);
9167   for (i = 0; i < argc; ++i)
9168     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9169
9170   return list;
9171 }
9172
9173 static PyObject *
9174 put_table (char * const * const argv)
9175 {
9176   PyObject *list, *item;
9177   int argc, i;
9178
9179   for (argc = 0; argv[argc] != NULL; ++argc)
9180     ;
9181
9182   list = PyList_New (argc >> 1);
9183   for (i = 0; i < argc; i += 2) {
9184     item = PyTuple_New (2);
9185     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9186     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9187     PyList_SetItem (list, i >> 1, item);
9188   }
9189
9190   return list;
9191 }
9192
9193 static void
9194 free_strings (char **argv)
9195 {
9196   int argc;
9197
9198   for (argc = 0; argv[argc] != NULL; ++argc)
9199     free (argv[argc]);
9200   free (argv);
9201 }
9202
9203 static PyObject *
9204 py_guestfs_create (PyObject *self, PyObject *args)
9205 {
9206   guestfs_h *g;
9207
9208   g = guestfs_create ();
9209   if (g == NULL) {
9210     PyErr_SetString (PyExc_RuntimeError,
9211                      \"guestfs.create: failed to allocate handle\");
9212     return NULL;
9213   }
9214   guestfs_set_error_handler (g, NULL, NULL);
9215   return put_handle (g);
9216 }
9217
9218 static PyObject *
9219 py_guestfs_close (PyObject *self, PyObject *args)
9220 {
9221   PyObject *py_g;
9222   guestfs_h *g;
9223
9224   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9225     return NULL;
9226   g = get_handle (py_g);
9227
9228   guestfs_close (g);
9229
9230   Py_INCREF (Py_None);
9231   return Py_None;
9232 }
9233
9234 ";
9235
9236   let emit_put_list_function typ =
9237     pr "static PyObject *\n";
9238     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9239     pr "{\n";
9240     pr "  PyObject *list;\n";
9241     pr "  int i;\n";
9242     pr "\n";
9243     pr "  list = PyList_New (%ss->len);\n" typ;
9244     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9245     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9246     pr "  return list;\n";
9247     pr "};\n";
9248     pr "\n"
9249   in
9250
9251   (* Structures, turned into Python dictionaries. *)
9252   List.iter (
9253     fun (typ, cols) ->
9254       pr "static PyObject *\n";
9255       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9256       pr "{\n";
9257       pr "  PyObject *dict;\n";
9258       pr "\n";
9259       pr "  dict = PyDict_New ();\n";
9260       List.iter (
9261         function
9262         | name, FString ->
9263             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9264             pr "                        PyString_FromString (%s->%s));\n"
9265               typ name
9266         | name, FBuffer ->
9267             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9268             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9269               typ name typ name
9270         | name, FUUID ->
9271             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9272             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9273               typ name
9274         | name, (FBytes|FUInt64) ->
9275             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9276             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9277               typ name
9278         | name, FInt64 ->
9279             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9280             pr "                        PyLong_FromLongLong (%s->%s));\n"
9281               typ name
9282         | name, FUInt32 ->
9283             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9284             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9285               typ name
9286         | name, FInt32 ->
9287             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9288             pr "                        PyLong_FromLong (%s->%s));\n"
9289               typ name
9290         | name, FOptPercent ->
9291             pr "  if (%s->%s >= 0)\n" typ name;
9292             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9293             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9294               typ name;
9295             pr "  else {\n";
9296             pr "    Py_INCREF (Py_None);\n";
9297             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9298             pr "  }\n"
9299         | name, FChar ->
9300             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9301             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9302       ) cols;
9303       pr "  return dict;\n";
9304       pr "};\n";
9305       pr "\n";
9306
9307   ) structs;
9308
9309   (* Emit a put_TYPE_list function definition only if that function is used. *)
9310   List.iter (
9311     function
9312     | typ, (RStructListOnly | RStructAndList) ->
9313         (* generate the function for typ *)
9314         emit_put_list_function typ
9315     | typ, _ -> () (* empty *)
9316   ) (rstructs_used_by all_functions);
9317
9318   (* Python wrapper functions. *)
9319   List.iter (
9320     fun (name, style, _, _, _, _, _) ->
9321       pr "static PyObject *\n";
9322       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9323       pr "{\n";
9324
9325       pr "  PyObject *py_g;\n";
9326       pr "  guestfs_h *g;\n";
9327       pr "  PyObject *py_r;\n";
9328
9329       let error_code =
9330         match fst style with
9331         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9332         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9333         | RConstString _ | RConstOptString _ ->
9334             pr "  const char *r;\n"; "NULL"
9335         | RString _ -> pr "  char *r;\n"; "NULL"
9336         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9337         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9338         | RStructList (_, typ) ->
9339             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9340         | RBufferOut _ ->
9341             pr "  char *r;\n";
9342             pr "  size_t size;\n";
9343             "NULL" in
9344
9345       List.iter (
9346         function
9347         | Pathname n | Device n | Dev_or_Path n | String n
9348         | FileIn n | FileOut n ->
9349             pr "  const char *%s;\n" n
9350         | OptString n -> pr "  const char *%s;\n" n
9351         | BufferIn n ->
9352             pr "  const char *%s;\n" n;
9353             pr "  Py_ssize_t %s_size;\n" n
9354         | StringList n | DeviceList n ->
9355             pr "  PyObject *py_%s;\n" n;
9356             pr "  char **%s;\n" n
9357         | Bool n -> pr "  int %s;\n" n
9358         | Int n -> pr "  int %s;\n" n
9359         | Int64 n -> pr "  long long %s;\n" n
9360       ) (snd style);
9361
9362       pr "\n";
9363
9364       (* Convert the parameters. *)
9365       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9366       List.iter (
9367         function
9368         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9369         | OptString _ -> pr "z"
9370         | StringList _ | DeviceList _ -> pr "O"
9371         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9372         | Int _ -> pr "i"
9373         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9374                              * emulate C's int/long/long long in Python?
9375                              *)
9376         | BufferIn _ -> pr "s#"
9377       ) (snd style);
9378       pr ":guestfs_%s\",\n" name;
9379       pr "                         &py_g";
9380       List.iter (
9381         function
9382         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9383         | OptString n -> pr ", &%s" n
9384         | StringList n | DeviceList n -> pr ", &py_%s" n
9385         | Bool n -> pr ", &%s" n
9386         | Int n -> pr ", &%s" n
9387         | Int64 n -> pr ", &%s" n
9388         | BufferIn n -> pr ", &%s, &%s_size" n n
9389       ) (snd style);
9390
9391       pr "))\n";
9392       pr "    return NULL;\n";
9393
9394       pr "  g = get_handle (py_g);\n";
9395       List.iter (
9396         function
9397         | Pathname _ | Device _ | Dev_or_Path _ | String _
9398         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9399         | BufferIn _ -> ()
9400         | StringList n | DeviceList n ->
9401             pr "  %s = get_string_list (py_%s);\n" n n;
9402             pr "  if (!%s) return NULL;\n" n
9403       ) (snd style);
9404
9405       pr "\n";
9406
9407       pr "  r = guestfs_%s " name;
9408       generate_c_call_args ~handle:"g" style;
9409       pr ";\n";
9410
9411       List.iter (
9412         function
9413         | Pathname _ | Device _ | Dev_or_Path _ | String _
9414         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9415         | BufferIn _ -> ()
9416         | StringList n | DeviceList n ->
9417             pr "  free (%s);\n" n
9418       ) (snd style);
9419
9420       pr "  if (r == %s) {\n" error_code;
9421       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9422       pr "    return NULL;\n";
9423       pr "  }\n";
9424       pr "\n";
9425
9426       (match fst style with
9427        | RErr ->
9428            pr "  Py_INCREF (Py_None);\n";
9429            pr "  py_r = Py_None;\n"
9430        | RInt _
9431        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9432        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9433        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9434        | RConstOptString _ ->
9435            pr "  if (r)\n";
9436            pr "    py_r = PyString_FromString (r);\n";
9437            pr "  else {\n";
9438            pr "    Py_INCREF (Py_None);\n";
9439            pr "    py_r = Py_None;\n";
9440            pr "  }\n"
9441        | RString _ ->
9442            pr "  py_r = PyString_FromString (r);\n";
9443            pr "  free (r);\n"
9444        | RStringList _ ->
9445            pr "  py_r = put_string_list (r);\n";
9446            pr "  free_strings (r);\n"
9447        | RStruct (_, typ) ->
9448            pr "  py_r = put_%s (r);\n" typ;
9449            pr "  guestfs_free_%s (r);\n" typ
9450        | RStructList (_, typ) ->
9451            pr "  py_r = put_%s_list (r);\n" typ;
9452            pr "  guestfs_free_%s_list (r);\n" typ
9453        | RHashtable n ->
9454            pr "  py_r = put_table (r);\n";
9455            pr "  free_strings (r);\n"
9456        | RBufferOut _ ->
9457            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9458            pr "  free (r);\n"
9459       );
9460
9461       pr "  return py_r;\n";
9462       pr "}\n";
9463       pr "\n"
9464   ) all_functions;
9465
9466   (* Table of functions. *)
9467   pr "static PyMethodDef methods[] = {\n";
9468   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9469   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9470   List.iter (
9471     fun (name, _, _, _, _, _, _) ->
9472       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9473         name name
9474   ) all_functions;
9475   pr "  { NULL, NULL, 0, NULL }\n";
9476   pr "};\n";
9477   pr "\n";
9478
9479   (* Init function. *)
9480   pr "\
9481 void
9482 initlibguestfsmod (void)
9483 {
9484   static int initialized = 0;
9485
9486   if (initialized) return;
9487   Py_InitModule ((char *) \"libguestfsmod\", methods);
9488   initialized = 1;
9489 }
9490 "
9491
9492 (* Generate Python module. *)
9493 and generate_python_py () =
9494   generate_header HashStyle LGPLv2plus;
9495
9496   pr "\
9497 u\"\"\"Python bindings for libguestfs
9498
9499 import guestfs
9500 g = guestfs.GuestFS ()
9501 g.add_drive (\"guest.img\")
9502 g.launch ()
9503 parts = g.list_partitions ()
9504
9505 The guestfs module provides a Python binding to the libguestfs API
9506 for examining and modifying virtual machine disk images.
9507
9508 Amongst the things this is good for: making batch configuration
9509 changes to guests, getting disk used/free statistics (see also:
9510 virt-df), migrating between virtualization systems (see also:
9511 virt-p2v), performing partial backups, performing partial guest
9512 clones, cloning guests and changing registry/UUID/hostname info, and
9513 much else besides.
9514
9515 Libguestfs uses Linux kernel and qemu code, and can access any type of
9516 guest filesystem that Linux and qemu can, including but not limited
9517 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9518 schemes, qcow, qcow2, vmdk.
9519
9520 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9521 LVs, what filesystem is in each LV, etc.).  It can also run commands
9522 in the context of the guest.  Also you can access filesystems over
9523 FUSE.
9524
9525 Errors which happen while using the API are turned into Python
9526 RuntimeError exceptions.
9527
9528 To create a guestfs handle you usually have to perform the following
9529 sequence of calls:
9530
9531 # Create the handle, call add_drive at least once, and possibly
9532 # several times if the guest has multiple block devices:
9533 g = guestfs.GuestFS ()
9534 g.add_drive (\"guest.img\")
9535
9536 # Launch the qemu subprocess and wait for it to become ready:
9537 g.launch ()
9538
9539 # Now you can issue commands, for example:
9540 logvols = g.lvs ()
9541
9542 \"\"\"
9543
9544 import libguestfsmod
9545
9546 class GuestFS:
9547     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9548
9549     def __init__ (self):
9550         \"\"\"Create a new libguestfs handle.\"\"\"
9551         self._o = libguestfsmod.create ()
9552
9553     def __del__ (self):
9554         libguestfsmod.close (self._o)
9555
9556 ";
9557
9558   List.iter (
9559     fun (name, style, _, flags, _, _, longdesc) ->
9560       pr "    def %s " name;
9561       generate_py_call_args ~handle:"self" (snd style);
9562       pr ":\n";
9563
9564       if not (List.mem NotInDocs flags) then (
9565         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9566         let doc =
9567           match fst style with
9568           | RErr | RInt _ | RInt64 _ | RBool _
9569           | RConstOptString _ | RConstString _
9570           | RString _ | RBufferOut _ -> doc
9571           | RStringList _ ->
9572               doc ^ "\n\nThis function returns a list of strings."
9573           | RStruct (_, typ) ->
9574               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9575           | RStructList (_, typ) ->
9576               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9577           | RHashtable _ ->
9578               doc ^ "\n\nThis function returns a dictionary." in
9579         let doc =
9580           if List.mem ProtocolLimitWarning flags then
9581             doc ^ "\n\n" ^ protocol_limit_warning
9582           else doc in
9583         let doc =
9584           if List.mem DangerWillRobinson flags then
9585             doc ^ "\n\n" ^ danger_will_robinson
9586           else doc in
9587         let doc =
9588           match deprecation_notice flags with
9589           | None -> doc
9590           | Some txt -> doc ^ "\n\n" ^ txt in
9591         let doc = pod2text ~width:60 name doc in
9592         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9593         let doc = String.concat "\n        " doc in
9594         pr "        u\"\"\"%s\"\"\"\n" doc;
9595       );
9596       pr "        return libguestfsmod.%s " name;
9597       generate_py_call_args ~handle:"self._o" (snd style);
9598       pr "\n";
9599       pr "\n";
9600   ) all_functions
9601
9602 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9603 and generate_py_call_args ~handle args =
9604   pr "(%s" handle;
9605   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9606   pr ")"
9607
9608 (* Useful if you need the longdesc POD text as plain text.  Returns a
9609  * list of lines.
9610  *
9611  * Because this is very slow (the slowest part of autogeneration),
9612  * we memoize the results.
9613  *)
9614 and pod2text ~width name longdesc =
9615   let key = width, name, longdesc in
9616   try Hashtbl.find pod2text_memo key
9617   with Not_found ->
9618     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9619     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9620     close_out chan;
9621     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9622     let chan = open_process_in cmd in
9623     let lines = ref [] in
9624     let rec loop i =
9625       let line = input_line chan in
9626       if i = 1 then             (* discard the first line of output *)
9627         loop (i+1)
9628       else (
9629         let line = triml line in
9630         lines := line :: !lines;
9631         loop (i+1)
9632       ) in
9633     let lines = try loop 1 with End_of_file -> List.rev !lines in
9634     unlink filename;
9635     (match close_process_in chan with
9636      | WEXITED 0 -> ()
9637      | WEXITED i ->
9638          failwithf "pod2text: process exited with non-zero status (%d)" i
9639      | WSIGNALED i | WSTOPPED i ->
9640          failwithf "pod2text: process signalled or stopped by signal %d" i
9641     );
9642     Hashtbl.add pod2text_memo key lines;
9643     pod2text_memo_updated ();
9644     lines
9645
9646 (* Generate ruby bindings. *)
9647 and generate_ruby_c () =
9648   generate_header CStyle LGPLv2plus;
9649
9650   pr "\
9651 #include <stdio.h>
9652 #include <stdlib.h>
9653
9654 #include <ruby.h>
9655
9656 #include \"guestfs.h\"
9657
9658 #include \"extconf.h\"
9659
9660 /* For Ruby < 1.9 */
9661 #ifndef RARRAY_LEN
9662 #define RARRAY_LEN(r) (RARRAY((r))->len)
9663 #endif
9664
9665 static VALUE m_guestfs;                 /* guestfs module */
9666 static VALUE c_guestfs;                 /* guestfs_h handle */
9667 static VALUE e_Error;                   /* used for all errors */
9668
9669 static void ruby_guestfs_free (void *p)
9670 {
9671   if (!p) return;
9672   guestfs_close ((guestfs_h *) p);
9673 }
9674
9675 static VALUE ruby_guestfs_create (VALUE m)
9676 {
9677   guestfs_h *g;
9678
9679   g = guestfs_create ();
9680   if (!g)
9681     rb_raise (e_Error, \"failed to create guestfs handle\");
9682
9683   /* Don't print error messages to stderr by default. */
9684   guestfs_set_error_handler (g, NULL, NULL);
9685
9686   /* Wrap it, and make sure the close function is called when the
9687    * handle goes away.
9688    */
9689   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9690 }
9691
9692 static VALUE ruby_guestfs_close (VALUE gv)
9693 {
9694   guestfs_h *g;
9695   Data_Get_Struct (gv, guestfs_h, g);
9696
9697   ruby_guestfs_free (g);
9698   DATA_PTR (gv) = NULL;
9699
9700   return Qnil;
9701 }
9702
9703 ";
9704
9705   List.iter (
9706     fun (name, style, _, _, _, _, _) ->
9707       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9708       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9709       pr ")\n";
9710       pr "{\n";
9711       pr "  guestfs_h *g;\n";
9712       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9713       pr "  if (!g)\n";
9714       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9715         name;
9716       pr "\n";
9717
9718       List.iter (
9719         function
9720         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9721             pr "  Check_Type (%sv, T_STRING);\n" n;
9722             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9723             pr "  if (!%s)\n" n;
9724             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9725             pr "              \"%s\", \"%s\");\n" n name
9726         | BufferIn n ->
9727             pr "  Check_Type (%sv, T_STRING);\n" n;
9728             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9729             pr "  if (!%s)\n" n;
9730             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9731             pr "              \"%s\", \"%s\");\n" n name;
9732             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
9733         | OptString n ->
9734             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9735         | StringList n | DeviceList n ->
9736             pr "  char **%s;\n" n;
9737             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9738             pr "  {\n";
9739             pr "    int i, len;\n";
9740             pr "    len = RARRAY_LEN (%sv);\n" n;
9741             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9742               n;
9743             pr "    for (i = 0; i < len; ++i) {\n";
9744             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9745             pr "      %s[i] = StringValueCStr (v);\n" n;
9746             pr "    }\n";
9747             pr "    %s[len] = NULL;\n" n;
9748             pr "  }\n";
9749         | Bool n ->
9750             pr "  int %s = RTEST (%sv);\n" n n
9751         | Int n ->
9752             pr "  int %s = NUM2INT (%sv);\n" n n
9753         | Int64 n ->
9754             pr "  long long %s = NUM2LL (%sv);\n" n n
9755       ) (snd style);
9756       pr "\n";
9757
9758       let error_code =
9759         match fst style with
9760         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9761         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9762         | RConstString _ | RConstOptString _ ->
9763             pr "  const char *r;\n"; "NULL"
9764         | RString _ -> pr "  char *r;\n"; "NULL"
9765         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9766         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9767         | RStructList (_, typ) ->
9768             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9769         | RBufferOut _ ->
9770             pr "  char *r;\n";
9771             pr "  size_t size;\n";
9772             "NULL" in
9773       pr "\n";
9774
9775       pr "  r = guestfs_%s " name;
9776       generate_c_call_args ~handle:"g" style;
9777       pr ";\n";
9778
9779       List.iter (
9780         function
9781         | Pathname _ | Device _ | Dev_or_Path _ | String _
9782         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9783         | BufferIn _ -> ()
9784         | StringList n | DeviceList n ->
9785             pr "  free (%s);\n" n
9786       ) (snd style);
9787
9788       pr "  if (r == %s)\n" error_code;
9789       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9790       pr "\n";
9791
9792       (match fst style with
9793        | RErr ->
9794            pr "  return Qnil;\n"
9795        | RInt _ | RBool _ ->
9796            pr "  return INT2NUM (r);\n"
9797        | RInt64 _ ->
9798            pr "  return ULL2NUM (r);\n"
9799        | RConstString _ ->
9800            pr "  return rb_str_new2 (r);\n";
9801        | RConstOptString _ ->
9802            pr "  if (r)\n";
9803            pr "    return rb_str_new2 (r);\n";
9804            pr "  else\n";
9805            pr "    return Qnil;\n";
9806        | RString _ ->
9807            pr "  VALUE rv = rb_str_new2 (r);\n";
9808            pr "  free (r);\n";
9809            pr "  return rv;\n";
9810        | RStringList _ ->
9811            pr "  int i, len = 0;\n";
9812            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9813            pr "  VALUE rv = rb_ary_new2 (len);\n";
9814            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9815            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9816            pr "    free (r[i]);\n";
9817            pr "  }\n";
9818            pr "  free (r);\n";
9819            pr "  return rv;\n"
9820        | RStruct (_, typ) ->
9821            let cols = cols_of_struct typ in
9822            generate_ruby_struct_code typ cols
9823        | RStructList (_, typ) ->
9824            let cols = cols_of_struct typ in
9825            generate_ruby_struct_list_code typ cols
9826        | RHashtable _ ->
9827            pr "  VALUE rv = rb_hash_new ();\n";
9828            pr "  int i;\n";
9829            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9830            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9831            pr "    free (r[i]);\n";
9832            pr "    free (r[i+1]);\n";
9833            pr "  }\n";
9834            pr "  free (r);\n";
9835            pr "  return rv;\n"
9836        | RBufferOut _ ->
9837            pr "  VALUE rv = rb_str_new (r, size);\n";
9838            pr "  free (r);\n";
9839            pr "  return rv;\n";
9840       );
9841
9842       pr "}\n";
9843       pr "\n"
9844   ) all_functions;
9845
9846   pr "\
9847 /* Initialize the module. */
9848 void Init__guestfs ()
9849 {
9850   m_guestfs = rb_define_module (\"Guestfs\");
9851   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9852   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9853
9854   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9855   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9856
9857 ";
9858   (* Define the rest of the methods. *)
9859   List.iter (
9860     fun (name, style, _, _, _, _, _) ->
9861       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9862       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9863   ) all_functions;
9864
9865   pr "}\n"
9866
9867 (* Ruby code to return a struct. *)
9868 and generate_ruby_struct_code typ cols =
9869   pr "  VALUE rv = rb_hash_new ();\n";
9870   List.iter (
9871     function
9872     | name, FString ->
9873         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9874     | name, FBuffer ->
9875         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9876     | name, FUUID ->
9877         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9878     | name, (FBytes|FUInt64) ->
9879         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9880     | name, FInt64 ->
9881         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9882     | name, FUInt32 ->
9883         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9884     | name, FInt32 ->
9885         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9886     | name, FOptPercent ->
9887         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9888     | name, FChar -> (* XXX wrong? *)
9889         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9890   ) cols;
9891   pr "  guestfs_free_%s (r);\n" typ;
9892   pr "  return rv;\n"
9893
9894 (* Ruby code to return a struct list. *)
9895 and generate_ruby_struct_list_code typ cols =
9896   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9897   pr "  int i;\n";
9898   pr "  for (i = 0; i < r->len; ++i) {\n";
9899   pr "    VALUE hv = rb_hash_new ();\n";
9900   List.iter (
9901     function
9902     | name, FString ->
9903         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9904     | name, FBuffer ->
9905         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
9906     | name, FUUID ->
9907         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9908     | name, (FBytes|FUInt64) ->
9909         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9910     | name, FInt64 ->
9911         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9912     | name, FUInt32 ->
9913         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9914     | name, FInt32 ->
9915         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9916     | name, FOptPercent ->
9917         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9918     | name, FChar -> (* XXX wrong? *)
9919         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9920   ) cols;
9921   pr "    rb_ary_push (rv, hv);\n";
9922   pr "  }\n";
9923   pr "  guestfs_free_%s_list (r);\n" typ;
9924   pr "  return rv;\n"
9925
9926 (* Generate Java bindings GuestFS.java file. *)
9927 and generate_java_java () =
9928   generate_header CStyle LGPLv2plus;
9929
9930   pr "\
9931 package com.redhat.et.libguestfs;
9932
9933 import java.util.HashMap;
9934 import com.redhat.et.libguestfs.LibGuestFSException;
9935 import com.redhat.et.libguestfs.PV;
9936 import com.redhat.et.libguestfs.VG;
9937 import com.redhat.et.libguestfs.LV;
9938 import com.redhat.et.libguestfs.Stat;
9939 import com.redhat.et.libguestfs.StatVFS;
9940 import com.redhat.et.libguestfs.IntBool;
9941 import com.redhat.et.libguestfs.Dirent;
9942
9943 /**
9944  * The GuestFS object is a libguestfs handle.
9945  *
9946  * @author rjones
9947  */
9948 public class GuestFS {
9949   // Load the native code.
9950   static {
9951     System.loadLibrary (\"guestfs_jni\");
9952   }
9953
9954   /**
9955    * The native guestfs_h pointer.
9956    */
9957   long g;
9958
9959   /**
9960    * Create a libguestfs handle.
9961    *
9962    * @throws LibGuestFSException
9963    */
9964   public GuestFS () throws LibGuestFSException
9965   {
9966     g = _create ();
9967   }
9968   private native long _create () throws LibGuestFSException;
9969
9970   /**
9971    * Close a libguestfs handle.
9972    *
9973    * You can also leave handles to be collected by the garbage
9974    * collector, but this method ensures that the resources used
9975    * by the handle are freed up immediately.  If you call any
9976    * other methods after closing the handle, you will get an
9977    * exception.
9978    *
9979    * @throws LibGuestFSException
9980    */
9981   public void close () throws LibGuestFSException
9982   {
9983     if (g != 0)
9984       _close (g);
9985     g = 0;
9986   }
9987   private native void _close (long g) throws LibGuestFSException;
9988
9989   public void finalize () throws LibGuestFSException
9990   {
9991     close ();
9992   }
9993
9994 ";
9995
9996   List.iter (
9997     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9998       if not (List.mem NotInDocs flags); then (
9999         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10000         let doc =
10001           if List.mem ProtocolLimitWarning flags then
10002             doc ^ "\n\n" ^ protocol_limit_warning
10003           else doc in
10004         let doc =
10005           if List.mem DangerWillRobinson flags then
10006             doc ^ "\n\n" ^ danger_will_robinson
10007           else doc in
10008         let doc =
10009           match deprecation_notice flags with
10010           | None -> doc
10011           | Some txt -> doc ^ "\n\n" ^ txt in
10012         let doc = pod2text ~width:60 name doc in
10013         let doc = List.map (            (* RHBZ#501883 *)
10014           function
10015           | "" -> "<p>"
10016           | nonempty -> nonempty
10017         ) doc in
10018         let doc = String.concat "\n   * " doc in
10019
10020         pr "  /**\n";
10021         pr "   * %s\n" shortdesc;
10022         pr "   * <p>\n";
10023         pr "   * %s\n" doc;
10024         pr "   * @throws LibGuestFSException\n";
10025         pr "   */\n";
10026         pr "  ";
10027       );
10028       generate_java_prototype ~public:true ~semicolon:false name style;
10029       pr "\n";
10030       pr "  {\n";
10031       pr "    if (g == 0)\n";
10032       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10033         name;
10034       pr "    ";
10035       if fst style <> RErr then pr "return ";
10036       pr "_%s " name;
10037       generate_java_call_args ~handle:"g" (snd style);
10038       pr ";\n";
10039       pr "  }\n";
10040       pr "  ";
10041       generate_java_prototype ~privat:true ~native:true name style;
10042       pr "\n";
10043       pr "\n";
10044   ) all_functions;
10045
10046   pr "}\n"
10047
10048 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10049 and generate_java_call_args ~handle args =
10050   pr "(%s" handle;
10051   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10052   pr ")"
10053
10054 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10055     ?(semicolon=true) name style =
10056   if privat then pr "private ";
10057   if public then pr "public ";
10058   if native then pr "native ";
10059
10060   (* return type *)
10061   (match fst style with
10062    | RErr -> pr "void ";
10063    | RInt _ -> pr "int ";
10064    | RInt64 _ -> pr "long ";
10065    | RBool _ -> pr "boolean ";
10066    | RConstString _ | RConstOptString _ | RString _
10067    | RBufferOut _ -> pr "String ";
10068    | RStringList _ -> pr "String[] ";
10069    | RStruct (_, typ) ->
10070        let name = java_name_of_struct typ in
10071        pr "%s " name;
10072    | RStructList (_, typ) ->
10073        let name = java_name_of_struct typ in
10074        pr "%s[] " name;
10075    | RHashtable _ -> pr "HashMap<String,String> ";
10076   );
10077
10078   if native then pr "_%s " name else pr "%s " name;
10079   pr "(";
10080   let needs_comma = ref false in
10081   if native then (
10082     pr "long g";
10083     needs_comma := true
10084   );
10085
10086   (* args *)
10087   List.iter (
10088     fun arg ->
10089       if !needs_comma then pr ", ";
10090       needs_comma := true;
10091
10092       match arg with
10093       | Pathname n
10094       | Device n | Dev_or_Path n
10095       | String n
10096       | OptString n
10097       | FileIn n
10098       | FileOut n ->
10099           pr "String %s" n
10100       | BufferIn n ->
10101           pr "byte[] %s" n
10102       | StringList n | DeviceList n ->
10103           pr "String[] %s" n
10104       | Bool n ->
10105           pr "boolean %s" n
10106       | Int n ->
10107           pr "int %s" n
10108       | Int64 n ->
10109           pr "long %s" n
10110   ) (snd style);
10111
10112   pr ")\n";
10113   pr "    throws LibGuestFSException";
10114   if semicolon then pr ";"
10115
10116 and generate_java_struct jtyp cols () =
10117   generate_header CStyle LGPLv2plus;
10118
10119   pr "\
10120 package com.redhat.et.libguestfs;
10121
10122 /**
10123  * Libguestfs %s structure.
10124  *
10125  * @author rjones
10126  * @see GuestFS
10127  */
10128 public class %s {
10129 " jtyp jtyp;
10130
10131   List.iter (
10132     function
10133     | name, FString
10134     | name, FUUID
10135     | name, FBuffer -> pr "  public String %s;\n" name
10136     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10137     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10138     | name, FChar -> pr "  public char %s;\n" name
10139     | name, FOptPercent ->
10140         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10141         pr "  public float %s;\n" name
10142   ) cols;
10143
10144   pr "}\n"
10145
10146 and generate_java_c () =
10147   generate_header CStyle LGPLv2plus;
10148
10149   pr "\
10150 #include <stdio.h>
10151 #include <stdlib.h>
10152 #include <string.h>
10153
10154 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10155 #include \"guestfs.h\"
10156
10157 /* Note that this function returns.  The exception is not thrown
10158  * until after the wrapper function returns.
10159  */
10160 static void
10161 throw_exception (JNIEnv *env, const char *msg)
10162 {
10163   jclass cl;
10164   cl = (*env)->FindClass (env,
10165                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10166   (*env)->ThrowNew (env, cl, msg);
10167 }
10168
10169 JNIEXPORT jlong JNICALL
10170 Java_com_redhat_et_libguestfs_GuestFS__1create
10171   (JNIEnv *env, jobject obj)
10172 {
10173   guestfs_h *g;
10174
10175   g = guestfs_create ();
10176   if (g == NULL) {
10177     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10178     return 0;
10179   }
10180   guestfs_set_error_handler (g, NULL, NULL);
10181   return (jlong) (long) g;
10182 }
10183
10184 JNIEXPORT void JNICALL
10185 Java_com_redhat_et_libguestfs_GuestFS__1close
10186   (JNIEnv *env, jobject obj, jlong jg)
10187 {
10188   guestfs_h *g = (guestfs_h *) (long) jg;
10189   guestfs_close (g);
10190 }
10191
10192 ";
10193
10194   List.iter (
10195     fun (name, style, _, _, _, _, _) ->
10196       pr "JNIEXPORT ";
10197       (match fst style with
10198        | RErr -> pr "void ";
10199        | RInt _ -> pr "jint ";
10200        | RInt64 _ -> pr "jlong ";
10201        | RBool _ -> pr "jboolean ";
10202        | RConstString _ | RConstOptString _ | RString _
10203        | RBufferOut _ -> pr "jstring ";
10204        | RStruct _ | RHashtable _ ->
10205            pr "jobject ";
10206        | RStringList _ | RStructList _ ->
10207            pr "jobjectArray ";
10208       );
10209       pr "JNICALL\n";
10210       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10211       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10212       pr "\n";
10213       pr "  (JNIEnv *env, jobject obj, jlong jg";
10214       List.iter (
10215         function
10216         | Pathname n
10217         | Device n | Dev_or_Path n
10218         | String n
10219         | OptString n
10220         | FileIn n
10221         | FileOut n ->
10222             pr ", jstring j%s" n
10223         | BufferIn n ->
10224             pr ", jbyteArray j%s" n
10225         | StringList n | DeviceList n ->
10226             pr ", jobjectArray j%s" n
10227         | Bool n ->
10228             pr ", jboolean j%s" n
10229         | Int n ->
10230             pr ", jint j%s" n
10231         | Int64 n ->
10232             pr ", jlong j%s" n
10233       ) (snd style);
10234       pr ")\n";
10235       pr "{\n";
10236       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10237       let error_code, no_ret =
10238         match fst style with
10239         | RErr -> pr "  int r;\n"; "-1", ""
10240         | RBool _
10241         | RInt _ -> pr "  int r;\n"; "-1", "0"
10242         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10243         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10244         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10245         | RString _ ->
10246             pr "  jstring jr;\n";
10247             pr "  char *r;\n"; "NULL", "NULL"
10248         | RStringList _ ->
10249             pr "  jobjectArray jr;\n";
10250             pr "  int r_len;\n";
10251             pr "  jclass cl;\n";
10252             pr "  jstring jstr;\n";
10253             pr "  char **r;\n"; "NULL", "NULL"
10254         | RStruct (_, typ) ->
10255             pr "  jobject jr;\n";
10256             pr "  jclass cl;\n";
10257             pr "  jfieldID fl;\n";
10258             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10259         | RStructList (_, typ) ->
10260             pr "  jobjectArray jr;\n";
10261             pr "  jclass cl;\n";
10262             pr "  jfieldID fl;\n";
10263             pr "  jobject jfl;\n";
10264             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10265         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10266         | RBufferOut _ ->
10267             pr "  jstring jr;\n";
10268             pr "  char *r;\n";
10269             pr "  size_t size;\n";
10270             "NULL", "NULL" in
10271       List.iter (
10272         function
10273         | Pathname n
10274         | Device n | Dev_or_Path n
10275         | String n
10276         | OptString n
10277         | FileIn n
10278         | FileOut n ->
10279             pr "  const char *%s;\n" n
10280         | BufferIn n ->
10281             pr "  jbyte *%s;\n" n;
10282             pr "  size_t %s_size;\n" n
10283         | StringList n | DeviceList n ->
10284             pr "  int %s_len;\n" n;
10285             pr "  const char **%s;\n" n
10286         | Bool n
10287         | Int n ->
10288             pr "  int %s;\n" n
10289         | Int64 n ->
10290             pr "  int64_t %s;\n" n
10291       ) (snd style);
10292
10293       let needs_i =
10294         (match fst style with
10295          | RStringList _ | RStructList _ -> true
10296          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10297          | RConstOptString _
10298          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10299           List.exists (function
10300                        | StringList _ -> true
10301                        | DeviceList _ -> true
10302                        | _ -> false) (snd style) in
10303       if needs_i then
10304         pr "  int i;\n";
10305
10306       pr "\n";
10307
10308       (* Get the parameters. *)
10309       List.iter (
10310         function
10311         | Pathname n
10312         | Device n | Dev_or_Path n
10313         | String n
10314         | FileIn n
10315         | FileOut n ->
10316             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10317         | OptString n ->
10318             (* This is completely undocumented, but Java null becomes
10319              * a NULL parameter.
10320              *)
10321             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10322         | BufferIn n ->
10323             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10324             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10325         | StringList n | DeviceList n ->
10326             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10327             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10328             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10329             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10330               n;
10331             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10332             pr "  }\n";
10333             pr "  %s[%s_len] = NULL;\n" n n;
10334         | Bool n
10335         | Int n
10336         | Int64 n ->
10337             pr "  %s = j%s;\n" n n
10338       ) (snd style);
10339
10340       (* Make the call. *)
10341       pr "  r = guestfs_%s " name;
10342       generate_c_call_args ~handle:"g" style;
10343       pr ";\n";
10344
10345       (* Release the parameters. *)
10346       List.iter (
10347         function
10348         | Pathname n
10349         | Device n | Dev_or_Path n
10350         | String n
10351         | FileIn n
10352         | FileOut n ->
10353             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10354         | OptString n ->
10355             pr "  if (j%s)\n" n;
10356             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10357         | BufferIn n ->
10358             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10359         | StringList n | DeviceList n ->
10360             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10361             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10362               n;
10363             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10364             pr "  }\n";
10365             pr "  free (%s);\n" n
10366         | Bool n
10367         | Int n
10368         | Int64 n -> ()
10369       ) (snd style);
10370
10371       (* Check for errors. *)
10372       pr "  if (r == %s) {\n" error_code;
10373       pr "    throw_exception (env, guestfs_last_error (g));\n";
10374       pr "    return %s;\n" no_ret;
10375       pr "  }\n";
10376
10377       (* Return value. *)
10378       (match fst style with
10379        | RErr -> ()
10380        | RInt _ -> pr "  return (jint) r;\n"
10381        | RBool _ -> pr "  return (jboolean) r;\n"
10382        | RInt64 _ -> pr "  return (jlong) r;\n"
10383        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10384        | RConstOptString _ ->
10385            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10386        | RString _ ->
10387            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10388            pr "  free (r);\n";
10389            pr "  return jr;\n"
10390        | RStringList _ ->
10391            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10392            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10393            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10394            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10395            pr "  for (i = 0; i < r_len; ++i) {\n";
10396            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10397            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10398            pr "    free (r[i]);\n";
10399            pr "  }\n";
10400            pr "  free (r);\n";
10401            pr "  return jr;\n"
10402        | RStruct (_, typ) ->
10403            let jtyp = java_name_of_struct typ in
10404            let cols = cols_of_struct typ in
10405            generate_java_struct_return typ jtyp cols
10406        | RStructList (_, typ) ->
10407            let jtyp = java_name_of_struct typ in
10408            let cols = cols_of_struct typ in
10409            generate_java_struct_list_return typ jtyp cols
10410        | RHashtable _ ->
10411            (* XXX *)
10412            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10413            pr "  return NULL;\n"
10414        | RBufferOut _ ->
10415            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10416            pr "  free (r);\n";
10417            pr "  return jr;\n"
10418       );
10419
10420       pr "}\n";
10421       pr "\n"
10422   ) all_functions
10423
10424 and generate_java_struct_return typ jtyp cols =
10425   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10426   pr "  jr = (*env)->AllocObject (env, cl);\n";
10427   List.iter (
10428     function
10429     | name, FString ->
10430         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10431         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10432     | name, FUUID ->
10433         pr "  {\n";
10434         pr "    char s[33];\n";
10435         pr "    memcpy (s, r->%s, 32);\n" name;
10436         pr "    s[32] = 0;\n";
10437         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10438         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10439         pr "  }\n";
10440     | name, FBuffer ->
10441         pr "  {\n";
10442         pr "    int len = r->%s_len;\n" name;
10443         pr "    char s[len+1];\n";
10444         pr "    memcpy (s, r->%s, len);\n" name;
10445         pr "    s[len] = 0;\n";
10446         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10447         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10448         pr "  }\n";
10449     | name, (FBytes|FUInt64|FInt64) ->
10450         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10451         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10452     | name, (FUInt32|FInt32) ->
10453         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10454         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10455     | name, FOptPercent ->
10456         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10457         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10458     | name, FChar ->
10459         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10460         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10461   ) cols;
10462   pr "  free (r);\n";
10463   pr "  return jr;\n"
10464
10465 and generate_java_struct_list_return typ jtyp cols =
10466   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10467   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10468   pr "  for (i = 0; i < r->len; ++i) {\n";
10469   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10470   List.iter (
10471     function
10472     | name, FString ->
10473         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10474         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10475     | name, FUUID ->
10476         pr "    {\n";
10477         pr "      char s[33];\n";
10478         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10479         pr "      s[32] = 0;\n";
10480         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10481         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10482         pr "    }\n";
10483     | name, FBuffer ->
10484         pr "    {\n";
10485         pr "      int len = r->val[i].%s_len;\n" name;
10486         pr "      char s[len+1];\n";
10487         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10488         pr "      s[len] = 0;\n";
10489         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10490         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10491         pr "    }\n";
10492     | name, (FBytes|FUInt64|FInt64) ->
10493         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10494         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10495     | name, (FUInt32|FInt32) ->
10496         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10497         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10498     | name, FOptPercent ->
10499         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10500         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10501     | name, FChar ->
10502         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10503         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10504   ) cols;
10505   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10506   pr "  }\n";
10507   pr "  guestfs_free_%s_list (r);\n" typ;
10508   pr "  return jr;\n"
10509
10510 and generate_java_makefile_inc () =
10511   generate_header HashStyle GPLv2plus;
10512
10513   pr "java_built_sources = \\\n";
10514   List.iter (
10515     fun (typ, jtyp) ->
10516         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10517   ) java_structs;
10518   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10519
10520 and generate_haskell_hs () =
10521   generate_header HaskellStyle LGPLv2plus;
10522
10523   (* XXX We only know how to generate partial FFI for Haskell
10524    * at the moment.  Please help out!
10525    *)
10526   let can_generate style =
10527     match style with
10528     | RErr, _
10529     | RInt _, _
10530     | RInt64 _, _ -> true
10531     | RBool _, _
10532     | RConstString _, _
10533     | RConstOptString _, _
10534     | RString _, _
10535     | RStringList _, _
10536     | RStruct _, _
10537     | RStructList _, _
10538     | RHashtable _, _
10539     | RBufferOut _, _ -> false in
10540
10541   pr "\
10542 {-# INCLUDE <guestfs.h> #-}
10543 {-# LANGUAGE ForeignFunctionInterface #-}
10544
10545 module Guestfs (
10546   create";
10547
10548   (* List out the names of the actions we want to export. *)
10549   List.iter (
10550     fun (name, style, _, _, _, _, _) ->
10551       if can_generate style then pr ",\n  %s" name
10552   ) all_functions;
10553
10554   pr "
10555   ) where
10556
10557 -- Unfortunately some symbols duplicate ones already present
10558 -- in Prelude.  We don't know which, so we hard-code a list
10559 -- here.
10560 import Prelude hiding (truncate)
10561
10562 import Foreign
10563 import Foreign.C
10564 import Foreign.C.Types
10565 import IO
10566 import Control.Exception
10567 import Data.Typeable
10568
10569 data GuestfsS = GuestfsS            -- represents the opaque C struct
10570 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10571 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10572
10573 -- XXX define properly later XXX
10574 data PV = PV
10575 data VG = VG
10576 data LV = LV
10577 data IntBool = IntBool
10578 data Stat = Stat
10579 data StatVFS = StatVFS
10580 data Hashtable = Hashtable
10581
10582 foreign import ccall unsafe \"guestfs_create\" c_create
10583   :: IO GuestfsP
10584 foreign import ccall unsafe \"&guestfs_close\" c_close
10585   :: FunPtr (GuestfsP -> IO ())
10586 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10587   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10588
10589 create :: IO GuestfsH
10590 create = do
10591   p <- c_create
10592   c_set_error_handler p nullPtr nullPtr
10593   h <- newForeignPtr c_close p
10594   return h
10595
10596 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10597   :: GuestfsP -> IO CString
10598
10599 -- last_error :: GuestfsH -> IO (Maybe String)
10600 -- last_error h = do
10601 --   str <- withForeignPtr h (\\p -> c_last_error p)
10602 --   maybePeek peekCString str
10603
10604 last_error :: GuestfsH -> IO (String)
10605 last_error h = do
10606   str <- withForeignPtr h (\\p -> c_last_error p)
10607   if (str == nullPtr)
10608     then return \"no error\"
10609     else peekCString str
10610
10611 ";
10612
10613   (* Generate wrappers for each foreign function. *)
10614   List.iter (
10615     fun (name, style, _, _, _, _, _) ->
10616       if can_generate style then (
10617         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10618         pr "  :: ";
10619         generate_haskell_prototype ~handle:"GuestfsP" style;
10620         pr "\n";
10621         pr "\n";
10622         pr "%s :: " name;
10623         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10624         pr "\n";
10625         pr "%s %s = do\n" name
10626           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10627         pr "  r <- ";
10628         (* Convert pointer arguments using with* functions. *)
10629         List.iter (
10630           function
10631           | FileIn n
10632           | FileOut n
10633           | Pathname n | Device n | Dev_or_Path n | String n ->
10634               pr "withCString %s $ \\%s -> " n n
10635           | BufferIn n ->
10636               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10637           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10638           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10639           | Bool _ | Int _ | Int64 _ -> ()
10640         ) (snd style);
10641         (* Convert integer arguments. *)
10642         let args =
10643           List.map (
10644             function
10645             | Bool n -> sprintf "(fromBool %s)" n
10646             | Int n -> sprintf "(fromIntegral %s)" n
10647             | Int64 n -> sprintf "(fromIntegral %s)" n
10648             | FileIn n | FileOut n
10649             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10650             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10651           ) (snd style) in
10652         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10653           (String.concat " " ("p" :: args));
10654         (match fst style with
10655          | RErr | RInt _ | RInt64 _ | RBool _ ->
10656              pr "  if (r == -1)\n";
10657              pr "    then do\n";
10658              pr "      err <- last_error h\n";
10659              pr "      fail err\n";
10660          | RConstString _ | RConstOptString _ | RString _
10661          | RStringList _ | RStruct _
10662          | RStructList _ | RHashtable _ | RBufferOut _ ->
10663              pr "  if (r == nullPtr)\n";
10664              pr "    then do\n";
10665              pr "      err <- last_error h\n";
10666              pr "      fail err\n";
10667         );
10668         (match fst style with
10669          | RErr ->
10670              pr "    else return ()\n"
10671          | RInt _ ->
10672              pr "    else return (fromIntegral r)\n"
10673          | RInt64 _ ->
10674              pr "    else return (fromIntegral r)\n"
10675          | RBool _ ->
10676              pr "    else return (toBool r)\n"
10677          | RConstString _
10678          | RConstOptString _
10679          | RString _
10680          | RStringList _
10681          | RStruct _
10682          | RStructList _
10683          | RHashtable _
10684          | RBufferOut _ ->
10685              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10686         );
10687         pr "\n";
10688       )
10689   ) all_functions
10690
10691 and generate_haskell_prototype ~handle ?(hs = false) style =
10692   pr "%s -> " handle;
10693   let string = if hs then "String" else "CString" in
10694   let int = if hs then "Int" else "CInt" in
10695   let bool = if hs then "Bool" else "CInt" in
10696   let int64 = if hs then "Integer" else "Int64" in
10697   List.iter (
10698     fun arg ->
10699       (match arg with
10700        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10701        | BufferIn _ ->
10702            if hs then pr "String"
10703            else pr "CString -> CInt"
10704        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10705        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10706        | Bool _ -> pr "%s" bool
10707        | Int _ -> pr "%s" int
10708        | Int64 _ -> pr "%s" int
10709        | FileIn _ -> pr "%s" string
10710        | FileOut _ -> pr "%s" string
10711       );
10712       pr " -> ";
10713   ) (snd style);
10714   pr "IO (";
10715   (match fst style with
10716    | RErr -> if not hs then pr "CInt"
10717    | RInt _ -> pr "%s" int
10718    | RInt64 _ -> pr "%s" int64
10719    | RBool _ -> pr "%s" bool
10720    | RConstString _ -> pr "%s" string
10721    | RConstOptString _ -> pr "Maybe %s" string
10722    | RString _ -> pr "%s" string
10723    | RStringList _ -> pr "[%s]" string
10724    | RStruct (_, typ) ->
10725        let name = java_name_of_struct typ in
10726        pr "%s" name
10727    | RStructList (_, typ) ->
10728        let name = java_name_of_struct typ in
10729        pr "[%s]" name
10730    | RHashtable _ -> pr "Hashtable"
10731    | RBufferOut _ -> pr "%s" string
10732   );
10733   pr ")"
10734
10735 and generate_csharp () =
10736   generate_header CPlusPlusStyle LGPLv2plus;
10737
10738   (* XXX Make this configurable by the C# assembly users. *)
10739   let library = "libguestfs.so.0" in
10740
10741   pr "\
10742 // These C# bindings are highly experimental at present.
10743 //
10744 // Firstly they only work on Linux (ie. Mono).  In order to get them
10745 // to work on Windows (ie. .Net) you would need to port the library
10746 // itself to Windows first.
10747 //
10748 // The second issue is that some calls are known to be incorrect and
10749 // can cause Mono to segfault.  Particularly: calls which pass or
10750 // return string[], or return any structure value.  This is because
10751 // we haven't worked out the correct way to do this from C#.
10752 //
10753 // The third issue is that when compiling you get a lot of warnings.
10754 // We are not sure whether the warnings are important or not.
10755 //
10756 // Fourthly we do not routinely build or test these bindings as part
10757 // of the make && make check cycle, which means that regressions might
10758 // go unnoticed.
10759 //
10760 // Suggestions and patches are welcome.
10761
10762 // To compile:
10763 //
10764 // gmcs Libguestfs.cs
10765 // mono Libguestfs.exe
10766 //
10767 // (You'll probably want to add a Test class / static main function
10768 // otherwise this won't do anything useful).
10769
10770 using System;
10771 using System.IO;
10772 using System.Runtime.InteropServices;
10773 using System.Runtime.Serialization;
10774 using System.Collections;
10775
10776 namespace Guestfs
10777 {
10778   class Error : System.ApplicationException
10779   {
10780     public Error (string message) : base (message) {}
10781     protected Error (SerializationInfo info, StreamingContext context) {}
10782   }
10783
10784   class Guestfs
10785   {
10786     IntPtr _handle;
10787
10788     [DllImport (\"%s\")]
10789     static extern IntPtr guestfs_create ();
10790
10791     public Guestfs ()
10792     {
10793       _handle = guestfs_create ();
10794       if (_handle == IntPtr.Zero)
10795         throw new Error (\"could not create guestfs handle\");
10796     }
10797
10798     [DllImport (\"%s\")]
10799     static extern void guestfs_close (IntPtr h);
10800
10801     ~Guestfs ()
10802     {
10803       guestfs_close (_handle);
10804     }
10805
10806     [DllImport (\"%s\")]
10807     static extern string guestfs_last_error (IntPtr h);
10808
10809 " library library library;
10810
10811   (* Generate C# structure bindings.  We prefix struct names with
10812    * underscore because C# cannot have conflicting struct names and
10813    * method names (eg. "class stat" and "stat").
10814    *)
10815   List.iter (
10816     fun (typ, cols) ->
10817       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10818       pr "    public class _%s {\n" typ;
10819       List.iter (
10820         function
10821         | name, FChar -> pr "      char %s;\n" name
10822         | name, FString -> pr "      string %s;\n" name
10823         | name, FBuffer ->
10824             pr "      uint %s_len;\n" name;
10825             pr "      string %s;\n" name
10826         | name, FUUID ->
10827             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10828             pr "      string %s;\n" name
10829         | name, FUInt32 -> pr "      uint %s;\n" name
10830         | name, FInt32 -> pr "      int %s;\n" name
10831         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10832         | name, FInt64 -> pr "      long %s;\n" name
10833         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10834       ) cols;
10835       pr "    }\n";
10836       pr "\n"
10837   ) structs;
10838
10839   (* Generate C# function bindings. *)
10840   List.iter (
10841     fun (name, style, _, _, _, shortdesc, _) ->
10842       let rec csharp_return_type () =
10843         match fst style with
10844         | RErr -> "void"
10845         | RBool n -> "bool"
10846         | RInt n -> "int"
10847         | RInt64 n -> "long"
10848         | RConstString n
10849         | RConstOptString n
10850         | RString n
10851         | RBufferOut n -> "string"
10852         | RStruct (_,n) -> "_" ^ n
10853         | RHashtable n -> "Hashtable"
10854         | RStringList n -> "string[]"
10855         | RStructList (_,n) -> sprintf "_%s[]" n
10856
10857       and c_return_type () =
10858         match fst style with
10859         | RErr
10860         | RBool _
10861         | RInt _ -> "int"
10862         | RInt64 _ -> "long"
10863         | RConstString _
10864         | RConstOptString _
10865         | RString _
10866         | RBufferOut _ -> "string"
10867         | RStruct (_,n) -> "_" ^ n
10868         | RHashtable _
10869         | RStringList _ -> "string[]"
10870         | RStructList (_,n) -> sprintf "_%s[]" n
10871
10872       and c_error_comparison () =
10873         match fst style with
10874         | RErr
10875         | RBool _
10876         | RInt _
10877         | RInt64 _ -> "== -1"
10878         | RConstString _
10879         | RConstOptString _
10880         | RString _
10881         | RBufferOut _
10882         | RStruct (_,_)
10883         | RHashtable _
10884         | RStringList _
10885         | RStructList (_,_) -> "== null"
10886
10887       and generate_extern_prototype () =
10888         pr "    static extern %s guestfs_%s (IntPtr h"
10889           (c_return_type ()) name;
10890         List.iter (
10891           function
10892           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10893           | FileIn n | FileOut n
10894           | BufferIn n ->
10895               pr ", [In] string %s" n
10896           | StringList n | DeviceList n ->
10897               pr ", [In] string[] %s" n
10898           | Bool n ->
10899               pr ", bool %s" n
10900           | Int n ->
10901               pr ", int %s" n
10902           | Int64 n ->
10903               pr ", long %s" n
10904         ) (snd style);
10905         pr ");\n"
10906
10907       and generate_public_prototype () =
10908         pr "    public %s %s (" (csharp_return_type ()) name;
10909         let comma = ref false in
10910         let next () =
10911           if !comma then pr ", ";
10912           comma := true
10913         in
10914         List.iter (
10915           function
10916           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10917           | FileIn n | FileOut n
10918           | BufferIn n ->
10919               next (); pr "string %s" n
10920           | StringList n | DeviceList n ->
10921               next (); pr "string[] %s" n
10922           | Bool n ->
10923               next (); pr "bool %s" n
10924           | Int n ->
10925               next (); pr "int %s" n
10926           | Int64 n ->
10927               next (); pr "long %s" n
10928         ) (snd style);
10929         pr ")\n"
10930
10931       and generate_call () =
10932         pr "guestfs_%s (_handle" name;
10933         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10934         pr ");\n";
10935       in
10936
10937       pr "    [DllImport (\"%s\")]\n" library;
10938       generate_extern_prototype ();
10939       pr "\n";
10940       pr "    /// <summary>\n";
10941       pr "    /// %s\n" shortdesc;
10942       pr "    /// </summary>\n";
10943       generate_public_prototype ();
10944       pr "    {\n";
10945       pr "      %s r;\n" (c_return_type ());
10946       pr "      r = ";
10947       generate_call ();
10948       pr "      if (r %s)\n" (c_error_comparison ());
10949       pr "        throw new Error (guestfs_last_error (_handle));\n";
10950       (match fst style with
10951        | RErr -> ()
10952        | RBool _ ->
10953            pr "      return r != 0 ? true : false;\n"
10954        | RHashtable _ ->
10955            pr "      Hashtable rr = new Hashtable ();\n";
10956            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10957            pr "        rr.Add (r[i], r[i+1]);\n";
10958            pr "      return rr;\n"
10959        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10960        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10961        | RStructList _ ->
10962            pr "      return r;\n"
10963       );
10964       pr "    }\n";
10965       pr "\n";
10966   ) all_functions_sorted;
10967
10968   pr "  }
10969 }
10970 "
10971
10972 and generate_bindtests () =
10973   generate_header CStyle LGPLv2plus;
10974
10975   pr "\
10976 #include <stdio.h>
10977 #include <stdlib.h>
10978 #include <inttypes.h>
10979 #include <string.h>
10980
10981 #include \"guestfs.h\"
10982 #include \"guestfs-internal.h\"
10983 #include \"guestfs-internal-actions.h\"
10984 #include \"guestfs_protocol.h\"
10985
10986 #define error guestfs_error
10987 #define safe_calloc guestfs_safe_calloc
10988 #define safe_malloc guestfs_safe_malloc
10989
10990 static void
10991 print_strings (char *const *argv)
10992 {
10993   int argc;
10994
10995   printf (\"[\");
10996   for (argc = 0; argv[argc] != NULL; ++argc) {
10997     if (argc > 0) printf (\", \");
10998     printf (\"\\\"%%s\\\"\", argv[argc]);
10999   }
11000   printf (\"]\\n\");
11001 }
11002
11003 /* The test0 function prints its parameters to stdout. */
11004 ";
11005
11006   let test0, tests =
11007     match test_functions with
11008     | [] -> assert false
11009     | test0 :: tests -> test0, tests in
11010
11011   let () =
11012     let (name, style, _, _, _, _, _) = test0 in
11013     generate_prototype ~extern:false ~semicolon:false ~newline:true
11014       ~handle:"g" ~prefix:"guestfs__" name style;
11015     pr "{\n";
11016     List.iter (
11017       function
11018       | Pathname n
11019       | Device n | Dev_or_Path n
11020       | String n
11021       | FileIn n
11022       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11023       | BufferIn n ->
11024           pr "  for (size_t i = 0; i < %s_size; ++i)\n" n;
11025           pr "    printf (\"<%%02x>\", %s[i]);\n" n;
11026           pr "  printf (\"\\n\");\n"
11027       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11028       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11029       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11030       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11031       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11032     ) (snd style);
11033     pr "  /* Java changes stdout line buffering so we need this: */\n";
11034     pr "  fflush (stdout);\n";
11035     pr "  return 0;\n";
11036     pr "}\n";
11037     pr "\n" in
11038
11039   List.iter (
11040     fun (name, style, _, _, _, _, _) ->
11041       if String.sub name (String.length name - 3) 3 <> "err" then (
11042         pr "/* Test normal return. */\n";
11043         generate_prototype ~extern:false ~semicolon:false ~newline:true
11044           ~handle:"g" ~prefix:"guestfs__" name style;
11045         pr "{\n";
11046         (match fst style with
11047          | RErr ->
11048              pr "  return 0;\n"
11049          | RInt _ ->
11050              pr "  int r;\n";
11051              pr "  sscanf (val, \"%%d\", &r);\n";
11052              pr "  return r;\n"
11053          | RInt64 _ ->
11054              pr "  int64_t r;\n";
11055              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11056              pr "  return r;\n"
11057          | RBool _ ->
11058              pr "  return STREQ (val, \"true\");\n"
11059          | RConstString _
11060          | RConstOptString _ ->
11061              (* Can't return the input string here.  Return a static
11062               * string so we ensure we get a segfault if the caller
11063               * tries to free it.
11064               *)
11065              pr "  return \"static string\";\n"
11066          | RString _ ->
11067              pr "  return strdup (val);\n"
11068          | RStringList _ ->
11069              pr "  char **strs;\n";
11070              pr "  int n, i;\n";
11071              pr "  sscanf (val, \"%%d\", &n);\n";
11072              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11073              pr "  for (i = 0; i < n; ++i) {\n";
11074              pr "    strs[i] = safe_malloc (g, 16);\n";
11075              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11076              pr "  }\n";
11077              pr "  strs[n] = NULL;\n";
11078              pr "  return strs;\n"
11079          | RStruct (_, typ) ->
11080              pr "  struct guestfs_%s *r;\n" typ;
11081              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11082              pr "  return r;\n"
11083          | RStructList (_, typ) ->
11084              pr "  struct guestfs_%s_list *r;\n" typ;
11085              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11086              pr "  sscanf (val, \"%%d\", &r->len);\n";
11087              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11088              pr "  return r;\n"
11089          | RHashtable _ ->
11090              pr "  char **strs;\n";
11091              pr "  int n, i;\n";
11092              pr "  sscanf (val, \"%%d\", &n);\n";
11093              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11094              pr "  for (i = 0; i < n; ++i) {\n";
11095              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11096              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11097              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11098              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11099              pr "  }\n";
11100              pr "  strs[n*2] = NULL;\n";
11101              pr "  return strs;\n"
11102          | RBufferOut _ ->
11103              pr "  return strdup (val);\n"
11104         );
11105         pr "}\n";
11106         pr "\n"
11107       ) else (
11108         pr "/* Test error return. */\n";
11109         generate_prototype ~extern:false ~semicolon:false ~newline:true
11110           ~handle:"g" ~prefix:"guestfs__" name style;
11111         pr "{\n";
11112         pr "  error (g, \"error\");\n";
11113         (match fst style with
11114          | RErr | RInt _ | RInt64 _ | RBool _ ->
11115              pr "  return -1;\n"
11116          | RConstString _ | RConstOptString _
11117          | RString _ | RStringList _ | RStruct _
11118          | RStructList _
11119          | RHashtable _
11120          | RBufferOut _ ->
11121              pr "  return NULL;\n"
11122         );
11123         pr "}\n";
11124         pr "\n"
11125       )
11126   ) tests
11127
11128 and generate_ocaml_bindtests () =
11129   generate_header OCamlStyle GPLv2plus;
11130
11131   pr "\
11132 let () =
11133   let g = Guestfs.create () in
11134 ";
11135
11136   let mkargs args =
11137     String.concat " " (
11138       List.map (
11139         function
11140         | CallString s -> "\"" ^ s ^ "\""
11141         | CallOptString None -> "None"
11142         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11143         | CallStringList xs ->
11144             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11145         | CallInt i when i >= 0 -> string_of_int i
11146         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11147         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11148         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11149         | CallBool b -> string_of_bool b
11150         | CallBuffer s -> sprintf "%S" s
11151       ) args
11152     )
11153   in
11154
11155   generate_lang_bindtests (
11156     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11157   );
11158
11159   pr "print_endline \"EOF\"\n"
11160
11161 and generate_perl_bindtests () =
11162   pr "#!/usr/bin/perl -w\n";
11163   generate_header HashStyle GPLv2plus;
11164
11165   pr "\
11166 use strict;
11167
11168 use Sys::Guestfs;
11169
11170 my $g = Sys::Guestfs->new ();
11171 ";
11172
11173   let mkargs args =
11174     String.concat ", " (
11175       List.map (
11176         function
11177         | CallString s -> "\"" ^ s ^ "\""
11178         | CallOptString None -> "undef"
11179         | CallOptString (Some s) -> sprintf "\"%s\"" s
11180         | CallStringList xs ->
11181             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11182         | CallInt i -> string_of_int i
11183         | CallInt64 i -> Int64.to_string i
11184         | CallBool b -> if b then "1" else "0"
11185         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11186       ) args
11187     )
11188   in
11189
11190   generate_lang_bindtests (
11191     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11192   );
11193
11194   pr "print \"EOF\\n\"\n"
11195
11196 and generate_python_bindtests () =
11197   generate_header HashStyle GPLv2plus;
11198
11199   pr "\
11200 import guestfs
11201
11202 g = guestfs.GuestFS ()
11203 ";
11204
11205   let mkargs args =
11206     String.concat ", " (
11207       List.map (
11208         function
11209         | CallString s -> "\"" ^ s ^ "\""
11210         | CallOptString None -> "None"
11211         | CallOptString (Some s) -> sprintf "\"%s\"" s
11212         | CallStringList xs ->
11213             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11214         | CallInt i -> string_of_int i
11215         | CallInt64 i -> Int64.to_string i
11216         | CallBool b -> if b then "1" else "0"
11217         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11218       ) args
11219     )
11220   in
11221
11222   generate_lang_bindtests (
11223     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11224   );
11225
11226   pr "print \"EOF\"\n"
11227
11228 and generate_ruby_bindtests () =
11229   generate_header HashStyle GPLv2plus;
11230
11231   pr "\
11232 require 'guestfs'
11233
11234 g = Guestfs::create()
11235 ";
11236
11237   let mkargs args =
11238     String.concat ", " (
11239       List.map (
11240         function
11241         | CallString s -> "\"" ^ s ^ "\""
11242         | CallOptString None -> "nil"
11243         | CallOptString (Some s) -> sprintf "\"%s\"" s
11244         | CallStringList xs ->
11245             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11246         | CallInt i -> string_of_int i
11247         | CallInt64 i -> Int64.to_string i
11248         | CallBool b -> string_of_bool b
11249         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11250       ) args
11251     )
11252   in
11253
11254   generate_lang_bindtests (
11255     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11256   );
11257
11258   pr "print \"EOF\\n\"\n"
11259
11260 and generate_java_bindtests () =
11261   generate_header CStyle GPLv2plus;
11262
11263   pr "\
11264 import com.redhat.et.libguestfs.*;
11265
11266 public class Bindtests {
11267     public static void main (String[] argv)
11268     {
11269         try {
11270             GuestFS g = new GuestFS ();
11271 ";
11272
11273   let mkargs args =
11274     String.concat ", " (
11275       List.map (
11276         function
11277         | CallString s -> "\"" ^ s ^ "\""
11278         | CallOptString None -> "null"
11279         | CallOptString (Some s) -> sprintf "\"%s\"" s
11280         | CallStringList xs ->
11281             "new String[]{" ^
11282               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11283         | CallInt i -> string_of_int i
11284         | CallInt64 i -> Int64.to_string i
11285         | CallBool b -> string_of_bool b
11286         | CallBuffer s ->
11287             "new byte[] { " ^ String.concat "," (
11288               map_chars (fun c -> string_of_int (Char.code c)) s
11289             ) ^ " }"
11290       ) args
11291     )
11292   in
11293
11294   generate_lang_bindtests (
11295     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11296   );
11297
11298   pr "
11299             System.out.println (\"EOF\");
11300         }
11301         catch (Exception exn) {
11302             System.err.println (exn);
11303             System.exit (1);
11304         }
11305     }
11306 }
11307 "
11308
11309 and generate_haskell_bindtests () =
11310   generate_header HaskellStyle GPLv2plus;
11311
11312   pr "\
11313 module Bindtests where
11314 import qualified Guestfs
11315
11316 main = do
11317   g <- Guestfs.create
11318 ";
11319
11320   let mkargs args =
11321     String.concat " " (
11322       List.map (
11323         function
11324         | CallString s -> "\"" ^ s ^ "\""
11325         | CallOptString None -> "Nothing"
11326         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11327         | CallStringList xs ->
11328             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11329         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11330         | CallInt i -> string_of_int i
11331         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11332         | CallInt64 i -> Int64.to_string i
11333         | CallBool true -> "True"
11334         | CallBool false -> "False"
11335         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11336       ) args
11337     )
11338   in
11339
11340   generate_lang_bindtests (
11341     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11342   );
11343
11344   pr "  putStrLn \"EOF\"\n"
11345
11346 (* Language-independent bindings tests - we do it this way to
11347  * ensure there is parity in testing bindings across all languages.
11348  *)
11349 and generate_lang_bindtests call =
11350   call "test0" [CallString "abc"; CallOptString (Some "def");
11351                 CallStringList []; CallBool false;
11352                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11353                 CallBuffer "abc\000abc"];
11354   call "test0" [CallString "abc"; CallOptString None;
11355                 CallStringList []; CallBool false;
11356                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11357                 CallBuffer "abc\000abc"];
11358   call "test0" [CallString ""; CallOptString (Some "def");
11359                 CallStringList []; CallBool false;
11360                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11361                 CallBuffer "abc\000abc"];
11362   call "test0" [CallString ""; CallOptString (Some "");
11363                 CallStringList []; CallBool false;
11364                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11365                 CallBuffer "abc\000abc"];
11366   call "test0" [CallString "abc"; CallOptString (Some "def");
11367                 CallStringList ["1"]; CallBool false;
11368                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11369                 CallBuffer "abc\000abc"];
11370   call "test0" [CallString "abc"; CallOptString (Some "def");
11371                 CallStringList ["1"; "2"]; CallBool false;
11372                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11373                 CallBuffer "abc\000abc"];
11374   call "test0" [CallString "abc"; CallOptString (Some "def");
11375                 CallStringList ["1"]; CallBool true;
11376                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11377                 CallBuffer "abc\000abc"];
11378   call "test0" [CallString "abc"; CallOptString (Some "def");
11379                 CallStringList ["1"]; CallBool false;
11380                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11381                 CallBuffer "abc\000abc"];
11382   call "test0" [CallString "abc"; CallOptString (Some "def");
11383                 CallStringList ["1"]; CallBool false;
11384                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11385                 CallBuffer "abc\000abc"];
11386   call "test0" [CallString "abc"; CallOptString (Some "def");
11387                 CallStringList ["1"]; CallBool false;
11388                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11389                 CallBuffer "abc\000abc"];
11390   call "test0" [CallString "abc"; CallOptString (Some "def");
11391                 CallStringList ["1"]; CallBool false;
11392                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11393                 CallBuffer "abc\000abc"];
11394   call "test0" [CallString "abc"; CallOptString (Some "def");
11395                 CallStringList ["1"]; CallBool false;
11396                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11397                 CallBuffer "abc\000abc"];
11398   call "test0" [CallString "abc"; CallOptString (Some "def");
11399                 CallStringList ["1"]; CallBool false;
11400                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11401                 CallBuffer "abc\000abc"]
11402
11403 (* XXX Add here tests of the return and error functions. *)
11404
11405 (* Code to generator bindings for virt-inspector.  Currently only
11406  * implemented for OCaml code (for virt-p2v 2.0).
11407  *)
11408 let rng_input = "inspector/virt-inspector.rng"
11409
11410 (* Read the input file and parse it into internal structures.  This is
11411  * by no means a complete RELAX NG parser, but is just enough to be
11412  * able to parse the specific input file.
11413  *)
11414 type rng =
11415   | Element of string * rng list        (* <element name=name/> *)
11416   | Attribute of string * rng list        (* <attribute name=name/> *)
11417   | Interleave of rng list                (* <interleave/> *)
11418   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11419   | OneOrMore of rng                        (* <oneOrMore/> *)
11420   | Optional of rng                        (* <optional/> *)
11421   | Choice of string list                (* <choice><value/>*</choice> *)
11422   | Value of string                        (* <value>str</value> *)
11423   | Text                                (* <text/> *)
11424
11425 let rec string_of_rng = function
11426   | Element (name, xs) ->
11427       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11428   | Attribute (name, xs) ->
11429       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11430   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11431   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11432   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11433   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11434   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11435   | Value value -> "Value \"" ^ value ^ "\""
11436   | Text -> "Text"
11437
11438 and string_of_rng_list xs =
11439   String.concat ", " (List.map string_of_rng xs)
11440
11441 let rec parse_rng ?defines context = function
11442   | [] -> []
11443   | Xml.Element ("element", ["name", name], children) :: rest ->
11444       Element (name, parse_rng ?defines context children)
11445       :: parse_rng ?defines context rest
11446   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11447       Attribute (name, parse_rng ?defines context children)
11448       :: parse_rng ?defines context rest
11449   | Xml.Element ("interleave", [], children) :: rest ->
11450       Interleave (parse_rng ?defines context children)
11451       :: parse_rng ?defines context rest
11452   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11453       let rng = parse_rng ?defines context [child] in
11454       (match rng with
11455        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11456        | _ ->
11457            failwithf "%s: <zeroOrMore> contains more than one child element"
11458              context
11459       )
11460   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11461       let rng = parse_rng ?defines context [child] in
11462       (match rng with
11463        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11464        | _ ->
11465            failwithf "%s: <oneOrMore> contains more than one child element"
11466              context
11467       )
11468   | Xml.Element ("optional", [], [child]) :: rest ->
11469       let rng = parse_rng ?defines context [child] in
11470       (match rng with
11471        | [child] -> Optional child :: parse_rng ?defines context rest
11472        | _ ->
11473            failwithf "%s: <optional> contains more than one child element"
11474              context
11475       )
11476   | Xml.Element ("choice", [], children) :: rest ->
11477       let values = List.map (
11478         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11479         | _ ->
11480             failwithf "%s: can't handle anything except <value> in <choice>"
11481               context
11482       ) children in
11483       Choice values
11484       :: parse_rng ?defines context rest
11485   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11486       Value value :: parse_rng ?defines context rest
11487   | Xml.Element ("text", [], []) :: rest ->
11488       Text :: parse_rng ?defines context rest
11489   | Xml.Element ("ref", ["name", name], []) :: rest ->
11490       (* Look up the reference.  Because of limitations in this parser,
11491        * we can't handle arbitrarily nested <ref> yet.  You can only
11492        * use <ref> from inside <start>.
11493        *)
11494       (match defines with
11495        | None ->
11496            failwithf "%s: contains <ref>, but no refs are defined yet" context
11497        | Some map ->
11498            let rng = StringMap.find name map in
11499            rng @ parse_rng ?defines context rest
11500       )
11501   | x :: _ ->
11502       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11503
11504 let grammar =
11505   let xml = Xml.parse_file rng_input in
11506   match xml with
11507   | Xml.Element ("grammar", _,
11508                  Xml.Element ("start", _, gram) :: defines) ->
11509       (* The <define/> elements are referenced in the <start> section,
11510        * so build a map of those first.
11511        *)
11512       let defines = List.fold_left (
11513         fun map ->
11514           function Xml.Element ("define", ["name", name], defn) ->
11515             StringMap.add name defn map
11516           | _ ->
11517               failwithf "%s: expected <define name=name/>" rng_input
11518       ) StringMap.empty defines in
11519       let defines = StringMap.mapi parse_rng defines in
11520
11521       (* Parse the <start> clause, passing the defines. *)
11522       parse_rng ~defines "<start>" gram
11523   | _ ->
11524       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11525         rng_input
11526
11527 let name_of_field = function
11528   | Element (name, _) | Attribute (name, _)
11529   | ZeroOrMore (Element (name, _))
11530   | OneOrMore (Element (name, _))
11531   | Optional (Element (name, _)) -> name
11532   | Optional (Attribute (name, _)) -> name
11533   | Text -> (* an unnamed field in an element *)
11534       "data"
11535   | rng ->
11536       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11537
11538 (* At the moment this function only generates OCaml types.  However we
11539  * should parameterize it later so it can generate types/structs in a
11540  * variety of languages.
11541  *)
11542 let generate_types xs =
11543   (* A simple type is one that can be printed out directly, eg.
11544    * "string option".  A complex type is one which has a name and has
11545    * to be defined via another toplevel definition, eg. a struct.
11546    *
11547    * generate_type generates code for either simple or complex types.
11548    * In the simple case, it returns the string ("string option").  In
11549    * the complex case, it returns the name ("mountpoint").  In the
11550    * complex case it has to print out the definition before returning,
11551    * so it should only be called when we are at the beginning of a
11552    * new line (BOL context).
11553    *)
11554   let rec generate_type = function
11555     | Text ->                                (* string *)
11556         "string", true
11557     | Choice values ->                        (* [`val1|`val2|...] *)
11558         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11559     | ZeroOrMore rng ->                        (* <rng> list *)
11560         let t, is_simple = generate_type rng in
11561         t ^ " list (* 0 or more *)", is_simple
11562     | OneOrMore rng ->                        (* <rng> list *)
11563         let t, is_simple = generate_type rng in
11564         t ^ " list (* 1 or more *)", is_simple
11565                                         (* virt-inspector hack: bool *)
11566     | Optional (Attribute (name, [Value "1"])) ->
11567         "bool", true
11568     | Optional rng ->                        (* <rng> list *)
11569         let t, is_simple = generate_type rng in
11570         t ^ " option", is_simple
11571                                         (* type name = { fields ... } *)
11572     | Element (name, fields) when is_attrs_interleave fields ->
11573         generate_type_struct name (get_attrs_interleave fields)
11574     | Element (name, [field])                (* type name = field *)
11575     | Attribute (name, [field]) ->
11576         let t, is_simple = generate_type field in
11577         if is_simple then (t, true)
11578         else (
11579           pr "type %s = %s\n" name t;
11580           name, false
11581         )
11582     | Element (name, fields) ->              (* type name = { fields ... } *)
11583         generate_type_struct name fields
11584     | rng ->
11585         failwithf "generate_type failed at: %s" (string_of_rng rng)
11586
11587   and is_attrs_interleave = function
11588     | [Interleave _] -> true
11589     | Attribute _ :: fields -> is_attrs_interleave fields
11590     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11591     | _ -> false
11592
11593   and get_attrs_interleave = function
11594     | [Interleave fields] -> fields
11595     | ((Attribute _) as field) :: fields
11596     | ((Optional (Attribute _)) as field) :: fields ->
11597         field :: get_attrs_interleave fields
11598     | _ -> assert false
11599
11600   and generate_types xs =
11601     List.iter (fun x -> ignore (generate_type x)) xs
11602
11603   and generate_type_struct name fields =
11604     (* Calculate the types of the fields first.  We have to do this
11605      * before printing anything so we are still in BOL context.
11606      *)
11607     let types = List.map fst (List.map generate_type fields) in
11608
11609     (* Special case of a struct containing just a string and another
11610      * field.  Turn it into an assoc list.
11611      *)
11612     match types with
11613     | ["string"; other] ->
11614         let fname1, fname2 =
11615           match fields with
11616           | [f1; f2] -> name_of_field f1, name_of_field f2
11617           | _ -> assert false in
11618         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11619         name, false
11620
11621     | types ->
11622         pr "type %s = {\n" name;
11623         List.iter (
11624           fun (field, ftype) ->
11625             let fname = name_of_field field in
11626             pr "  %s_%s : %s;\n" name fname ftype
11627         ) (List.combine fields types);
11628         pr "}\n";
11629         (* Return the name of this type, and
11630          * false because it's not a simple type.
11631          *)
11632         name, false
11633   in
11634
11635   generate_types xs
11636
11637 let generate_parsers xs =
11638   (* As for generate_type above, generate_parser makes a parser for
11639    * some type, and returns the name of the parser it has generated.
11640    * Because it (may) need to print something, it should always be
11641    * called in BOL context.
11642    *)
11643   let rec generate_parser = function
11644     | Text ->                                (* string *)
11645         "string_child_or_empty"
11646     | Choice values ->                        (* [`val1|`val2|...] *)
11647         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11648           (String.concat "|"
11649              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11650     | ZeroOrMore rng ->                        (* <rng> list *)
11651         let pa = generate_parser rng in
11652         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11653     | OneOrMore rng ->                        (* <rng> list *)
11654         let pa = generate_parser rng in
11655         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11656                                         (* virt-inspector hack: bool *)
11657     | Optional (Attribute (name, [Value "1"])) ->
11658         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11659     | Optional rng ->                        (* <rng> list *)
11660         let pa = generate_parser rng in
11661         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11662                                         (* type name = { fields ... } *)
11663     | Element (name, fields) when is_attrs_interleave fields ->
11664         generate_parser_struct name (get_attrs_interleave fields)
11665     | Element (name, [field]) ->        (* type name = field *)
11666         let pa = generate_parser field in
11667         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11668         pr "let %s =\n" parser_name;
11669         pr "  %s\n" pa;
11670         pr "let parse_%s = %s\n" name parser_name;
11671         parser_name
11672     | Attribute (name, [field]) ->
11673         let pa = generate_parser field in
11674         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11675         pr "let %s =\n" parser_name;
11676         pr "  %s\n" pa;
11677         pr "let parse_%s = %s\n" name parser_name;
11678         parser_name
11679     | Element (name, fields) ->              (* type name = { fields ... } *)
11680         generate_parser_struct name ([], fields)
11681     | rng ->
11682         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11683
11684   and is_attrs_interleave = function
11685     | [Interleave _] -> true
11686     | Attribute _ :: fields -> is_attrs_interleave fields
11687     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11688     | _ -> false
11689
11690   and get_attrs_interleave = function
11691     | [Interleave fields] -> [], fields
11692     | ((Attribute _) as field) :: fields
11693     | ((Optional (Attribute _)) as field) :: fields ->
11694         let attrs, interleaves = get_attrs_interleave fields in
11695         (field :: attrs), interleaves
11696     | _ -> assert false
11697
11698   and generate_parsers xs =
11699     List.iter (fun x -> ignore (generate_parser x)) xs
11700
11701   and generate_parser_struct name (attrs, interleaves) =
11702     (* Generate parsers for the fields first.  We have to do this
11703      * before printing anything so we are still in BOL context.
11704      *)
11705     let fields = attrs @ interleaves in
11706     let pas = List.map generate_parser fields in
11707
11708     (* Generate an intermediate tuple from all the fields first.
11709      * If the type is just a string + another field, then we will
11710      * return this directly, otherwise it is turned into a record.
11711      *
11712      * RELAX NG note: This code treats <interleave> and plain lists of
11713      * fields the same.  In other words, it doesn't bother enforcing
11714      * any ordering of fields in the XML.
11715      *)
11716     pr "let parse_%s x =\n" name;
11717     pr "  let t = (\n    ";
11718     let comma = ref false in
11719     List.iter (
11720       fun x ->
11721         if !comma then pr ",\n    ";
11722         comma := true;
11723         match x with
11724         | Optional (Attribute (fname, [field])), pa ->
11725             pr "%s x" pa
11726         | Optional (Element (fname, [field])), pa ->
11727             pr "%s (optional_child %S x)" pa fname
11728         | Attribute (fname, [Text]), _ ->
11729             pr "attribute %S x" fname
11730         | (ZeroOrMore _ | OneOrMore _), pa ->
11731             pr "%s x" pa
11732         | Text, pa ->
11733             pr "%s x" pa
11734         | (field, pa) ->
11735             let fname = name_of_field field in
11736             pr "%s (child %S x)" pa fname
11737     ) (List.combine fields pas);
11738     pr "\n  ) in\n";
11739
11740     (match fields with
11741      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11742          pr "  t\n"
11743
11744      | _ ->
11745          pr "  (Obj.magic t : %s)\n" name
11746 (*
11747          List.iter (
11748            function
11749            | (Optional (Attribute (fname, [field])), pa) ->
11750                pr "  %s_%s =\n" name fname;
11751                pr "    %s x;\n" pa
11752            | (Optional (Element (fname, [field])), pa) ->
11753                pr "  %s_%s =\n" name fname;
11754                pr "    (let x = optional_child %S x in\n" fname;
11755                pr "     %s x);\n" pa
11756            | (field, pa) ->
11757                let fname = name_of_field field in
11758                pr "  %s_%s =\n" name fname;
11759                pr "    (let x = child %S x in\n" fname;
11760                pr "     %s x);\n" pa
11761          ) (List.combine fields pas);
11762          pr "}\n"
11763 *)
11764     );
11765     sprintf "parse_%s" name
11766   in
11767
11768   generate_parsers xs
11769
11770 (* Generate ocaml/guestfs_inspector.mli. *)
11771 let generate_ocaml_inspector_mli () =
11772   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11773
11774   pr "\
11775 (** This is an OCaml language binding to the external [virt-inspector]
11776     program.
11777
11778     For more information, please read the man page [virt-inspector(1)].
11779 *)
11780
11781 ";
11782
11783   generate_types grammar;
11784   pr "(** The nested information returned from the {!inspect} function. *)\n";
11785   pr "\n";
11786
11787   pr "\
11788 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11789 (** To inspect a libvirt domain called [name], pass a singleton
11790     list: [inspect [name]].  When using libvirt only, you may
11791     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11792
11793     To inspect a disk image or images, pass a list of the filenames
11794     of the disk images: [inspect filenames]
11795
11796     This function inspects the given guest or disk images and
11797     returns a list of operating system(s) found and a large amount
11798     of information about them.  In the vast majority of cases,
11799     a virtual machine only contains a single operating system.
11800
11801     If the optional [~xml] parameter is given, then this function
11802     skips running the external virt-inspector program and just
11803     parses the given XML directly (which is expected to be XML
11804     produced from a previous run of virt-inspector).  The list of
11805     names and connect URI are ignored in this case.
11806
11807     This function can throw a wide variety of exceptions, for example
11808     if the external virt-inspector program cannot be found, or if
11809     it doesn't generate valid XML.
11810 *)
11811 "
11812
11813 (* Generate ocaml/guestfs_inspector.ml. *)
11814 let generate_ocaml_inspector_ml () =
11815   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11816
11817   pr "open Unix\n";
11818   pr "\n";
11819
11820   generate_types grammar;
11821   pr "\n";
11822
11823   pr "\
11824 (* Misc functions which are used by the parser code below. *)
11825 let first_child = function
11826   | Xml.Element (_, _, c::_) -> c
11827   | Xml.Element (name, _, []) ->
11828       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11829   | Xml.PCData str ->
11830       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11831
11832 let string_child_or_empty = function
11833   | Xml.Element (_, _, [Xml.PCData s]) -> s
11834   | Xml.Element (_, _, []) -> \"\"
11835   | Xml.Element (x, _, _) ->
11836       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11837                 x ^ \" instead\")
11838   | Xml.PCData str ->
11839       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11840
11841 let optional_child name xml =
11842   let children = Xml.children xml in
11843   try
11844     Some (List.find (function
11845                      | Xml.Element (n, _, _) when n = name -> true
11846                      | _ -> false) children)
11847   with
11848     Not_found -> None
11849
11850 let child name xml =
11851   match optional_child name xml with
11852   | Some c -> c
11853   | None ->
11854       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11855
11856 let attribute name xml =
11857   try Xml.attrib xml name
11858   with Xml.No_attribute _ ->
11859     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11860
11861 ";
11862
11863   generate_parsers grammar;
11864   pr "\n";
11865
11866   pr "\
11867 (* Run external virt-inspector, then use parser to parse the XML. *)
11868 let inspect ?connect ?xml names =
11869   let xml =
11870     match xml with
11871     | None ->
11872         if names = [] then invalid_arg \"inspect: no names given\";
11873         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11874           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11875           names in
11876         let cmd = List.map Filename.quote cmd in
11877         let cmd = String.concat \" \" cmd in
11878         let chan = open_process_in cmd in
11879         let xml = Xml.parse_in chan in
11880         (match close_process_in chan with
11881          | WEXITED 0 -> ()
11882          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11883          | WSIGNALED i | WSTOPPED i ->
11884              failwith (\"external virt-inspector command died or stopped on sig \" ^
11885                        string_of_int i)
11886         );
11887         xml
11888     | Some doc ->
11889         Xml.parse_string doc in
11890   parse_operatingsystems xml
11891 "
11892
11893 and generate_max_proc_nr () =
11894   pr "%d\n" max_proc_nr
11895
11896 let output_to filename k =
11897   let filename_new = filename ^ ".new" in
11898   chan := open_out filename_new;
11899   k ();
11900   close_out !chan;
11901   chan := Pervasives.stdout;
11902
11903   (* Is the new file different from the current file? *)
11904   if Sys.file_exists filename && files_equal filename filename_new then
11905     unlink filename_new                 (* same, so skip it *)
11906   else (
11907     (* different, overwrite old one *)
11908     (try chmod filename 0o644 with Unix_error _ -> ());
11909     rename filename_new filename;
11910     chmod filename 0o444;
11911     printf "written %s\n%!" filename;
11912   )
11913
11914 let perror msg = function
11915   | Unix_error (err, _, _) ->
11916       eprintf "%s: %s\n" msg (error_message err)
11917   | exn ->
11918       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11919
11920 (* Main program. *)
11921 let () =
11922   let lock_fd =
11923     try openfile "HACKING" [O_RDWR] 0
11924     with
11925     | Unix_error (ENOENT, _, _) ->
11926         eprintf "\
11927 You are probably running this from the wrong directory.
11928 Run it from the top source directory using the command
11929   src/generator.ml
11930 ";
11931         exit 1
11932     | exn ->
11933         perror "open: HACKING" exn;
11934         exit 1 in
11935
11936   (* Acquire a lock so parallel builds won't try to run the generator
11937    * twice at the same time.  Subsequent builds will wait for the first
11938    * one to finish.  Note the lock is released implicitly when the
11939    * program exits.
11940    *)
11941   (try lockf lock_fd F_LOCK 1
11942    with exn ->
11943      perror "lock: HACKING" exn;
11944      exit 1);
11945
11946   check_functions ();
11947
11948   output_to "src/guestfs_protocol.x" generate_xdr;
11949   output_to "src/guestfs-structs.h" generate_structs_h;
11950   output_to "src/guestfs-actions.h" generate_actions_h;
11951   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11952   output_to "src/guestfs-actions.c" generate_client_actions;
11953   output_to "src/guestfs-bindtests.c" generate_bindtests;
11954   output_to "src/guestfs-structs.pod" generate_structs_pod;
11955   output_to "src/guestfs-actions.pod" generate_actions_pod;
11956   output_to "src/guestfs-availability.pod" generate_availability_pod;
11957   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11958   output_to "src/libguestfs.syms" generate_linker_script;
11959   output_to "daemon/actions.h" generate_daemon_actions_h;
11960   output_to "daemon/stubs.c" generate_daemon_actions;
11961   output_to "daemon/names.c" generate_daemon_names;
11962   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11963   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11964   output_to "capitests/tests.c" generate_tests;
11965   output_to "fish/cmds.c" generate_fish_cmds;
11966   output_to "fish/completion.c" generate_fish_completion;
11967   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11968   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11969   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11970   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11971   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11972   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11973   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11974   output_to "perl/Guestfs.xs" generate_perl_xs;
11975   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11976   output_to "perl/bindtests.pl" generate_perl_bindtests;
11977   output_to "python/guestfs-py.c" generate_python_c;
11978   output_to "python/guestfs.py" generate_python_py;
11979   output_to "python/bindtests.py" generate_python_bindtests;
11980   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11981   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11982   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11983
11984   List.iter (
11985     fun (typ, jtyp) ->
11986       let cols = cols_of_struct typ in
11987       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11988       output_to filename (generate_java_struct jtyp cols);
11989   ) java_structs;
11990
11991   output_to "java/Makefile.inc" generate_java_makefile_inc;
11992   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11993   output_to "java/Bindtests.java" generate_java_bindtests;
11994   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11995   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11996   output_to "csharp/Libguestfs.cs" generate_csharp;
11997
11998   (* Always generate this file last, and unconditionally.  It's used
11999    * by the Makefile to know when we must re-run the generator.
12000    *)
12001   let chan = open_out "src/stamp-generator" in
12002   fprintf chan "1\n";
12003   close_out chan;
12004
12005   printf "generated %d lines of code\n" !lines