generator: Remove unnecessary parameter.
[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     (* Run the test only if 'string' is available in the daemon. *)
313   | IfAvailable of string
314
315 (* Some initial scenarios for testing. *)
316 and test_init =
317     (* Do nothing, block devices could contain random stuff including
318      * LVM PVs, and some filesystems might be mounted.  This is usually
319      * a bad idea.
320      *)
321   | InitNone
322
323     (* Block devices are empty and no filesystems are mounted. *)
324   | InitEmpty
325
326     (* /dev/sda contains a single partition /dev/sda1, with random
327      * content.  /dev/sdb and /dev/sdc may have random content.
328      * No LVM.
329      *)
330   | InitPartition
331
332     (* /dev/sda contains a single partition /dev/sda1, which is formatted
333      * as ext2, empty [except for lost+found] and mounted on /.
334      * /dev/sdb and /dev/sdc may have random content.
335      * No LVM.
336      *)
337   | InitBasicFS
338
339     (* /dev/sda:
340      *   /dev/sda1 (is a PV):
341      *     /dev/VG/LV (size 8MB):
342      *       formatted as ext2, empty [except for lost+found], mounted on /
343      * /dev/sdb and /dev/sdc may have random content.
344      *)
345   | InitBasicFSonLVM
346
347     (* /dev/sdd (the ISO, see images/ directory in source)
348      * is mounted on /
349      *)
350   | InitISOFS
351
352 (* Sequence of commands for testing. *)
353 and seq = cmd list
354 and cmd = string list
355
356 (* Note about long descriptions: When referring to another
357  * action, use the format C<guestfs_other> (ie. the full name of
358  * the C function).  This will be replaced as appropriate in other
359  * language bindings.
360  *
361  * Apart from that, long descriptions are just perldoc paragraphs.
362  *)
363
364 (* Generate a random UUID (used in tests). *)
365 let uuidgen () =
366   let chan = open_process_in "uuidgen" in
367   let uuid = input_line chan in
368   (match close_process_in chan with
369    | WEXITED 0 -> ()
370    | WEXITED _ ->
371        failwith "uuidgen: process exited with non-zero status"
372    | WSIGNALED _ | WSTOPPED _ ->
373        failwith "uuidgen: process signalled or stopped by signal"
374   );
375   uuid
376
377 (* These test functions are used in the language binding tests. *)
378
379 let test_all_args = [
380   String "str";
381   OptString "optstr";
382   StringList "strlist";
383   Bool "b";
384   Int "integer";
385   Int64 "integer64";
386   FileIn "filein";
387   FileOut "fileout";
388   BufferIn "bufferin";
389 ]
390
391 let test_all_rets = [
392   (* except for RErr, which is tested thoroughly elsewhere *)
393   "test0rint",         RInt "valout";
394   "test0rint64",       RInt64 "valout";
395   "test0rbool",        RBool "valout";
396   "test0rconststring", RConstString "valout";
397   "test0rconstoptstring", RConstOptString "valout";
398   "test0rstring",      RString "valout";
399   "test0rstringlist",  RStringList "valout";
400   "test0rstruct",      RStruct ("valout", "lvm_pv");
401   "test0rstructlist",  RStructList ("valout", "lvm_pv");
402   "test0rhashtable",   RHashtable "valout";
403 ]
404
405 let test_functions = [
406   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
407    [],
408    "internal test function - do not use",
409    "\
410 This is an internal test function which is used to test whether
411 the automatically generated bindings can handle every possible
412 parameter type correctly.
413
414 It echos the contents of each parameter to stdout.
415
416 You probably don't want to call this function.");
417 ] @ List.flatten (
418   List.map (
419     fun (name, ret) ->
420       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
421         [],
422         "internal test function - do not use",
423         "\
424 This is an internal test function which is used to test whether
425 the automatically generated bindings can handle every possible
426 return type correctly.
427
428 It converts string C<val> to the return type.
429
430 You probably don't want to call this function.");
431        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
432         [],
433         "internal test function - do not use",
434         "\
435 This is an internal test function which is used to test whether
436 the automatically generated bindings can handle every possible
437 return type correctly.
438
439 This function always returns an error.
440
441 You probably don't want to call this function.")]
442   ) test_all_rets
443 )
444
445 (* non_daemon_functions are any functions which don't get processed
446  * in the daemon, eg. functions for setting and getting local
447  * configuration values.
448  *)
449
450 let non_daemon_functions = test_functions @ [
451   ("launch", (RErr, []), -1, [FishAlias "run"],
452    [],
453    "launch the qemu subprocess",
454    "\
455 Internally libguestfs is implemented by running a virtual machine
456 using L<qemu(1)>.
457
458 You should call this after configuring the handle
459 (eg. adding drives) but before performing any actions.");
460
461   ("wait_ready", (RErr, []), -1, [NotInFish],
462    [],
463    "wait until the qemu subprocess launches (no op)",
464    "\
465 This function is a no op.
466
467 In versions of the API E<lt> 1.0.71 you had to call this function
468 just after calling C<guestfs_launch> to wait for the launch
469 to complete.  However this is no longer necessary because
470 C<guestfs_launch> now does the waiting.
471
472 If you see any calls to this function in code then you can just
473 remove them, unless you want to retain compatibility with older
474 versions of the API.");
475
476   ("kill_subprocess", (RErr, []), -1, [],
477    [],
478    "kill the qemu subprocess",
479    "\
480 This kills the qemu subprocess.  You should never need to call this.");
481
482   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
483    [],
484    "add an image to examine or modify",
485    "\
486 This function adds a virtual machine disk image C<filename> to the
487 guest.  The first time you call this function, the disk appears as IDE
488 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
489 so on.
490
491 You don't necessarily need to be root when using libguestfs.  However
492 you obviously do need sufficient permissions to access the filename
493 for whatever operations you want to perform (ie. read access if you
494 just want to read the image or write access if you want to modify the
495 image).
496
497 This is equivalent to the qemu parameter
498 C<-drive file=filename,cache=off,if=...>.
499
500 C<cache=off> is omitted in cases where it is not supported by
501 the underlying filesystem.
502
503 C<if=...> is set at compile time by the configuration option
504 C<./configure --with-drive-if=...>.  In the rare case where you
505 might need to change this at run time, use C<guestfs_add_drive_with_if>
506 or C<guestfs_add_drive_ro_with_if>.
507
508 Note that this call checks for the existence of C<filename>.  This
509 stops you from specifying other types of drive which are supported
510 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
511 the general C<guestfs_config> call instead.");
512
513   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
514    [],
515    "add a CD-ROM disk image to examine",
516    "\
517 This function adds a virtual CD-ROM disk image to the guest.
518
519 This is equivalent to the qemu parameter C<-cdrom filename>.
520
521 Notes:
522
523 =over 4
524
525 =item *
526
527 This call checks for the existence of C<filename>.  This
528 stops you from specifying other types of drive which are supported
529 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
530 the general C<guestfs_config> call instead.
531
532 =item *
533
534 If you just want to add an ISO file (often you use this as an
535 efficient way to transfer large files into the guest), then you
536 should probably use C<guestfs_add_drive_ro> instead.
537
538 =back");
539
540   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
541    [],
542    "add a drive in snapshot mode (read-only)",
543    "\
544 This adds a drive in snapshot mode, making it effectively
545 read-only.
546
547 Note that writes to the device are allowed, and will be seen for
548 the duration of the guestfs handle, but they are written
549 to a temporary file which is discarded as soon as the guestfs
550 handle is closed.  We don't currently have any method to enable
551 changes to be committed, although qemu can support this.
552
553 This is equivalent to the qemu parameter
554 C<-drive file=filename,snapshot=on,readonly=on,if=...>.
555
556 C<if=...> is set at compile time by the configuration option
557 C<./configure --with-drive-if=...>.  In the rare case where you
558 might need to change this at run time, use C<guestfs_add_drive_with_if>
559 or C<guestfs_add_drive_ro_with_if>.
560
561 C<readonly=on> is only added where qemu supports this option.
562
563 Note that this call checks for the existence of C<filename>.  This
564 stops you from specifying other types of drive which are supported
565 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
566 the general C<guestfs_config> call instead.");
567
568   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
569    [],
570    "add qemu parameters",
571    "\
572 This can be used to add arbitrary qemu command line parameters
573 of the form C<-param value>.  Actually it's not quite arbitrary - we
574 prevent you from setting some parameters which would interfere with
575 parameters that we use.
576
577 The first character of C<param> string must be a C<-> (dash).
578
579 C<value> can be NULL.");
580
581   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
582    [],
583    "set the qemu binary",
584    "\
585 Set the qemu binary that we will use.
586
587 The default is chosen when the library was compiled by the
588 configure script.
589
590 You can also override this by setting the C<LIBGUESTFS_QEMU>
591 environment variable.
592
593 Setting C<qemu> to C<NULL> restores the default qemu binary.
594
595 Note that you should call this function as early as possible
596 after creating the handle.  This is because some pre-launch
597 operations depend on testing qemu features (by running C<qemu -help>).
598 If the qemu binary changes, we don't retest features, and
599 so you might see inconsistent results.  Using the environment
600 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
601 the qemu binary at the same time as the handle is created.");
602
603   ("get_qemu", (RConstString "qemu", []), -1, [],
604    [InitNone, Always, TestRun (
605       [["get_qemu"]])],
606    "get the qemu binary",
607    "\
608 Return the current qemu binary.
609
610 This is always non-NULL.  If it wasn't set already, then this will
611 return the default qemu binary name.");
612
613   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
614    [],
615    "set the search path",
616    "\
617 Set the path that libguestfs searches for kernel and initrd.img.
618
619 The default is C<$libdir/guestfs> unless overridden by setting
620 C<LIBGUESTFS_PATH> environment variable.
621
622 Setting C<path> to C<NULL> restores the default path.");
623
624   ("get_path", (RConstString "path", []), -1, [],
625    [InitNone, Always, TestRun (
626       [["get_path"]])],
627    "get the search path",
628    "\
629 Return the current search path.
630
631 This is always non-NULL.  If it wasn't set already, then this will
632 return the default path.");
633
634   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
635    [],
636    "add options to kernel command line",
637    "\
638 This function is used to add additional options to the
639 guest kernel command line.
640
641 The default is C<NULL> unless overridden by setting
642 C<LIBGUESTFS_APPEND> environment variable.
643
644 Setting C<append> to C<NULL> means I<no> additional options
645 are passed (libguestfs always adds a few of its own).");
646
647   ("get_append", (RConstOptString "append", []), -1, [],
648    (* This cannot be tested with the current framework.  The
649     * function can return NULL in normal operations, which the
650     * test framework interprets as an error.
651     *)
652    [],
653    "get the additional kernel options",
654    "\
655 Return the additional kernel options which are added to the
656 guest kernel command line.
657
658 If C<NULL> then no options are added.");
659
660   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
661    [],
662    "set autosync mode",
663    "\
664 If C<autosync> is true, this enables autosync.  Libguestfs will make a
665 best effort attempt to run C<guestfs_umount_all> followed by
666 C<guestfs_sync> when the handle is closed
667 (also if the program exits without closing handles).
668
669 This is disabled by default (except in guestfish where it is
670 enabled by default).");
671
672   ("get_autosync", (RBool "autosync", []), -1, [],
673    [InitNone, Always, TestRun (
674       [["get_autosync"]])],
675    "get autosync mode",
676    "\
677 Get the autosync flag.");
678
679   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
680    [],
681    "set verbose mode",
682    "\
683 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
684
685 Verbose messages are disabled unless the environment variable
686 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
687
688   ("get_verbose", (RBool "verbose", []), -1, [],
689    [],
690    "get verbose mode",
691    "\
692 This returns the verbose messages flag.");
693
694   ("is_ready", (RBool "ready", []), -1, [],
695    [InitNone, Always, TestOutputTrue (
696       [["is_ready"]])],
697    "is ready to accept commands",
698    "\
699 This returns true iff this handle is ready to accept commands
700 (in the C<READY> state).
701
702 For more information on states, see L<guestfs(3)>.");
703
704   ("is_config", (RBool "config", []), -1, [],
705    [InitNone, Always, TestOutputFalse (
706       [["is_config"]])],
707    "is in configuration state",
708    "\
709 This returns true iff this handle is being configured
710 (in the C<CONFIG> state).
711
712 For more information on states, see L<guestfs(3)>.");
713
714   ("is_launching", (RBool "launching", []), -1, [],
715    [InitNone, Always, TestOutputFalse (
716       [["is_launching"]])],
717    "is launching subprocess",
718    "\
719 This returns true iff this handle is launching the subprocess
720 (in the C<LAUNCHING> state).
721
722 For more information on states, see L<guestfs(3)>.");
723
724   ("is_busy", (RBool "busy", []), -1, [],
725    [InitNone, Always, TestOutputFalse (
726       [["is_busy"]])],
727    "is busy processing a command",
728    "\
729 This returns true iff this handle is busy processing a command
730 (in the C<BUSY> state).
731
732 For more information on states, see L<guestfs(3)>.");
733
734   ("get_state", (RInt "state", []), -1, [],
735    [],
736    "get the current state",
737    "\
738 This returns the current state as an opaque integer.  This is
739 only useful for printing debug and internal error messages.
740
741 For more information on states, see L<guestfs(3)>.");
742
743   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
744    [InitNone, Always, TestOutputInt (
745       [["set_memsize"; "500"];
746        ["get_memsize"]], 500)],
747    "set memory allocated to the qemu subprocess",
748    "\
749 This sets the memory size in megabytes allocated to the
750 qemu subprocess.  This only has any effect if called before
751 C<guestfs_launch>.
752
753 You can also change this by setting the environment
754 variable C<LIBGUESTFS_MEMSIZE> before the handle is
755 created.
756
757 For more information on the architecture of libguestfs,
758 see L<guestfs(3)>.");
759
760   ("get_memsize", (RInt "memsize", []), -1, [],
761    [InitNone, Always, TestOutputIntOp (
762       [["get_memsize"]], ">=", 256)],
763    "get memory allocated to the qemu subprocess",
764    "\
765 This gets the memory size in megabytes allocated to the
766 qemu subprocess.
767
768 If C<guestfs_set_memsize> was not called
769 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
770 then this returns the compiled-in default value for memsize.
771
772 For more information on the architecture of libguestfs,
773 see L<guestfs(3)>.");
774
775   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
776    [InitNone, Always, TestOutputIntOp (
777       [["get_pid"]], ">=", 1)],
778    "get PID of qemu subprocess",
779    "\
780 Return the process ID of the qemu subprocess.  If there is no
781 qemu subprocess, then this will return an error.
782
783 This is an internal call used for debugging and testing.");
784
785   ("version", (RStruct ("version", "version"), []), -1, [],
786    [InitNone, Always, TestOutputStruct (
787       [["version"]], [CompareWithInt ("major", 1)])],
788    "get the library version number",
789    "\
790 Return the libguestfs version number that the program is linked
791 against.
792
793 Note that because of dynamic linking this is not necessarily
794 the version of libguestfs that you compiled against.  You can
795 compile the program, and then at runtime dynamically link
796 against a completely different C<libguestfs.so> library.
797
798 This call was added in version C<1.0.58>.  In previous
799 versions of libguestfs there was no way to get the version
800 number.  From C code you can use dynamic linker functions
801 to find out if this symbol exists (if it doesn't, then
802 it's an earlier version).
803
804 The call returns a structure with four elements.  The first
805 three (C<major>, C<minor> and C<release>) are numbers and
806 correspond to the usual version triplet.  The fourth element
807 (C<extra>) is a string and is normally empty, but may be
808 used for distro-specific information.
809
810 To construct the original version string:
811 C<$major.$minor.$release$extra>
812
813 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
814
815 I<Note:> Don't use this call to test for availability
816 of features.  In enterprise distributions we backport
817 features from later versions into earlier versions,
818 making this an unreliable way to test for features.
819 Use C<guestfs_available> instead.");
820
821   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
822    [InitNone, Always, TestOutputTrue (
823       [["set_selinux"; "true"];
824        ["get_selinux"]])],
825    "set SELinux enabled or disabled at appliance boot",
826    "\
827 This sets the selinux flag that is passed to the appliance
828 at boot time.  The default is C<selinux=0> (disabled).
829
830 Note that if SELinux is enabled, it is always in
831 Permissive mode (C<enforcing=0>).
832
833 For more information on the architecture of libguestfs,
834 see L<guestfs(3)>.");
835
836   ("get_selinux", (RBool "selinux", []), -1, [],
837    [],
838    "get SELinux enabled flag",
839    "\
840 This returns the current setting of the selinux flag which
841 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
842
843 For more information on the architecture of libguestfs,
844 see L<guestfs(3)>.");
845
846   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
847    [InitNone, Always, TestOutputFalse (
848       [["set_trace"; "false"];
849        ["get_trace"]])],
850    "enable or disable command traces",
851    "\
852 If the command trace flag is set to 1, then commands are
853 printed on stdout before they are executed in a format
854 which is very similar to the one used by guestfish.  In
855 other words, you can run a program with this enabled, and
856 you will get out a script which you can feed to guestfish
857 to perform the same set of actions.
858
859 If you want to trace C API calls into libguestfs (and
860 other libraries) then possibly a better way is to use
861 the external ltrace(1) command.
862
863 Command traces are disabled unless the environment variable
864 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
865
866   ("get_trace", (RBool "trace", []), -1, [],
867    [],
868    "get command trace enabled flag",
869    "\
870 Return the command trace flag.");
871
872   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
873    [InitNone, Always, TestOutputFalse (
874       [["set_direct"; "false"];
875        ["get_direct"]])],
876    "enable or disable direct appliance mode",
877    "\
878 If the direct appliance mode flag is enabled, then stdin and
879 stdout are passed directly through to the appliance once it
880 is launched.
881
882 One consequence of this is that log messages aren't caught
883 by the library and handled by C<guestfs_set_log_message_callback>,
884 but go straight to stdout.
885
886 You probably don't want to use this unless you know what you
887 are doing.
888
889 The default is disabled.");
890
891   ("get_direct", (RBool "direct", []), -1, [],
892    [],
893    "get direct appliance mode flag",
894    "\
895 Return the direct appliance mode flag.");
896
897   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
898    [InitNone, Always, TestOutputTrue (
899       [["set_recovery_proc"; "true"];
900        ["get_recovery_proc"]])],
901    "enable or disable the recovery process",
902    "\
903 If this is called with the parameter C<false> then
904 C<guestfs_launch> does not create a recovery process.  The
905 purpose of the recovery process is to stop runaway qemu
906 processes in the case where the main program aborts abruptly.
907
908 This only has any effect if called before C<guestfs_launch>,
909 and the default is true.
910
911 About the only time when you would want to disable this is
912 if the main process will fork itself into the background
913 (\"daemonize\" itself).  In this case the recovery process
914 thinks that the main program has disappeared and so kills
915 qemu, which is not very helpful.");
916
917   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
918    [],
919    "get recovery process enabled flag",
920    "\
921 Return the recovery process enabled flag.");
922
923   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
924    [],
925    "add a drive specifying the QEMU block emulation to use",
926    "\
927 This is the same as C<guestfs_add_drive> but it allows you
928 to specify the QEMU interface emulation to use at run time.");
929
930   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
931    [],
932    "add a drive read-only specifying the QEMU block emulation to use",
933    "\
934 This is the same as C<guestfs_add_drive_ro> but it allows you
935 to specify the QEMU interface emulation to use at run time.");
936
937 ]
938
939 (* daemon_functions are any functions which cause some action
940  * to take place in the daemon.
941  *)
942
943 let daemon_functions = [
944   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
945    [InitEmpty, Always, TestOutput (
946       [["part_disk"; "/dev/sda"; "mbr"];
947        ["mkfs"; "ext2"; "/dev/sda1"];
948        ["mount"; "/dev/sda1"; "/"];
949        ["write"; "/new"; "new file contents"];
950        ["cat"; "/new"]], "new file contents")],
951    "mount a guest disk at a position in the filesystem",
952    "\
953 Mount a guest disk at a position in the filesystem.  Block devices
954 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
955 the guest.  If those block devices contain partitions, they will have
956 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
957 names can be used.
958
959 The rules are the same as for L<mount(2)>:  A filesystem must
960 first be mounted on C</> before others can be mounted.  Other
961 filesystems can only be mounted on directories which already
962 exist.
963
964 The mounted filesystem is writable, if we have sufficient permissions
965 on the underlying device.
966
967 B<Important note:>
968 When you use this call, the filesystem options C<sync> and C<noatime>
969 are set implicitly.  This was originally done because we thought it
970 would improve reliability, but it turns out that I<-o sync> has a
971 very large negative performance impact and negligible effect on
972 reliability.  Therefore we recommend that you avoid using
973 C<guestfs_mount> in any code that needs performance, and instead
974 use C<guestfs_mount_options> (use an empty string for the first
975 parameter if you don't want any options).");
976
977   ("sync", (RErr, []), 2, [],
978    [ InitEmpty, Always, TestRun [["sync"]]],
979    "sync disks, writes are flushed through to the disk image",
980    "\
981 This syncs the disk, so that any writes are flushed through to the
982 underlying disk image.
983
984 You should always call this if you have modified a disk image, before
985 closing the handle.");
986
987   ("touch", (RErr, [Pathname "path"]), 3, [],
988    [InitBasicFS, Always, TestOutputTrue (
989       [["touch"; "/new"];
990        ["exists"; "/new"]])],
991    "update file timestamps or create a new file",
992    "\
993 Touch acts like the L<touch(1)> command.  It can be used to
994 update the timestamps on a file, or, if the file does not exist,
995 to create a new zero-length file.
996
997 This command only works on regular files, and will fail on other
998 file types such as directories, symbolic links, block special etc.");
999
1000   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
1001    [InitISOFS, Always, TestOutput (
1002       [["cat"; "/known-2"]], "abcdef\n")],
1003    "list the contents of a file",
1004    "\
1005 Return the contents of the file named C<path>.
1006
1007 Note that this function cannot correctly handle binary files
1008 (specifically, files containing C<\\0> character which is treated
1009 as end of string).  For those you need to use the C<guestfs_read_file>
1010 or C<guestfs_download> functions which have a more complex interface.");
1011
1012   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1013    [], (* XXX Tricky to test because it depends on the exact format
1014         * of the 'ls -l' command, which changes between F10 and F11.
1015         *)
1016    "list the files in a directory (long format)",
1017    "\
1018 List the files in C<directory> (relative to the root directory,
1019 there is no cwd) in the format of 'ls -la'.
1020
1021 This command is mostly useful for interactive sessions.  It
1022 is I<not> intended that you try to parse the output string.");
1023
1024   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1025    [InitBasicFS, Always, TestOutputList (
1026       [["touch"; "/new"];
1027        ["touch"; "/newer"];
1028        ["touch"; "/newest"];
1029        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1030    "list the files in a directory",
1031    "\
1032 List the files in C<directory> (relative to the root directory,
1033 there is no cwd).  The '.' and '..' entries are not returned, but
1034 hidden files are shown.
1035
1036 This command is mostly useful for interactive sessions.  Programs
1037 should probably use C<guestfs_readdir> instead.");
1038
1039   ("list_devices", (RStringList "devices", []), 7, [],
1040    [InitEmpty, Always, TestOutputListOfDevices (
1041       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1042    "list the block devices",
1043    "\
1044 List all the block devices.
1045
1046 The full block device names are returned, eg. C</dev/sda>");
1047
1048   ("list_partitions", (RStringList "partitions", []), 8, [],
1049    [InitBasicFS, Always, TestOutputListOfDevices (
1050       [["list_partitions"]], ["/dev/sda1"]);
1051     InitEmpty, Always, TestOutputListOfDevices (
1052       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1053        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1054    "list the partitions",
1055    "\
1056 List all the partitions detected on all block devices.
1057
1058 The full partition device names are returned, eg. C</dev/sda1>
1059
1060 This does not return logical volumes.  For that you will need to
1061 call C<guestfs_lvs>.");
1062
1063   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1064    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1065       [["pvs"]], ["/dev/sda1"]);
1066     InitEmpty, Always, TestOutputListOfDevices (
1067       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1068        ["pvcreate"; "/dev/sda1"];
1069        ["pvcreate"; "/dev/sda2"];
1070        ["pvcreate"; "/dev/sda3"];
1071        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1072    "list the LVM physical volumes (PVs)",
1073    "\
1074 List all the physical volumes detected.  This is the equivalent
1075 of the L<pvs(8)> command.
1076
1077 This returns a list of just the device names that contain
1078 PVs (eg. C</dev/sda2>).
1079
1080 See also C<guestfs_pvs_full>.");
1081
1082   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1083    [InitBasicFSonLVM, Always, TestOutputList (
1084       [["vgs"]], ["VG"]);
1085     InitEmpty, Always, TestOutputList (
1086       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1087        ["pvcreate"; "/dev/sda1"];
1088        ["pvcreate"; "/dev/sda2"];
1089        ["pvcreate"; "/dev/sda3"];
1090        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1091        ["vgcreate"; "VG2"; "/dev/sda3"];
1092        ["vgs"]], ["VG1"; "VG2"])],
1093    "list the LVM volume groups (VGs)",
1094    "\
1095 List all the volumes groups detected.  This is the equivalent
1096 of the L<vgs(8)> command.
1097
1098 This returns a list of just the volume group names that were
1099 detected (eg. C<VolGroup00>).
1100
1101 See also C<guestfs_vgs_full>.");
1102
1103   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1104    [InitBasicFSonLVM, Always, TestOutputList (
1105       [["lvs"]], ["/dev/VG/LV"]);
1106     InitEmpty, Always, TestOutputList (
1107       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1108        ["pvcreate"; "/dev/sda1"];
1109        ["pvcreate"; "/dev/sda2"];
1110        ["pvcreate"; "/dev/sda3"];
1111        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1112        ["vgcreate"; "VG2"; "/dev/sda3"];
1113        ["lvcreate"; "LV1"; "VG1"; "50"];
1114        ["lvcreate"; "LV2"; "VG1"; "50"];
1115        ["lvcreate"; "LV3"; "VG2"; "50"];
1116        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1117    "list the LVM logical volumes (LVs)",
1118    "\
1119 List all the logical volumes detected.  This is the equivalent
1120 of the L<lvs(8)> command.
1121
1122 This returns a list of the logical volume device names
1123 (eg. C</dev/VolGroup00/LogVol00>).
1124
1125 See also C<guestfs_lvs_full>.");
1126
1127   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1128    [], (* XXX how to test? *)
1129    "list the LVM physical volumes (PVs)",
1130    "\
1131 List all the physical volumes detected.  This is the equivalent
1132 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1133
1134   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1135    [], (* XXX how to test? *)
1136    "list the LVM volume groups (VGs)",
1137    "\
1138 List all the volumes groups detected.  This is the equivalent
1139 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1140
1141   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1142    [], (* XXX how to test? *)
1143    "list the LVM logical volumes (LVs)",
1144    "\
1145 List all the logical volumes detected.  This is the equivalent
1146 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1147
1148   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1149    [InitISOFS, Always, TestOutputList (
1150       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1151     InitISOFS, Always, TestOutputList (
1152       [["read_lines"; "/empty"]], [])],
1153    "read file as lines",
1154    "\
1155 Return the contents of the file named C<path>.
1156
1157 The file contents are returned as a list of lines.  Trailing
1158 C<LF> and C<CRLF> character sequences are I<not> returned.
1159
1160 Note that this function cannot correctly handle binary files
1161 (specifically, files containing C<\\0> character which is treated
1162 as end of line).  For those you need to use the C<guestfs_read_file>
1163 function which has a more complex interface.");
1164
1165   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1166    [], (* XXX Augeas code needs tests. *)
1167    "create a new Augeas handle",
1168    "\
1169 Create a new Augeas handle for editing configuration files.
1170 If there was any previous Augeas handle associated with this
1171 guestfs session, then it is closed.
1172
1173 You must call this before using any other C<guestfs_aug_*>
1174 commands.
1175
1176 C<root> is the filesystem root.  C<root> must not be NULL,
1177 use C</> instead.
1178
1179 The flags are the same as the flags defined in
1180 E<lt>augeas.hE<gt>, the logical I<or> of the following
1181 integers:
1182
1183 =over 4
1184
1185 =item C<AUG_SAVE_BACKUP> = 1
1186
1187 Keep the original file with a C<.augsave> extension.
1188
1189 =item C<AUG_SAVE_NEWFILE> = 2
1190
1191 Save changes into a file with extension C<.augnew>, and
1192 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1193
1194 =item C<AUG_TYPE_CHECK> = 4
1195
1196 Typecheck lenses (can be expensive).
1197
1198 =item C<AUG_NO_STDINC> = 8
1199
1200 Do not use standard load path for modules.
1201
1202 =item C<AUG_SAVE_NOOP> = 16
1203
1204 Make save a no-op, just record what would have been changed.
1205
1206 =item C<AUG_NO_LOAD> = 32
1207
1208 Do not load the tree in C<guestfs_aug_init>.
1209
1210 =back
1211
1212 To close the handle, you can call C<guestfs_aug_close>.
1213
1214 To find out more about Augeas, see L<http://augeas.net/>.");
1215
1216   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1217    [], (* XXX Augeas code needs tests. *)
1218    "close the current Augeas handle",
1219    "\
1220 Close the current Augeas handle and free up any resources
1221 used by it.  After calling this, you have to call
1222 C<guestfs_aug_init> again before you can use any other
1223 Augeas functions.");
1224
1225   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1226    [], (* XXX Augeas code needs tests. *)
1227    "define an Augeas variable",
1228    "\
1229 Defines an Augeas variable C<name> whose value is the result
1230 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1231 undefined.
1232
1233 On success this returns the number of nodes in C<expr>, or
1234 C<0> if C<expr> evaluates to something which is not a nodeset.");
1235
1236   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1237    [], (* XXX Augeas code needs tests. *)
1238    "define an Augeas node",
1239    "\
1240 Defines a variable C<name> whose value is the result of
1241 evaluating C<expr>.
1242
1243 If C<expr> evaluates to an empty nodeset, a node is created,
1244 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1245 C<name> will be the nodeset containing that single node.
1246
1247 On success this returns a pair containing the
1248 number of nodes in the nodeset, and a boolean flag
1249 if a node was created.");
1250
1251   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1252    [], (* XXX Augeas code needs tests. *)
1253    "look up the value of an Augeas path",
1254    "\
1255 Look up the value associated with C<path>.  If C<path>
1256 matches exactly one node, the C<value> is returned.");
1257
1258   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1259    [], (* XXX Augeas code needs tests. *)
1260    "set Augeas path to value",
1261    "\
1262 Set the value associated with C<path> to C<val>.
1263
1264 In the Augeas API, it is possible to clear a node by setting
1265 the value to NULL.  Due to an oversight in the libguestfs API
1266 you cannot do that with this call.  Instead you must use the
1267 C<guestfs_aug_clear> call.");
1268
1269   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1270    [], (* XXX Augeas code needs tests. *)
1271    "insert a sibling Augeas node",
1272    "\
1273 Create a new sibling C<label> for C<path>, inserting it into
1274 the tree before or after C<path> (depending on the boolean
1275 flag C<before>).
1276
1277 C<path> must match exactly one existing node in the tree, and
1278 C<label> must be a label, ie. not contain C</>, C<*> or end
1279 with a bracketed index C<[N]>.");
1280
1281   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1282    [], (* XXX Augeas code needs tests. *)
1283    "remove an Augeas path",
1284    "\
1285 Remove C<path> and all of its children.
1286
1287 On success this returns the number of entries which were removed.");
1288
1289   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1290    [], (* XXX Augeas code needs tests. *)
1291    "move Augeas node",
1292    "\
1293 Move the node C<src> to C<dest>.  C<src> must match exactly
1294 one node.  C<dest> is overwritten if it exists.");
1295
1296   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1297    [], (* XXX Augeas code needs tests. *)
1298    "return Augeas nodes which match augpath",
1299    "\
1300 Returns a list of paths which match the path expression C<path>.
1301 The returned paths are sufficiently qualified so that they match
1302 exactly one node in the current tree.");
1303
1304   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1305    [], (* XXX Augeas code needs tests. *)
1306    "write all pending Augeas changes to disk",
1307    "\
1308 This writes all pending changes to disk.
1309
1310 The flags which were passed to C<guestfs_aug_init> affect exactly
1311 how files are saved.");
1312
1313   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1314    [], (* XXX Augeas code needs tests. *)
1315    "load files into the tree",
1316    "\
1317 Load files into the tree.
1318
1319 See C<aug_load> in the Augeas documentation for the full gory
1320 details.");
1321
1322   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1323    [], (* XXX Augeas code needs tests. *)
1324    "list Augeas nodes under augpath",
1325    "\
1326 This is just a shortcut for listing C<guestfs_aug_match>
1327 C<path/*> and sorting the resulting nodes into alphabetical order.");
1328
1329   ("rm", (RErr, [Pathname "path"]), 29, [],
1330    [InitBasicFS, Always, TestRun
1331       [["touch"; "/new"];
1332        ["rm"; "/new"]];
1333     InitBasicFS, Always, TestLastFail
1334       [["rm"; "/new"]];
1335     InitBasicFS, Always, TestLastFail
1336       [["mkdir"; "/new"];
1337        ["rm"; "/new"]]],
1338    "remove a file",
1339    "\
1340 Remove the single file C<path>.");
1341
1342   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1343    [InitBasicFS, Always, TestRun
1344       [["mkdir"; "/new"];
1345        ["rmdir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["rmdir"; "/new"]];
1348     InitBasicFS, Always, TestLastFail
1349       [["touch"; "/new"];
1350        ["rmdir"; "/new"]]],
1351    "remove a directory",
1352    "\
1353 Remove the single directory C<path>.");
1354
1355   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1356    [InitBasicFS, Always, TestOutputFalse
1357       [["mkdir"; "/new"];
1358        ["mkdir"; "/new/foo"];
1359        ["touch"; "/new/foo/bar"];
1360        ["rm_rf"; "/new"];
1361        ["exists"; "/new"]]],
1362    "remove a file or directory recursively",
1363    "\
1364 Remove the file or directory C<path>, recursively removing the
1365 contents if its a directory.  This is like the C<rm -rf> shell
1366 command.");
1367
1368   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1369    [InitBasicFS, Always, TestOutputTrue
1370       [["mkdir"; "/new"];
1371        ["is_dir"; "/new"]];
1372     InitBasicFS, Always, TestLastFail
1373       [["mkdir"; "/new/foo/bar"]]],
1374    "create a directory",
1375    "\
1376 Create a directory named C<path>.");
1377
1378   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1379    [InitBasicFS, Always, TestOutputTrue
1380       [["mkdir_p"; "/new/foo/bar"];
1381        ["is_dir"; "/new/foo/bar"]];
1382     InitBasicFS, Always, TestOutputTrue
1383       [["mkdir_p"; "/new/foo/bar"];
1384        ["is_dir"; "/new/foo"]];
1385     InitBasicFS, Always, TestOutputTrue
1386       [["mkdir_p"; "/new/foo/bar"];
1387        ["is_dir"; "/new"]];
1388     (* Regression tests for RHBZ#503133: *)
1389     InitBasicFS, Always, TestRun
1390       [["mkdir"; "/new"];
1391        ["mkdir_p"; "/new"]];
1392     InitBasicFS, Always, TestLastFail
1393       [["touch"; "/new"];
1394        ["mkdir_p"; "/new"]]],
1395    "create a directory and parents",
1396    "\
1397 Create a directory named C<path>, creating any parent directories
1398 as necessary.  This is like the C<mkdir -p> shell command.");
1399
1400   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1401    [], (* XXX Need stat command to test *)
1402    "change file mode",
1403    "\
1404 Change the mode (permissions) of C<path> to C<mode>.  Only
1405 numeric modes are supported.
1406
1407 I<Note>: When using this command from guestfish, C<mode>
1408 by default would be decimal, unless you prefix it with
1409 C<0> to get octal, ie. use C<0700> not C<700>.
1410
1411 The mode actually set is affected by the umask.");
1412
1413   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1414    [], (* XXX Need stat command to test *)
1415    "change file owner and group",
1416    "\
1417 Change the file owner to C<owner> and group to C<group>.
1418
1419 Only numeric uid and gid are supported.  If you want to use
1420 names, you will need to locate and parse the password file
1421 yourself (Augeas support makes this relatively easy).");
1422
1423   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1424    [InitISOFS, Always, TestOutputTrue (
1425       [["exists"; "/empty"]]);
1426     InitISOFS, Always, TestOutputTrue (
1427       [["exists"; "/directory"]])],
1428    "test if file or directory exists",
1429    "\
1430 This returns C<true> if and only if there is a file, directory
1431 (or anything) with the given C<path> name.
1432
1433 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1434
1435   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1436    [InitISOFS, Always, TestOutputTrue (
1437       [["is_file"; "/known-1"]]);
1438     InitISOFS, Always, TestOutputFalse (
1439       [["is_file"; "/directory"]])],
1440    "test if file exists",
1441    "\
1442 This returns C<true> if and only if there is a file
1443 with the given C<path> name.  Note that it returns false for
1444 other objects like directories.
1445
1446 See also C<guestfs_stat>.");
1447
1448   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1449    [InitISOFS, Always, TestOutputFalse (
1450       [["is_dir"; "/known-3"]]);
1451     InitISOFS, Always, TestOutputTrue (
1452       [["is_dir"; "/directory"]])],
1453    "test if file exists",
1454    "\
1455 This returns C<true> if and only if there is a directory
1456 with the given C<path> name.  Note that it returns false for
1457 other objects like files.
1458
1459 See also C<guestfs_stat>.");
1460
1461   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1462    [InitEmpty, Always, TestOutputListOfDevices (
1463       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1464        ["pvcreate"; "/dev/sda1"];
1465        ["pvcreate"; "/dev/sda2"];
1466        ["pvcreate"; "/dev/sda3"];
1467        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1468    "create an LVM physical volume",
1469    "\
1470 This creates an LVM physical volume on the named C<device>,
1471 where C<device> should usually be a partition name such
1472 as C</dev/sda1>.");
1473
1474   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1475    [InitEmpty, Always, TestOutputList (
1476       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1477        ["pvcreate"; "/dev/sda1"];
1478        ["pvcreate"; "/dev/sda2"];
1479        ["pvcreate"; "/dev/sda3"];
1480        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1481        ["vgcreate"; "VG2"; "/dev/sda3"];
1482        ["vgs"]], ["VG1"; "VG2"])],
1483    "create an LVM volume group",
1484    "\
1485 This creates an LVM volume group called C<volgroup>
1486 from the non-empty list of physical volumes C<physvols>.");
1487
1488   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1489    [InitEmpty, Always, TestOutputList (
1490       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1491        ["pvcreate"; "/dev/sda1"];
1492        ["pvcreate"; "/dev/sda2"];
1493        ["pvcreate"; "/dev/sda3"];
1494        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1495        ["vgcreate"; "VG2"; "/dev/sda3"];
1496        ["lvcreate"; "LV1"; "VG1"; "50"];
1497        ["lvcreate"; "LV2"; "VG1"; "50"];
1498        ["lvcreate"; "LV3"; "VG2"; "50"];
1499        ["lvcreate"; "LV4"; "VG2"; "50"];
1500        ["lvcreate"; "LV5"; "VG2"; "50"];
1501        ["lvs"]],
1502       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1503        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1504    "create an LVM logical volume",
1505    "\
1506 This creates an LVM logical volume called C<logvol>
1507 on the volume group C<volgroup>, with C<size> megabytes.");
1508
1509   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1510    [InitEmpty, Always, TestOutput (
1511       [["part_disk"; "/dev/sda"; "mbr"];
1512        ["mkfs"; "ext2"; "/dev/sda1"];
1513        ["mount_options"; ""; "/dev/sda1"; "/"];
1514        ["write"; "/new"; "new file contents"];
1515        ["cat"; "/new"]], "new file contents")],
1516    "make a filesystem",
1517    "\
1518 This creates a filesystem on C<device> (usually a partition
1519 or LVM logical volume).  The filesystem type is C<fstype>, for
1520 example C<ext3>.");
1521
1522   ("sfdisk", (RErr, [Device "device";
1523                      Int "cyls"; Int "heads"; Int "sectors";
1524                      StringList "lines"]), 43, [DangerWillRobinson],
1525    [],
1526    "create partitions on a block device",
1527    "\
1528 This is a direct interface to the L<sfdisk(8)> program for creating
1529 partitions on block devices.
1530
1531 C<device> should be a block device, for example C</dev/sda>.
1532
1533 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1534 and sectors on the device, which are passed directly to sfdisk as
1535 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1536 of these, then the corresponding parameter is omitted.  Usually for
1537 'large' disks, you can just pass C<0> for these, but for small
1538 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1539 out the right geometry and you will need to tell it.
1540
1541 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1542 information refer to the L<sfdisk(8)> manpage.
1543
1544 To create a single partition occupying the whole disk, you would
1545 pass C<lines> as a single element list, when the single element being
1546 the string C<,> (comma).
1547
1548 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1549 C<guestfs_part_init>");
1550
1551   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1552    (* Regression test for RHBZ#597135. *)
1553    [InitBasicFS, Always, TestLastFail
1554       [["write_file"; "/new"; "abc"; "10000"]]],
1555    "create a file",
1556    "\
1557 This call creates a file called C<path>.  The contents of the
1558 file is the string C<content> (which can contain any 8 bit data),
1559 with length C<size>.
1560
1561 As a special case, if C<size> is C<0>
1562 then the length is calculated using C<strlen> (so in this case
1563 the content cannot contain embedded ASCII NULs).
1564
1565 I<NB.> Owing to a bug, writing content containing ASCII NUL
1566 characters does I<not> work, even if the length is specified.");
1567
1568   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1569    [InitEmpty, Always, TestOutputListOfDevices (
1570       [["part_disk"; "/dev/sda"; "mbr"];
1571        ["mkfs"; "ext2"; "/dev/sda1"];
1572        ["mount_options"; ""; "/dev/sda1"; "/"];
1573        ["mounts"]], ["/dev/sda1"]);
1574     InitEmpty, Always, TestOutputList (
1575       [["part_disk"; "/dev/sda"; "mbr"];
1576        ["mkfs"; "ext2"; "/dev/sda1"];
1577        ["mount_options"; ""; "/dev/sda1"; "/"];
1578        ["umount"; "/"];
1579        ["mounts"]], [])],
1580    "unmount a filesystem",
1581    "\
1582 This unmounts the given filesystem.  The filesystem may be
1583 specified either by its mountpoint (path) or the device which
1584 contains the filesystem.");
1585
1586   ("mounts", (RStringList "devices", []), 46, [],
1587    [InitBasicFS, Always, TestOutputListOfDevices (
1588       [["mounts"]], ["/dev/sda1"])],
1589    "show mounted filesystems",
1590    "\
1591 This returns the list of currently mounted filesystems.  It returns
1592 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1593
1594 Some internal mounts are not shown.
1595
1596 See also: C<guestfs_mountpoints>");
1597
1598   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1599    [InitBasicFS, Always, TestOutputList (
1600       [["umount_all"];
1601        ["mounts"]], []);
1602     (* check that umount_all can unmount nested mounts correctly: *)
1603     InitEmpty, Always, TestOutputList (
1604       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1605        ["mkfs"; "ext2"; "/dev/sda1"];
1606        ["mkfs"; "ext2"; "/dev/sda2"];
1607        ["mkfs"; "ext2"; "/dev/sda3"];
1608        ["mount_options"; ""; "/dev/sda1"; "/"];
1609        ["mkdir"; "/mp1"];
1610        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1611        ["mkdir"; "/mp1/mp2"];
1612        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1613        ["mkdir"; "/mp1/mp2/mp3"];
1614        ["umount_all"];
1615        ["mounts"]], [])],
1616    "unmount all filesystems",
1617    "\
1618 This unmounts all mounted filesystems.
1619
1620 Some internal mounts are not unmounted by this call.");
1621
1622   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1623    [],
1624    "remove all LVM LVs, VGs and PVs",
1625    "\
1626 This command removes all LVM logical volumes, volume groups
1627 and physical volumes.");
1628
1629   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1630    [InitISOFS, Always, TestOutput (
1631       [["file"; "/empty"]], "empty");
1632     InitISOFS, Always, TestOutput (
1633       [["file"; "/known-1"]], "ASCII text");
1634     InitISOFS, Always, TestLastFail (
1635       [["file"; "/notexists"]]);
1636     InitISOFS, Always, TestOutput (
1637       [["file"; "/abssymlink"]], "symbolic link");
1638     InitISOFS, Always, TestOutput (
1639       [["file"; "/directory"]], "directory")],
1640    "determine file type",
1641    "\
1642 This call uses the standard L<file(1)> command to determine
1643 the type or contents of the file.
1644
1645 This call will also transparently look inside various types
1646 of compressed file.
1647
1648 The exact command which runs is C<file -zb path>.  Note in
1649 particular that the filename is not prepended to the output
1650 (the C<-b> option).
1651
1652 This command can also be used on C</dev/> devices
1653 (and partitions, LV names).  You can for example use this
1654 to determine if a device contains a filesystem, although
1655 it's usually better to use C<guestfs_vfs_type>.
1656
1657 If the C<path> does not begin with C</dev/> then
1658 this command only works for the content of regular files.
1659 For other file types (directory, symbolic link etc) it
1660 will just return the string C<directory> etc.");
1661
1662   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1663    [InitBasicFS, Always, TestOutput (
1664       [["upload"; "test-command"; "/test-command"];
1665        ["chmod"; "0o755"; "/test-command"];
1666        ["command"; "/test-command 1"]], "Result1");
1667     InitBasicFS, Always, TestOutput (
1668       [["upload"; "test-command"; "/test-command"];
1669        ["chmod"; "0o755"; "/test-command"];
1670        ["command"; "/test-command 2"]], "Result2\n");
1671     InitBasicFS, Always, TestOutput (
1672       [["upload"; "test-command"; "/test-command"];
1673        ["chmod"; "0o755"; "/test-command"];
1674        ["command"; "/test-command 3"]], "\nResult3");
1675     InitBasicFS, Always, TestOutput (
1676       [["upload"; "test-command"; "/test-command"];
1677        ["chmod"; "0o755"; "/test-command"];
1678        ["command"; "/test-command 4"]], "\nResult4\n");
1679     InitBasicFS, Always, TestOutput (
1680       [["upload"; "test-command"; "/test-command"];
1681        ["chmod"; "0o755"; "/test-command"];
1682        ["command"; "/test-command 5"]], "\nResult5\n\n");
1683     InitBasicFS, Always, TestOutput (
1684       [["upload"; "test-command"; "/test-command"];
1685        ["chmod"; "0o755"; "/test-command"];
1686        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1687     InitBasicFS, Always, TestOutput (
1688       [["upload"; "test-command"; "/test-command"];
1689        ["chmod"; "0o755"; "/test-command"];
1690        ["command"; "/test-command 7"]], "");
1691     InitBasicFS, Always, TestOutput (
1692       [["upload"; "test-command"; "/test-command"];
1693        ["chmod"; "0o755"; "/test-command"];
1694        ["command"; "/test-command 8"]], "\n");
1695     InitBasicFS, Always, TestOutput (
1696       [["upload"; "test-command"; "/test-command"];
1697        ["chmod"; "0o755"; "/test-command"];
1698        ["command"; "/test-command 9"]], "\n\n");
1699     InitBasicFS, Always, TestOutput (
1700       [["upload"; "test-command"; "/test-command"];
1701        ["chmod"; "0o755"; "/test-command"];
1702        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1703     InitBasicFS, Always, TestOutput (
1704       [["upload"; "test-command"; "/test-command"];
1705        ["chmod"; "0o755"; "/test-command"];
1706        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1707     InitBasicFS, Always, TestLastFail (
1708       [["upload"; "test-command"; "/test-command"];
1709        ["chmod"; "0o755"; "/test-command"];
1710        ["command"; "/test-command"]])],
1711    "run a command from the guest filesystem",
1712    "\
1713 This call runs a command from the guest filesystem.  The
1714 filesystem must be mounted, and must contain a compatible
1715 operating system (ie. something Linux, with the same
1716 or compatible processor architecture).
1717
1718 The single parameter is an argv-style list of arguments.
1719 The first element is the name of the program to run.
1720 Subsequent elements are parameters.  The list must be
1721 non-empty (ie. must contain a program name).  Note that
1722 the command runs directly, and is I<not> invoked via
1723 the shell (see C<guestfs_sh>).
1724
1725 The return value is anything printed to I<stdout> by
1726 the command.
1727
1728 If the command returns a non-zero exit status, then
1729 this function returns an error message.  The error message
1730 string is the content of I<stderr> from the command.
1731
1732 The C<$PATH> environment variable will contain at least
1733 C</usr/bin> and C</bin>.  If you require a program from
1734 another location, you should provide the full path in the
1735 first parameter.
1736
1737 Shared libraries and data files required by the program
1738 must be available on filesystems which are mounted in the
1739 correct places.  It is the caller's responsibility to ensure
1740 all filesystems that are needed are mounted at the right
1741 locations.");
1742
1743   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1744    [InitBasicFS, Always, TestOutputList (
1745       [["upload"; "test-command"; "/test-command"];
1746        ["chmod"; "0o755"; "/test-command"];
1747        ["command_lines"; "/test-command 1"]], ["Result1"]);
1748     InitBasicFS, Always, TestOutputList (
1749       [["upload"; "test-command"; "/test-command"];
1750        ["chmod"; "0o755"; "/test-command"];
1751        ["command_lines"; "/test-command 2"]], ["Result2"]);
1752     InitBasicFS, Always, TestOutputList (
1753       [["upload"; "test-command"; "/test-command"];
1754        ["chmod"; "0o755"; "/test-command"];
1755        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1756     InitBasicFS, Always, TestOutputList (
1757       [["upload"; "test-command"; "/test-command"];
1758        ["chmod"; "0o755"; "/test-command"];
1759        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1760     InitBasicFS, Always, TestOutputList (
1761       [["upload"; "test-command"; "/test-command"];
1762        ["chmod"; "0o755"; "/test-command"];
1763        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1764     InitBasicFS, Always, TestOutputList (
1765       [["upload"; "test-command"; "/test-command"];
1766        ["chmod"; "0o755"; "/test-command"];
1767        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1768     InitBasicFS, Always, TestOutputList (
1769       [["upload"; "test-command"; "/test-command"];
1770        ["chmod"; "0o755"; "/test-command"];
1771        ["command_lines"; "/test-command 7"]], []);
1772     InitBasicFS, Always, TestOutputList (
1773       [["upload"; "test-command"; "/test-command"];
1774        ["chmod"; "0o755"; "/test-command"];
1775        ["command_lines"; "/test-command 8"]], [""]);
1776     InitBasicFS, Always, TestOutputList (
1777       [["upload"; "test-command"; "/test-command"];
1778        ["chmod"; "0o755"; "/test-command"];
1779        ["command_lines"; "/test-command 9"]], ["";""]);
1780     InitBasicFS, Always, TestOutputList (
1781       [["upload"; "test-command"; "/test-command"];
1782        ["chmod"; "0o755"; "/test-command"];
1783        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1784     InitBasicFS, Always, TestOutputList (
1785       [["upload"; "test-command"; "/test-command"];
1786        ["chmod"; "0o755"; "/test-command"];
1787        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1788    "run a command, returning lines",
1789    "\
1790 This is the same as C<guestfs_command>, but splits the
1791 result into a list of lines.
1792
1793 See also: C<guestfs_sh_lines>");
1794
1795   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1796    [InitISOFS, Always, TestOutputStruct (
1797       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1798    "get file information",
1799    "\
1800 Returns file information for the given C<path>.
1801
1802 This is the same as the C<stat(2)> system call.");
1803
1804   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1805    [InitISOFS, Always, TestOutputStruct (
1806       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1807    "get file information for a symbolic link",
1808    "\
1809 Returns file information for the given C<path>.
1810
1811 This is the same as C<guestfs_stat> except that if C<path>
1812 is a symbolic link, then the link is stat-ed, not the file it
1813 refers to.
1814
1815 This is the same as the C<lstat(2)> system call.");
1816
1817   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1818    [InitISOFS, Always, TestOutputStruct (
1819       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1820    "get file system statistics",
1821    "\
1822 Returns file system statistics for any mounted file system.
1823 C<path> should be a file or directory in the mounted file system
1824 (typically it is the mount point itself, but it doesn't need to be).
1825
1826 This is the same as the C<statvfs(2)> system call.");
1827
1828   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1829    [], (* XXX test *)
1830    "get ext2/ext3/ext4 superblock details",
1831    "\
1832 This returns the contents of the ext2, ext3 or ext4 filesystem
1833 superblock on C<device>.
1834
1835 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1836 manpage for more details.  The list of fields returned isn't
1837 clearly defined, and depends on both the version of C<tune2fs>
1838 that libguestfs was built against, and the filesystem itself.");
1839
1840   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1841    [InitEmpty, Always, TestOutputTrue (
1842       [["blockdev_setro"; "/dev/sda"];
1843        ["blockdev_getro"; "/dev/sda"]])],
1844    "set block device to read-only",
1845    "\
1846 Sets the block device named C<device> to read-only.
1847
1848 This uses the L<blockdev(8)> command.");
1849
1850   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1851    [InitEmpty, Always, TestOutputFalse (
1852       [["blockdev_setrw"; "/dev/sda"];
1853        ["blockdev_getro"; "/dev/sda"]])],
1854    "set block device to read-write",
1855    "\
1856 Sets the block device named C<device> to read-write.
1857
1858 This uses the L<blockdev(8)> command.");
1859
1860   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1861    [InitEmpty, Always, TestOutputTrue (
1862       [["blockdev_setro"; "/dev/sda"];
1863        ["blockdev_getro"; "/dev/sda"]])],
1864    "is block device set to read-only",
1865    "\
1866 Returns a boolean indicating if the block device is read-only
1867 (true if read-only, false if not).
1868
1869 This uses the L<blockdev(8)> command.");
1870
1871   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1872    [InitEmpty, Always, TestOutputInt (
1873       [["blockdev_getss"; "/dev/sda"]], 512)],
1874    "get sectorsize of block device",
1875    "\
1876 This returns the size of sectors on a block device.
1877 Usually 512, but can be larger for modern devices.
1878
1879 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1880 for that).
1881
1882 This uses the L<blockdev(8)> command.");
1883
1884   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1885    [InitEmpty, Always, TestOutputInt (
1886       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1887    "get blocksize of block device",
1888    "\
1889 This returns the block size of a device.
1890
1891 (Note this is different from both I<size in blocks> and
1892 I<filesystem block size>).
1893
1894 This uses the L<blockdev(8)> command.");
1895
1896   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1897    [], (* XXX test *)
1898    "set blocksize of block device",
1899    "\
1900 This sets the block size of a device.
1901
1902 (Note this is different from both I<size in blocks> and
1903 I<filesystem block size>).
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1908    [InitEmpty, Always, TestOutputInt (
1909       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1910    "get total size of device in 512-byte sectors",
1911    "\
1912 This returns the size of the device in units of 512-byte sectors
1913 (even if the sectorsize isn't 512 bytes ... weird).
1914
1915 See also C<guestfs_blockdev_getss> for the real sector size of
1916 the device, and C<guestfs_blockdev_getsize64> for the more
1917 useful I<size in bytes>.
1918
1919 This uses the L<blockdev(8)> command.");
1920
1921   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1922    [InitEmpty, Always, TestOutputInt (
1923       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1924    "get total size of device in bytes",
1925    "\
1926 This returns the size of the device in bytes.
1927
1928 See also C<guestfs_blockdev_getsz>.
1929
1930 This uses the L<blockdev(8)> command.");
1931
1932   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1933    [InitEmpty, Always, TestRun
1934       [["blockdev_flushbufs"; "/dev/sda"]]],
1935    "flush device buffers",
1936    "\
1937 This tells the kernel to flush internal buffers associated
1938 with C<device>.
1939
1940 This uses the L<blockdev(8)> command.");
1941
1942   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1943    [InitEmpty, Always, TestRun
1944       [["blockdev_rereadpt"; "/dev/sda"]]],
1945    "reread partition table",
1946    "\
1947 Reread the partition table on C<device>.
1948
1949 This uses the L<blockdev(8)> command.");
1950
1951   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1952    [InitBasicFS, Always, TestOutput (
1953       (* Pick a file from cwd which isn't likely to change. *)
1954       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1955        ["checksum"; "md5"; "/COPYING.LIB"]],
1956       Digest.to_hex (Digest.file "COPYING.LIB"))],
1957    "upload a file from the local machine",
1958    "\
1959 Upload local file C<filename> to C<remotefilename> on the
1960 filesystem.
1961
1962 C<filename> can also be a named pipe.
1963
1964 See also C<guestfs_download>.");
1965
1966   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1967    [InitBasicFS, Always, TestOutput (
1968       (* Pick a file from cwd which isn't likely to change. *)
1969       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1970        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1971        ["upload"; "testdownload.tmp"; "/upload"];
1972        ["checksum"; "md5"; "/upload"]],
1973       Digest.to_hex (Digest.file "COPYING.LIB"))],
1974    "download a file to the local machine",
1975    "\
1976 Download file C<remotefilename> and save it as C<filename>
1977 on the local machine.
1978
1979 C<filename> can also be a named pipe.
1980
1981 See also C<guestfs_upload>, C<guestfs_cat>.");
1982
1983   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1984    [InitISOFS, Always, TestOutput (
1985       [["checksum"; "crc"; "/known-3"]], "2891671662");
1986     InitISOFS, Always, TestLastFail (
1987       [["checksum"; "crc"; "/notexists"]]);
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1990     InitISOFS, Always, TestOutput (
1991       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1992     InitISOFS, Always, TestOutput (
1993       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1994     InitISOFS, Always, TestOutput (
1995       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1998     InitISOFS, Always, TestOutput (
1999       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
2000     (* Test for RHBZ#579608, absolute symbolic links. *)
2001     InitISOFS, Always, TestOutput (
2002       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2003    "compute MD5, SHAx or CRC checksum of file",
2004    "\
2005 This call computes the MD5, SHAx or CRC checksum of the
2006 file named C<path>.
2007
2008 The type of checksum to compute is given by the C<csumtype>
2009 parameter which must have one of the following values:
2010
2011 =over 4
2012
2013 =item C<crc>
2014
2015 Compute the cyclic redundancy check (CRC) specified by POSIX
2016 for the C<cksum> command.
2017
2018 =item C<md5>
2019
2020 Compute the MD5 hash (using the C<md5sum> program).
2021
2022 =item C<sha1>
2023
2024 Compute the SHA1 hash (using the C<sha1sum> program).
2025
2026 =item C<sha224>
2027
2028 Compute the SHA224 hash (using the C<sha224sum> program).
2029
2030 =item C<sha256>
2031
2032 Compute the SHA256 hash (using the C<sha256sum> program).
2033
2034 =item C<sha384>
2035
2036 Compute the SHA384 hash (using the C<sha384sum> program).
2037
2038 =item C<sha512>
2039
2040 Compute the SHA512 hash (using the C<sha512sum> program).
2041
2042 =back
2043
2044 The checksum is returned as a printable string.
2045
2046 To get the checksum for a device, use C<guestfs_checksum_device>.
2047
2048 To get the checksums for many files, use C<guestfs_checksums_out>.");
2049
2050   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2051    [InitBasicFS, Always, TestOutput (
2052       [["tar_in"; "../images/helloworld.tar"; "/"];
2053        ["cat"; "/hello"]], "hello\n")],
2054    "unpack tarfile to directory",
2055    "\
2056 This command uploads and unpacks local file C<tarfile> (an
2057 I<uncompressed> tar file) into C<directory>.
2058
2059 To upload a compressed tarball, use C<guestfs_tgz_in>
2060 or C<guestfs_txz_in>.");
2061
2062   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2063    [],
2064    "pack directory into tarfile",
2065    "\
2066 This command packs the contents of C<directory> and downloads
2067 it to local file C<tarfile>.
2068
2069 To download a compressed tarball, use C<guestfs_tgz_out>
2070 or C<guestfs_txz_out>.");
2071
2072   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2073    [InitBasicFS, Always, TestOutput (
2074       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2075        ["cat"; "/hello"]], "hello\n")],
2076    "unpack compressed tarball to directory",
2077    "\
2078 This command uploads and unpacks local file C<tarball> (a
2079 I<gzip compressed> tar file) into C<directory>.
2080
2081 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2082
2083   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2084    [],
2085    "pack directory into compressed tarball",
2086    "\
2087 This command packs the contents of C<directory> and downloads
2088 it to local file C<tarball>.
2089
2090 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2091
2092   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2093    [InitBasicFS, Always, TestLastFail (
2094       [["umount"; "/"];
2095        ["mount_ro"; "/dev/sda1"; "/"];
2096        ["touch"; "/new"]]);
2097     InitBasicFS, Always, TestOutput (
2098       [["write"; "/new"; "data"];
2099        ["umount"; "/"];
2100        ["mount_ro"; "/dev/sda1"; "/"];
2101        ["cat"; "/new"]], "data")],
2102    "mount a guest disk, read-only",
2103    "\
2104 This is the same as the C<guestfs_mount> command, but it
2105 mounts the filesystem with the read-only (I<-o ro>) flag.");
2106
2107   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2108    [],
2109    "mount a guest disk with mount options",
2110    "\
2111 This is the same as the C<guestfs_mount> command, but it
2112 allows you to set the mount options as for the
2113 L<mount(8)> I<-o> flag.
2114
2115 If the C<options> parameter is an empty string, then
2116 no options are passed (all options default to whatever
2117 the filesystem uses).");
2118
2119   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2120    [],
2121    "mount a guest disk with mount options and vfstype",
2122    "\
2123 This is the same as the C<guestfs_mount> command, but it
2124 allows you to set both the mount options and the vfstype
2125 as for the L<mount(8)> I<-o> and I<-t> flags.");
2126
2127   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2128    [],
2129    "debugging and internals",
2130    "\
2131 The C<guestfs_debug> command exposes some internals of
2132 C<guestfsd> (the guestfs daemon) that runs inside the
2133 qemu subprocess.
2134
2135 There is no comprehensive help for this command.  You have
2136 to look at the file C<daemon/debug.c> in the libguestfs source
2137 to find out what you can do.");
2138
2139   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2140    [InitEmpty, Always, TestOutputList (
2141       [["part_disk"; "/dev/sda"; "mbr"];
2142        ["pvcreate"; "/dev/sda1"];
2143        ["vgcreate"; "VG"; "/dev/sda1"];
2144        ["lvcreate"; "LV1"; "VG"; "50"];
2145        ["lvcreate"; "LV2"; "VG"; "50"];
2146        ["lvremove"; "/dev/VG/LV1"];
2147        ["lvs"]], ["/dev/VG/LV2"]);
2148     InitEmpty, Always, TestOutputList (
2149       [["part_disk"; "/dev/sda"; "mbr"];
2150        ["pvcreate"; "/dev/sda1"];
2151        ["vgcreate"; "VG"; "/dev/sda1"];
2152        ["lvcreate"; "LV1"; "VG"; "50"];
2153        ["lvcreate"; "LV2"; "VG"; "50"];
2154        ["lvremove"; "/dev/VG"];
2155        ["lvs"]], []);
2156     InitEmpty, Always, TestOutputList (
2157       [["part_disk"; "/dev/sda"; "mbr"];
2158        ["pvcreate"; "/dev/sda1"];
2159        ["vgcreate"; "VG"; "/dev/sda1"];
2160        ["lvcreate"; "LV1"; "VG"; "50"];
2161        ["lvcreate"; "LV2"; "VG"; "50"];
2162        ["lvremove"; "/dev/VG"];
2163        ["vgs"]], ["VG"])],
2164    "remove an LVM logical volume",
2165    "\
2166 Remove an LVM logical volume C<device>, where C<device> is
2167 the path to the LV, such as C</dev/VG/LV>.
2168
2169 You can also remove all LVs in a volume group by specifying
2170 the VG name, C</dev/VG>.");
2171
2172   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2173    [InitEmpty, Always, TestOutputList (
2174       [["part_disk"; "/dev/sda"; "mbr"];
2175        ["pvcreate"; "/dev/sda1"];
2176        ["vgcreate"; "VG"; "/dev/sda1"];
2177        ["lvcreate"; "LV1"; "VG"; "50"];
2178        ["lvcreate"; "LV2"; "VG"; "50"];
2179        ["vgremove"; "VG"];
2180        ["lvs"]], []);
2181     InitEmpty, Always, TestOutputList (
2182       [["part_disk"; "/dev/sda"; "mbr"];
2183        ["pvcreate"; "/dev/sda1"];
2184        ["vgcreate"; "VG"; "/dev/sda1"];
2185        ["lvcreate"; "LV1"; "VG"; "50"];
2186        ["lvcreate"; "LV2"; "VG"; "50"];
2187        ["vgremove"; "VG"];
2188        ["vgs"]], [])],
2189    "remove an LVM volume group",
2190    "\
2191 Remove an LVM volume group C<vgname>, (for example C<VG>).
2192
2193 This also forcibly removes all logical volumes in the volume
2194 group (if any).");
2195
2196   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2197    [InitEmpty, Always, TestOutputListOfDevices (
2198       [["part_disk"; "/dev/sda"; "mbr"];
2199        ["pvcreate"; "/dev/sda1"];
2200        ["vgcreate"; "VG"; "/dev/sda1"];
2201        ["lvcreate"; "LV1"; "VG"; "50"];
2202        ["lvcreate"; "LV2"; "VG"; "50"];
2203        ["vgremove"; "VG"];
2204        ["pvremove"; "/dev/sda1"];
2205        ["lvs"]], []);
2206     InitEmpty, Always, TestOutputListOfDevices (
2207       [["part_disk"; "/dev/sda"; "mbr"];
2208        ["pvcreate"; "/dev/sda1"];
2209        ["vgcreate"; "VG"; "/dev/sda1"];
2210        ["lvcreate"; "LV1"; "VG"; "50"];
2211        ["lvcreate"; "LV2"; "VG"; "50"];
2212        ["vgremove"; "VG"];
2213        ["pvremove"; "/dev/sda1"];
2214        ["vgs"]], []);
2215     InitEmpty, Always, TestOutputListOfDevices (
2216       [["part_disk"; "/dev/sda"; "mbr"];
2217        ["pvcreate"; "/dev/sda1"];
2218        ["vgcreate"; "VG"; "/dev/sda1"];
2219        ["lvcreate"; "LV1"; "VG"; "50"];
2220        ["lvcreate"; "LV2"; "VG"; "50"];
2221        ["vgremove"; "VG"];
2222        ["pvremove"; "/dev/sda1"];
2223        ["pvs"]], [])],
2224    "remove an LVM physical volume",
2225    "\
2226 This wipes a physical volume C<device> so that LVM will no longer
2227 recognise it.
2228
2229 The implementation uses the C<pvremove> command which refuses to
2230 wipe physical volumes that contain any volume groups, so you have
2231 to remove those first.");
2232
2233   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2234    [InitBasicFS, Always, TestOutput (
2235       [["set_e2label"; "/dev/sda1"; "testlabel"];
2236        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2237    "set the ext2/3/4 filesystem label",
2238    "\
2239 This sets the ext2/3/4 filesystem label of the filesystem on
2240 C<device> to C<label>.  Filesystem labels are limited to
2241 16 characters.
2242
2243 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2244 to return the existing label on a filesystem.");
2245
2246   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2247    [],
2248    "get the ext2/3/4 filesystem label",
2249    "\
2250 This returns the ext2/3/4 filesystem label of the filesystem on
2251 C<device>.");
2252
2253   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2254    (let uuid = uuidgen () in
2255     [InitBasicFS, Always, TestOutput (
2256        [["set_e2uuid"; "/dev/sda1"; uuid];
2257         ["get_e2uuid"; "/dev/sda1"]], uuid);
2258      InitBasicFS, Always, TestOutput (
2259        [["set_e2uuid"; "/dev/sda1"; "clear"];
2260         ["get_e2uuid"; "/dev/sda1"]], "");
2261      (* We can't predict what UUIDs will be, so just check the commands run. *)
2262      InitBasicFS, Always, TestRun (
2263        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2264      InitBasicFS, Always, TestRun (
2265        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2266    "set the ext2/3/4 filesystem UUID",
2267    "\
2268 This sets the ext2/3/4 filesystem UUID of the filesystem on
2269 C<device> to C<uuid>.  The format of the UUID and alternatives
2270 such as C<clear>, C<random> and C<time> are described in the
2271 L<tune2fs(8)> manpage.
2272
2273 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2274 to return the existing UUID of a filesystem.");
2275
2276   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2277    (* Regression test for RHBZ#597112. *)
2278    (let uuid = uuidgen () in
2279     [InitBasicFS, Always, TestOutput (
2280        [["mke2journal"; "1024"; "/dev/sdb"];
2281         ["set_e2uuid"; "/dev/sdb"; uuid];
2282         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2283    "get the ext2/3/4 filesystem UUID",
2284    "\
2285 This returns the ext2/3/4 filesystem UUID of the filesystem on
2286 C<device>.");
2287
2288   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2289    [InitBasicFS, Always, TestOutputInt (
2290       [["umount"; "/dev/sda1"];
2291        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2292     InitBasicFS, Always, TestOutputInt (
2293       [["umount"; "/dev/sda1"];
2294        ["zero"; "/dev/sda1"];
2295        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2296    "run the filesystem checker",
2297    "\
2298 This runs the filesystem checker (fsck) on C<device> which
2299 should have filesystem type C<fstype>.
2300
2301 The returned integer is the status.  See L<fsck(8)> for the
2302 list of status codes from C<fsck>.
2303
2304 Notes:
2305
2306 =over 4
2307
2308 =item *
2309
2310 Multiple status codes can be summed together.
2311
2312 =item *
2313
2314 A non-zero return code can mean \"success\", for example if
2315 errors have been corrected on the filesystem.
2316
2317 =item *
2318
2319 Checking or repairing NTFS volumes is not supported
2320 (by linux-ntfs).
2321
2322 =back
2323
2324 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2325
2326   ("zero", (RErr, [Device "device"]), 85, [],
2327    [InitBasicFS, Always, TestOutput (
2328       [["umount"; "/dev/sda1"];
2329        ["zero"; "/dev/sda1"];
2330        ["file"; "/dev/sda1"]], "data")],
2331    "write zeroes to the device",
2332    "\
2333 This command writes zeroes over the first few blocks of C<device>.
2334
2335 How many blocks are zeroed isn't specified (but it's I<not> enough
2336 to securely wipe the device).  It should be sufficient to remove
2337 any partition tables, filesystem superblocks and so on.
2338
2339 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2340
2341   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2342    (* See:
2343     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2344     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2345     *)
2346    [InitBasicFS, Always, TestOutputTrue (
2347       [["mkdir_p"; "/boot/grub"];
2348        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2349        ["grub_install"; "/"; "/dev/vda"];
2350        ["is_dir"; "/boot"]])],
2351    "install GRUB",
2352    "\
2353 This command installs GRUB (the Grand Unified Bootloader) on
2354 C<device>, with the root directory being C<root>.
2355
2356 Note: If grub-install reports the error
2357 \"No suitable drive was found in the generated device map.\"
2358 it may be that you need to create a C</boot/grub/device.map>
2359 file first that contains the mapping between grub device names
2360 and Linux device names.  It is usually sufficient to create
2361 a file containing:
2362
2363  (hd0) /dev/vda
2364
2365 replacing C</dev/vda> with the name of the installation device.");
2366
2367   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2368    [InitBasicFS, Always, TestOutput (
2369       [["write"; "/old"; "file content"];
2370        ["cp"; "/old"; "/new"];
2371        ["cat"; "/new"]], "file content");
2372     InitBasicFS, Always, TestOutputTrue (
2373       [["write"; "/old"; "file content"];
2374        ["cp"; "/old"; "/new"];
2375        ["is_file"; "/old"]]);
2376     InitBasicFS, Always, TestOutput (
2377       [["write"; "/old"; "file content"];
2378        ["mkdir"; "/dir"];
2379        ["cp"; "/old"; "/dir/new"];
2380        ["cat"; "/dir/new"]], "file content")],
2381    "copy a file",
2382    "\
2383 This copies a file from C<src> to C<dest> where C<dest> is
2384 either a destination filename or destination directory.");
2385
2386   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2387    [InitBasicFS, Always, TestOutput (
2388       [["mkdir"; "/olddir"];
2389        ["mkdir"; "/newdir"];
2390        ["write"; "/olddir/file"; "file content"];
2391        ["cp_a"; "/olddir"; "/newdir"];
2392        ["cat"; "/newdir/olddir/file"]], "file content")],
2393    "copy a file or directory recursively",
2394    "\
2395 This copies a file or directory from C<src> to C<dest>
2396 recursively using the C<cp -a> command.");
2397
2398   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2399    [InitBasicFS, Always, TestOutput (
2400       [["write"; "/old"; "file content"];
2401        ["mv"; "/old"; "/new"];
2402        ["cat"; "/new"]], "file content");
2403     InitBasicFS, Always, TestOutputFalse (
2404       [["write"; "/old"; "file content"];
2405        ["mv"; "/old"; "/new"];
2406        ["is_file"; "/old"]])],
2407    "move a file",
2408    "\
2409 This moves a file from C<src> to C<dest> where C<dest> is
2410 either a destination filename or destination directory.");
2411
2412   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2413    [InitEmpty, Always, TestRun (
2414       [["drop_caches"; "3"]])],
2415    "drop kernel page cache, dentries and inodes",
2416    "\
2417 This instructs the guest kernel to drop its page cache,
2418 and/or dentries and inode caches.  The parameter C<whattodrop>
2419 tells the kernel what precisely to drop, see
2420 L<http://linux-mm.org/Drop_Caches>
2421
2422 Setting C<whattodrop> to 3 should drop everything.
2423
2424 This automatically calls L<sync(2)> before the operation,
2425 so that the maximum guest memory is freed.");
2426
2427   ("dmesg", (RString "kmsgs", []), 91, [],
2428    [InitEmpty, Always, TestRun (
2429       [["dmesg"]])],
2430    "return kernel messages",
2431    "\
2432 This returns the kernel messages (C<dmesg> output) from
2433 the guest kernel.  This is sometimes useful for extended
2434 debugging of problems.
2435
2436 Another way to get the same information is to enable
2437 verbose messages with C<guestfs_set_verbose> or by setting
2438 the environment variable C<LIBGUESTFS_DEBUG=1> before
2439 running the program.");
2440
2441   ("ping_daemon", (RErr, []), 92, [],
2442    [InitEmpty, Always, TestRun (
2443       [["ping_daemon"]])],
2444    "ping the guest daemon",
2445    "\
2446 This is a test probe into the guestfs daemon running inside
2447 the qemu subprocess.  Calling this function checks that the
2448 daemon responds to the ping message, without affecting the daemon
2449 or attached block device(s) in any other way.");
2450
2451   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2452    [InitBasicFS, Always, TestOutputTrue (
2453       [["write"; "/file1"; "contents of a file"];
2454        ["cp"; "/file1"; "/file2"];
2455        ["equal"; "/file1"; "/file2"]]);
2456     InitBasicFS, Always, TestOutputFalse (
2457       [["write"; "/file1"; "contents of a file"];
2458        ["write"; "/file2"; "contents of another file"];
2459        ["equal"; "/file1"; "/file2"]]);
2460     InitBasicFS, Always, TestLastFail (
2461       [["equal"; "/file1"; "/file2"]])],
2462    "test if two files have equal contents",
2463    "\
2464 This compares the two files C<file1> and C<file2> and returns
2465 true if their content is exactly equal, or false otherwise.
2466
2467 The external L<cmp(1)> program is used for the comparison.");
2468
2469   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2470    [InitISOFS, Always, TestOutputList (
2471       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2472     InitISOFS, Always, TestOutputList (
2473       [["strings"; "/empty"]], []);
2474     (* Test for RHBZ#579608, absolute symbolic links. *)
2475     InitISOFS, Always, TestRun (
2476       [["strings"; "/abssymlink"]])],
2477    "print the printable strings in a file",
2478    "\
2479 This runs the L<strings(1)> command on a file and returns
2480 the list of printable strings found.");
2481
2482   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2483    [InitISOFS, Always, TestOutputList (
2484       [["strings_e"; "b"; "/known-5"]], []);
2485     InitBasicFS, Always, TestOutputList (
2486       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2487        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2488    "print the printable strings in a file",
2489    "\
2490 This is like the C<guestfs_strings> command, but allows you to
2491 specify the encoding of strings that are looked for in
2492 the source file C<path>.
2493
2494 Allowed encodings are:
2495
2496 =over 4
2497
2498 =item s
2499
2500 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2501 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2502
2503 =item S
2504
2505 Single 8-bit-byte characters.
2506
2507 =item b
2508
2509 16-bit big endian strings such as those encoded in
2510 UTF-16BE or UCS-2BE.
2511
2512 =item l (lower case letter L)
2513
2514 16-bit little endian such as UTF-16LE and UCS-2LE.
2515 This is useful for examining binaries in Windows guests.
2516
2517 =item B
2518
2519 32-bit big endian such as UCS-4BE.
2520
2521 =item L
2522
2523 32-bit little endian such as UCS-4LE.
2524
2525 =back
2526
2527 The returned strings are transcoded to UTF-8.");
2528
2529   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2530    [InitISOFS, Always, TestOutput (
2531       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2532     (* Test for RHBZ#501888c2 regression which caused large hexdump
2533      * commands to segfault.
2534      *)
2535     InitISOFS, Always, TestRun (
2536       [["hexdump"; "/100krandom"]]);
2537     (* Test for RHBZ#579608, absolute symbolic links. *)
2538     InitISOFS, Always, TestRun (
2539       [["hexdump"; "/abssymlink"]])],
2540    "dump a file in hexadecimal",
2541    "\
2542 This runs C<hexdump -C> on the given C<path>.  The result is
2543 the human-readable, canonical hex dump of the file.");
2544
2545   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2546    [InitNone, Always, TestOutput (
2547       [["part_disk"; "/dev/sda"; "mbr"];
2548        ["mkfs"; "ext3"; "/dev/sda1"];
2549        ["mount_options"; ""; "/dev/sda1"; "/"];
2550        ["write"; "/new"; "test file"];
2551        ["umount"; "/dev/sda1"];
2552        ["zerofree"; "/dev/sda1"];
2553        ["mount_options"; ""; "/dev/sda1"; "/"];
2554        ["cat"; "/new"]], "test file")],
2555    "zero unused inodes and disk blocks on ext2/3 filesystem",
2556    "\
2557 This runs the I<zerofree> program on C<device>.  This program
2558 claims to zero unused inodes and disk blocks on an ext2/3
2559 filesystem, thus making it possible to compress the filesystem
2560 more effectively.
2561
2562 You should B<not> run this program if the filesystem is
2563 mounted.
2564
2565 It is possible that using this program can damage the filesystem
2566 or data on the filesystem.");
2567
2568   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2569    [],
2570    "resize an LVM physical volume",
2571    "\
2572 This resizes (expands or shrinks) an existing LVM physical
2573 volume to match the new size of the underlying device.");
2574
2575   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2576                        Int "cyls"; Int "heads"; Int "sectors";
2577                        String "line"]), 99, [DangerWillRobinson],
2578    [],
2579    "modify a single partition on a block device",
2580    "\
2581 This runs L<sfdisk(8)> option to modify just the single
2582 partition C<n> (note: C<n> counts from 1).
2583
2584 For other parameters, see C<guestfs_sfdisk>.  You should usually
2585 pass C<0> for the cyls/heads/sectors parameters.
2586
2587 See also: C<guestfs_part_add>");
2588
2589   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2590    [],
2591    "display the partition table",
2592    "\
2593 This displays the partition table on C<device>, in the
2594 human-readable output of the L<sfdisk(8)> command.  It is
2595 not intended to be parsed.
2596
2597 See also: C<guestfs_part_list>");
2598
2599   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2600    [],
2601    "display the kernel geometry",
2602    "\
2603 This displays the kernel's idea of the geometry of C<device>.
2604
2605 The result is in human-readable format, and not designed to
2606 be parsed.");
2607
2608   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2609    [],
2610    "display the disk geometry from the partition table",
2611    "\
2612 This displays the disk geometry of C<device> read from the
2613 partition table.  Especially in the case where the underlying
2614 block device has been resized, this can be different from the
2615 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2616
2617 The result is in human-readable format, and not designed to
2618 be parsed.");
2619
2620   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2621    [],
2622    "activate or deactivate all volume groups",
2623    "\
2624 This command activates or (if C<activate> is false) deactivates
2625 all logical volumes in all volume groups.
2626 If activated, then they are made known to the
2627 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2628 then those devices disappear.
2629
2630 This command is the same as running C<vgchange -a y|n>");
2631
2632   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2633    [],
2634    "activate or deactivate some volume groups",
2635    "\
2636 This command activates or (if C<activate> is false) deactivates
2637 all logical volumes in the listed volume groups C<volgroups>.
2638 If activated, then they are made known to the
2639 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2640 then those devices disappear.
2641
2642 This command is the same as running C<vgchange -a y|n volgroups...>
2643
2644 Note that if C<volgroups> is an empty list then B<all> volume groups
2645 are activated or deactivated.");
2646
2647   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2648    [InitNone, Always, TestOutput (
2649       [["part_disk"; "/dev/sda"; "mbr"];
2650        ["pvcreate"; "/dev/sda1"];
2651        ["vgcreate"; "VG"; "/dev/sda1"];
2652        ["lvcreate"; "LV"; "VG"; "10"];
2653        ["mkfs"; "ext2"; "/dev/VG/LV"];
2654        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2655        ["write"; "/new"; "test content"];
2656        ["umount"; "/"];
2657        ["lvresize"; "/dev/VG/LV"; "20"];
2658        ["e2fsck_f"; "/dev/VG/LV"];
2659        ["resize2fs"; "/dev/VG/LV"];
2660        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2661        ["cat"; "/new"]], "test content");
2662     InitNone, Always, TestRun (
2663       (* Make an LV smaller to test RHBZ#587484. *)
2664       [["part_disk"; "/dev/sda"; "mbr"];
2665        ["pvcreate"; "/dev/sda1"];
2666        ["vgcreate"; "VG"; "/dev/sda1"];
2667        ["lvcreate"; "LV"; "VG"; "20"];
2668        ["lvresize"; "/dev/VG/LV"; "10"]])],
2669    "resize an LVM logical volume",
2670    "\
2671 This resizes (expands or shrinks) an existing LVM logical
2672 volume to C<mbytes>.  When reducing, data in the reduced part
2673 is lost.");
2674
2675   ("resize2fs", (RErr, [Device "device"]), 106, [],
2676    [], (* lvresize tests this *)
2677    "resize an ext2, ext3 or ext4 filesystem",
2678    "\
2679 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2680 the underlying device.
2681
2682 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2683 on the C<device> before calling this command.  For unknown reasons
2684 C<resize2fs> sometimes gives an error about this and sometimes not.
2685 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2686 calling this function.");
2687
2688   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2689    [InitBasicFS, Always, TestOutputList (
2690       [["find"; "/"]], ["lost+found"]);
2691     InitBasicFS, Always, TestOutputList (
2692       [["touch"; "/a"];
2693        ["mkdir"; "/b"];
2694        ["touch"; "/b/c"];
2695        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2696     InitBasicFS, Always, TestOutputList (
2697       [["mkdir_p"; "/a/b/c"];
2698        ["touch"; "/a/b/c/d"];
2699        ["find"; "/a/b/"]], ["c"; "c/d"])],
2700    "find all files and directories",
2701    "\
2702 This command lists out all files and directories, recursively,
2703 starting at C<directory>.  It is essentially equivalent to
2704 running the shell command C<find directory -print> but some
2705 post-processing happens on the output, described below.
2706
2707 This returns a list of strings I<without any prefix>.  Thus
2708 if the directory structure was:
2709
2710  /tmp/a
2711  /tmp/b
2712  /tmp/c/d
2713
2714 then the returned list from C<guestfs_find> C</tmp> would be
2715 4 elements:
2716
2717  a
2718  b
2719  c
2720  c/d
2721
2722 If C<directory> is not a directory, then this command returns
2723 an error.
2724
2725 The returned list is sorted.
2726
2727 See also C<guestfs_find0>.");
2728
2729   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2730    [], (* lvresize tests this *)
2731    "check an ext2/ext3 filesystem",
2732    "\
2733 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2734 filesystem checker on C<device>, noninteractively (C<-p>),
2735 even if the filesystem appears to be clean (C<-f>).
2736
2737 This command is only needed because of C<guestfs_resize2fs>
2738 (q.v.).  Normally you should use C<guestfs_fsck>.");
2739
2740   ("sleep", (RErr, [Int "secs"]), 109, [],
2741    [InitNone, Always, TestRun (
2742       [["sleep"; "1"]])],
2743    "sleep for some seconds",
2744    "\
2745 Sleep for C<secs> seconds.");
2746
2747   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2748    [InitNone, Always, TestOutputInt (
2749       [["part_disk"; "/dev/sda"; "mbr"];
2750        ["mkfs"; "ntfs"; "/dev/sda1"];
2751        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2752     InitNone, Always, TestOutputInt (
2753       [["part_disk"; "/dev/sda"; "mbr"];
2754        ["mkfs"; "ext2"; "/dev/sda1"];
2755        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2756    "probe NTFS volume",
2757    "\
2758 This command runs the L<ntfs-3g.probe(8)> command which probes
2759 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2760 be mounted read-write, and some cannot be mounted at all).
2761
2762 C<rw> is a boolean flag.  Set it to true if you want to test
2763 if the volume can be mounted read-write.  Set it to false if
2764 you want to test if the volume can be mounted read-only.
2765
2766 The return value is an integer which C<0> if the operation
2767 would succeed, or some non-zero value documented in the
2768 L<ntfs-3g.probe(8)> manual page.");
2769
2770   ("sh", (RString "output", [String "command"]), 111, [],
2771    [], (* XXX needs tests *)
2772    "run a command via the shell",
2773    "\
2774 This call runs a command from the guest filesystem via the
2775 guest's C</bin/sh>.
2776
2777 This is like C<guestfs_command>, but passes the command to:
2778
2779  /bin/sh -c \"command\"
2780
2781 Depending on the guest's shell, this usually results in
2782 wildcards being expanded, shell expressions being interpolated
2783 and so on.
2784
2785 All the provisos about C<guestfs_command> apply to this call.");
2786
2787   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2788    [], (* XXX needs tests *)
2789    "run a command via the shell returning lines",
2790    "\
2791 This is the same as C<guestfs_sh>, but splits the result
2792 into a list of lines.
2793
2794 See also: C<guestfs_command_lines>");
2795
2796   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2797    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2798     * code in stubs.c, since all valid glob patterns must start with "/".
2799     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2800     *)
2801    [InitBasicFS, Always, TestOutputList (
2802       [["mkdir_p"; "/a/b/c"];
2803        ["touch"; "/a/b/c/d"];
2804        ["touch"; "/a/b/c/e"];
2805        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2806     InitBasicFS, Always, TestOutputList (
2807       [["mkdir_p"; "/a/b/c"];
2808        ["touch"; "/a/b/c/d"];
2809        ["touch"; "/a/b/c/e"];
2810        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2811     InitBasicFS, Always, TestOutputList (
2812       [["mkdir_p"; "/a/b/c"];
2813        ["touch"; "/a/b/c/d"];
2814        ["touch"; "/a/b/c/e"];
2815        ["glob_expand"; "/a/*/x/*"]], [])],
2816    "expand a wildcard path",
2817    "\
2818 This command searches for all the pathnames matching
2819 C<pattern> according to the wildcard expansion rules
2820 used by the shell.
2821
2822 If no paths match, then this returns an empty list
2823 (note: not an error).
2824
2825 It is just a wrapper around the C L<glob(3)> function
2826 with flags C<GLOB_MARK|GLOB_BRACE>.
2827 See that manual page for more details.");
2828
2829   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2830    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2831       [["scrub_device"; "/dev/sdc"]])],
2832    "scrub (securely wipe) a device",
2833    "\
2834 This command writes patterns over C<device> to make data retrieval
2835 more difficult.
2836
2837 It is an interface to the L<scrub(1)> program.  See that
2838 manual page for more details.");
2839
2840   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2841    [InitBasicFS, Always, TestRun (
2842       [["write"; "/file"; "content"];
2843        ["scrub_file"; "/file"]])],
2844    "scrub (securely wipe) a file",
2845    "\
2846 This command writes patterns over a file to make data retrieval
2847 more difficult.
2848
2849 The file is I<removed> after scrubbing.
2850
2851 It is an interface to the L<scrub(1)> program.  See that
2852 manual page for more details.");
2853
2854   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2855    [], (* XXX needs testing *)
2856    "scrub (securely wipe) free space",
2857    "\
2858 This command creates the directory C<dir> and then fills it
2859 with files until the filesystem is full, and scrubs the files
2860 as for C<guestfs_scrub_file>, and deletes them.
2861 The intention is to scrub any free space on the partition
2862 containing C<dir>.
2863
2864 It is an interface to the L<scrub(1)> program.  See that
2865 manual page for more details.");
2866
2867   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2868    [InitBasicFS, Always, TestRun (
2869       [["mkdir"; "/tmp"];
2870        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2871    "create a temporary directory",
2872    "\
2873 This command creates a temporary directory.  The
2874 C<template> parameter should be a full pathname for the
2875 temporary directory name with the final six characters being
2876 \"XXXXXX\".
2877
2878 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2879 the second one being suitable for Windows filesystems.
2880
2881 The name of the temporary directory that was created
2882 is returned.
2883
2884 The temporary directory is created with mode 0700
2885 and is owned by root.
2886
2887 The caller is responsible for deleting the temporary
2888 directory and its contents after use.
2889
2890 See also: L<mkdtemp(3)>");
2891
2892   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2893    [InitISOFS, Always, TestOutputInt (
2894       [["wc_l"; "/10klines"]], 10000);
2895     (* Test for RHBZ#579608, absolute symbolic links. *)
2896     InitISOFS, Always, TestOutputInt (
2897       [["wc_l"; "/abssymlink"]], 10000)],
2898    "count lines in a file",
2899    "\
2900 This command counts the lines in a file, using the
2901 C<wc -l> external command.");
2902
2903   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2904    [InitISOFS, Always, TestOutputInt (
2905       [["wc_w"; "/10klines"]], 10000)],
2906    "count words in a file",
2907    "\
2908 This command counts the words in a file, using the
2909 C<wc -w> external command.");
2910
2911   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2912    [InitISOFS, Always, TestOutputInt (
2913       [["wc_c"; "/100kallspaces"]], 102400)],
2914    "count characters in a file",
2915    "\
2916 This command counts the characters in a file, using the
2917 C<wc -c> external command.");
2918
2919   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2920    [InitISOFS, Always, TestOutputList (
2921       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2922     (* Test for RHBZ#579608, absolute symbolic links. *)
2923     InitISOFS, Always, TestOutputList (
2924       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2925    "return first 10 lines of a file",
2926    "\
2927 This command returns up to the first 10 lines of a file as
2928 a list of strings.");
2929
2930   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2931    [InitISOFS, Always, TestOutputList (
2932       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2933     InitISOFS, Always, TestOutputList (
2934       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2935     InitISOFS, Always, TestOutputList (
2936       [["head_n"; "0"; "/10klines"]], [])],
2937    "return first N lines of a file",
2938    "\
2939 If the parameter C<nrlines> is a positive number, this returns the first
2940 C<nrlines> lines of the file C<path>.
2941
2942 If the parameter C<nrlines> is a negative number, this returns lines
2943 from the file C<path>, excluding the last C<nrlines> lines.
2944
2945 If the parameter C<nrlines> is zero, this returns an empty list.");
2946
2947   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2948    [InitISOFS, Always, TestOutputList (
2949       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2950    "return last 10 lines of a file",
2951    "\
2952 This command returns up to the last 10 lines of a file as
2953 a list of strings.");
2954
2955   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2956    [InitISOFS, Always, TestOutputList (
2957       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2958     InitISOFS, Always, TestOutputList (
2959       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2960     InitISOFS, Always, TestOutputList (
2961       [["tail_n"; "0"; "/10klines"]], [])],
2962    "return last N lines of a file",
2963    "\
2964 If the parameter C<nrlines> is a positive number, this returns the last
2965 C<nrlines> lines of the file C<path>.
2966
2967 If the parameter C<nrlines> is a negative number, this returns lines
2968 from the file C<path>, starting with the C<-nrlines>th line.
2969
2970 If the parameter C<nrlines> is zero, this returns an empty list.");
2971
2972   ("df", (RString "output", []), 125, [],
2973    [], (* XXX Tricky to test because it depends on the exact format
2974         * of the 'df' command and other imponderables.
2975         *)
2976    "report file system disk space usage",
2977    "\
2978 This command runs the C<df> command to report disk space used.
2979
2980 This command is mostly useful for interactive sessions.  It
2981 is I<not> intended that you try to parse the output string.
2982 Use C<statvfs> from programs.");
2983
2984   ("df_h", (RString "output", []), 126, [],
2985    [], (* XXX Tricky to test because it depends on the exact format
2986         * of the 'df' command and other imponderables.
2987         *)
2988    "report file system disk space usage (human readable)",
2989    "\
2990 This command runs the C<df -h> command to report disk space used
2991 in human-readable format.
2992
2993 This command is mostly useful for interactive sessions.  It
2994 is I<not> intended that you try to parse the output string.
2995 Use C<statvfs> from programs.");
2996
2997   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2998    [InitISOFS, Always, TestOutputInt (
2999       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
3000    "estimate file space usage",
3001    "\
3002 This command runs the C<du -s> command to estimate file space
3003 usage for C<path>.
3004
3005 C<path> can be a file or a directory.  If C<path> is a directory
3006 then the estimate includes the contents of the directory and all
3007 subdirectories (recursively).
3008
3009 The result is the estimated size in I<kilobytes>
3010 (ie. units of 1024 bytes).");
3011
3012   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3013    [InitISOFS, Always, TestOutputList (
3014       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3015    "list files in an initrd",
3016    "\
3017 This command lists out files contained in an initrd.
3018
3019 The files are listed without any initial C</> character.  The
3020 files are listed in the order they appear (not necessarily
3021 alphabetical).  Directory names are listed as separate items.
3022
3023 Old Linux kernels (2.4 and earlier) used a compressed ext2
3024 filesystem as initrd.  We I<only> support the newer initramfs
3025 format (compressed cpio files).");
3026
3027   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3028    [],
3029    "mount a file using the loop device",
3030    "\
3031 This command lets you mount C<file> (a filesystem image
3032 in a file) on a mount point.  It is entirely equivalent to
3033 the command C<mount -o loop file mountpoint>.");
3034
3035   ("mkswap", (RErr, [Device "device"]), 130, [],
3036    [InitEmpty, Always, TestRun (
3037       [["part_disk"; "/dev/sda"; "mbr"];
3038        ["mkswap"; "/dev/sda1"]])],
3039    "create a swap partition",
3040    "\
3041 Create a swap partition on C<device>.");
3042
3043   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3044    [InitEmpty, Always, TestRun (
3045       [["part_disk"; "/dev/sda"; "mbr"];
3046        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3047    "create a swap partition with a label",
3048    "\
3049 Create a swap partition on C<device> with label C<label>.
3050
3051 Note that you cannot attach a swap label to a block device
3052 (eg. C</dev/sda>), just to a partition.  This appears to be
3053 a limitation of the kernel or swap tools.");
3054
3055   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3056    (let uuid = uuidgen () in
3057     [InitEmpty, Always, TestRun (
3058        [["part_disk"; "/dev/sda"; "mbr"];
3059         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3060    "create a swap partition with an explicit UUID",
3061    "\
3062 Create a swap partition on C<device> with UUID C<uuid>.");
3063
3064   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3065    [InitBasicFS, Always, TestOutputStruct (
3066       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3067        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3068        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3069     InitBasicFS, Always, TestOutputStruct (
3070       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3071        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3072    "make block, character or FIFO devices",
3073    "\
3074 This call creates block or character special devices, or
3075 named pipes (FIFOs).
3076
3077 The C<mode> parameter should be the mode, using the standard
3078 constants.  C<devmajor> and C<devminor> are the
3079 device major and minor numbers, only used when creating block
3080 and character special devices.
3081
3082 Note that, just like L<mknod(2)>, the mode must be bitwise
3083 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3084 just creates a regular file).  These constants are
3085 available in the standard Linux header files, or you can use
3086 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3087 which are wrappers around this command which bitwise OR
3088 in the appropriate constant for you.
3089
3090 The mode actually set is affected by the umask.");
3091
3092   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3093    [InitBasicFS, Always, TestOutputStruct (
3094       [["mkfifo"; "0o777"; "/node"];
3095        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3096    "make FIFO (named pipe)",
3097    "\
3098 This call creates a FIFO (named pipe) called C<path> with
3099 mode C<mode>.  It is just a convenient wrapper around
3100 C<guestfs_mknod>.
3101
3102 The mode actually set is affected by the umask.");
3103
3104   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3105    [InitBasicFS, Always, TestOutputStruct (
3106       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3107        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3108    "make block device node",
3109    "\
3110 This call creates a block device node called C<path> with
3111 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3112 It is just a convenient wrapper around C<guestfs_mknod>.
3113
3114 The mode actually set is affected by the umask.");
3115
3116   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3117    [InitBasicFS, Always, TestOutputStruct (
3118       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3119        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3120    "make char device node",
3121    "\
3122 This call creates a char device node called C<path> with
3123 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3124 It is just a convenient wrapper around C<guestfs_mknod>.
3125
3126 The mode actually set is affected by the umask.");
3127
3128   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3129    [InitEmpty, Always, TestOutputInt (
3130       [["umask"; "0o22"]], 0o22)],
3131    "set file mode creation mask (umask)",
3132    "\
3133 This function sets the mask used for creating new files and
3134 device nodes to C<mask & 0777>.
3135
3136 Typical umask values would be C<022> which creates new files
3137 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3138 C<002> which creates new files with permissions like
3139 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3140
3141 The default umask is C<022>.  This is important because it
3142 means that directories and device nodes will be created with
3143 C<0644> or C<0755> mode even if you specify C<0777>.
3144
3145 See also C<guestfs_get_umask>,
3146 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3147
3148 This call returns the previous umask.");
3149
3150   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3151    [],
3152    "read directories entries",
3153    "\
3154 This returns the list of directory entries in directory C<dir>.
3155
3156 All entries in the directory are returned, including C<.> and
3157 C<..>.  The entries are I<not> sorted, but returned in the same
3158 order as the underlying filesystem.
3159
3160 Also this call returns basic file type information about each
3161 file.  The C<ftyp> field will contain one of the following characters:
3162
3163 =over 4
3164
3165 =item 'b'
3166
3167 Block special
3168
3169 =item 'c'
3170
3171 Char special
3172
3173 =item 'd'
3174
3175 Directory
3176
3177 =item 'f'
3178
3179 FIFO (named pipe)
3180
3181 =item 'l'
3182
3183 Symbolic link
3184
3185 =item 'r'
3186
3187 Regular file
3188
3189 =item 's'
3190
3191 Socket
3192
3193 =item 'u'
3194
3195 Unknown file type
3196
3197 =item '?'
3198
3199 The L<readdir(3)> call returned a C<d_type> field with an
3200 unexpected value
3201
3202 =back
3203
3204 This function is primarily intended for use by programs.  To
3205 get a simple list of names, use C<guestfs_ls>.  To get a printable
3206 directory for human consumption, use C<guestfs_ll>.");
3207
3208   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3209    [],
3210    "create partitions on a block device",
3211    "\
3212 This is a simplified interface to the C<guestfs_sfdisk>
3213 command, where partition sizes are specified in megabytes
3214 only (rounded to the nearest cylinder) and you don't need
3215 to specify the cyls, heads and sectors parameters which
3216 were rarely if ever used anyway.
3217
3218 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3219 and C<guestfs_part_disk>");
3220
3221   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3222    [],
3223    "determine file type inside a compressed file",
3224    "\
3225 This command runs C<file> after first decompressing C<path>
3226 using C<method>.
3227
3228 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3229
3230 Since 1.0.63, use C<guestfs_file> instead which can now
3231 process compressed files.");
3232
3233   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3234    [],
3235    "list extended attributes of a file or directory",
3236    "\
3237 This call lists the extended attributes of the file or directory
3238 C<path>.
3239
3240 At the system call level, this is a combination of the
3241 L<listxattr(2)> and L<getxattr(2)> calls.
3242
3243 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3244
3245   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3246    [],
3247    "list extended attributes of a file or directory",
3248    "\
3249 This is the same as C<guestfs_getxattrs>, but if C<path>
3250 is a symbolic link, then it returns the extended attributes
3251 of the link itself.");
3252
3253   ("setxattr", (RErr, [String "xattr";
3254                        String "val"; Int "vallen"; (* will be BufferIn *)
3255                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3256    [],
3257    "set extended attribute of a file or directory",
3258    "\
3259 This call sets the extended attribute named C<xattr>
3260 of the file C<path> to the value C<val> (of length C<vallen>).
3261 The value is arbitrary 8 bit data.
3262
3263 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3264
3265   ("lsetxattr", (RErr, [String "xattr";
3266                         String "val"; Int "vallen"; (* will be BufferIn *)
3267                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3268    [],
3269    "set extended attribute of a file or directory",
3270    "\
3271 This is the same as C<guestfs_setxattr>, but if C<path>
3272 is a symbolic link, then it sets an extended attribute
3273 of the link itself.");
3274
3275   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3276    [],
3277    "remove extended attribute of a file or directory",
3278    "\
3279 This call removes the extended attribute named C<xattr>
3280 of the file C<path>.
3281
3282 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3283
3284   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3285    [],
3286    "remove extended attribute of a file or directory",
3287    "\
3288 This is the same as C<guestfs_removexattr>, but if C<path>
3289 is a symbolic link, then it removes an extended attribute
3290 of the link itself.");
3291
3292   ("mountpoints", (RHashtable "mps", []), 147, [],
3293    [],
3294    "show mountpoints",
3295    "\
3296 This call is similar to C<guestfs_mounts>.  That call returns
3297 a list of devices.  This one returns a hash table (map) of
3298 device name to directory where the device is mounted.");
3299
3300   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3301    (* This is a special case: while you would expect a parameter
3302     * of type "Pathname", that doesn't work, because it implies
3303     * NEED_ROOT in the generated calling code in stubs.c, and
3304     * this function cannot use NEED_ROOT.
3305     *)
3306    [],
3307    "create a mountpoint",
3308    "\
3309 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3310 specialized calls that can be used to create extra mountpoints
3311 before mounting the first filesystem.
3312
3313 These calls are I<only> necessary in some very limited circumstances,
3314 mainly the case where you want to mount a mix of unrelated and/or
3315 read-only filesystems together.
3316
3317 For example, live CDs often contain a \"Russian doll\" nest of
3318 filesystems, an ISO outer layer, with a squashfs image inside, with
3319 an ext2/3 image inside that.  You can unpack this as follows
3320 in guestfish:
3321
3322  add-ro Fedora-11-i686-Live.iso
3323  run
3324  mkmountpoint /cd
3325  mkmountpoint /squash
3326  mkmountpoint /ext3
3327  mount /dev/sda /cd
3328  mount-loop /cd/LiveOS/squashfs.img /squash
3329  mount-loop /squash/LiveOS/ext3fs.img /ext3
3330
3331 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3332
3333   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3334    [],
3335    "remove a mountpoint",
3336    "\
3337 This calls removes a mountpoint that was previously created
3338 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3339 for full details.");
3340
3341   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3342    [InitISOFS, Always, TestOutputBuffer (
3343       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3344     (* Test various near large, large and too large files (RHBZ#589039). *)
3345     InitBasicFS, Always, TestLastFail (
3346       [["touch"; "/a"];
3347        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3348        ["read_file"; "/a"]]);
3349     InitBasicFS, Always, TestLastFail (
3350       [["touch"; "/a"];
3351        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3352        ["read_file"; "/a"]]);
3353     InitBasicFS, Always, TestLastFail (
3354       [["touch"; "/a"];
3355        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3356        ["read_file"; "/a"]])],
3357    "read a file",
3358    "\
3359 This calls returns the contents of the file C<path> as a
3360 buffer.
3361
3362 Unlike C<guestfs_cat>, this function can correctly
3363 handle files that contain embedded ASCII NUL characters.
3364 However unlike C<guestfs_download>, this function is limited
3365 in the total size of file that can be handled.");
3366
3367   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3368    [InitISOFS, Always, TestOutputList (
3369       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3370     InitISOFS, Always, TestOutputList (
3371       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3372     (* Test for RHBZ#579608, absolute symbolic links. *)
3373     InitISOFS, Always, TestOutputList (
3374       [["grep"; "nomatch"; "/abssymlink"]], [])],
3375    "return lines matching a pattern",
3376    "\
3377 This calls the external C<grep> program and returns the
3378 matching lines.");
3379
3380   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3381    [InitISOFS, Always, TestOutputList (
3382       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3383    "return lines matching a pattern",
3384    "\
3385 This calls the external C<egrep> program and returns the
3386 matching lines.");
3387
3388   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3389    [InitISOFS, Always, TestOutputList (
3390       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3391    "return lines matching a pattern",
3392    "\
3393 This calls the external C<fgrep> program and returns the
3394 matching lines.");
3395
3396   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3397    [InitISOFS, Always, TestOutputList (
3398       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3399    "return lines matching a pattern",
3400    "\
3401 This calls the external C<grep -i> program and returns the
3402 matching lines.");
3403
3404   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3405    [InitISOFS, Always, TestOutputList (
3406       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3407    "return lines matching a pattern",
3408    "\
3409 This calls the external C<egrep -i> program and returns the
3410 matching lines.");
3411
3412   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3413    [InitISOFS, Always, TestOutputList (
3414       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3415    "return lines matching a pattern",
3416    "\
3417 This calls the external C<fgrep -i> program and returns the
3418 matching lines.");
3419
3420   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3421    [InitISOFS, Always, TestOutputList (
3422       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3423    "return lines matching a pattern",
3424    "\
3425 This calls the external C<zgrep> program and returns the
3426 matching lines.");
3427
3428   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3429    [InitISOFS, Always, TestOutputList (
3430       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3431    "return lines matching a pattern",
3432    "\
3433 This calls the external C<zegrep> program and returns the
3434 matching lines.");
3435
3436   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3437    [InitISOFS, Always, TestOutputList (
3438       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3439    "return lines matching a pattern",
3440    "\
3441 This calls the external C<zfgrep> program and returns the
3442 matching lines.");
3443
3444   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3445    [InitISOFS, Always, TestOutputList (
3446       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3447    "return lines matching a pattern",
3448    "\
3449 This calls the external C<zgrep -i> program and returns the
3450 matching lines.");
3451
3452   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3453    [InitISOFS, Always, TestOutputList (
3454       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3455    "return lines matching a pattern",
3456    "\
3457 This calls the external C<zegrep -i> program and returns the
3458 matching lines.");
3459
3460   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3461    [InitISOFS, Always, TestOutputList (
3462       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3463    "return lines matching a pattern",
3464    "\
3465 This calls the external C<zfgrep -i> program and returns the
3466 matching lines.");
3467
3468   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3469    [InitISOFS, Always, TestOutput (
3470       [["realpath"; "/../directory"]], "/directory")],
3471    "canonicalized absolute pathname",
3472    "\
3473 Return the canonicalized absolute pathname of C<path>.  The
3474 returned path has no C<.>, C<..> or symbolic link path elements.");
3475
3476   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3477    [InitBasicFS, Always, TestOutputStruct (
3478       [["touch"; "/a"];
3479        ["ln"; "/a"; "/b"];
3480        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3481    "create a hard link",
3482    "\
3483 This command creates a hard link using the C<ln> command.");
3484
3485   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3486    [InitBasicFS, Always, TestOutputStruct (
3487       [["touch"; "/a"];
3488        ["touch"; "/b"];
3489        ["ln_f"; "/a"; "/b"];
3490        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3491    "create a hard link",
3492    "\
3493 This command creates a hard link using the C<ln -f> command.
3494 The C<-f> option removes the link (C<linkname>) if it exists already.");
3495
3496   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3497    [InitBasicFS, Always, TestOutputStruct (
3498       [["touch"; "/a"];
3499        ["ln_s"; "a"; "/b"];
3500        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3501    "create a symbolic link",
3502    "\
3503 This command creates a symbolic link using the C<ln -s> command.");
3504
3505   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3506    [InitBasicFS, Always, TestOutput (
3507       [["mkdir_p"; "/a/b"];
3508        ["touch"; "/a/b/c"];
3509        ["ln_sf"; "../d"; "/a/b/c"];
3510        ["readlink"; "/a/b/c"]], "../d")],
3511    "create a symbolic link",
3512    "\
3513 This command creates a symbolic link using the C<ln -sf> command,
3514 The C<-f> option removes the link (C<linkname>) if it exists already.");
3515
3516   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3517    [] (* XXX tested above *),
3518    "read the target of a symbolic link",
3519    "\
3520 This command reads the target of a symbolic link.");
3521
3522   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3523    [InitBasicFS, Always, TestOutputStruct (
3524       [["fallocate"; "/a"; "1000000"];
3525        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3526    "preallocate a file in the guest filesystem",
3527    "\
3528 This command preallocates a file (containing zero bytes) named
3529 C<path> of size C<len> bytes.  If the file exists already, it
3530 is overwritten.
3531
3532 Do not confuse this with the guestfish-specific
3533 C<alloc> command which allocates a file in the host and
3534 attaches it as a device.");
3535
3536   ("swapon_device", (RErr, [Device "device"]), 170, [],
3537    [InitPartition, Always, TestRun (
3538       [["mkswap"; "/dev/sda1"];
3539        ["swapon_device"; "/dev/sda1"];
3540        ["swapoff_device"; "/dev/sda1"]])],
3541    "enable swap on device",
3542    "\
3543 This command enables the libguestfs appliance to use the
3544 swap device or partition named C<device>.  The increased
3545 memory is made available for all commands, for example
3546 those run using C<guestfs_command> or C<guestfs_sh>.
3547
3548 Note that you should not swap to existing guest swap
3549 partitions unless you know what you are doing.  They may
3550 contain hibernation information, or other information that
3551 the guest doesn't want you to trash.  You also risk leaking
3552 information about the host to the guest this way.  Instead,
3553 attach a new host device to the guest and swap on that.");
3554
3555   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3556    [], (* XXX tested by swapon_device *)
3557    "disable swap on device",
3558    "\
3559 This command disables the libguestfs appliance swap
3560 device or partition named C<device>.
3561 See C<guestfs_swapon_device>.");
3562
3563   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3564    [InitBasicFS, Always, TestRun (
3565       [["fallocate"; "/swap"; "8388608"];
3566        ["mkswap_file"; "/swap"];
3567        ["swapon_file"; "/swap"];
3568        ["swapoff_file"; "/swap"]])],
3569    "enable swap on file",
3570    "\
3571 This command enables swap to a file.
3572 See C<guestfs_swapon_device> for other notes.");
3573
3574   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3575    [], (* XXX tested by swapon_file *)
3576    "disable swap on file",
3577    "\
3578 This command disables the libguestfs appliance swap on file.");
3579
3580   ("swapon_label", (RErr, [String "label"]), 174, [],
3581    [InitEmpty, Always, TestRun (
3582       [["part_disk"; "/dev/sdb"; "mbr"];
3583        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3584        ["swapon_label"; "swapit"];
3585        ["swapoff_label"; "swapit"];
3586        ["zero"; "/dev/sdb"];
3587        ["blockdev_rereadpt"; "/dev/sdb"]])],
3588    "enable swap on labeled swap partition",
3589    "\
3590 This command enables swap to a labeled swap partition.
3591 See C<guestfs_swapon_device> for other notes.");
3592
3593   ("swapoff_label", (RErr, [String "label"]), 175, [],
3594    [], (* XXX tested by swapon_label *)
3595    "disable swap on labeled swap partition",
3596    "\
3597 This command disables the libguestfs appliance swap on
3598 labeled swap partition.");
3599
3600   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3601    (let uuid = uuidgen () in
3602     [InitEmpty, Always, TestRun (
3603        [["mkswap_U"; uuid; "/dev/sdb"];
3604         ["swapon_uuid"; uuid];
3605         ["swapoff_uuid"; uuid]])]),
3606    "enable swap on swap partition by UUID",
3607    "\
3608 This command enables swap to a swap partition with the given UUID.
3609 See C<guestfs_swapon_device> for other notes.");
3610
3611   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3612    [], (* XXX tested by swapon_uuid *)
3613    "disable swap on swap partition by UUID",
3614    "\
3615 This command disables the libguestfs appliance swap partition
3616 with the given UUID.");
3617
3618   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3619    [InitBasicFS, Always, TestRun (
3620       [["fallocate"; "/swap"; "8388608"];
3621        ["mkswap_file"; "/swap"]])],
3622    "create a swap file",
3623    "\
3624 Create a swap file.
3625
3626 This command just writes a swap file signature to an existing
3627 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3628
3629   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3630    [InitISOFS, Always, TestRun (
3631       [["inotify_init"; "0"]])],
3632    "create an inotify handle",
3633    "\
3634 This command creates a new inotify handle.
3635 The inotify subsystem can be used to notify events which happen to
3636 objects in the guest filesystem.
3637
3638 C<maxevents> is the maximum number of events which will be
3639 queued up between calls to C<guestfs_inotify_read> or
3640 C<guestfs_inotify_files>.
3641 If this is passed as C<0>, then the kernel (or previously set)
3642 default is used.  For Linux 2.6.29 the default was 16384 events.
3643 Beyond this limit, the kernel throws away events, but records
3644 the fact that it threw them away by setting a flag
3645 C<IN_Q_OVERFLOW> in the returned structure list (see
3646 C<guestfs_inotify_read>).
3647
3648 Before any events are generated, you have to add some
3649 watches to the internal watch list.  See:
3650 C<guestfs_inotify_add_watch>,
3651 C<guestfs_inotify_rm_watch> and
3652 C<guestfs_inotify_watch_all>.
3653
3654 Queued up events should be read periodically by calling
3655 C<guestfs_inotify_read>
3656 (or C<guestfs_inotify_files> which is just a helpful
3657 wrapper around C<guestfs_inotify_read>).  If you don't
3658 read the events out often enough then you risk the internal
3659 queue overflowing.
3660
3661 The handle should be closed after use by calling
3662 C<guestfs_inotify_close>.  This also removes any
3663 watches automatically.
3664
3665 See also L<inotify(7)> for an overview of the inotify interface
3666 as exposed by the Linux kernel, which is roughly what we expose
3667 via libguestfs.  Note that there is one global inotify handle
3668 per libguestfs instance.");
3669
3670   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3671    [InitBasicFS, Always, TestOutputList (
3672       [["inotify_init"; "0"];
3673        ["inotify_add_watch"; "/"; "1073741823"];
3674        ["touch"; "/a"];
3675        ["touch"; "/b"];
3676        ["inotify_files"]], ["a"; "b"])],
3677    "add an inotify watch",
3678    "\
3679 Watch C<path> for the events listed in C<mask>.
3680
3681 Note that if C<path> is a directory then events within that
3682 directory are watched, but this does I<not> happen recursively
3683 (in subdirectories).
3684
3685 Note for non-C or non-Linux callers: the inotify events are
3686 defined by the Linux kernel ABI and are listed in
3687 C</usr/include/sys/inotify.h>.");
3688
3689   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3690    [],
3691    "remove an inotify watch",
3692    "\
3693 Remove a previously defined inotify watch.
3694 See C<guestfs_inotify_add_watch>.");
3695
3696   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3697    [],
3698    "return list of inotify events",
3699    "\
3700 Return the complete queue of events that have happened
3701 since the previous read call.
3702
3703 If no events have happened, this returns an empty list.
3704
3705 I<Note>: In order to make sure that all events have been
3706 read, you must call this function repeatedly until it
3707 returns an empty list.  The reason is that the call will
3708 read events up to the maximum appliance-to-host message
3709 size and leave remaining events in the queue.");
3710
3711   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3712    [],
3713    "return list of watched files that had events",
3714    "\
3715 This function is a helpful wrapper around C<guestfs_inotify_read>
3716 which just returns a list of pathnames of objects that were
3717 touched.  The returned pathnames are sorted and deduplicated.");
3718
3719   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3720    [],
3721    "close the inotify handle",
3722    "\
3723 This closes the inotify handle which was previously
3724 opened by inotify_init.  It removes all watches, throws
3725 away any pending events, and deallocates all resources.");
3726
3727   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3728    [],
3729    "set SELinux security context",
3730    "\
3731 This sets the SELinux security context of the daemon
3732 to the string C<context>.
3733
3734 See the documentation about SELINUX in L<guestfs(3)>.");
3735
3736   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3737    [],
3738    "get SELinux security context",
3739    "\
3740 This gets the SELinux security context of the daemon.
3741
3742 See the documentation about SELINUX in L<guestfs(3)>,
3743 and C<guestfs_setcon>");
3744
3745   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3746    [InitEmpty, Always, TestOutput (
3747       [["part_disk"; "/dev/sda"; "mbr"];
3748        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3749        ["mount_options"; ""; "/dev/sda1"; "/"];
3750        ["write"; "/new"; "new file contents"];
3751        ["cat"; "/new"]], "new file contents");
3752     InitEmpty, Always, TestRun (
3753       [["part_disk"; "/dev/sda"; "mbr"];
3754        ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3755     InitEmpty, Always, TestLastFail (
3756       [["part_disk"; "/dev/sda"; "mbr"];
3757        ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3758     InitEmpty, Always, TestLastFail (
3759       [["part_disk"; "/dev/sda"; "mbr"];
3760        ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3761     InitEmpty, IfAvailable "ntfsprogs", TestRun (
3762       [["part_disk"; "/dev/sda"; "mbr"];
3763        ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3764    "make a filesystem with block size",
3765    "\
3766 This call is similar to C<guestfs_mkfs>, but it allows you to
3767 control the block size of the resulting filesystem.  Supported
3768 block sizes depend on the filesystem type, but typically they
3769 are C<1024>, C<2048> or C<4096> only.
3770
3771 For VFAT and NTFS the C<blocksize> parameter is treated as
3772 the requested cluster size.");
3773
3774   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3775    [InitEmpty, Always, TestOutput (
3776       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3777        ["mke2journal"; "4096"; "/dev/sda1"];
3778        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3779        ["mount_options"; ""; "/dev/sda2"; "/"];
3780        ["write"; "/new"; "new file contents"];
3781        ["cat"; "/new"]], "new file contents")],
3782    "make ext2/3/4 external journal",
3783    "\
3784 This creates an ext2 external journal on C<device>.  It is equivalent
3785 to the command:
3786
3787  mke2fs -O journal_dev -b blocksize device");
3788
3789   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3790    [InitEmpty, Always, TestOutput (
3791       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3792        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3793        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3794        ["mount_options"; ""; "/dev/sda2"; "/"];
3795        ["write"; "/new"; "new file contents"];
3796        ["cat"; "/new"]], "new file contents")],
3797    "make ext2/3/4 external journal with label",
3798    "\
3799 This creates an ext2 external journal on C<device> with label C<label>.");
3800
3801   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3802    (let uuid = uuidgen () in
3803     [InitEmpty, Always, TestOutput (
3804        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3805         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3806         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3807         ["mount_options"; ""; "/dev/sda2"; "/"];
3808         ["write"; "/new"; "new file contents"];
3809         ["cat"; "/new"]], "new file contents")]),
3810    "make ext2/3/4 external journal with UUID",
3811    "\
3812 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3813
3814   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3815    [],
3816    "make ext2/3/4 filesystem with external journal",
3817    "\
3818 This creates an ext2/3/4 filesystem on C<device> with
3819 an external journal on C<journal>.  It is equivalent
3820 to the command:
3821
3822  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3823
3824 See also C<guestfs_mke2journal>.");
3825
3826   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3827    [],
3828    "make ext2/3/4 filesystem with external journal",
3829    "\
3830 This creates an ext2/3/4 filesystem on C<device> with
3831 an external journal on the journal labeled C<label>.
3832
3833 See also C<guestfs_mke2journal_L>.");
3834
3835   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3836    [],
3837    "make ext2/3/4 filesystem with external journal",
3838    "\
3839 This creates an ext2/3/4 filesystem on C<device> with
3840 an external journal on the journal with UUID C<uuid>.
3841
3842 See also C<guestfs_mke2journal_U>.");
3843
3844   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3845    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3846    "load a kernel module",
3847    "\
3848 This loads a kernel module in the appliance.
3849
3850 The kernel module must have been whitelisted when libguestfs
3851 was built (see C<appliance/kmod.whitelist.in> in the source).");
3852
3853   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3854    [InitNone, Always, TestOutput (
3855       [["echo_daemon"; "This is a test"]], "This is a test"
3856     )],
3857    "echo arguments back to the client",
3858    "\
3859 This command concatenates the list of C<words> passed with single spaces
3860 between them and returns the resulting string.
3861
3862 You can use this command to test the connection through to the daemon.
3863
3864 See also C<guestfs_ping_daemon>.");
3865
3866   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3867    [], (* There is a regression test for this. *)
3868    "find all files and directories, returning NUL-separated list",
3869    "\
3870 This command lists out all files and directories, recursively,
3871 starting at C<directory>, placing the resulting list in the
3872 external file called C<files>.
3873
3874 This command works the same way as C<guestfs_find> with the
3875 following exceptions:
3876
3877 =over 4
3878
3879 =item *
3880
3881 The resulting list is written to an external file.
3882
3883 =item *
3884
3885 Items (filenames) in the result are separated
3886 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3887
3888 =item *
3889
3890 This command is not limited in the number of names that it
3891 can return.
3892
3893 =item *
3894
3895 The result list is not sorted.
3896
3897 =back");
3898
3899   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3900    [InitISOFS, Always, TestOutput (
3901       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3902     InitISOFS, Always, TestOutput (
3903       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3904     InitISOFS, Always, TestOutput (
3905       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3906     InitISOFS, Always, TestLastFail (
3907       [["case_sensitive_path"; "/Known-1/"]]);
3908     InitBasicFS, Always, TestOutput (
3909       [["mkdir"; "/a"];
3910        ["mkdir"; "/a/bbb"];
3911        ["touch"; "/a/bbb/c"];
3912        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3913     InitBasicFS, Always, TestOutput (
3914       [["mkdir"; "/a"];
3915        ["mkdir"; "/a/bbb"];
3916        ["touch"; "/a/bbb/c"];
3917        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3918     InitBasicFS, Always, TestLastFail (
3919       [["mkdir"; "/a"];
3920        ["mkdir"; "/a/bbb"];
3921        ["touch"; "/a/bbb/c"];
3922        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3923    "return true path on case-insensitive filesystem",
3924    "\
3925 This can be used to resolve case insensitive paths on
3926 a filesystem which is case sensitive.  The use case is
3927 to resolve paths which you have read from Windows configuration
3928 files or the Windows Registry, to the true path.
3929
3930 The command handles a peculiarity of the Linux ntfs-3g
3931 filesystem driver (and probably others), which is that although
3932 the underlying filesystem is case-insensitive, the driver
3933 exports the filesystem to Linux as case-sensitive.
3934
3935 One consequence of this is that special directories such
3936 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3937 (or other things) depending on the precise details of how
3938 they were created.  In Windows itself this would not be
3939 a problem.
3940
3941 Bug or feature?  You decide:
3942 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3943
3944 This function resolves the true case of each element in the
3945 path and returns the case-sensitive path.
3946
3947 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3948 might return C<\"/WINDOWS/system32\"> (the exact return value
3949 would depend on details of how the directories were originally
3950 created under Windows).
3951
3952 I<Note>:
3953 This function does not handle drive names, backslashes etc.
3954
3955 See also C<guestfs_realpath>.");
3956
3957   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3958    [InitBasicFS, Always, TestOutput (
3959       [["vfs_type"; "/dev/sda1"]], "ext2")],
3960    "get the Linux VFS type corresponding to a mounted device",
3961    "\
3962 This command gets the filesystem type corresponding to
3963 the filesystem on C<device>.
3964
3965 For most filesystems, the result is the name of the Linux
3966 VFS module which would be used to mount this filesystem
3967 if you mounted it without specifying the filesystem type.
3968 For example a string such as C<ext3> or C<ntfs>.");
3969
3970   ("truncate", (RErr, [Pathname "path"]), 199, [],
3971    [InitBasicFS, Always, TestOutputStruct (
3972       [["write"; "/test"; "some stuff so size is not zero"];
3973        ["truncate"; "/test"];
3974        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3975    "truncate a file to zero size",
3976    "\
3977 This command truncates C<path> to a zero-length file.  The
3978 file must exist already.");
3979
3980   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3981    [InitBasicFS, Always, TestOutputStruct (
3982       [["touch"; "/test"];
3983        ["truncate_size"; "/test"; "1000"];
3984        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3985    "truncate a file to a particular size",
3986    "\
3987 This command truncates C<path> to size C<size> bytes.  The file
3988 must exist already.
3989
3990 If the current file size is less than C<size> then
3991 the file is extended to the required size with zero bytes.
3992 This creates a sparse file (ie. disk blocks are not allocated
3993 for the file until you write to it).  To create a non-sparse
3994 file of zeroes, use C<guestfs_fallocate64> instead.");
3995
3996   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3997    [InitBasicFS, Always, TestOutputStruct (
3998       [["touch"; "/test"];
3999        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
4000        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
4001    "set timestamp of a file with nanosecond precision",
4002    "\
4003 This command sets the timestamps of a file with nanosecond
4004 precision.
4005
4006 C<atsecs, atnsecs> are the last access time (atime) in secs and
4007 nanoseconds from the epoch.
4008
4009 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4010 secs and nanoseconds from the epoch.
4011
4012 If the C<*nsecs> field contains the special value C<-1> then
4013 the corresponding timestamp is set to the current time.  (The
4014 C<*secs> field is ignored in this case).
4015
4016 If the C<*nsecs> field contains the special value C<-2> then
4017 the corresponding timestamp is left unchanged.  (The
4018 C<*secs> field is ignored in this case).");
4019
4020   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4021    [InitBasicFS, Always, TestOutputStruct (
4022       [["mkdir_mode"; "/test"; "0o111"];
4023        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4024    "create a directory with a particular mode",
4025    "\
4026 This command creates a directory, setting the initial permissions
4027 of the directory to C<mode>.
4028
4029 For common Linux filesystems, the actual mode which is set will
4030 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
4031 interpret the mode in other ways.
4032
4033 See also C<guestfs_mkdir>, C<guestfs_umask>");
4034
4035   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4036    [], (* XXX *)
4037    "change file owner and group",
4038    "\
4039 Change the file owner to C<owner> and group to C<group>.
4040 This is like C<guestfs_chown> but if C<path> is a symlink then
4041 the link itself is changed, not the target.
4042
4043 Only numeric uid and gid are supported.  If you want to use
4044 names, you will need to locate and parse the password file
4045 yourself (Augeas support makes this relatively easy).");
4046
4047   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4048    [], (* XXX *)
4049    "lstat on multiple files",
4050    "\
4051 This call allows you to perform the C<guestfs_lstat> operation
4052 on multiple files, where all files are in the directory C<path>.
4053 C<names> is the list of files from this directory.
4054
4055 On return you get a list of stat structs, with a one-to-one
4056 correspondence to the C<names> list.  If any name did not exist
4057 or could not be lstat'd, then the C<ino> field of that structure
4058 is set to C<-1>.
4059
4060 This call is intended for programs that want to efficiently
4061 list a directory contents without making many round-trips.
4062 See also C<guestfs_lxattrlist> for a similarly efficient call
4063 for getting extended attributes.  Very long directory listings
4064 might cause the protocol message size to be exceeded, causing
4065 this call to fail.  The caller must split up such requests
4066 into smaller groups of names.");
4067
4068   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4069    [], (* XXX *)
4070    "lgetxattr on multiple files",
4071    "\
4072 This call allows you to get the extended attributes
4073 of multiple files, where all files are in the directory C<path>.
4074 C<names> is the list of files from this directory.
4075
4076 On return you get a flat list of xattr structs which must be
4077 interpreted sequentially.  The first xattr struct always has a zero-length
4078 C<attrname>.  C<attrval> in this struct is zero-length
4079 to indicate there was an error doing C<lgetxattr> for this
4080 file, I<or> is a C string which is a decimal number
4081 (the number of following attributes for this file, which could
4082 be C<\"0\">).  Then after the first xattr struct are the
4083 zero or more attributes for the first named file.
4084 This repeats for the second and subsequent files.
4085
4086 This call is intended for programs that want to efficiently
4087 list a directory contents without making many round-trips.
4088 See also C<guestfs_lstatlist> for a similarly efficient call
4089 for getting standard stats.  Very long directory listings
4090 might cause the protocol message size to be exceeded, causing
4091 this call to fail.  The caller must split up such requests
4092 into smaller groups of names.");
4093
4094   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4095    [], (* XXX *)
4096    "readlink on multiple files",
4097    "\
4098 This call allows you to do a C<readlink> operation
4099 on multiple files, where all files are in the directory C<path>.
4100 C<names> is the list of files from this directory.
4101
4102 On return you get a list of strings, with a one-to-one
4103 correspondence to the C<names> list.  Each string is the
4104 value of the symbolic link.
4105
4106 If the C<readlink(2)> operation fails on any name, then
4107 the corresponding result string is the empty string C<\"\">.
4108 However the whole operation is completed even if there
4109 were C<readlink(2)> errors, and so you can call this
4110 function with names where you don't know if they are
4111 symbolic links already (albeit slightly less efficient).
4112
4113 This call is intended for programs that want to efficiently
4114 list a directory contents without making many round-trips.
4115 Very long directory listings might cause the protocol
4116 message size to be exceeded, causing
4117 this call to fail.  The caller must split up such requests
4118 into smaller groups of names.");
4119
4120   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4121    [InitISOFS, Always, TestOutputBuffer (
4122       [["pread"; "/known-4"; "1"; "3"]], "\n");
4123     InitISOFS, Always, TestOutputBuffer (
4124       [["pread"; "/empty"; "0"; "100"]], "")],
4125    "read part of a file",
4126    "\
4127 This command lets you read part of a file.  It reads C<count>
4128 bytes of the file, starting at C<offset>, from file C<path>.
4129
4130 This may read fewer bytes than requested.  For further details
4131 see the L<pread(2)> system call.
4132
4133 See also C<guestfs_pwrite>.");
4134
4135   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4136    [InitEmpty, Always, TestRun (
4137       [["part_init"; "/dev/sda"; "gpt"]])],
4138    "create an empty partition table",
4139    "\
4140 This creates an empty partition table on C<device> of one of the
4141 partition types listed below.  Usually C<parttype> should be
4142 either C<msdos> or C<gpt> (for large disks).
4143
4144 Initially there are no partitions.  Following this, you should
4145 call C<guestfs_part_add> for each partition required.
4146
4147 Possible values for C<parttype> are:
4148
4149 =over 4
4150
4151 =item B<efi> | B<gpt>
4152
4153 Intel EFI / GPT partition table.
4154
4155 This is recommended for >= 2 TB partitions that will be accessed
4156 from Linux and Intel-based Mac OS X.  It also has limited backwards
4157 compatibility with the C<mbr> format.
4158
4159 =item B<mbr> | B<msdos>
4160
4161 The standard PC \"Master Boot Record\" (MBR) format used
4162 by MS-DOS and Windows.  This partition type will B<only> work
4163 for device sizes up to 2 TB.  For large disks we recommend
4164 using C<gpt>.
4165
4166 =back
4167
4168 Other partition table types that may work but are not
4169 supported include:
4170
4171 =over 4
4172
4173 =item B<aix>
4174
4175 AIX disk labels.
4176
4177 =item B<amiga> | B<rdb>
4178
4179 Amiga \"Rigid Disk Block\" format.
4180
4181 =item B<bsd>
4182
4183 BSD disk labels.
4184
4185 =item B<dasd>
4186
4187 DASD, used on IBM mainframes.
4188
4189 =item B<dvh>
4190
4191 MIPS/SGI volumes.
4192
4193 =item B<mac>
4194
4195 Old Mac partition format.  Modern Macs use C<gpt>.
4196
4197 =item B<pc98>
4198
4199 NEC PC-98 format, common in Japan apparently.
4200
4201 =item B<sun>
4202
4203 Sun disk labels.
4204
4205 =back");
4206
4207   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4208    [InitEmpty, Always, TestRun (
4209       [["part_init"; "/dev/sda"; "mbr"];
4210        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4211     InitEmpty, Always, TestRun (
4212       [["part_init"; "/dev/sda"; "gpt"];
4213        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4214        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4215     InitEmpty, Always, TestRun (
4216       [["part_init"; "/dev/sda"; "mbr"];
4217        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4218        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4219        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4220        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4221    "add a partition to the device",
4222    "\
4223 This command adds a partition to C<device>.  If there is no partition
4224 table on the device, call C<guestfs_part_init> first.
4225
4226 The C<prlogex> parameter is the type of partition.  Normally you
4227 should pass C<p> or C<primary> here, but MBR partition tables also
4228 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4229 types.
4230
4231 C<startsect> and C<endsect> are the start and end of the partition
4232 in I<sectors>.  C<endsect> may be negative, which means it counts
4233 backwards from the end of the disk (C<-1> is the last sector).
4234
4235 Creating a partition which covers the whole disk is not so easy.
4236 Use C<guestfs_part_disk> to do that.");
4237
4238   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4239    [InitEmpty, Always, TestRun (
4240       [["part_disk"; "/dev/sda"; "mbr"]]);
4241     InitEmpty, Always, TestRun (
4242       [["part_disk"; "/dev/sda"; "gpt"]])],
4243    "partition whole disk with a single primary partition",
4244    "\
4245 This command is simply a combination of C<guestfs_part_init>
4246 followed by C<guestfs_part_add> to create a single primary partition
4247 covering the whole disk.
4248
4249 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4250 but other possible values are described in C<guestfs_part_init>.");
4251
4252   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4253    [InitEmpty, Always, TestRun (
4254       [["part_disk"; "/dev/sda"; "mbr"];
4255        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4256    "make a partition bootable",
4257    "\
4258 This sets the bootable flag on partition numbered C<partnum> on
4259 device C<device>.  Note that partitions are numbered from 1.
4260
4261 The bootable flag is used by some operating systems (notably
4262 Windows) to determine which partition to boot from.  It is by
4263 no means universally recognized.");
4264
4265   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4266    [InitEmpty, Always, TestRun (
4267       [["part_disk"; "/dev/sda"; "gpt"];
4268        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4269    "set partition name",
4270    "\
4271 This sets the partition name on partition numbered C<partnum> on
4272 device C<device>.  Note that partitions are numbered from 1.
4273
4274 The partition name can only be set on certain types of partition
4275 table.  This works on C<gpt> but not on C<mbr> partitions.");
4276
4277   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4278    [], (* XXX Add a regression test for this. *)
4279    "list partitions on a device",
4280    "\
4281 This command parses the partition table on C<device> and
4282 returns the list of partitions found.
4283
4284 The fields in the returned structure are:
4285
4286 =over 4
4287
4288 =item B<part_num>
4289
4290 Partition number, counting from 1.
4291
4292 =item B<part_start>
4293
4294 Start of the partition I<in bytes>.  To get sectors you have to
4295 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4296
4297 =item B<part_end>
4298
4299 End of the partition in bytes.
4300
4301 =item B<part_size>
4302
4303 Size of the partition in bytes.
4304
4305 =back");
4306
4307   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4308    [InitEmpty, Always, TestOutput (
4309       [["part_disk"; "/dev/sda"; "gpt"];
4310        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4311    "get the partition table type",
4312    "\
4313 This command examines the partition table on C<device> and
4314 returns the partition table type (format) being used.
4315
4316 Common return values include: C<msdos> (a DOS/Windows style MBR
4317 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4318 values are possible, although unusual.  See C<guestfs_part_init>
4319 for a full list.");
4320
4321   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4322    [InitBasicFS, Always, TestOutputBuffer (
4323       [["fill"; "0x63"; "10"; "/test"];
4324        ["read_file"; "/test"]], "cccccccccc")],
4325    "fill a file with octets",
4326    "\
4327 This command creates a new file called C<path>.  The initial
4328 content of the file is C<len> octets of C<c>, where C<c>
4329 must be a number in the range C<[0..255]>.
4330
4331 To fill a file with zero bytes (sparsely), it is
4332 much more efficient to use C<guestfs_truncate_size>.
4333 To create a file with a pattern of repeating bytes
4334 use C<guestfs_fill_pattern>.");
4335
4336   ("available", (RErr, [StringList "groups"]), 216, [],
4337    [InitNone, Always, TestRun [["available"; ""]]],
4338    "test availability of some parts of the API",
4339    "\
4340 This command is used to check the availability of some
4341 groups of functionality in the appliance, which not all builds of
4342 the libguestfs appliance will be able to provide.
4343
4344 The libguestfs groups, and the functions that those
4345 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4346 You can also fetch this list at runtime by calling
4347 C<guestfs_available_all_groups>.
4348
4349 The argument C<groups> is a list of group names, eg:
4350 C<[\"inotify\", \"augeas\"]> would check for the availability of
4351 the Linux inotify functions and Augeas (configuration file
4352 editing) functions.
4353
4354 The command returns no error if I<all> requested groups are available.
4355
4356 It fails with an error if one or more of the requested
4357 groups is unavailable in the appliance.
4358
4359 If an unknown group name is included in the
4360 list of groups then an error is always returned.
4361
4362 I<Notes:>
4363
4364 =over 4
4365
4366 =item *
4367
4368 You must call C<guestfs_launch> before calling this function.
4369
4370 The reason is because we don't know what groups are
4371 supported by the appliance/daemon until it is running and can
4372 be queried.
4373
4374 =item *
4375
4376 If a group of functions is available, this does not necessarily
4377 mean that they will work.  You still have to check for errors
4378 when calling individual API functions even if they are
4379 available.
4380
4381 =item *
4382
4383 It is usually the job of distro packagers to build
4384 complete functionality into the libguestfs appliance.
4385 Upstream libguestfs, if built from source with all
4386 requirements satisfied, will support everything.
4387
4388 =item *
4389
4390 This call was added in version C<1.0.80>.  In previous
4391 versions of libguestfs all you could do would be to speculatively
4392 execute a command to find out if the daemon implemented it.
4393 See also C<guestfs_version>.
4394
4395 =back");
4396
4397   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4398    [InitBasicFS, Always, TestOutputBuffer (
4399       [["write"; "/src"; "hello, world"];
4400        ["dd"; "/src"; "/dest"];
4401        ["read_file"; "/dest"]], "hello, world")],
4402    "copy from source to destination using dd",
4403    "\
4404 This command copies from one source device or file C<src>
4405 to another destination device or file C<dest>.  Normally you
4406 would use this to copy to or from a device or partition, for
4407 example to duplicate a filesystem.
4408
4409 If the destination is a device, it must be as large or larger
4410 than the source file or device, otherwise the copy will fail.
4411 This command cannot do partial copies (see C<guestfs_copy_size>).");
4412
4413   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4414    [InitBasicFS, Always, TestOutputInt (
4415       [["write"; "/file"; "hello, world"];
4416        ["filesize"; "/file"]], 12)],
4417    "return the size of the file in bytes",
4418    "\
4419 This command returns the size of C<file> in bytes.
4420
4421 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4422 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4423 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4424
4425   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4426    [InitBasicFSonLVM, Always, TestOutputList (
4427       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4428        ["lvs"]], ["/dev/VG/LV2"])],
4429    "rename an LVM logical volume",
4430    "\
4431 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4432
4433   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4434    [InitBasicFSonLVM, Always, TestOutputList (
4435       [["umount"; "/"];
4436        ["vg_activate"; "false"; "VG"];
4437        ["vgrename"; "VG"; "VG2"];
4438        ["vg_activate"; "true"; "VG2"];
4439        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4440        ["vgs"]], ["VG2"])],
4441    "rename an LVM volume group",
4442    "\
4443 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4444
4445   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4446    [InitISOFS, Always, TestOutputBuffer (
4447       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4448    "list the contents of a single file in an initrd",
4449    "\
4450 This command unpacks the file C<filename> from the initrd file
4451 called C<initrdpath>.  The filename must be given I<without> the
4452 initial C</> character.
4453
4454 For example, in guestfish you could use the following command
4455 to examine the boot script (usually called C</init>)
4456 contained in a Linux initrd or initramfs image:
4457
4458  initrd-cat /boot/initrd-<version>.img init
4459
4460 See also C<guestfs_initrd_list>.");
4461
4462   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4463    [],
4464    "get the UUID of a physical volume",
4465    "\
4466 This command returns the UUID of the LVM PV C<device>.");
4467
4468   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4469    [],
4470    "get the UUID of a volume group",
4471    "\
4472 This command returns the UUID of the LVM VG named C<vgname>.");
4473
4474   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4475    [],
4476    "get the UUID of a logical volume",
4477    "\
4478 This command returns the UUID of the LVM LV C<device>.");
4479
4480   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4481    [],
4482    "get the PV UUIDs containing the volume group",
4483    "\
4484 Given a VG called C<vgname>, this returns the UUIDs of all
4485 the physical volumes that this volume group resides on.
4486
4487 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4488 calls to associate physical volumes and volume groups.
4489
4490 See also C<guestfs_vglvuuids>.");
4491
4492   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4493    [],
4494    "get the LV UUIDs of all LVs in the volume group",
4495    "\
4496 Given a VG called C<vgname>, this returns the UUIDs of all
4497 the logical volumes created in this volume group.
4498
4499 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4500 calls to associate logical volumes and volume groups.
4501
4502 See also C<guestfs_vgpvuuids>.");
4503
4504   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4505    [InitBasicFS, Always, TestOutputBuffer (
4506       [["write"; "/src"; "hello, world"];
4507        ["copy_size"; "/src"; "/dest"; "5"];
4508        ["read_file"; "/dest"]], "hello")],
4509    "copy size bytes from source to destination using dd",
4510    "\
4511 This command copies exactly C<size> bytes from one source device
4512 or file C<src> to another destination device or file C<dest>.
4513
4514 Note this will fail if the source is too short or if the destination
4515 is not large enough.");
4516
4517   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4518    [InitBasicFSonLVM, Always, TestRun (
4519       [["zero_device"; "/dev/VG/LV"]])],
4520    "write zeroes to an entire device",
4521    "\
4522 This command writes zeroes over the entire C<device>.  Compare
4523 with C<guestfs_zero> which just zeroes the first few blocks of
4524 a device.");
4525
4526   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4527    [InitBasicFS, Always, TestOutput (
4528       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4529        ["cat"; "/hello"]], "hello\n")],
4530    "unpack compressed tarball to directory",
4531    "\
4532 This command uploads and unpacks local file C<tarball> (an
4533 I<xz compressed> tar file) into C<directory>.");
4534
4535   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4536    [],
4537    "pack directory into compressed tarball",
4538    "\
4539 This command packs the contents of C<directory> and downloads
4540 it to local file C<tarball> (as an xz compressed tar archive).");
4541
4542   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4543    [],
4544    "resize an NTFS filesystem",
4545    "\
4546 This command resizes an NTFS filesystem, expanding or
4547 shrinking it to the size of the underlying device.
4548 See also L<ntfsresize(8)>.");
4549
4550   ("vgscan", (RErr, []), 232, [],
4551    [InitEmpty, Always, TestRun (
4552       [["vgscan"]])],
4553    "rescan for LVM physical volumes, volume groups and logical volumes",
4554    "\
4555 This rescans all block devices and rebuilds the list of LVM
4556 physical volumes, volume groups and logical volumes.");
4557
4558   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4559    [InitEmpty, Always, TestRun (
4560       [["part_init"; "/dev/sda"; "mbr"];
4561        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4562        ["part_del"; "/dev/sda"; "1"]])],
4563    "delete a partition",
4564    "\
4565 This command deletes the partition numbered C<partnum> on C<device>.
4566
4567 Note that in the case of MBR partitioning, deleting an
4568 extended partition also deletes any logical partitions
4569 it contains.");
4570
4571   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4572    [InitEmpty, Always, TestOutputTrue (
4573       [["part_init"; "/dev/sda"; "mbr"];
4574        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4575        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4576        ["part_get_bootable"; "/dev/sda"; "1"]])],
4577    "return true if a partition is bootable",
4578    "\
4579 This command returns true if the partition C<partnum> on
4580 C<device> has the bootable flag set.
4581
4582 See also C<guestfs_part_set_bootable>.");
4583
4584   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4585    [InitEmpty, Always, TestOutputInt (
4586       [["part_init"; "/dev/sda"; "mbr"];
4587        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4588        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4589        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4590    "get the MBR type byte (ID byte) from a partition",
4591    "\
4592 Returns the MBR type byte (also known as the ID byte) from
4593 the numbered partition C<partnum>.
4594
4595 Note that only MBR (old DOS-style) partitions have type bytes.
4596 You will get undefined results for other partition table
4597 types (see C<guestfs_part_get_parttype>).");
4598
4599   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4600    [], (* tested by part_get_mbr_id *)
4601    "set the MBR type byte (ID byte) of a partition",
4602    "\
4603 Sets the MBR type byte (also known as the ID byte) of
4604 the numbered partition C<partnum> to C<idbyte>.  Note
4605 that the type bytes quoted in most documentation are
4606 in fact hexadecimal numbers, but usually documented
4607 without any leading \"0x\" which might be confusing.
4608
4609 Note that only MBR (old DOS-style) partitions have type bytes.
4610 You will get undefined results for other partition table
4611 types (see C<guestfs_part_get_parttype>).");
4612
4613   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4614    [InitISOFS, Always, TestOutput (
4615       [["checksum_device"; "md5"; "/dev/sdd"]],
4616       (Digest.to_hex (Digest.file "images/test.iso")))],
4617    "compute MD5, SHAx or CRC checksum of the contents of a device",
4618    "\
4619 This call computes the MD5, SHAx or CRC checksum of the
4620 contents of the device named C<device>.  For the types of
4621 checksums supported see the C<guestfs_checksum> command.");
4622
4623   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4624    [InitNone, Always, TestRun (
4625       [["part_disk"; "/dev/sda"; "mbr"];
4626        ["pvcreate"; "/dev/sda1"];
4627        ["vgcreate"; "VG"; "/dev/sda1"];
4628        ["lvcreate"; "LV"; "VG"; "10"];
4629        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4630    "expand an LV to fill free space",
4631    "\
4632 This expands an existing logical volume C<lv> so that it fills
4633 C<pc>% of the remaining free space in the volume group.  Commonly
4634 you would call this with pc = 100 which expands the logical volume
4635 as much as possible, using all remaining free space in the volume
4636 group.");
4637
4638   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4639    [], (* XXX Augeas code needs tests. *)
4640    "clear Augeas path",
4641    "\
4642 Set the value associated with C<path> to C<NULL>.  This
4643 is the same as the L<augtool(1)> C<clear> command.");
4644
4645   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4646    [InitEmpty, Always, TestOutputInt (
4647       [["get_umask"]], 0o22)],
4648    "get the current umask",
4649    "\
4650 Return the current umask.  By default the umask is C<022>
4651 unless it has been set by calling C<guestfs_umask>.");
4652
4653   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4654    [],
4655    "upload a file to the appliance (internal use only)",
4656    "\
4657 The C<guestfs_debug_upload> command uploads a file to
4658 the libguestfs appliance.
4659
4660 There is no comprehensive help for this command.  You have
4661 to look at the file C<daemon/debug.c> in the libguestfs source
4662 to find out what it is for.");
4663
4664   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4665    [InitBasicFS, Always, TestOutput (
4666       [["base64_in"; "../images/hello.b64"; "/hello"];
4667        ["cat"; "/hello"]], "hello\n")],
4668    "upload base64-encoded data to file",
4669    "\
4670 This command uploads base64-encoded data from C<base64file>
4671 to C<filename>.");
4672
4673   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4674    [],
4675    "download file and encode as base64",
4676    "\
4677 This command downloads the contents of C<filename>, writing
4678 it out to local file C<base64file> encoded as base64.");
4679
4680   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4681    [],
4682    "compute MD5, SHAx or CRC checksum of files in a directory",
4683    "\
4684 This command computes the checksums of all regular files in
4685 C<directory> and then emits a list of those checksums to
4686 the local output file C<sumsfile>.
4687
4688 This can be used for verifying the integrity of a virtual
4689 machine.  However to be properly secure you should pay
4690 attention to the output of the checksum command (it uses
4691 the ones from GNU coreutils).  In particular when the
4692 filename is not printable, coreutils uses a special
4693 backslash syntax.  For more information, see the GNU
4694 coreutils info file.");
4695
4696   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4697    [InitBasicFS, Always, TestOutputBuffer (
4698       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4699        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4700    "fill a file with a repeating pattern of bytes",
4701    "\
4702 This function is like C<guestfs_fill> except that it creates
4703 a new file of length C<len> containing the repeating pattern
4704 of bytes in C<pattern>.  The pattern is truncated if necessary
4705 to ensure the length of the file is exactly C<len> bytes.");
4706
4707   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4708    [InitBasicFS, Always, TestOutput (
4709       [["write"; "/new"; "new file contents"];
4710        ["cat"; "/new"]], "new file contents");
4711     InitBasicFS, Always, TestOutput (
4712       [["write"; "/new"; "\nnew file contents\n"];
4713        ["cat"; "/new"]], "\nnew file contents\n");
4714     InitBasicFS, Always, TestOutput (
4715       [["write"; "/new"; "\n\n"];
4716        ["cat"; "/new"]], "\n\n");
4717     InitBasicFS, Always, TestOutput (
4718       [["write"; "/new"; ""];
4719        ["cat"; "/new"]], "");
4720     InitBasicFS, Always, TestOutput (
4721       [["write"; "/new"; "\n\n\n"];
4722        ["cat"; "/new"]], "\n\n\n");
4723     InitBasicFS, Always, TestOutput (
4724       [["write"; "/new"; "\n"];
4725        ["cat"; "/new"]], "\n")],
4726    "create a new file",
4727    "\
4728 This call creates a file called C<path>.  The content of the
4729 file is the string C<content> (which can contain any 8 bit data).");
4730
4731   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4732    [InitBasicFS, Always, TestOutput (
4733       [["write"; "/new"; "new file contents"];
4734        ["pwrite"; "/new"; "data"; "4"];
4735        ["cat"; "/new"]], "new data contents");
4736     InitBasicFS, Always, TestOutput (
4737       [["write"; "/new"; "new file contents"];
4738        ["pwrite"; "/new"; "is extended"; "9"];
4739        ["cat"; "/new"]], "new file is extended");
4740     InitBasicFS, Always, TestOutput (
4741       [["write"; "/new"; "new file contents"];
4742        ["pwrite"; "/new"; ""; "4"];
4743        ["cat"; "/new"]], "new file contents")],
4744    "write to part of a file",
4745    "\
4746 This command writes to part of a file.  It writes the data
4747 buffer C<content> to the file C<path> starting at offset C<offset>.
4748
4749 This command implements the L<pwrite(2)> system call, and like
4750 that system call it may not write the full data requested.  The
4751 return value is the number of bytes that were actually written
4752 to the file.  This could even be 0, although short writes are
4753 unlikely for regular files in ordinary circumstances.
4754
4755 See also C<guestfs_pread>.");
4756
4757   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4758    [],
4759    "resize an ext2, ext3 or ext4 filesystem (with size)",
4760    "\
4761 This command is the same as C<guestfs_resize2fs> except that it
4762 allows you to specify the new size (in bytes) explicitly.");
4763
4764   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4765    [],
4766    "resize an LVM physical volume (with size)",
4767    "\
4768 This command is the same as C<guestfs_pvresize> except that it
4769 allows you to specify the new size (in bytes) explicitly.");
4770
4771   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4772    [],
4773    "resize an NTFS filesystem (with size)",
4774    "\
4775 This command is the same as C<guestfs_ntfsresize> except that it
4776 allows you to specify the new size (in bytes) explicitly.");
4777
4778   ("available_all_groups", (RStringList "groups", []), 251, [],
4779    [InitNone, Always, TestRun [["available_all_groups"]]],
4780    "return a list of all optional groups",
4781    "\
4782 This command returns a list of all optional groups that this
4783 daemon knows about.  Note this returns both supported and unsupported
4784 groups.  To find out which ones the daemon can actually support
4785 you have to call C<guestfs_available> on each member of the
4786 returned list.
4787
4788 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4789
4790   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4791    [InitBasicFS, Always, TestOutputStruct (
4792       [["fallocate64"; "/a"; "1000000"];
4793        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4794    "preallocate a file in the guest filesystem",
4795    "\
4796 This command preallocates a file (containing zero bytes) named
4797 C<path> of size C<len> bytes.  If the file exists already, it
4798 is overwritten.
4799
4800 Note that this call allocates disk blocks for the file.
4801 To create a sparse file use C<guestfs_truncate_size> instead.
4802
4803 The deprecated call C<guestfs_fallocate> does the same,
4804 but owing to an oversight it only allowed 30 bit lengths
4805 to be specified, effectively limiting the maximum size
4806 of files created through that call to 1GB.
4807
4808 Do not confuse this with the guestfish-specific
4809 C<alloc> and C<sparse> commands which create
4810 a file in the host and attach it as a device.");
4811
4812   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4813    [InitBasicFS, Always, TestOutput (
4814        [["set_e2label"; "/dev/sda1"; "LTEST"];
4815         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4816    "get the filesystem label",
4817    "\
4818 This returns the filesystem label of the filesystem on
4819 C<device>.
4820
4821 If the filesystem is unlabeled, this returns the empty string.");
4822
4823   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4824    (let uuid = uuidgen () in
4825     [InitBasicFS, Always, TestOutput (
4826        [["set_e2uuid"; "/dev/sda1"; uuid];
4827         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4828    "get the filesystem UUID",
4829    "\
4830 This returns the filesystem UUID of the filesystem on
4831 C<device>.
4832
4833 If the filesystem does not have a UUID, this returns the empty string.");
4834
4835   ("lvm_set_filter", (RErr, [DeviceList "devices"]), 255, [Optional "lvm2"],
4836    (* Can't be tested with the current framework because
4837     * the VG is being used by the mounted filesystem, so
4838     * the vgchange -an command we do first will fail.
4839     *)
4840     [],
4841    "set LVM device filter",
4842    "\
4843 This sets the LVM device filter so that LVM will only be
4844 able to \"see\" the block devices in the list C<devices>,
4845 and will ignore all other attached block devices.
4846
4847 Where disk image(s) contain duplicate PVs or VGs, this
4848 command is useful to get LVM to ignore the duplicates, otherwise
4849 LVM can get confused.  Note also there are two types
4850 of duplication possible: either cloned PVs/VGs which have
4851 identical UUIDs; or VGs that are not cloned but just happen
4852 to have the same name.  In normal operation you cannot
4853 create this situation, but you can do it outside LVM, eg.
4854 by cloning disk images or by bit twiddling inside the LVM
4855 metadata.
4856
4857 This command also clears the LVM cache and performs a volume
4858 group scan.
4859
4860 You can filter whole block devices or individual partitions.
4861
4862 You cannot use this if any VG is currently in use (eg.
4863 contains a mounted filesystem), even if you are not
4864 filtering out that VG.");
4865
4866   ("lvm_clear_filter", (RErr, []), 256, [],
4867    [], (* see note on lvm_set_filter *)
4868    "clear LVM device filter",
4869    "\
4870 This undoes the effect of C<guestfs_lvm_set_filter>.  LVM
4871 will be able to see every block device.
4872
4873 This command also clears the LVM cache and performs a volume
4874 group scan.");
4875
4876 ]
4877
4878 let all_functions = non_daemon_functions @ daemon_functions
4879
4880 (* In some places we want the functions to be displayed sorted
4881  * alphabetically, so this is useful:
4882  *)
4883 let all_functions_sorted =
4884   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4885                compare n1 n2) all_functions
4886
4887 (* This is used to generate the src/MAX_PROC_NR file which
4888  * contains the maximum procedure number, a surrogate for the
4889  * ABI version number.  See src/Makefile.am for the details.
4890  *)
4891 let max_proc_nr =
4892   let proc_nrs = List.map (
4893     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4894   ) daemon_functions in
4895   List.fold_left max 0 proc_nrs
4896
4897 (* Field types for structures. *)
4898 type field =
4899   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4900   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4901   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4902   | FUInt32
4903   | FInt32
4904   | FUInt64
4905   | FInt64
4906   | FBytes                      (* Any int measure that counts bytes. *)
4907   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4908   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4909
4910 (* Because we generate extra parsing code for LVM command line tools,
4911  * we have to pull out the LVM columns separately here.
4912  *)
4913 let lvm_pv_cols = [
4914   "pv_name", FString;
4915   "pv_uuid", FUUID;
4916   "pv_fmt", FString;
4917   "pv_size", FBytes;
4918   "dev_size", FBytes;
4919   "pv_free", FBytes;
4920   "pv_used", FBytes;
4921   "pv_attr", FString (* XXX *);
4922   "pv_pe_count", FInt64;
4923   "pv_pe_alloc_count", FInt64;
4924   "pv_tags", FString;
4925   "pe_start", FBytes;
4926   "pv_mda_count", FInt64;
4927   "pv_mda_free", FBytes;
4928   (* Not in Fedora 10:
4929      "pv_mda_size", FBytes;
4930   *)
4931 ]
4932 let lvm_vg_cols = [
4933   "vg_name", FString;
4934   "vg_uuid", FUUID;
4935   "vg_fmt", FString;
4936   "vg_attr", FString (* XXX *);
4937   "vg_size", FBytes;
4938   "vg_free", FBytes;
4939   "vg_sysid", FString;
4940   "vg_extent_size", FBytes;
4941   "vg_extent_count", FInt64;
4942   "vg_free_count", FInt64;
4943   "max_lv", FInt64;
4944   "max_pv", FInt64;
4945   "pv_count", FInt64;
4946   "lv_count", FInt64;
4947   "snap_count", FInt64;
4948   "vg_seqno", FInt64;
4949   "vg_tags", FString;
4950   "vg_mda_count", FInt64;
4951   "vg_mda_free", FBytes;
4952   (* Not in Fedora 10:
4953      "vg_mda_size", FBytes;
4954   *)
4955 ]
4956 let lvm_lv_cols = [
4957   "lv_name", FString;
4958   "lv_uuid", FUUID;
4959   "lv_attr", FString (* XXX *);
4960   "lv_major", FInt64;
4961   "lv_minor", FInt64;
4962   "lv_kernel_major", FInt64;
4963   "lv_kernel_minor", FInt64;
4964   "lv_size", FBytes;
4965   "seg_count", FInt64;
4966   "origin", FString;
4967   "snap_percent", FOptPercent;
4968   "copy_percent", FOptPercent;
4969   "move_pv", FString;
4970   "lv_tags", FString;
4971   "mirror_log", FString;
4972   "modules", FString;
4973 ]
4974
4975 (* Names and fields in all structures (in RStruct and RStructList)
4976  * that we support.
4977  *)
4978 let structs = [
4979   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4980    * not use this struct in any new code.
4981    *)
4982   "int_bool", [
4983     "i", FInt32;                (* for historical compatibility *)
4984     "b", FInt32;                (* for historical compatibility *)
4985   ];
4986
4987   (* LVM PVs, VGs, LVs. *)
4988   "lvm_pv", lvm_pv_cols;
4989   "lvm_vg", lvm_vg_cols;
4990   "lvm_lv", lvm_lv_cols;
4991
4992   (* Column names and types from stat structures.
4993    * NB. Can't use things like 'st_atime' because glibc header files
4994    * define some of these as macros.  Ugh.
4995    *)
4996   "stat", [
4997     "dev", FInt64;
4998     "ino", FInt64;
4999     "mode", FInt64;
5000     "nlink", FInt64;
5001     "uid", FInt64;
5002     "gid", FInt64;
5003     "rdev", FInt64;
5004     "size", FInt64;
5005     "blksize", FInt64;
5006     "blocks", FInt64;
5007     "atime", FInt64;
5008     "mtime", FInt64;
5009     "ctime", FInt64;
5010   ];
5011   "statvfs", [
5012     "bsize", FInt64;
5013     "frsize", FInt64;
5014     "blocks", FInt64;
5015     "bfree", FInt64;
5016     "bavail", FInt64;
5017     "files", FInt64;
5018     "ffree", FInt64;
5019     "favail", FInt64;
5020     "fsid", FInt64;
5021     "flag", FInt64;
5022     "namemax", FInt64;
5023   ];
5024
5025   (* Column names in dirent structure. *)
5026   "dirent", [
5027     "ino", FInt64;
5028     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
5029     "ftyp", FChar;
5030     "name", FString;
5031   ];
5032
5033   (* Version numbers. *)
5034   "version", [
5035     "major", FInt64;
5036     "minor", FInt64;
5037     "release", FInt64;
5038     "extra", FString;
5039   ];
5040
5041   (* Extended attribute. *)
5042   "xattr", [
5043     "attrname", FString;
5044     "attrval", FBuffer;
5045   ];
5046
5047   (* Inotify events. *)
5048   "inotify_event", [
5049     "in_wd", FInt64;
5050     "in_mask", FUInt32;
5051     "in_cookie", FUInt32;
5052     "in_name", FString;
5053   ];
5054
5055   (* Partition table entry. *)
5056   "partition", [
5057     "part_num", FInt32;
5058     "part_start", FBytes;
5059     "part_end", FBytes;
5060     "part_size", FBytes;
5061   ];
5062 ] (* end of structs *)
5063
5064 (* Ugh, Java has to be different ..
5065  * These names are also used by the Haskell bindings.
5066  *)
5067 let java_structs = [
5068   "int_bool", "IntBool";
5069   "lvm_pv", "PV";
5070   "lvm_vg", "VG";
5071   "lvm_lv", "LV";
5072   "stat", "Stat";
5073   "statvfs", "StatVFS";
5074   "dirent", "Dirent";
5075   "version", "Version";
5076   "xattr", "XAttr";
5077   "inotify_event", "INotifyEvent";
5078   "partition", "Partition";
5079 ]
5080
5081 (* What structs are actually returned. *)
5082 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5083
5084 (* Returns a list of RStruct/RStructList structs that are returned
5085  * by any function.  Each element of returned list is a pair:
5086  *
5087  * (structname, RStructOnly)
5088  *    == there exists function which returns RStruct (_, structname)
5089  * (structname, RStructListOnly)
5090  *    == there exists function which returns RStructList (_, structname)
5091  * (structname, RStructAndList)
5092  *    == there are functions returning both RStruct (_, structname)
5093  *                                      and RStructList (_, structname)
5094  *)
5095 let rstructs_used_by functions =
5096   (* ||| is a "logical OR" for rstructs_used_t *)
5097   let (|||) a b =
5098     match a, b with
5099     | RStructAndList, _
5100     | _, RStructAndList -> RStructAndList
5101     | RStructOnly, RStructListOnly
5102     | RStructListOnly, RStructOnly -> RStructAndList
5103     | RStructOnly, RStructOnly -> RStructOnly
5104     | RStructListOnly, RStructListOnly -> RStructListOnly
5105   in
5106
5107   let h = Hashtbl.create 13 in
5108
5109   (* if elem->oldv exists, update entry using ||| operator,
5110    * else just add elem->newv to the hash
5111    *)
5112   let update elem newv =
5113     try  let oldv = Hashtbl.find h elem in
5114          Hashtbl.replace h elem (newv ||| oldv)
5115     with Not_found -> Hashtbl.add h elem newv
5116   in
5117
5118   List.iter (
5119     fun (_, style, _, _, _, _, _) ->
5120       match fst style with
5121       | RStruct (_, structname) -> update structname RStructOnly
5122       | RStructList (_, structname) -> update structname RStructListOnly
5123       | _ -> ()
5124   ) functions;
5125
5126   (* return key->values as a list of (key,value) *)
5127   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5128
5129 (* Used for testing language bindings. *)
5130 type callt =
5131   | CallString of string
5132   | CallOptString of string option
5133   | CallStringList of string list
5134   | CallInt of int
5135   | CallInt64 of int64
5136   | CallBool of bool
5137   | CallBuffer of string
5138
5139 (* Used to memoize the result of pod2text. *)
5140 let pod2text_memo_filename = "src/.pod2text.data"
5141 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5142   try
5143     let chan = open_in pod2text_memo_filename in
5144     let v = input_value chan in
5145     close_in chan;
5146     v
5147   with
5148     _ -> Hashtbl.create 13
5149 let pod2text_memo_updated () =
5150   let chan = open_out pod2text_memo_filename in
5151   output_value chan pod2text_memo;
5152   close_out chan
5153
5154 (* Useful functions.
5155  * Note we don't want to use any external OCaml libraries which
5156  * makes this a bit harder than it should be.
5157  *)
5158 module StringMap = Map.Make (String)
5159
5160 let failwithf fs = ksprintf failwith fs
5161
5162 let unique = let i = ref 0 in fun () -> incr i; !i
5163
5164 let replace_char s c1 c2 =
5165   let s2 = String.copy s in
5166   let r = ref false in
5167   for i = 0 to String.length s2 - 1 do
5168     if String.unsafe_get s2 i = c1 then (
5169       String.unsafe_set s2 i c2;
5170       r := true
5171     )
5172   done;
5173   if not !r then s else s2
5174
5175 let isspace c =
5176   c = ' '
5177   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5178
5179 let triml ?(test = isspace) str =
5180   let i = ref 0 in
5181   let n = ref (String.length str) in
5182   while !n > 0 && test str.[!i]; do
5183     decr n;
5184     incr i
5185   done;
5186   if !i = 0 then str
5187   else String.sub str !i !n
5188
5189 let trimr ?(test = isspace) str =
5190   let n = ref (String.length str) in
5191   while !n > 0 && test str.[!n-1]; do
5192     decr n
5193   done;
5194   if !n = String.length str then str
5195   else String.sub str 0 !n
5196
5197 let trim ?(test = isspace) str =
5198   trimr ~test (triml ~test str)
5199
5200 let rec find s sub =
5201   let len = String.length s in
5202   let sublen = String.length sub in
5203   let rec loop i =
5204     if i <= len-sublen then (
5205       let rec loop2 j =
5206         if j < sublen then (
5207           if s.[i+j] = sub.[j] then loop2 (j+1)
5208           else -1
5209         ) else
5210           i (* found *)
5211       in
5212       let r = loop2 0 in
5213       if r = -1 then loop (i+1) else r
5214     ) else
5215       -1 (* not found *)
5216   in
5217   loop 0
5218
5219 let rec replace_str s s1 s2 =
5220   let len = String.length s in
5221   let sublen = String.length s1 in
5222   let i = find s s1 in
5223   if i = -1 then s
5224   else (
5225     let s' = String.sub s 0 i in
5226     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5227     s' ^ s2 ^ replace_str s'' s1 s2
5228   )
5229
5230 let rec string_split sep str =
5231   let len = String.length str in
5232   let seplen = String.length sep in
5233   let i = find str sep in
5234   if i = -1 then [str]
5235   else (
5236     let s' = String.sub str 0 i in
5237     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5238     s' :: string_split sep s''
5239   )
5240
5241 let files_equal n1 n2 =
5242   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5243   match Sys.command cmd with
5244   | 0 -> true
5245   | 1 -> false
5246   | i -> failwithf "%s: failed with error code %d" cmd i
5247
5248 let rec filter_map f = function
5249   | [] -> []
5250   | x :: xs ->
5251       match f x with
5252       | Some y -> y :: filter_map f xs
5253       | None -> filter_map f xs
5254
5255 let rec find_map f = function
5256   | [] -> raise Not_found
5257   | x :: xs ->
5258       match f x with
5259       | Some y -> y
5260       | None -> find_map f xs
5261
5262 let iteri f xs =
5263   let rec loop i = function
5264     | [] -> ()
5265     | x :: xs -> f i x; loop (i+1) xs
5266   in
5267   loop 0 xs
5268
5269 let mapi f xs =
5270   let rec loop i = function
5271     | [] -> []
5272     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5273   in
5274   loop 0 xs
5275
5276 let count_chars c str =
5277   let count = ref 0 in
5278   for i = 0 to String.length str - 1 do
5279     if c = String.unsafe_get str i then incr count
5280   done;
5281   !count
5282
5283 let explode str =
5284   let r = ref [] in
5285   for i = 0 to String.length str - 1 do
5286     let c = String.unsafe_get str i in
5287     r := c :: !r;
5288   done;
5289   List.rev !r
5290
5291 let map_chars f str =
5292   List.map f (explode str)
5293
5294 let name_of_argt = function
5295   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5296   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5297   | FileIn n | FileOut n | BufferIn n -> n
5298
5299 let java_name_of_struct typ =
5300   try List.assoc typ java_structs
5301   with Not_found ->
5302     failwithf
5303       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5304
5305 let cols_of_struct typ =
5306   try List.assoc typ structs
5307   with Not_found ->
5308     failwithf "cols_of_struct: unknown struct %s" typ
5309
5310 let seq_of_test = function
5311   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5312   | TestOutputListOfDevices (s, _)
5313   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5314   | TestOutputTrue s | TestOutputFalse s
5315   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5316   | TestOutputStruct (s, _)
5317   | TestLastFail s -> s
5318
5319 (* Handling for function flags. *)
5320 let protocol_limit_warning =
5321   "Because of the message protocol, there is a transfer limit
5322 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5323
5324 let danger_will_robinson =
5325   "B<This command is dangerous.  Without careful use you
5326 can easily destroy all your data>."
5327
5328 let deprecation_notice flags =
5329   try
5330     let alt =
5331       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5332     let txt =
5333       sprintf "This function is deprecated.
5334 In new code, use the C<%s> call instead.
5335
5336 Deprecated functions will not be removed from the API, but the
5337 fact that they are deprecated indicates that there are problems
5338 with correct use of these functions." alt in
5339     Some txt
5340   with
5341     Not_found -> None
5342
5343 (* Create list of optional groups. *)
5344 let optgroups =
5345   let h = Hashtbl.create 13 in
5346   List.iter (
5347     fun (name, _, _, flags, _, _, _) ->
5348       List.iter (
5349         function
5350         | Optional group ->
5351             let names = try Hashtbl.find h group with Not_found -> [] in
5352             Hashtbl.replace h group (name :: names)
5353         | _ -> ()
5354       ) flags
5355   ) daemon_functions;
5356   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5357   let groups =
5358     List.map (
5359       fun group -> group, List.sort compare (Hashtbl.find h group)
5360     ) groups in
5361   List.sort (fun x y -> compare (fst x) (fst y)) groups
5362
5363 (* Check function names etc. for consistency. *)
5364 let check_functions () =
5365   let contains_uppercase str =
5366     let len = String.length str in
5367     let rec loop i =
5368       if i >= len then false
5369       else (
5370         let c = str.[i] in
5371         if c >= 'A' && c <= 'Z' then true
5372         else loop (i+1)
5373       )
5374     in
5375     loop 0
5376   in
5377
5378   (* Check function names. *)
5379   List.iter (
5380     fun (name, _, _, _, _, _, _) ->
5381       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5382         failwithf "function name %s does not need 'guestfs' prefix" name;
5383       if name = "" then
5384         failwithf "function name is empty";
5385       if name.[0] < 'a' || name.[0] > 'z' then
5386         failwithf "function name %s must start with lowercase a-z" name;
5387       if String.contains name '-' then
5388         failwithf "function name %s should not contain '-', use '_' instead."
5389           name
5390   ) all_functions;
5391
5392   (* Check function parameter/return names. *)
5393   List.iter (
5394     fun (name, style, _, _, _, _, _) ->
5395       let check_arg_ret_name n =
5396         if contains_uppercase n then
5397           failwithf "%s param/ret %s should not contain uppercase chars"
5398             name n;
5399         if String.contains n '-' || String.contains n '_' then
5400           failwithf "%s param/ret %s should not contain '-' or '_'"
5401             name n;
5402         if n = "value" then
5403           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;
5404         if n = "int" || n = "char" || n = "short" || n = "long" then
5405           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5406         if n = "i" || n = "n" then
5407           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5408         if n = "argv" || n = "args" then
5409           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5410
5411         (* List Haskell, OCaml and C keywords here.
5412          * http://www.haskell.org/haskellwiki/Keywords
5413          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5414          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5415          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5416          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5417          * Omitting _-containing words, since they're handled above.
5418          * Omitting the OCaml reserved word, "val", is ok,
5419          * and saves us from renaming several parameters.
5420          *)
5421         let reserved = [
5422           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5423           "char"; "class"; "const"; "constraint"; "continue"; "data";
5424           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5425           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5426           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5427           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5428           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5429           "interface";
5430           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5431           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5432           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5433           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5434           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5435           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5436           "volatile"; "when"; "where"; "while";
5437           ] in
5438         if List.mem n reserved then
5439           failwithf "%s has param/ret using reserved word %s" name n;
5440       in
5441
5442       (match fst style with
5443        | RErr -> ()
5444        | RInt n | RInt64 n | RBool n
5445        | RConstString n | RConstOptString n | RString n
5446        | RStringList n | RStruct (n, _) | RStructList (n, _)
5447        | RHashtable n | RBufferOut n ->
5448            check_arg_ret_name n
5449       );
5450       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5451   ) all_functions;
5452
5453   (* Check short descriptions. *)
5454   List.iter (
5455     fun (name, _, _, _, _, shortdesc, _) ->
5456       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5457         failwithf "short description of %s should begin with lowercase." name;
5458       let c = shortdesc.[String.length shortdesc-1] in
5459       if c = '\n' || c = '.' then
5460         failwithf "short description of %s should not end with . or \\n." name
5461   ) all_functions;
5462
5463   (* Check long descriptions. *)
5464   List.iter (
5465     fun (name, _, _, _, _, _, longdesc) ->
5466       if longdesc.[String.length longdesc-1] = '\n' then
5467         failwithf "long description of %s should not end with \\n." name
5468   ) all_functions;
5469
5470   (* Check proc_nrs. *)
5471   List.iter (
5472     fun (name, _, proc_nr, _, _, _, _) ->
5473       if proc_nr <= 0 then
5474         failwithf "daemon function %s should have proc_nr > 0" name
5475   ) daemon_functions;
5476
5477   List.iter (
5478     fun (name, _, proc_nr, _, _, _, _) ->
5479       if proc_nr <> -1 then
5480         failwithf "non-daemon function %s should have proc_nr -1" name
5481   ) non_daemon_functions;
5482
5483   let proc_nrs =
5484     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5485       daemon_functions in
5486   let proc_nrs =
5487     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5488   let rec loop = function
5489     | [] -> ()
5490     | [_] -> ()
5491     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5492         loop rest
5493     | (name1,nr1) :: (name2,nr2) :: _ ->
5494         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5495           name1 name2 nr1 nr2
5496   in
5497   loop proc_nrs;
5498
5499   (* Check tests. *)
5500   List.iter (
5501     function
5502       (* Ignore functions that have no tests.  We generate a
5503        * warning when the user does 'make check' instead.
5504        *)
5505     | name, _, _, _, [], _, _ -> ()
5506     | name, _, _, _, tests, _, _ ->
5507         let funcs =
5508           List.map (
5509             fun (_, _, test) ->
5510               match seq_of_test test with
5511               | [] ->
5512                   failwithf "%s has a test containing an empty sequence" name
5513               | cmds -> List.map List.hd cmds
5514           ) tests in
5515         let funcs = List.flatten funcs in
5516
5517         let tested = List.mem name funcs in
5518
5519         if not tested then
5520           failwithf "function %s has tests but does not test itself" name
5521   ) all_functions
5522
5523 (* 'pr' prints to the current output file. *)
5524 let chan = ref Pervasives.stdout
5525 let lines = ref 0
5526 let pr fs =
5527   ksprintf
5528     (fun str ->
5529        let i = count_chars '\n' str in
5530        lines := !lines + i;
5531        output_string !chan str
5532     ) fs
5533
5534 let copyright_years =
5535   let this_year = 1900 + (localtime (time ())).tm_year in
5536   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5537
5538 (* Generate a header block in a number of standard styles. *)
5539 type comment_style =
5540     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5541 type license = GPLv2plus | LGPLv2plus
5542
5543 let generate_header ?(extra_inputs = []) comment license =
5544   let inputs = "src/generator.ml" :: extra_inputs in
5545   let c = match comment with
5546     | CStyle ->         pr "/* "; " *"
5547     | CPlusPlusStyle -> pr "// "; "//"
5548     | HashStyle ->      pr "# ";  "#"
5549     | OCamlStyle ->     pr "(* "; " *"
5550     | HaskellStyle ->   pr "{- "; "  " in
5551   pr "libguestfs generated file\n";
5552   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5553   List.iter (pr "%s   %s\n" c) inputs;
5554   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5555   pr "%s\n" c;
5556   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5557   pr "%s\n" c;
5558   (match license with
5559    | GPLv2plus ->
5560        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5561        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5562        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5563        pr "%s (at your option) any later version.\n" c;
5564        pr "%s\n" c;
5565        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5566        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5567        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5568        pr "%s GNU General Public License for more details.\n" c;
5569        pr "%s\n" c;
5570        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5571        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5572        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5573
5574    | LGPLv2plus ->
5575        pr "%s This library is free software; you can redistribute it and/or\n" c;
5576        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5577        pr "%s License as published by the Free Software Foundation; either\n" c;
5578        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5579        pr "%s\n" c;
5580        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5581        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5582        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5583        pr "%s Lesser General Public License for more details.\n" c;
5584        pr "%s\n" c;
5585        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5586        pr "%s License along with this library; if not, write to the Free Software\n" c;
5587        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5588   );
5589   (match comment with
5590    | CStyle -> pr " */\n"
5591    | CPlusPlusStyle
5592    | HashStyle -> ()
5593    | OCamlStyle -> pr " *)\n"
5594    | HaskellStyle -> pr "-}\n"
5595   );
5596   pr "\n"
5597
5598 (* Start of main code generation functions below this line. *)
5599
5600 (* Generate the pod documentation for the C API. *)
5601 let rec generate_actions_pod () =
5602   List.iter (
5603     fun (shortname, style, _, flags, _, _, longdesc) ->
5604       if not (List.mem NotInDocs flags) then (
5605         let name = "guestfs_" ^ shortname in
5606         pr "=head2 %s\n\n" name;
5607         pr " ";
5608         generate_prototype ~extern:false ~handle:"g" name style;
5609         pr "\n\n";
5610         pr "%s\n\n" longdesc;
5611         (match fst style with
5612          | RErr ->
5613              pr "This function returns 0 on success or -1 on error.\n\n"
5614          | RInt _ ->
5615              pr "On error this function returns -1.\n\n"
5616          | RInt64 _ ->
5617              pr "On error this function returns -1.\n\n"
5618          | RBool _ ->
5619              pr "This function returns a C truth value on success or -1 on error.\n\n"
5620          | RConstString _ ->
5621              pr "This function returns a string, or NULL on error.
5622 The string is owned by the guest handle and must I<not> be freed.\n\n"
5623          | RConstOptString _ ->
5624              pr "This function returns a string which may be NULL.
5625 There is way to return an error from this function.
5626 The string is owned by the guest handle and must I<not> be freed.\n\n"
5627          | RString _ ->
5628              pr "This function returns a string, or NULL on error.
5629 I<The caller must free the returned string after use>.\n\n"
5630          | RStringList _ ->
5631              pr "This function returns a NULL-terminated array of strings
5632 (like L<environ(3)>), or NULL if there was an error.
5633 I<The caller must free the strings and the array after use>.\n\n"
5634          | RStruct (_, typ) ->
5635              pr "This function returns a C<struct guestfs_%s *>,
5636 or NULL if there was an error.
5637 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5638          | RStructList (_, typ) ->
5639              pr "This function returns a C<struct guestfs_%s_list *>
5640 (see E<lt>guestfs-structs.hE<gt>),
5641 or NULL if there was an error.
5642 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5643          | RHashtable _ ->
5644              pr "This function returns a NULL-terminated array of
5645 strings, or NULL if there was an error.
5646 The array of strings will always have length C<2n+1>, where
5647 C<n> keys and values alternate, followed by the trailing NULL entry.
5648 I<The caller must free the strings and the array after use>.\n\n"
5649          | RBufferOut _ ->
5650              pr "This function returns a buffer, or NULL on error.
5651 The size of the returned buffer is written to C<*size_r>.
5652 I<The caller must free the returned buffer after use>.\n\n"
5653         );
5654         if List.mem ProtocolLimitWarning flags then
5655           pr "%s\n\n" protocol_limit_warning;
5656         if List.mem DangerWillRobinson flags then
5657           pr "%s\n\n" danger_will_robinson;
5658         match deprecation_notice flags with
5659         | None -> ()
5660         | Some txt -> pr "%s\n\n" txt
5661       )
5662   ) all_functions_sorted
5663
5664 and generate_structs_pod () =
5665   (* Structs documentation. *)
5666   List.iter (
5667     fun (typ, cols) ->
5668       pr "=head2 guestfs_%s\n" typ;
5669       pr "\n";
5670       pr " struct guestfs_%s {\n" typ;
5671       List.iter (
5672         function
5673         | name, FChar -> pr "   char %s;\n" name
5674         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5675         | name, FInt32 -> pr "   int32_t %s;\n" name
5676         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5677         | name, FInt64 -> pr "   int64_t %s;\n" name
5678         | name, FString -> pr "   char *%s;\n" name
5679         | name, FBuffer ->
5680             pr "   /* The next two fields describe a byte array. */\n";
5681             pr "   uint32_t %s_len;\n" name;
5682             pr "   char *%s;\n" name
5683         | name, FUUID ->
5684             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5685             pr "   char %s[32];\n" name
5686         | name, FOptPercent ->
5687             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5688             pr "   float %s;\n" name
5689       ) cols;
5690       pr " };\n";
5691       pr " \n";
5692       pr " struct guestfs_%s_list {\n" typ;
5693       pr "   uint32_t len; /* Number of elements in list. */\n";
5694       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5695       pr " };\n";
5696       pr " \n";
5697       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5698       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5699         typ typ;
5700       pr "\n"
5701   ) structs
5702
5703 and generate_availability_pod () =
5704   (* Availability documentation. *)
5705   pr "=over 4\n";
5706   pr "\n";
5707   List.iter (
5708     fun (group, functions) ->
5709       pr "=item B<%s>\n" group;
5710       pr "\n";
5711       pr "The following functions:\n";
5712       List.iter (pr "L</guestfs_%s>\n") functions;
5713       pr "\n"
5714   ) optgroups;
5715   pr "=back\n";
5716   pr "\n"
5717
5718 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5719  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5720  *
5721  * We have to use an underscore instead of a dash because otherwise
5722  * rpcgen generates incorrect code.
5723  *
5724  * This header is NOT exported to clients, but see also generate_structs_h.
5725  *)
5726 and generate_xdr () =
5727   generate_header CStyle LGPLv2plus;
5728
5729   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5730   pr "typedef string str<>;\n";
5731   pr "\n";
5732
5733   (* Internal structures. *)
5734   List.iter (
5735     function
5736     | typ, cols ->
5737         pr "struct guestfs_int_%s {\n" typ;
5738         List.iter (function
5739                    | name, FChar -> pr "  char %s;\n" name
5740                    | name, FString -> pr "  string %s<>;\n" name
5741                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5742                    | name, FUUID -> pr "  opaque %s[32];\n" name
5743                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5744                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5745                    | name, FOptPercent -> pr "  float %s;\n" name
5746                   ) cols;
5747         pr "};\n";
5748         pr "\n";
5749         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5750         pr "\n";
5751   ) structs;
5752
5753   List.iter (
5754     fun (shortname, style, _, _, _, _, _) ->
5755       let name = "guestfs_" ^ shortname in
5756
5757       (match snd style with
5758        | [] -> ()
5759        | args ->
5760            pr "struct %s_args {\n" name;
5761            List.iter (
5762              function
5763              | Pathname n | Device n | Dev_or_Path n | String n ->
5764                  pr "  string %s<>;\n" n
5765              | OptString n -> pr "  str *%s;\n" n
5766              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5767              | Bool n -> pr "  bool %s;\n" n
5768              | Int n -> pr "  int %s;\n" n
5769              | Int64 n -> pr "  hyper %s;\n" n
5770              | BufferIn n ->
5771                  pr "  opaque %s<>;\n" n
5772              | FileIn _ | FileOut _ -> ()
5773            ) args;
5774            pr "};\n\n"
5775       );
5776       (match fst style with
5777        | RErr -> ()
5778        | RInt n ->
5779            pr "struct %s_ret {\n" name;
5780            pr "  int %s;\n" n;
5781            pr "};\n\n"
5782        | RInt64 n ->
5783            pr "struct %s_ret {\n" name;
5784            pr "  hyper %s;\n" n;
5785            pr "};\n\n"
5786        | RBool n ->
5787            pr "struct %s_ret {\n" name;
5788            pr "  bool %s;\n" n;
5789            pr "};\n\n"
5790        | RConstString _ | RConstOptString _ ->
5791            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5792        | RString n ->
5793            pr "struct %s_ret {\n" name;
5794            pr "  string %s<>;\n" n;
5795            pr "};\n\n"
5796        | RStringList n ->
5797            pr "struct %s_ret {\n" name;
5798            pr "  str %s<>;\n" n;
5799            pr "};\n\n"
5800        | RStruct (n, typ) ->
5801            pr "struct %s_ret {\n" name;
5802            pr "  guestfs_int_%s %s;\n" typ n;
5803            pr "};\n\n"
5804        | RStructList (n, typ) ->
5805            pr "struct %s_ret {\n" name;
5806            pr "  guestfs_int_%s_list %s;\n" typ n;
5807            pr "};\n\n"
5808        | RHashtable n ->
5809            pr "struct %s_ret {\n" name;
5810            pr "  str %s<>;\n" n;
5811            pr "};\n\n"
5812        | RBufferOut n ->
5813            pr "struct %s_ret {\n" name;
5814            pr "  opaque %s<>;\n" n;
5815            pr "};\n\n"
5816       );
5817   ) daemon_functions;
5818
5819   (* Table of procedure numbers. *)
5820   pr "enum guestfs_procedure {\n";
5821   List.iter (
5822     fun (shortname, _, proc_nr, _, _, _, _) ->
5823       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5824   ) daemon_functions;
5825   pr "  GUESTFS_PROC_NR_PROCS\n";
5826   pr "};\n";
5827   pr "\n";
5828
5829   (* Having to choose a maximum message size is annoying for several
5830    * reasons (it limits what we can do in the API), but it (a) makes
5831    * the protocol a lot simpler, and (b) provides a bound on the size
5832    * of the daemon which operates in limited memory space.
5833    *)
5834   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5835   pr "\n";
5836
5837   (* Message header, etc. *)
5838   pr "\
5839 /* The communication protocol is now documented in the guestfs(3)
5840  * manpage.
5841  */
5842
5843 const GUESTFS_PROGRAM = 0x2000F5F5;
5844 const GUESTFS_PROTOCOL_VERSION = 1;
5845
5846 /* These constants must be larger than any possible message length. */
5847 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5848 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5849
5850 enum guestfs_message_direction {
5851   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5852   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5853 };
5854
5855 enum guestfs_message_status {
5856   GUESTFS_STATUS_OK = 0,
5857   GUESTFS_STATUS_ERROR = 1
5858 };
5859
5860 const GUESTFS_ERROR_LEN = 256;
5861
5862 struct guestfs_message_error {
5863   string error_message<GUESTFS_ERROR_LEN>;
5864 };
5865
5866 struct guestfs_message_header {
5867   unsigned prog;                     /* GUESTFS_PROGRAM */
5868   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5869   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5870   guestfs_message_direction direction;
5871   unsigned serial;                   /* message serial number */
5872   guestfs_message_status status;
5873 };
5874
5875 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5876
5877 struct guestfs_chunk {
5878   int cancel;                        /* if non-zero, transfer is cancelled */
5879   /* data size is 0 bytes if the transfer has finished successfully */
5880   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5881 };
5882 "
5883
5884 (* Generate the guestfs-structs.h file. *)
5885 and generate_structs_h () =
5886   generate_header CStyle LGPLv2plus;
5887
5888   (* This is a public exported header file containing various
5889    * structures.  The structures are carefully written to have
5890    * exactly the same in-memory format as the XDR structures that
5891    * we use on the wire to the daemon.  The reason for creating
5892    * copies of these structures here is just so we don't have to
5893    * export the whole of guestfs_protocol.h (which includes much
5894    * unrelated and XDR-dependent stuff that we don't want to be
5895    * public, or required by clients).
5896    *
5897    * To reiterate, we will pass these structures to and from the
5898    * client with a simple assignment or memcpy, so the format
5899    * must be identical to what rpcgen / the RFC defines.
5900    *)
5901
5902   (* Public structures. *)
5903   List.iter (
5904     fun (typ, cols) ->
5905       pr "struct guestfs_%s {\n" typ;
5906       List.iter (
5907         function
5908         | name, FChar -> pr "  char %s;\n" name
5909         | name, FString -> pr "  char *%s;\n" name
5910         | name, FBuffer ->
5911             pr "  uint32_t %s_len;\n" name;
5912             pr "  char *%s;\n" name
5913         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5914         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5915         | name, FInt32 -> pr "  int32_t %s;\n" name
5916         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5917         | name, FInt64 -> pr "  int64_t %s;\n" name
5918         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5919       ) cols;
5920       pr "};\n";
5921       pr "\n";
5922       pr "struct guestfs_%s_list {\n" typ;
5923       pr "  uint32_t len;\n";
5924       pr "  struct guestfs_%s *val;\n" typ;
5925       pr "};\n";
5926       pr "\n";
5927       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5928       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5929       pr "\n"
5930   ) structs
5931
5932 (* Generate the guestfs-actions.h file. *)
5933 and generate_actions_h () =
5934   generate_header CStyle LGPLv2plus;
5935   List.iter (
5936     fun (shortname, style, _, _, _, _, _) ->
5937       let name = "guestfs_" ^ shortname in
5938       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5939         name style
5940   ) all_functions
5941
5942 (* Generate the guestfs-internal-actions.h file. *)
5943 and generate_internal_actions_h () =
5944   generate_header CStyle LGPLv2plus;
5945   List.iter (
5946     fun (shortname, style, _, _, _, _, _) ->
5947       let name = "guestfs__" ^ shortname in
5948       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5949         name style
5950   ) non_daemon_functions
5951
5952 (* Generate the client-side dispatch stubs. *)
5953 and generate_client_actions () =
5954   generate_header CStyle LGPLv2plus;
5955
5956   pr "\
5957 #include <stdio.h>
5958 #include <stdlib.h>
5959 #include <stdint.h>
5960 #include <string.h>
5961 #include <inttypes.h>
5962
5963 #include \"guestfs.h\"
5964 #include \"guestfs-internal.h\"
5965 #include \"guestfs-internal-actions.h\"
5966 #include \"guestfs_protocol.h\"
5967
5968 #define error guestfs_error
5969 //#define perrorf guestfs_perrorf
5970 #define safe_malloc guestfs_safe_malloc
5971 #define safe_realloc guestfs_safe_realloc
5972 //#define safe_strdup guestfs_safe_strdup
5973 #define safe_memdup guestfs_safe_memdup
5974
5975 /* Check the return message from a call for validity. */
5976 static int
5977 check_reply_header (guestfs_h *g,
5978                     const struct guestfs_message_header *hdr,
5979                     unsigned int proc_nr, unsigned int serial)
5980 {
5981   if (hdr->prog != GUESTFS_PROGRAM) {
5982     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5983     return -1;
5984   }
5985   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5986     error (g, \"wrong protocol version (%%d/%%d)\",
5987            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5988     return -1;
5989   }
5990   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5991     error (g, \"unexpected message direction (%%d/%%d)\",
5992            hdr->direction, GUESTFS_DIRECTION_REPLY);
5993     return -1;
5994   }
5995   if (hdr->proc != proc_nr) {
5996     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5997     return -1;
5998   }
5999   if (hdr->serial != serial) {
6000     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
6001     return -1;
6002   }
6003
6004   return 0;
6005 }
6006
6007 /* Check we are in the right state to run a high-level action. */
6008 static int
6009 check_state (guestfs_h *g, const char *caller)
6010 {
6011   if (!guestfs__is_ready (g)) {
6012     if (guestfs__is_config (g) || guestfs__is_launching (g))
6013       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
6014         caller);
6015     else
6016       error (g, \"%%s called from the wrong state, %%d != READY\",
6017         caller, guestfs__get_state (g));
6018     return -1;
6019   }
6020   return 0;
6021 }
6022
6023 ";
6024
6025   let error_code_of = function
6026     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
6027     | RConstString _ | RConstOptString _
6028     | RString _ | RStringList _
6029     | RStruct _ | RStructList _
6030     | RHashtable _ | RBufferOut _ -> "NULL"
6031   in
6032
6033   (* Generate code to check String-like parameters are not passed in
6034    * as NULL (returning an error if they are).
6035    *)
6036   let check_null_strings shortname style =
6037     let pr_newline = ref false in
6038     List.iter (
6039       function
6040       (* parameters which should not be NULL *)
6041       | String n
6042       | Device n
6043       | Pathname n
6044       | Dev_or_Path n
6045       | FileIn n
6046       | FileOut n
6047       | BufferIn n
6048       | StringList n
6049       | DeviceList n ->
6050           pr "  if (%s == NULL) {\n" n;
6051           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6052           pr "           \"%s\", \"%s\");\n" shortname n;
6053           pr "    return %s;\n" (error_code_of (fst style));
6054           pr "  }\n";
6055           pr_newline := true
6056
6057       (* can be NULL *)
6058       | OptString _
6059
6060       (* not applicable *)
6061       | Bool _
6062       | Int _
6063       | Int64 _ -> ()
6064     ) (snd style);
6065
6066     if !pr_newline then pr "\n";
6067   in
6068
6069   (* Generate code to generate guestfish call traces. *)
6070   let trace_call shortname style =
6071     pr "  if (guestfs__get_trace (g)) {\n";
6072
6073     let needs_i =
6074       List.exists (function
6075                    | StringList _ | DeviceList _ -> true
6076                    | _ -> false) (snd style) in
6077     if needs_i then (
6078       pr "    size_t i;\n";
6079       pr "\n"
6080     );
6081
6082     pr "    printf (\"%s\");\n" shortname;
6083     List.iter (
6084       function
6085       | String n                        (* strings *)
6086       | Device n
6087       | Pathname n
6088       | Dev_or_Path n
6089       | FileIn n
6090       | FileOut n
6091       | BufferIn n ->
6092           (* guestfish doesn't support string escaping, so neither do we *)
6093           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
6094       | OptString n ->                  (* string option *)
6095           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6096           pr "    else printf (\" null\");\n"
6097       | StringList n
6098       | DeviceList n ->                 (* string list *)
6099           pr "    putchar (' ');\n";
6100           pr "    putchar ('\"');\n";
6101           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6102           pr "      if (i > 0) putchar (' ');\n";
6103           pr "      fputs (%s[i], stdout);\n" n;
6104           pr "    }\n";
6105           pr "    putchar ('\"');\n";
6106       | Bool n ->                       (* boolean *)
6107           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6108       | Int n ->                        (* int *)
6109           pr "    printf (\" %%d\", %s);\n" n
6110       | Int64 n ->
6111           pr "    printf (\" %%\" PRIi64, %s);\n" n
6112     ) (snd style);
6113     pr "    putchar ('\\n');\n";
6114     pr "  }\n";
6115     pr "\n";
6116   in
6117
6118   (* For non-daemon functions, generate a wrapper around each function. *)
6119   List.iter (
6120     fun (shortname, style, _, _, _, _, _) ->
6121       let name = "guestfs_" ^ shortname in
6122
6123       generate_prototype ~extern:false ~semicolon:false ~newline:true
6124         ~handle:"g" name style;
6125       pr "{\n";
6126       check_null_strings shortname style;
6127       trace_call shortname style;
6128       pr "  return guestfs__%s " shortname;
6129       generate_c_call_args ~handle:"g" style;
6130       pr ";\n";
6131       pr "}\n";
6132       pr "\n"
6133   ) non_daemon_functions;
6134
6135   (* Client-side stubs for each function. *)
6136   List.iter (
6137     fun (shortname, style, _, _, _, _, _) ->
6138       let name = "guestfs_" ^ shortname in
6139       let error_code = error_code_of (fst style) in
6140
6141       (* Generate the action stub. *)
6142       generate_prototype ~extern:false ~semicolon:false ~newline:true
6143         ~handle:"g" name style;
6144
6145       pr "{\n";
6146
6147       (match snd style with
6148        | [] -> ()
6149        | _ -> pr "  struct %s_args args;\n" name
6150       );
6151
6152       pr "  guestfs_message_header hdr;\n";
6153       pr "  guestfs_message_error err;\n";
6154       let has_ret =
6155         match fst style with
6156         | RErr -> false
6157         | RConstString _ | RConstOptString _ ->
6158             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6159         | RInt _ | RInt64 _
6160         | RBool _ | RString _ | RStringList _
6161         | RStruct _ | RStructList _
6162         | RHashtable _ | RBufferOut _ ->
6163             pr "  struct %s_ret ret;\n" name;
6164             true in
6165
6166       pr "  int serial;\n";
6167       pr "  int r;\n";
6168       pr "\n";
6169       check_null_strings shortname style;
6170       trace_call shortname style;
6171       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6172         shortname error_code;
6173       pr "  guestfs___set_busy (g);\n";
6174       pr "\n";
6175
6176       (* Send the main header and arguments. *)
6177       (match snd style with
6178        | [] ->
6179            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6180              (String.uppercase shortname)
6181        | args ->
6182            List.iter (
6183              function
6184              | Pathname n | Device n | Dev_or_Path n | String n ->
6185                  pr "  args.%s = (char *) %s;\n" n n
6186              | OptString n ->
6187                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6188              | StringList n | DeviceList n ->
6189                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6190                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6191              | Bool n ->
6192                  pr "  args.%s = %s;\n" n n
6193              | Int n ->
6194                  pr "  args.%s = %s;\n" n n
6195              | Int64 n ->
6196                  pr "  args.%s = %s;\n" n n
6197              | FileIn _ | FileOut _ -> ()
6198              | BufferIn n ->
6199                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6200                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6201                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6202                    shortname;
6203                  pr "    guestfs___end_busy (g);\n";
6204                  pr "    return %s;\n" error_code;
6205                  pr "  }\n";
6206                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6207                  pr "  args.%s.%s_len = %s_size;\n" n n n
6208            ) args;
6209            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6210              (String.uppercase shortname);
6211            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6212              name;
6213       );
6214       pr "  if (serial == -1) {\n";
6215       pr "    guestfs___end_busy (g);\n";
6216       pr "    return %s;\n" error_code;
6217       pr "  }\n";
6218       pr "\n";
6219
6220       (* Send any additional files (FileIn) requested. *)
6221       let need_read_reply_label = ref false in
6222       List.iter (
6223         function
6224         | FileIn n ->
6225             pr "  r = guestfs___send_file (g, %s);\n" n;
6226             pr "  if (r == -1) {\n";
6227             pr "    guestfs___end_busy (g);\n";
6228             pr "    return %s;\n" error_code;
6229             pr "  }\n";
6230             pr "  if (r == -2) /* daemon cancelled */\n";
6231             pr "    goto read_reply;\n";
6232             need_read_reply_label := true;
6233             pr "\n";
6234         | _ -> ()
6235       ) (snd style);
6236
6237       (* Wait for the reply from the remote end. *)
6238       if !need_read_reply_label then pr " read_reply:\n";
6239       pr "  memset (&hdr, 0, sizeof hdr);\n";
6240       pr "  memset (&err, 0, sizeof err);\n";
6241       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6242       pr "\n";
6243       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6244       if not has_ret then
6245         pr "NULL, NULL"
6246       else
6247         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6248       pr ");\n";
6249
6250       pr "  if (r == -1) {\n";
6251       pr "    guestfs___end_busy (g);\n";
6252       pr "    return %s;\n" error_code;
6253       pr "  }\n";
6254       pr "\n";
6255
6256       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6257         (String.uppercase shortname);
6258       pr "    guestfs___end_busy (g);\n";
6259       pr "    return %s;\n" error_code;
6260       pr "  }\n";
6261       pr "\n";
6262
6263       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6264       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6265       pr "    free (err.error_message);\n";
6266       pr "    guestfs___end_busy (g);\n";
6267       pr "    return %s;\n" error_code;
6268       pr "  }\n";
6269       pr "\n";
6270
6271       (* Expecting to receive further files (FileOut)? *)
6272       List.iter (
6273         function
6274         | FileOut n ->
6275             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6276             pr "    guestfs___end_busy (g);\n";
6277             pr "    return %s;\n" error_code;
6278             pr "  }\n";
6279             pr "\n";
6280         | _ -> ()
6281       ) (snd style);
6282
6283       pr "  guestfs___end_busy (g);\n";
6284
6285       (match fst style with
6286        | RErr -> pr "  return 0;\n"
6287        | RInt n | RInt64 n | RBool n ->
6288            pr "  return ret.%s;\n" n
6289        | RConstString _ | RConstOptString _ ->
6290            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6291        | RString n ->
6292            pr "  return ret.%s; /* caller will free */\n" n
6293        | RStringList n | RHashtable n ->
6294            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6295            pr "  ret.%s.%s_val =\n" n n;
6296            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6297            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6298              n n;
6299            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6300            pr "  return ret.%s.%s_val;\n" n n
6301        | RStruct (n, _) ->
6302            pr "  /* caller will free this */\n";
6303            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6304        | RStructList (n, _) ->
6305            pr "  /* caller will free this */\n";
6306            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6307        | RBufferOut n ->
6308            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6309            pr "   * _val might be NULL here.  To make the API saner for\n";
6310            pr "   * callers, we turn this case into a unique pointer (using\n";
6311            pr "   * malloc(1)).\n";
6312            pr "   */\n";
6313            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6314            pr "    *size_r = ret.%s.%s_len;\n" n n;
6315            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6316            pr "  } else {\n";
6317            pr "    free (ret.%s.%s_val);\n" n n;
6318            pr "    char *p = safe_malloc (g, 1);\n";
6319            pr "    *size_r = ret.%s.%s_len;\n" n n;
6320            pr "    return p;\n";
6321            pr "  }\n";
6322       );
6323
6324       pr "}\n\n"
6325   ) daemon_functions;
6326
6327   (* Functions to free structures. *)
6328   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6329   pr " * structure format is identical to the XDR format.  See note in\n";
6330   pr " * generator.ml.\n";
6331   pr " */\n";
6332   pr "\n";
6333
6334   List.iter (
6335     fun (typ, _) ->
6336       pr "void\n";
6337       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6338       pr "{\n";
6339       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6340       pr "  free (x);\n";
6341       pr "}\n";
6342       pr "\n";
6343
6344       pr "void\n";
6345       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6346       pr "{\n";
6347       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6348       pr "  free (x);\n";
6349       pr "}\n";
6350       pr "\n";
6351
6352   ) structs;
6353
6354 (* Generate daemon/actions.h. *)
6355 and generate_daemon_actions_h () =
6356   generate_header CStyle GPLv2plus;
6357
6358   pr "#include \"../src/guestfs_protocol.h\"\n";
6359   pr "\n";
6360
6361   List.iter (
6362     fun (name, style, _, _, _, _, _) ->
6363       generate_prototype
6364         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6365         name style;
6366   ) daemon_functions
6367
6368 (* Generate the linker script which controls the visibility of
6369  * symbols in the public ABI and ensures no other symbols get
6370  * exported accidentally.
6371  *)
6372 and generate_linker_script () =
6373   generate_header HashStyle GPLv2plus;
6374
6375   let globals = [
6376     "guestfs_create";
6377     "guestfs_close";
6378     "guestfs_get_error_handler";
6379     "guestfs_get_out_of_memory_handler";
6380     "guestfs_last_error";
6381     "guestfs_set_close_callback";
6382     "guestfs_set_error_handler";
6383     "guestfs_set_launch_done_callback";
6384     "guestfs_set_log_message_callback";
6385     "guestfs_set_out_of_memory_handler";
6386     "guestfs_set_subprocess_quit_callback";
6387
6388     (* Unofficial parts of the API: the bindings code use these
6389      * functions, so it is useful to export them.
6390      *)
6391     "guestfs_safe_calloc";
6392     "guestfs_safe_malloc";
6393     "guestfs_safe_strdup";
6394     "guestfs_safe_memdup";
6395   ] in
6396   let functions =
6397     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6398       all_functions in
6399   let structs =
6400     List.concat (
6401       List.map (fun (typ, _) ->
6402                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6403         structs
6404     ) in
6405   let globals = List.sort compare (globals @ functions @ structs) in
6406
6407   pr "{\n";
6408   pr "    global:\n";
6409   List.iter (pr "        %s;\n") globals;
6410   pr "\n";
6411
6412   pr "    local:\n";
6413   pr "        *;\n";
6414   pr "};\n"
6415
6416 (* Generate the server-side stubs. *)
6417 and generate_daemon_actions () =
6418   generate_header CStyle GPLv2plus;
6419
6420   pr "#include <config.h>\n";
6421   pr "\n";
6422   pr "#include <stdio.h>\n";
6423   pr "#include <stdlib.h>\n";
6424   pr "#include <string.h>\n";
6425   pr "#include <inttypes.h>\n";
6426   pr "#include <rpc/types.h>\n";
6427   pr "#include <rpc/xdr.h>\n";
6428   pr "\n";
6429   pr "#include \"daemon.h\"\n";
6430   pr "#include \"c-ctype.h\"\n";
6431   pr "#include \"../src/guestfs_protocol.h\"\n";
6432   pr "#include \"actions.h\"\n";
6433   pr "\n";
6434
6435   List.iter (
6436     fun (name, style, _, _, _, _, _) ->
6437       (* Generate server-side stubs. *)
6438       pr "static void %s_stub (XDR *xdr_in)\n" name;
6439       pr "{\n";
6440       let error_code =
6441         match fst style with
6442         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6443         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6444         | RBool _ -> pr "  int r;\n"; "-1"
6445         | RConstString _ | RConstOptString _ ->
6446             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6447         | RString _ -> pr "  char *r;\n"; "NULL"
6448         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6449         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6450         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6451         | RBufferOut _ ->
6452             pr "  size_t size = 1;\n";
6453             pr "  char *r;\n";
6454             "NULL" in
6455
6456       (match snd style with
6457        | [] -> ()
6458        | args ->
6459            pr "  struct guestfs_%s_args args;\n" name;
6460            List.iter (
6461              function
6462              | Device n | Dev_or_Path n
6463              | Pathname n
6464              | String n -> ()
6465              | OptString n -> pr "  char *%s;\n" n
6466              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6467              | Bool n -> pr "  int %s;\n" n
6468              | Int n -> pr "  int %s;\n" n
6469              | Int64 n -> pr "  int64_t %s;\n" n
6470              | FileIn _ | FileOut _ -> ()
6471              | BufferIn n ->
6472                  pr "  const char *%s;\n" n;
6473                  pr "  size_t %s_size;\n" n
6474            ) args
6475       );
6476       pr "\n";
6477
6478       let is_filein =
6479         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6480
6481       (match snd style with
6482        | [] -> ()
6483        | args ->
6484            pr "  memset (&args, 0, sizeof args);\n";
6485            pr "\n";
6486            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6487            if is_filein then
6488              pr "    if (cancel_receive () != -2)\n";
6489            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6490            pr "    goto done;\n";
6491            pr "  }\n";
6492            let pr_args n =
6493              pr "  char *%s = args.%s;\n" n n
6494            in
6495            let pr_list_handling_code n =
6496              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6497              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6498              pr "  if (%s == NULL) {\n" n;
6499              if is_filein then
6500                pr "    if (cancel_receive () != -2)\n";
6501              pr "      reply_with_perror (\"realloc\");\n";
6502              pr "    goto done;\n";
6503              pr "  }\n";
6504              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6505              pr "  args.%s.%s_val = %s;\n" n n n;
6506            in
6507            List.iter (
6508              function
6509              | Pathname n ->
6510                  pr_args n;
6511                  pr "  ABS_PATH (%s, %s, goto done);\n"
6512                    n (if is_filein then "cancel_receive ()" else "0");
6513              | Device n ->
6514                  pr_args n;
6515                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6516                    n (if is_filein then "cancel_receive ()" else "0");
6517              | Dev_or_Path n ->
6518                  pr_args n;
6519                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6520                    n (if is_filein then "cancel_receive ()" else "0");
6521              | String n -> pr_args n
6522              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6523              | StringList n ->
6524                  pr_list_handling_code n;
6525              | DeviceList n ->
6526                  pr_list_handling_code n;
6527                  pr "  /* Ensure that each is a device,\n";
6528                  pr "   * and perform device name translation.\n";
6529                  pr "   */\n";
6530                  pr "  {\n";
6531                  pr "    size_t i;\n";
6532                  pr "    for (i = 0; %s[i] != NULL; ++i)\n" n;
6533                  pr "      RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6534                    (if is_filein then "cancel_receive ()" else "0");
6535                  pr "  }\n";
6536              | Bool n -> pr "  %s = args.%s;\n" n n
6537              | Int n -> pr "  %s = args.%s;\n" n n
6538              | Int64 n -> pr "  %s = args.%s;\n" n n
6539              | FileIn _ | FileOut _ -> ()
6540              | BufferIn n ->
6541                  pr "  %s = args.%s.%s_val;\n" n n n;
6542                  pr "  %s_size = args.%s.%s_len;\n" n n n
6543            ) args;
6544            pr "\n"
6545       );
6546
6547       (* this is used at least for do_equal *)
6548       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6549         (* Emit NEED_ROOT just once, even when there are two or
6550            more Pathname args *)
6551         pr "  NEED_ROOT (%s, goto done);\n"
6552           (if is_filein then "cancel_receive ()" else "0");
6553       );
6554
6555       (* Don't want to call the impl with any FileIn or FileOut
6556        * parameters, since these go "outside" the RPC protocol.
6557        *)
6558       let args' =
6559         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6560           (snd style) in
6561       pr "  r = do_%s " name;
6562       generate_c_call_args (fst style, args');
6563       pr ";\n";
6564
6565       (match fst style with
6566        | RErr | RInt _ | RInt64 _ | RBool _
6567        | RConstString _ | RConstOptString _
6568        | RString _ | RStringList _ | RHashtable _
6569        | RStruct (_, _) | RStructList (_, _) ->
6570            pr "  if (r == %s)\n" error_code;
6571            pr "    /* do_%s has already called reply_with_error */\n" name;
6572            pr "    goto done;\n";
6573            pr "\n"
6574        | RBufferOut _ ->
6575            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6576            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6577            pr "   */\n";
6578            pr "  if (size == 1 && r == %s)\n" error_code;
6579            pr "    /* do_%s has already called reply_with_error */\n" name;
6580            pr "    goto done;\n";
6581            pr "\n"
6582       );
6583
6584       (* If there are any FileOut parameters, then the impl must
6585        * send its own reply.
6586        *)
6587       let no_reply =
6588         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6589       if no_reply then
6590         pr "  /* do_%s has already sent a reply */\n" name
6591       else (
6592         match fst style with
6593         | RErr -> pr "  reply (NULL, NULL);\n"
6594         | RInt n | RInt64 n | RBool n ->
6595             pr "  struct guestfs_%s_ret ret;\n" name;
6596             pr "  ret.%s = r;\n" n;
6597             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6598               name
6599         | RConstString _ | RConstOptString _ ->
6600             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6601         | RString n ->
6602             pr "  struct guestfs_%s_ret ret;\n" name;
6603             pr "  ret.%s = r;\n" n;
6604             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6605               name;
6606             pr "  free (r);\n"
6607         | RStringList n | RHashtable n ->
6608             pr "  struct guestfs_%s_ret ret;\n" name;
6609             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6610             pr "  ret.%s.%s_val = r;\n" n n;
6611             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6612               name;
6613             pr "  free_strings (r);\n"
6614         | RStruct (n, _) ->
6615             pr "  struct guestfs_%s_ret ret;\n" name;
6616             pr "  ret.%s = *r;\n" n;
6617             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6618               name;
6619             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6620               name
6621         | RStructList (n, _) ->
6622             pr "  struct guestfs_%s_ret ret;\n" name;
6623             pr "  ret.%s = *r;\n" n;
6624             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6625               name;
6626             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6627               name
6628         | RBufferOut n ->
6629             pr "  struct guestfs_%s_ret ret;\n" name;
6630             pr "  ret.%s.%s_val = r;\n" n n;
6631             pr "  ret.%s.%s_len = size;\n" n n;
6632             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6633               name;
6634             pr "  free (r);\n"
6635       );
6636
6637       (* Free the args. *)
6638       pr "done:\n";
6639       (match snd style with
6640        | [] -> ()
6641        | _ ->
6642            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6643              name
6644       );
6645       pr "  return;\n";
6646       pr "}\n\n";
6647   ) daemon_functions;
6648
6649   (* Dispatch function. *)
6650   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6651   pr "{\n";
6652   pr "  switch (proc_nr) {\n";
6653
6654   List.iter (
6655     fun (name, style, _, _, _, _, _) ->
6656       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6657       pr "      %s_stub (xdr_in);\n" name;
6658       pr "      break;\n"
6659   ) daemon_functions;
6660
6661   pr "    default:\n";
6662   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";
6663   pr "  }\n";
6664   pr "}\n";
6665   pr "\n";
6666
6667   (* LVM columns and tokenization functions. *)
6668   (* XXX This generates crap code.  We should rethink how we
6669    * do this parsing.
6670    *)
6671   List.iter (
6672     function
6673     | typ, cols ->
6674         pr "static const char *lvm_%s_cols = \"%s\";\n"
6675           typ (String.concat "," (List.map fst cols));
6676         pr "\n";
6677
6678         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6679         pr "{\n";
6680         pr "  char *tok, *p, *next;\n";
6681         pr "  size_t i, j;\n";
6682         pr "\n";
6683         (*
6684           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6685           pr "\n";
6686         *)
6687         pr "  if (!str) {\n";
6688         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6689         pr "    return -1;\n";
6690         pr "  }\n";
6691         pr "  if (!*str || c_isspace (*str)) {\n";
6692         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6693         pr "    return -1;\n";
6694         pr "  }\n";
6695         pr "  tok = str;\n";
6696         List.iter (
6697           fun (name, coltype) ->
6698             pr "  if (!tok) {\n";
6699             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6700             pr "    return -1;\n";
6701             pr "  }\n";
6702             pr "  p = strchrnul (tok, ',');\n";
6703             pr "  if (*p) next = p+1; else next = NULL;\n";
6704             pr "  *p = '\\0';\n";
6705             (match coltype with
6706              | FString ->
6707                  pr "  r->%s = strdup (tok);\n" name;
6708                  pr "  if (r->%s == NULL) {\n" name;
6709                  pr "    perror (\"strdup\");\n";
6710                  pr "    return -1;\n";
6711                  pr "  }\n"
6712              | FUUID ->
6713                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6714                  pr "    if (tok[j] == '\\0') {\n";
6715                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6716                  pr "      return -1;\n";
6717                  pr "    } else if (tok[j] != '-')\n";
6718                  pr "      r->%s[i++] = tok[j];\n" name;
6719                  pr "  }\n";
6720              | FBytes ->
6721                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6722                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6723                  pr "    return -1;\n";
6724                  pr "  }\n";
6725              | FInt64 ->
6726                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6727                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6728                  pr "    return -1;\n";
6729                  pr "  }\n";
6730              | FOptPercent ->
6731                  pr "  if (tok[0] == '\\0')\n";
6732                  pr "    r->%s = -1;\n" name;
6733                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6734                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6735                  pr "    return -1;\n";
6736                  pr "  }\n";
6737              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6738                  assert false (* can never be an LVM column *)
6739             );
6740             pr "  tok = next;\n";
6741         ) cols;
6742
6743         pr "  if (tok != NULL) {\n";
6744         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6745         pr "    return -1;\n";
6746         pr "  }\n";
6747         pr "  return 0;\n";
6748         pr "}\n";
6749         pr "\n";
6750
6751         pr "guestfs_int_lvm_%s_list *\n" typ;
6752         pr "parse_command_line_%ss (void)\n" typ;
6753         pr "{\n";
6754         pr "  char *out, *err;\n";
6755         pr "  char *p, *pend;\n";
6756         pr "  int r, i;\n";
6757         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6758         pr "  void *newp;\n";
6759         pr "\n";
6760         pr "  ret = malloc (sizeof *ret);\n";
6761         pr "  if (!ret) {\n";
6762         pr "    reply_with_perror (\"malloc\");\n";
6763         pr "    return NULL;\n";
6764         pr "  }\n";
6765         pr "\n";
6766         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6767         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6768         pr "\n";
6769         pr "  r = command (&out, &err,\n";
6770         pr "           \"lvm\", \"%ss\",\n" typ;
6771         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6772         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6773         pr "  if (r == -1) {\n";
6774         pr "    reply_with_error (\"%%s\", err);\n";
6775         pr "    free (out);\n";
6776         pr "    free (err);\n";
6777         pr "    free (ret);\n";
6778         pr "    return NULL;\n";
6779         pr "  }\n";
6780         pr "\n";
6781         pr "  free (err);\n";
6782         pr "\n";
6783         pr "  /* Tokenize each line of the output. */\n";
6784         pr "  p = out;\n";
6785         pr "  i = 0;\n";
6786         pr "  while (p) {\n";
6787         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6788         pr "    if (pend) {\n";
6789         pr "      *pend = '\\0';\n";
6790         pr "      pend++;\n";
6791         pr "    }\n";
6792         pr "\n";
6793         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6794         pr "      p++;\n";
6795         pr "\n";
6796         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6797         pr "      p = pend;\n";
6798         pr "      continue;\n";
6799         pr "    }\n";
6800         pr "\n";
6801         pr "    /* Allocate some space to store this next entry. */\n";
6802         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6803         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6804         pr "    if (newp == NULL) {\n";
6805         pr "      reply_with_perror (\"realloc\");\n";
6806         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6807         pr "      free (ret);\n";
6808         pr "      free (out);\n";
6809         pr "      return NULL;\n";
6810         pr "    }\n";
6811         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6812         pr "\n";
6813         pr "    /* Tokenize the next entry. */\n";
6814         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6815         pr "    if (r == -1) {\n";
6816         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6817         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6818         pr "      free (ret);\n";
6819         pr "      free (out);\n";
6820         pr "      return NULL;\n";
6821         pr "    }\n";
6822         pr "\n";
6823         pr "    ++i;\n";
6824         pr "    p = pend;\n";
6825         pr "  }\n";
6826         pr "\n";
6827         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6828         pr "\n";
6829         pr "  free (out);\n";
6830         pr "  return ret;\n";
6831         pr "}\n"
6832
6833   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6834
6835 (* Generate a list of function names, for debugging in the daemon.. *)
6836 and generate_daemon_names () =
6837   generate_header CStyle GPLv2plus;
6838
6839   pr "#include <config.h>\n";
6840   pr "\n";
6841   pr "#include \"daemon.h\"\n";
6842   pr "\n";
6843
6844   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6845   pr "const char *function_names[] = {\n";
6846   List.iter (
6847     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6848   ) daemon_functions;
6849   pr "};\n";
6850
6851 (* Generate the optional groups for the daemon to implement
6852  * guestfs_available.
6853  *)
6854 and generate_daemon_optgroups_c () =
6855   generate_header CStyle GPLv2plus;
6856
6857   pr "#include <config.h>\n";
6858   pr "\n";
6859   pr "#include \"daemon.h\"\n";
6860   pr "#include \"optgroups.h\"\n";
6861   pr "\n";
6862
6863   pr "struct optgroup optgroups[] = {\n";
6864   List.iter (
6865     fun (group, _) ->
6866       pr "  { \"%s\", optgroup_%s_available },\n" group group
6867   ) optgroups;
6868   pr "  { NULL, NULL }\n";
6869   pr "};\n"
6870
6871 and generate_daemon_optgroups_h () =
6872   generate_header CStyle GPLv2plus;
6873
6874   List.iter (
6875     fun (group, _) ->
6876       pr "extern int optgroup_%s_available (void);\n" group
6877   ) optgroups
6878
6879 (* Generate the tests. *)
6880 and generate_tests () =
6881   generate_header CStyle GPLv2plus;
6882
6883   pr "\
6884 #include <stdio.h>
6885 #include <stdlib.h>
6886 #include <string.h>
6887 #include <unistd.h>
6888 #include <sys/types.h>
6889 #include <fcntl.h>
6890
6891 #include \"guestfs.h\"
6892 #include \"guestfs-internal.h\"
6893
6894 static guestfs_h *g;
6895 static int suppress_error = 0;
6896
6897 static void print_error (guestfs_h *g, void *data, const char *msg)
6898 {
6899   if (!suppress_error)
6900     fprintf (stderr, \"%%s\\n\", msg);
6901 }
6902
6903 /* FIXME: nearly identical code appears in fish.c */
6904 static void print_strings (char *const *argv)
6905 {
6906   size_t argc;
6907
6908   for (argc = 0; argv[argc] != NULL; ++argc)
6909     printf (\"\\t%%s\\n\", argv[argc]);
6910 }
6911
6912 /*
6913 static void print_table (char const *const *argv)
6914 {
6915   size_t i;
6916
6917   for (i = 0; argv[i] != NULL; i += 2)
6918     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6919 }
6920 */
6921
6922 static int
6923 is_available (const char *group)
6924 {
6925   const char *groups[] = { group, NULL };
6926   int r;
6927
6928   suppress_error = 1;
6929   r = guestfs_available (g, (char **) groups);
6930   suppress_error = 0;
6931
6932   return r == 0;
6933 }
6934
6935 static void
6936 incr (guestfs_h *g, void *iv)
6937 {
6938   int *i = (int *) iv;
6939   (*i)++;
6940 }
6941
6942 ";
6943
6944   (* Generate a list of commands which are not tested anywhere. *)
6945   pr "static void no_test_warnings (void)\n";
6946   pr "{\n";
6947
6948   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6949   List.iter (
6950     fun (_, _, _, _, tests, _, _) ->
6951       let tests = filter_map (
6952         function
6953         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6954         | (_, Disabled, _) -> None
6955       ) tests in
6956       let seq = List.concat (List.map seq_of_test tests) in
6957       let cmds_tested = List.map List.hd seq in
6958       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6959   ) all_functions;
6960
6961   List.iter (
6962     fun (name, _, _, _, _, _, _) ->
6963       if not (Hashtbl.mem hash name) then
6964         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6965   ) all_functions;
6966
6967   pr "}\n";
6968   pr "\n";
6969
6970   (* Generate the actual tests.  Note that we generate the tests
6971    * in reverse order, deliberately, so that (in general) the
6972    * newest tests run first.  This makes it quicker and easier to
6973    * debug them.
6974    *)
6975   let test_names =
6976     List.map (
6977       fun (name, _, _, flags, tests, _, _) ->
6978         mapi (generate_one_test name flags) tests
6979     ) (List.rev all_functions) in
6980   let test_names = List.concat test_names in
6981   let nr_tests = List.length test_names in
6982
6983   pr "\
6984 int main (int argc, char *argv[])
6985 {
6986   char c = 0;
6987   unsigned long int n_failed = 0;
6988   const char *filename;
6989   int fd;
6990   int nr_tests, test_num = 0;
6991
6992   setbuf (stdout, NULL);
6993
6994   no_test_warnings ();
6995
6996   g = guestfs_create ();
6997   if (g == NULL) {
6998     printf (\"guestfs_create FAILED\\n\");
6999     exit (EXIT_FAILURE);
7000   }
7001
7002   guestfs_set_error_handler (g, print_error, NULL);
7003
7004   guestfs_set_path (g, \"../appliance\");
7005
7006   filename = \"test1.img\";
7007   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7008   if (fd == -1) {
7009     perror (filename);
7010     exit (EXIT_FAILURE);
7011   }
7012   if (lseek (fd, %d, SEEK_SET) == -1) {
7013     perror (\"lseek\");
7014     close (fd);
7015     unlink (filename);
7016     exit (EXIT_FAILURE);
7017   }
7018   if (write (fd, &c, 1) == -1) {
7019     perror (\"write\");
7020     close (fd);
7021     unlink (filename);
7022     exit (EXIT_FAILURE);
7023   }
7024   if (close (fd) == -1) {
7025     perror (filename);
7026     unlink (filename);
7027     exit (EXIT_FAILURE);
7028   }
7029   if (guestfs_add_drive (g, filename) == -1) {
7030     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7031     exit (EXIT_FAILURE);
7032   }
7033
7034   filename = \"test2.img\";
7035   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7036   if (fd == -1) {
7037     perror (filename);
7038     exit (EXIT_FAILURE);
7039   }
7040   if (lseek (fd, %d, SEEK_SET) == -1) {
7041     perror (\"lseek\");
7042     close (fd);
7043     unlink (filename);
7044     exit (EXIT_FAILURE);
7045   }
7046   if (write (fd, &c, 1) == -1) {
7047     perror (\"write\");
7048     close (fd);
7049     unlink (filename);
7050     exit (EXIT_FAILURE);
7051   }
7052   if (close (fd) == -1) {
7053     perror (filename);
7054     unlink (filename);
7055     exit (EXIT_FAILURE);
7056   }
7057   if (guestfs_add_drive (g, filename) == -1) {
7058     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7059     exit (EXIT_FAILURE);
7060   }
7061
7062   filename = \"test3.img\";
7063   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7064   if (fd == -1) {
7065     perror (filename);
7066     exit (EXIT_FAILURE);
7067   }
7068   if (lseek (fd, %d, SEEK_SET) == -1) {
7069     perror (\"lseek\");
7070     close (fd);
7071     unlink (filename);
7072     exit (EXIT_FAILURE);
7073   }
7074   if (write (fd, &c, 1) == -1) {
7075     perror (\"write\");
7076     close (fd);
7077     unlink (filename);
7078     exit (EXIT_FAILURE);
7079   }
7080   if (close (fd) == -1) {
7081     perror (filename);
7082     unlink (filename);
7083     exit (EXIT_FAILURE);
7084   }
7085   if (guestfs_add_drive (g, filename) == -1) {
7086     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7087     exit (EXIT_FAILURE);
7088   }
7089
7090   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7091     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7092     exit (EXIT_FAILURE);
7093   }
7094
7095   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7096   alarm (600);
7097
7098   if (guestfs_launch (g) == -1) {
7099     printf (\"guestfs_launch FAILED\\n\");
7100     exit (EXIT_FAILURE);
7101   }
7102
7103   /* Cancel previous alarm. */
7104   alarm (0);
7105
7106   nr_tests = %d;
7107
7108 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7109
7110   iteri (
7111     fun i test_name ->
7112       pr "  test_num++;\n";
7113       pr "  if (guestfs_get_verbose (g))\n";
7114       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7115       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7116       pr "  if (%s () == -1) {\n" test_name;
7117       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7118       pr "    n_failed++;\n";
7119       pr "  }\n";
7120   ) test_names;
7121   pr "\n";
7122
7123   pr "  /* Check close callback is called. */
7124   int close_sentinel = 1;
7125   guestfs_set_close_callback (g, incr, &close_sentinel);
7126
7127   guestfs_close (g);
7128
7129   if (close_sentinel != 2) {
7130     fprintf (stderr, \"close callback was not called\\n\");
7131     exit (EXIT_FAILURE);
7132   }
7133
7134   unlink (\"test1.img\");
7135   unlink (\"test2.img\");
7136   unlink (\"test3.img\");
7137
7138 ";
7139
7140   pr "  if (n_failed > 0) {\n";
7141   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7142   pr "    exit (EXIT_FAILURE);\n";
7143   pr "  }\n";
7144   pr "\n";
7145
7146   pr "  exit (EXIT_SUCCESS);\n";
7147   pr "}\n"
7148
7149 and generate_one_test name flags i (init, prereq, test) =
7150   let test_name = sprintf "test_%s_%d" name i in
7151
7152   pr "\
7153 static int %s_skip (void)
7154 {
7155   const char *str;
7156
7157   str = getenv (\"TEST_ONLY\");
7158   if (str)
7159     return strstr (str, \"%s\") == NULL;
7160   str = getenv (\"SKIP_%s\");
7161   if (str && STREQ (str, \"1\")) return 1;
7162   str = getenv (\"SKIP_TEST_%s\");
7163   if (str && STREQ (str, \"1\")) return 1;
7164   return 0;
7165 }
7166
7167 " test_name name (String.uppercase test_name) (String.uppercase name);
7168
7169   (match prereq with
7170    | Disabled | Always | IfAvailable _ -> ()
7171    | If code | Unless code ->
7172        pr "static int %s_prereq (void)\n" test_name;
7173        pr "{\n";
7174        pr "  %s\n" code;
7175        pr "}\n";
7176        pr "\n";
7177   );
7178
7179   pr "\
7180 static int %s (void)
7181 {
7182   if (%s_skip ()) {
7183     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7184     return 0;
7185   }
7186
7187 " test_name test_name test_name;
7188
7189   (* Optional functions should only be tested if the relevant
7190    * support is available in the daemon.
7191    *)
7192   List.iter (
7193     function
7194     | Optional group ->
7195         pr "  if (!is_available (\"%s\")) {\n" group;
7196         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7197         pr "    return 0;\n";
7198         pr "  }\n";
7199     | _ -> ()
7200   ) flags;
7201
7202   (match prereq with
7203    | Disabled ->
7204        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7205    | If _ ->
7206        pr "  if (! %s_prereq ()) {\n" test_name;
7207        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7208        pr "    return 0;\n";
7209        pr "  }\n";
7210        pr "\n";
7211        generate_one_test_body name i test_name init test;
7212    | Unless _ ->
7213        pr "  if (%s_prereq ()) {\n" test_name;
7214        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7215        pr "    return 0;\n";
7216        pr "  }\n";
7217        pr "\n";
7218        generate_one_test_body name i test_name init test;
7219    | IfAvailable group ->
7220        pr "  if (!is_available (\"%s\")) {\n" group;
7221        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7222        pr "    return 0;\n";
7223        pr "  }\n";
7224        pr "\n";
7225        generate_one_test_body name i test_name init test;
7226    | Always ->
7227        generate_one_test_body name i test_name init test
7228   );
7229
7230   pr "  return 0;\n";
7231   pr "}\n";
7232   pr "\n";
7233   test_name
7234
7235 and generate_one_test_body name i test_name init test =
7236   (match init with
7237    | InitNone (* XXX at some point, InitNone and InitEmpty became
7238                * folded together as the same thing.  Really we should
7239                * make InitNone do nothing at all, but the tests may
7240                * need to be checked to make sure this is OK.
7241                *)
7242    | InitEmpty ->
7243        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7244        List.iter (generate_test_command_call test_name)
7245          [["blockdev_setrw"; "/dev/sda"];
7246           ["umount_all"];
7247           ["lvm_remove_all"]]
7248    | InitPartition ->
7249        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7250        List.iter (generate_test_command_call test_name)
7251          [["blockdev_setrw"; "/dev/sda"];
7252           ["umount_all"];
7253           ["lvm_remove_all"];
7254           ["part_disk"; "/dev/sda"; "mbr"]]
7255    | InitBasicFS ->
7256        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7257        List.iter (generate_test_command_call test_name)
7258          [["blockdev_setrw"; "/dev/sda"];
7259           ["umount_all"];
7260           ["lvm_remove_all"];
7261           ["part_disk"; "/dev/sda"; "mbr"];
7262           ["mkfs"; "ext2"; "/dev/sda1"];
7263           ["mount_options"; ""; "/dev/sda1"; "/"]]
7264    | InitBasicFSonLVM ->
7265        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7266          test_name;
7267        List.iter (generate_test_command_call test_name)
7268          [["blockdev_setrw"; "/dev/sda"];
7269           ["umount_all"];
7270           ["lvm_remove_all"];
7271           ["part_disk"; "/dev/sda"; "mbr"];
7272           ["pvcreate"; "/dev/sda1"];
7273           ["vgcreate"; "VG"; "/dev/sda1"];
7274           ["lvcreate"; "LV"; "VG"; "8"];
7275           ["mkfs"; "ext2"; "/dev/VG/LV"];
7276           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7277    | InitISOFS ->
7278        pr "  /* InitISOFS for %s */\n" test_name;
7279        List.iter (generate_test_command_call test_name)
7280          [["blockdev_setrw"; "/dev/sda"];
7281           ["umount_all"];
7282           ["lvm_remove_all"];
7283           ["mount_ro"; "/dev/sdd"; "/"]]
7284   );
7285
7286   let get_seq_last = function
7287     | [] ->
7288         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7289           test_name
7290     | seq ->
7291         let seq = List.rev seq in
7292         List.rev (List.tl seq), List.hd seq
7293   in
7294
7295   match test with
7296   | TestRun seq ->
7297       pr "  /* TestRun for %s (%d) */\n" name i;
7298       List.iter (generate_test_command_call test_name) seq
7299   | TestOutput (seq, expected) ->
7300       pr "  /* TestOutput for %s (%d) */\n" name i;
7301       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7302       let seq, last = get_seq_last seq in
7303       let test () =
7304         pr "    if (STRNEQ (r, expected)) {\n";
7305         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7306         pr "      return -1;\n";
7307         pr "    }\n"
7308       in
7309       List.iter (generate_test_command_call test_name) seq;
7310       generate_test_command_call ~test test_name last
7311   | TestOutputList (seq, expected) ->
7312       pr "  /* TestOutputList for %s (%d) */\n" name i;
7313       let seq, last = get_seq_last seq in
7314       let test () =
7315         iteri (
7316           fun i str ->
7317             pr "    if (!r[%d]) {\n" i;
7318             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7319             pr "      print_strings (r);\n";
7320             pr "      return -1;\n";
7321             pr "    }\n";
7322             pr "    {\n";
7323             pr "      const char *expected = \"%s\";\n" (c_quote str);
7324             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7325             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7326             pr "        return -1;\n";
7327             pr "      }\n";
7328             pr "    }\n"
7329         ) expected;
7330         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7331         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7332           test_name;
7333         pr "      print_strings (r);\n";
7334         pr "      return -1;\n";
7335         pr "    }\n"
7336       in
7337       List.iter (generate_test_command_call test_name) seq;
7338       generate_test_command_call ~test test_name last
7339   | TestOutputListOfDevices (seq, expected) ->
7340       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7341       let seq, last = get_seq_last seq in
7342       let test () =
7343         iteri (
7344           fun i str ->
7345             pr "    if (!r[%d]) {\n" i;
7346             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7347             pr "      print_strings (r);\n";
7348             pr "      return -1;\n";
7349             pr "    }\n";
7350             pr "    {\n";
7351             pr "      const char *expected = \"%s\";\n" (c_quote str);
7352             pr "      r[%d][5] = 's';\n" i;
7353             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7354             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7355             pr "        return -1;\n";
7356             pr "      }\n";
7357             pr "    }\n"
7358         ) expected;
7359         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7360         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7361           test_name;
7362         pr "      print_strings (r);\n";
7363         pr "      return -1;\n";
7364         pr "    }\n"
7365       in
7366       List.iter (generate_test_command_call test_name) seq;
7367       generate_test_command_call ~test test_name last
7368   | TestOutputInt (seq, expected) ->
7369       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7370       let seq, last = get_seq_last seq in
7371       let test () =
7372         pr "    if (r != %d) {\n" expected;
7373         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7374           test_name expected;
7375         pr "               (int) r);\n";
7376         pr "      return -1;\n";
7377         pr "    }\n"
7378       in
7379       List.iter (generate_test_command_call test_name) seq;
7380       generate_test_command_call ~test test_name last
7381   | TestOutputIntOp (seq, op, expected) ->
7382       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7383       let seq, last = get_seq_last seq in
7384       let test () =
7385         pr "    if (! (r %s %d)) {\n" op expected;
7386         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7387           test_name op expected;
7388         pr "               (int) r);\n";
7389         pr "      return -1;\n";
7390         pr "    }\n"
7391       in
7392       List.iter (generate_test_command_call test_name) seq;
7393       generate_test_command_call ~test test_name last
7394   | TestOutputTrue seq ->
7395       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7396       let seq, last = get_seq_last seq in
7397       let test () =
7398         pr "    if (!r) {\n";
7399         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7400           test_name;
7401         pr "      return -1;\n";
7402         pr "    }\n"
7403       in
7404       List.iter (generate_test_command_call test_name) seq;
7405       generate_test_command_call ~test test_name last
7406   | TestOutputFalse seq ->
7407       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7408       let seq, last = get_seq_last seq in
7409       let test () =
7410         pr "    if (r) {\n";
7411         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7412           test_name;
7413         pr "      return -1;\n";
7414         pr "    }\n"
7415       in
7416       List.iter (generate_test_command_call test_name) seq;
7417       generate_test_command_call ~test test_name last
7418   | TestOutputLength (seq, expected) ->
7419       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7420       let seq, last = get_seq_last seq in
7421       let test () =
7422         pr "    int j;\n";
7423         pr "    for (j = 0; j < %d; ++j)\n" expected;
7424         pr "      if (r[j] == NULL) {\n";
7425         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7426           test_name;
7427         pr "        print_strings (r);\n";
7428         pr "        return -1;\n";
7429         pr "      }\n";
7430         pr "    if (r[j] != NULL) {\n";
7431         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7432           test_name;
7433         pr "      print_strings (r);\n";
7434         pr "      return -1;\n";
7435         pr "    }\n"
7436       in
7437       List.iter (generate_test_command_call test_name) seq;
7438       generate_test_command_call ~test test_name last
7439   | TestOutputBuffer (seq, expected) ->
7440       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7441       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7442       let seq, last = get_seq_last seq in
7443       let len = String.length expected in
7444       let test () =
7445         pr "    if (size != %d) {\n" len;
7446         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7447         pr "      return -1;\n";
7448         pr "    }\n";
7449         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7450         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7451         pr "      return -1;\n";
7452         pr "    }\n"
7453       in
7454       List.iter (generate_test_command_call test_name) seq;
7455       generate_test_command_call ~test test_name last
7456   | TestOutputStruct (seq, checks) ->
7457       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7458       let seq, last = get_seq_last seq in
7459       let test () =
7460         List.iter (
7461           function
7462           | CompareWithInt (field, expected) ->
7463               pr "    if (r->%s != %d) {\n" field expected;
7464               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7465                 test_name field expected;
7466               pr "               (int) r->%s);\n" field;
7467               pr "      return -1;\n";
7468               pr "    }\n"
7469           | CompareWithIntOp (field, op, expected) ->
7470               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7471               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7472                 test_name field op expected;
7473               pr "               (int) r->%s);\n" field;
7474               pr "      return -1;\n";
7475               pr "    }\n"
7476           | CompareWithString (field, expected) ->
7477               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7478               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7479                 test_name field expected;
7480               pr "               r->%s);\n" field;
7481               pr "      return -1;\n";
7482               pr "    }\n"
7483           | CompareFieldsIntEq (field1, field2) ->
7484               pr "    if (r->%s != r->%s) {\n" field1 field2;
7485               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7486                 test_name field1 field2;
7487               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7488               pr "      return -1;\n";
7489               pr "    }\n"
7490           | CompareFieldsStrEq (field1, field2) ->
7491               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7492               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7493                 test_name field1 field2;
7494               pr "               r->%s, r->%s);\n" field1 field2;
7495               pr "      return -1;\n";
7496               pr "    }\n"
7497         ) checks
7498       in
7499       List.iter (generate_test_command_call test_name) seq;
7500       generate_test_command_call ~test test_name last
7501   | TestLastFail seq ->
7502       pr "  /* TestLastFail for %s (%d) */\n" name i;
7503       let seq, last = get_seq_last seq in
7504       List.iter (generate_test_command_call test_name) seq;
7505       generate_test_command_call test_name ~expect_error:true last
7506
7507 (* Generate the code to run a command, leaving the result in 'r'.
7508  * If you expect to get an error then you should set expect_error:true.
7509  *)
7510 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7511   match cmd with
7512   | [] -> assert false
7513   | name :: args ->
7514       (* Look up the command to find out what args/ret it has. *)
7515       let style =
7516         try
7517           let _, style, _, _, _, _, _ =
7518             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7519           style
7520         with Not_found ->
7521           failwithf "%s: in test, command %s was not found" test_name name in
7522
7523       if List.length (snd style) <> List.length args then
7524         failwithf "%s: in test, wrong number of args given to %s"
7525           test_name name;
7526
7527       pr "  {\n";
7528
7529       List.iter (
7530         function
7531         | OptString n, "NULL" -> ()
7532         | Pathname n, arg
7533         | Device n, arg
7534         | Dev_or_Path n, arg
7535         | String n, arg
7536         | OptString n, arg ->
7537             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7538         | BufferIn n, arg ->
7539             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7540             pr "    size_t %s_size = %d;\n" n (String.length arg)
7541         | Int _, _
7542         | Int64 _, _
7543         | Bool _, _
7544         | FileIn _, _ | FileOut _, _ -> ()
7545         | StringList n, "" | DeviceList n, "" ->
7546             pr "    const char *const %s[1] = { NULL };\n" n
7547         | StringList n, arg | DeviceList n, arg ->
7548             let strs = string_split " " arg in
7549             iteri (
7550               fun i str ->
7551                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7552             ) strs;
7553             pr "    const char *const %s[] = {\n" n;
7554             iteri (
7555               fun i _ -> pr "      %s_%d,\n" n i
7556             ) strs;
7557             pr "      NULL\n";
7558             pr "    };\n";
7559       ) (List.combine (snd style) args);
7560
7561       let error_code =
7562         match fst style with
7563         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7564         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7565         | RConstString _ | RConstOptString _ ->
7566             pr "    const char *r;\n"; "NULL"
7567         | RString _ -> pr "    char *r;\n"; "NULL"
7568         | RStringList _ | RHashtable _ ->
7569             pr "    char **r;\n";
7570             pr "    size_t i;\n";
7571             "NULL"
7572         | RStruct (_, typ) ->
7573             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7574         | RStructList (_, typ) ->
7575             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7576         | RBufferOut _ ->
7577             pr "    char *r;\n";
7578             pr "    size_t size;\n";
7579             "NULL" in
7580
7581       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7582       pr "    r = guestfs_%s (g" name;
7583
7584       (* Generate the parameters. *)
7585       List.iter (
7586         function
7587         | OptString _, "NULL" -> pr ", NULL"
7588         | Pathname n, _
7589         | Device n, _ | Dev_or_Path n, _
7590         | String n, _
7591         | OptString n, _ ->
7592             pr ", %s" n
7593         | BufferIn n, _ ->
7594             pr ", %s, %s_size" n n
7595         | FileIn _, arg | FileOut _, arg ->
7596             pr ", \"%s\"" (c_quote arg)
7597         | StringList n, _ | DeviceList n, _ ->
7598             pr ", (char **) %s" n
7599         | Int _, arg ->
7600             let i =
7601               try int_of_string arg
7602               with Failure "int_of_string" ->
7603                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7604             pr ", %d" i
7605         | Int64 _, arg ->
7606             let i =
7607               try Int64.of_string arg
7608               with Failure "int_of_string" ->
7609                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7610             pr ", %Ld" i
7611         | Bool _, arg ->
7612             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7613       ) (List.combine (snd style) args);
7614
7615       (match fst style with
7616        | RBufferOut _ -> pr ", &size"
7617        | _ -> ()
7618       );
7619
7620       pr ");\n";
7621
7622       if not expect_error then
7623         pr "    if (r == %s)\n" error_code
7624       else
7625         pr "    if (r != %s)\n" error_code;
7626       pr "      return -1;\n";
7627
7628       (* Insert the test code. *)
7629       (match test with
7630        | None -> ()
7631        | Some f -> f ()
7632       );
7633
7634       (match fst style with
7635        | RErr | RInt _ | RInt64 _ | RBool _
7636        | RConstString _ | RConstOptString _ -> ()
7637        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7638        | RStringList _ | RHashtable _ ->
7639            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7640            pr "      free (r[i]);\n";
7641            pr "    free (r);\n"
7642        | RStruct (_, typ) ->
7643            pr "    guestfs_free_%s (r);\n" typ
7644        | RStructList (_, typ) ->
7645            pr "    guestfs_free_%s_list (r);\n" typ
7646       );
7647
7648       pr "  }\n"
7649
7650 and c_quote str =
7651   let str = replace_str str "\r" "\\r" in
7652   let str = replace_str str "\n" "\\n" in
7653   let str = replace_str str "\t" "\\t" in
7654   let str = replace_str str "\000" "\\0" in
7655   str
7656
7657 (* Generate a lot of different functions for guestfish. *)
7658 and generate_fish_cmds () =
7659   generate_header CStyle GPLv2plus;
7660
7661   let all_functions =
7662     List.filter (
7663       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7664     ) all_functions in
7665   let all_functions_sorted =
7666     List.filter (
7667       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7668     ) all_functions_sorted in
7669
7670   pr "#include <config.h>\n";
7671   pr "\n";
7672   pr "#include <stdio.h>\n";
7673   pr "#include <stdlib.h>\n";
7674   pr "#include <string.h>\n";
7675   pr "#include <inttypes.h>\n";
7676   pr "\n";
7677   pr "#include <guestfs.h>\n";
7678   pr "#include \"c-ctype.h\"\n";
7679   pr "#include \"full-write.h\"\n";
7680   pr "#include \"xstrtol.h\"\n";
7681   pr "#include \"fish.h\"\n";
7682   pr "\n";
7683   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7684   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7685   pr "\n";
7686
7687   (* list_commands function, which implements guestfish -h *)
7688   pr "void list_commands (void)\n";
7689   pr "{\n";
7690   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7691   pr "  list_builtin_commands ();\n";
7692   List.iter (
7693     fun (name, _, _, flags, _, shortdesc, _) ->
7694       let name = replace_char name '_' '-' in
7695       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7696         name shortdesc
7697   ) all_functions_sorted;
7698   pr "  printf (\"    %%s\\n\",";
7699   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7700   pr "}\n";
7701   pr "\n";
7702
7703   (* display_command function, which implements guestfish -h cmd *)
7704   pr "int display_command (const char *cmd)\n";
7705   pr "{\n";
7706   List.iter (
7707     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7708       let name2 = replace_char name '_' '-' in
7709       let alias =
7710         try find_map (function FishAlias n -> Some n | _ -> None) flags
7711         with Not_found -> name in
7712       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7713       let synopsis =
7714         match snd style with
7715         | [] -> name2
7716         | args ->
7717             sprintf "%s %s"
7718               name2 (String.concat " " (List.map name_of_argt args)) in
7719
7720       let warnings =
7721         if List.mem ProtocolLimitWarning flags then
7722           ("\n\n" ^ protocol_limit_warning)
7723         else "" in
7724
7725       (* For DangerWillRobinson commands, we should probably have
7726        * guestfish prompt before allowing you to use them (especially
7727        * in interactive mode). XXX
7728        *)
7729       let warnings =
7730         warnings ^
7731           if List.mem DangerWillRobinson flags then
7732             ("\n\n" ^ danger_will_robinson)
7733           else "" in
7734
7735       let warnings =
7736         warnings ^
7737           match deprecation_notice flags with
7738           | None -> ""
7739           | Some txt -> "\n\n" ^ txt in
7740
7741       let describe_alias =
7742         if name <> alias then
7743           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7744         else "" in
7745
7746       pr "  if (";
7747       pr "STRCASEEQ (cmd, \"%s\")" name;
7748       if name <> name2 then
7749         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7750       if name <> alias then
7751         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7752       pr ") {\n";
7753       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7754         name2 shortdesc
7755         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7756          "=head1 DESCRIPTION\n\n" ^
7757          longdesc ^ warnings ^ describe_alias);
7758       pr "    return 0;\n";
7759       pr "  }\n";
7760       pr "  else\n"
7761   ) all_functions;
7762   pr "    return display_builtin_command (cmd);\n";
7763   pr "}\n";
7764   pr "\n";
7765
7766   let emit_print_list_function typ =
7767     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7768       typ typ typ;
7769     pr "{\n";
7770     pr "  unsigned int i;\n";
7771     pr "\n";
7772     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7773     pr "    printf (\"[%%d] = {\\n\", i);\n";
7774     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7775     pr "    printf (\"}\\n\");\n";
7776     pr "  }\n";
7777     pr "}\n";
7778     pr "\n";
7779   in
7780
7781   (* print_* functions *)
7782   List.iter (
7783     fun (typ, cols) ->
7784       let needs_i =
7785         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7786
7787       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7788       pr "{\n";
7789       if needs_i then (
7790         pr "  unsigned int i;\n";
7791         pr "\n"
7792       );
7793       List.iter (
7794         function
7795         | name, FString ->
7796             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7797         | name, FUUID ->
7798             pr "  printf (\"%%s%s: \", indent);\n" name;
7799             pr "  for (i = 0; i < 32; ++i)\n";
7800             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7801             pr "  printf (\"\\n\");\n"
7802         | name, FBuffer ->
7803             pr "  printf (\"%%s%s: \", indent);\n" name;
7804             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7805             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7806             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7807             pr "    else\n";
7808             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7809             pr "  printf (\"\\n\");\n"
7810         | name, (FUInt64|FBytes) ->
7811             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7812               name typ name
7813         | name, FInt64 ->
7814             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7815               name typ name
7816         | name, FUInt32 ->
7817             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7818               name typ name
7819         | name, FInt32 ->
7820             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7821               name typ name
7822         | name, FChar ->
7823             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7824               name typ name
7825         | name, FOptPercent ->
7826             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7827               typ name name typ name;
7828             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7829       ) cols;
7830       pr "}\n";
7831       pr "\n";
7832   ) structs;
7833
7834   (* Emit a print_TYPE_list function definition only if that function is used. *)
7835   List.iter (
7836     function
7837     | typ, (RStructListOnly | RStructAndList) ->
7838         (* generate the function for typ *)
7839         emit_print_list_function typ
7840     | typ, _ -> () (* empty *)
7841   ) (rstructs_used_by all_functions);
7842
7843   (* Emit a print_TYPE function definition only if that function is used. *)
7844   List.iter (
7845     function
7846     | typ, (RStructOnly | RStructAndList) ->
7847         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7848         pr "{\n";
7849         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7850         pr "}\n";
7851         pr "\n";
7852     | typ, _ -> () (* empty *)
7853   ) (rstructs_used_by all_functions);
7854
7855   (* run_<action> actions *)
7856   List.iter (
7857     fun (name, style, _, flags, _, _, _) ->
7858       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7859       pr "{\n";
7860       (match fst style with
7861        | RErr
7862        | RInt _
7863        | RBool _ -> pr "  int r;\n"
7864        | RInt64 _ -> pr "  int64_t r;\n"
7865        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7866        | RString _ -> pr "  char *r;\n"
7867        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7868        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7869        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7870        | RBufferOut _ ->
7871            pr "  char *r;\n";
7872            pr "  size_t size;\n";
7873       );
7874       List.iter (
7875         function
7876         | Device n
7877         | String n
7878         | OptString n -> pr "  const char *%s;\n" n
7879         | Pathname n
7880         | Dev_or_Path n
7881         | FileIn n
7882         | FileOut n -> pr "  char *%s;\n" n
7883         | BufferIn n ->
7884             pr "  const char *%s;\n" n;
7885             pr "  size_t %s_size;\n" n
7886         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7887         | Bool n -> pr "  int %s;\n" n
7888         | Int n -> pr "  int %s;\n" n
7889         | Int64 n -> pr "  int64_t %s;\n" n
7890       ) (snd style);
7891
7892       (* Check and convert parameters. *)
7893       let argc_expected = List.length (snd style) in
7894       pr "  if (argc != %d) {\n" argc_expected;
7895       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7896         argc_expected;
7897       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7898       pr "    return -1;\n";
7899       pr "  }\n";
7900
7901       let parse_integer fn fntyp rtyp range name i =
7902         pr "  {\n";
7903         pr "    strtol_error xerr;\n";
7904         pr "    %s r;\n" fntyp;
7905         pr "\n";
7906         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7907         pr "    if (xerr != LONGINT_OK) {\n";
7908         pr "      fprintf (stderr,\n";
7909         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7910         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7911         pr "      return -1;\n";
7912         pr "    }\n";
7913         (match range with
7914          | None -> ()
7915          | Some (min, max, comment) ->
7916              pr "    /* %s */\n" comment;
7917              pr "    if (r < %s || r > %s) {\n" min max;
7918              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7919                name;
7920              pr "      return -1;\n";
7921              pr "    }\n";
7922              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7923         );
7924         pr "    %s = r;\n" name;
7925         pr "  }\n";
7926       in
7927
7928       iteri (
7929         fun i ->
7930           function
7931           | Device name
7932           | String name ->
7933               pr "  %s = argv[%d];\n" name i
7934           | Pathname name
7935           | Dev_or_Path name ->
7936               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7937               pr "  if (%s == NULL) return -1;\n" name
7938           | OptString name ->
7939               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7940                 name i i
7941           | BufferIn name ->
7942               pr "  %s = argv[%d];\n" name i;
7943               pr "  %s_size = strlen (argv[%d]);\n" name i
7944           | FileIn name ->
7945               pr "  %s = file_in (argv[%d]);\n" name i;
7946               pr "  if (%s == NULL) return -1;\n" name
7947           | FileOut name ->
7948               pr "  %s = file_out (argv[%d]);\n" name i;
7949               pr "  if (%s == NULL) return -1;\n" name
7950           | StringList name | DeviceList name ->
7951               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7952               pr "  if (%s == NULL) return -1;\n" name;
7953           | Bool name ->
7954               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7955           | Int name ->
7956               let range =
7957                 let min = "(-(2LL<<30))"
7958                 and max = "((2LL<<30)-1)"
7959                 and comment =
7960                   "The Int type in the generator is a signed 31 bit int." in
7961                 Some (min, max, comment) in
7962               parse_integer "xstrtoll" "long long" "int" range name i
7963           | Int64 name ->
7964               parse_integer "xstrtoll" "long long" "int64_t" None name i
7965       ) (snd style);
7966
7967       (* Call C API function. *)
7968       pr "  r = guestfs_%s " name;
7969       generate_c_call_args ~handle:"g" style;
7970       pr ";\n";
7971
7972       List.iter (
7973         function
7974         | Device _ | String _
7975         | OptString _ | Bool _
7976         | Int _ | Int64 _
7977         | BufferIn _ -> ()
7978         | Pathname name | Dev_or_Path name | FileOut name ->
7979             pr "  free (%s);\n" name
7980         | FileIn name ->
7981             pr "  free_file_in (%s);\n" name
7982         | StringList name | DeviceList name ->
7983             pr "  free_strings (%s);\n" name
7984       ) (snd style);
7985
7986       (* Any output flags? *)
7987       let fish_output =
7988         let flags = filter_map (
7989           function FishOutput flag -> Some flag | _ -> None
7990         ) flags in
7991         match flags with
7992         | [] -> None
7993         | [f] -> Some f
7994         | _ ->
7995             failwithf "%s: more than one FishOutput flag is not allowed" name in
7996
7997       (* Check return value for errors and display command results. *)
7998       (match fst style with
7999        | RErr -> pr "  return r;\n"
8000        | RInt _ ->
8001            pr "  if (r == -1) return -1;\n";
8002            (match fish_output with
8003             | None ->
8004                 pr "  printf (\"%%d\\n\", r);\n";
8005             | Some FishOutputOctal ->
8006                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
8007             | Some FishOutputHexadecimal ->
8008                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8009            pr "  return 0;\n"
8010        | RInt64 _ ->
8011            pr "  if (r == -1) return -1;\n";
8012            (match fish_output with
8013             | None ->
8014                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
8015             | Some FishOutputOctal ->
8016                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
8017             | Some FishOutputHexadecimal ->
8018                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8019            pr "  return 0;\n"
8020        | RBool _ ->
8021            pr "  if (r == -1) return -1;\n";
8022            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
8023            pr "  return 0;\n"
8024        | RConstString _ ->
8025            pr "  if (r == NULL) return -1;\n";
8026            pr "  printf (\"%%s\\n\", r);\n";
8027            pr "  return 0;\n"
8028        | RConstOptString _ ->
8029            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
8030            pr "  return 0;\n"
8031        | RString _ ->
8032            pr "  if (r == NULL) return -1;\n";
8033            pr "  printf (\"%%s\\n\", r);\n";
8034            pr "  free (r);\n";
8035            pr "  return 0;\n"
8036        | RStringList _ ->
8037            pr "  if (r == NULL) return -1;\n";
8038            pr "  print_strings (r);\n";
8039            pr "  free_strings (r);\n";
8040            pr "  return 0;\n"
8041        | RStruct (_, typ) ->
8042            pr "  if (r == NULL) return -1;\n";
8043            pr "  print_%s (r);\n" typ;
8044            pr "  guestfs_free_%s (r);\n" typ;
8045            pr "  return 0;\n"
8046        | RStructList (_, typ) ->
8047            pr "  if (r == NULL) return -1;\n";
8048            pr "  print_%s_list (r);\n" typ;
8049            pr "  guestfs_free_%s_list (r);\n" typ;
8050            pr "  return 0;\n"
8051        | RHashtable _ ->
8052            pr "  if (r == NULL) return -1;\n";
8053            pr "  print_table (r);\n";
8054            pr "  free_strings (r);\n";
8055            pr "  return 0;\n"
8056        | RBufferOut _ ->
8057            pr "  if (r == NULL) return -1;\n";
8058            pr "  if (full_write (1, r, size) != size) {\n";
8059            pr "    perror (\"write\");\n";
8060            pr "    free (r);\n";
8061            pr "    return -1;\n";
8062            pr "  }\n";
8063            pr "  free (r);\n";
8064            pr "  return 0;\n"
8065       );
8066       pr "}\n";
8067       pr "\n"
8068   ) all_functions;
8069
8070   (* run_action function *)
8071   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8072   pr "{\n";
8073   List.iter (
8074     fun (name, _, _, flags, _, _, _) ->
8075       let name2 = replace_char name '_' '-' in
8076       let alias =
8077         try find_map (function FishAlias n -> Some n | _ -> None) flags
8078         with Not_found -> name in
8079       pr "  if (";
8080       pr "STRCASEEQ (cmd, \"%s\")" name;
8081       if name <> name2 then
8082         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8083       if name <> alias then
8084         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8085       pr ")\n";
8086       pr "    return run_%s (cmd, argc, argv);\n" name;
8087       pr "  else\n";
8088   ) all_functions;
8089   pr "    {\n";
8090   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8091   pr "      if (command_num == 1)\n";
8092   pr "        extended_help_message ();\n";
8093   pr "      return -1;\n";
8094   pr "    }\n";
8095   pr "  return 0;\n";
8096   pr "}\n";
8097   pr "\n"
8098
8099 (* Readline completion for guestfish. *)
8100 and generate_fish_completion () =
8101   generate_header CStyle GPLv2plus;
8102
8103   let all_functions =
8104     List.filter (
8105       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8106     ) all_functions in
8107
8108   pr "\
8109 #include <config.h>
8110
8111 #include <stdio.h>
8112 #include <stdlib.h>
8113 #include <string.h>
8114
8115 #ifdef HAVE_LIBREADLINE
8116 #include <readline/readline.h>
8117 #endif
8118
8119 #include \"fish.h\"
8120
8121 #ifdef HAVE_LIBREADLINE
8122
8123 static const char *const commands[] = {
8124   BUILTIN_COMMANDS_FOR_COMPLETION,
8125 ";
8126
8127   (* Get the commands, including the aliases.  They don't need to be
8128    * sorted - the generator() function just does a dumb linear search.
8129    *)
8130   let commands =
8131     List.map (
8132       fun (name, _, _, flags, _, _, _) ->
8133         let name2 = replace_char name '_' '-' in
8134         let alias =
8135           try find_map (function FishAlias n -> Some n | _ -> None) flags
8136           with Not_found -> name in
8137
8138         if name <> alias then [name2; alias] else [name2]
8139     ) all_functions in
8140   let commands = List.flatten commands in
8141
8142   List.iter (pr "  \"%s\",\n") commands;
8143
8144   pr "  NULL
8145 };
8146
8147 static char *
8148 generator (const char *text, int state)
8149 {
8150   static size_t index, len;
8151   const char *name;
8152
8153   if (!state) {
8154     index = 0;
8155     len = strlen (text);
8156   }
8157
8158   rl_attempted_completion_over = 1;
8159
8160   while ((name = commands[index]) != NULL) {
8161     index++;
8162     if (STRCASEEQLEN (name, text, len))
8163       return strdup (name);
8164   }
8165
8166   return NULL;
8167 }
8168
8169 #endif /* HAVE_LIBREADLINE */
8170
8171 #ifdef HAVE_RL_COMPLETION_MATCHES
8172 #define RL_COMPLETION_MATCHES rl_completion_matches
8173 #else
8174 #ifdef HAVE_COMPLETION_MATCHES
8175 #define RL_COMPLETION_MATCHES completion_matches
8176 #endif
8177 #endif /* else just fail if we don't have either symbol */
8178
8179 char **
8180 do_completion (const char *text, int start, int end)
8181 {
8182   char **matches = NULL;
8183
8184 #ifdef HAVE_LIBREADLINE
8185   rl_completion_append_character = ' ';
8186
8187   if (start == 0)
8188     matches = RL_COMPLETION_MATCHES (text, generator);
8189   else if (complete_dest_paths)
8190     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8191 #endif
8192
8193   return matches;
8194 }
8195 ";
8196
8197 (* Generate the POD documentation for guestfish. *)
8198 and generate_fish_actions_pod () =
8199   let all_functions_sorted =
8200     List.filter (
8201       fun (_, _, _, flags, _, _, _) ->
8202         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8203     ) all_functions_sorted in
8204
8205   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8206
8207   List.iter (
8208     fun (name, style, _, flags, _, _, longdesc) ->
8209       let longdesc =
8210         Str.global_substitute rex (
8211           fun s ->
8212             let sub =
8213               try Str.matched_group 1 s
8214               with Not_found ->
8215                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8216             "C<" ^ replace_char sub '_' '-' ^ ">"
8217         ) longdesc in
8218       let name = replace_char name '_' '-' in
8219       let alias =
8220         try find_map (function FishAlias n -> Some n | _ -> None) flags
8221         with Not_found -> name in
8222
8223       pr "=head2 %s" name;
8224       if name <> alias then
8225         pr " | %s" alias;
8226       pr "\n";
8227       pr "\n";
8228       pr " %s" name;
8229       List.iter (
8230         function
8231         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8232         | OptString n -> pr " %s" n
8233         | StringList n | DeviceList n -> pr " '%s ...'" n
8234         | Bool _ -> pr " true|false"
8235         | Int n -> pr " %s" n
8236         | Int64 n -> pr " %s" n
8237         | FileIn n | FileOut n -> pr " (%s|-)" n
8238         | BufferIn n -> pr " %s" n
8239       ) (snd style);
8240       pr "\n";
8241       pr "\n";
8242       pr "%s\n\n" longdesc;
8243
8244       if List.exists (function FileIn _ | FileOut _ -> true
8245                       | _ -> false) (snd style) then
8246         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8247
8248       if List.mem ProtocolLimitWarning flags then
8249         pr "%s\n\n" protocol_limit_warning;
8250
8251       if List.mem DangerWillRobinson flags then
8252         pr "%s\n\n" danger_will_robinson;
8253
8254       match deprecation_notice flags with
8255       | None -> ()
8256       | Some txt -> pr "%s\n\n" txt
8257   ) all_functions_sorted
8258
8259 (* Generate a C function prototype. *)
8260 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8261     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8262     ?(prefix = "")
8263     ?handle name style =
8264   if extern then pr "extern ";
8265   if static then pr "static ";
8266   (match fst style with
8267    | RErr -> pr "int "
8268    | RInt _ -> pr "int "
8269    | RInt64 _ -> pr "int64_t "
8270    | RBool _ -> pr "int "
8271    | RConstString _ | RConstOptString _ -> pr "const char *"
8272    | RString _ | RBufferOut _ -> pr "char *"
8273    | RStringList _ | RHashtable _ -> pr "char **"
8274    | RStruct (_, typ) ->
8275        if not in_daemon then pr "struct guestfs_%s *" typ
8276        else pr "guestfs_int_%s *" typ
8277    | RStructList (_, typ) ->
8278        if not in_daemon then pr "struct guestfs_%s_list *" typ
8279        else pr "guestfs_int_%s_list *" typ
8280   );
8281   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8282   pr "%s%s (" prefix name;
8283   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8284     pr "void"
8285   else (
8286     let comma = ref false in
8287     (match handle with
8288      | None -> ()
8289      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8290     );
8291     let next () =
8292       if !comma then (
8293         if single_line then pr ", " else pr ",\n\t\t"
8294       );
8295       comma := true
8296     in
8297     List.iter (
8298       function
8299       | Pathname n
8300       | Device n | Dev_or_Path n
8301       | String n
8302       | OptString n ->
8303           next ();
8304           pr "const char *%s" n
8305       | StringList n | DeviceList n ->
8306           next ();
8307           pr "char *const *%s" n
8308       | Bool n -> next (); pr "int %s" n
8309       | Int n -> next (); pr "int %s" n
8310       | Int64 n -> next (); pr "int64_t %s" n
8311       | FileIn n
8312       | FileOut n ->
8313           if not in_daemon then (next (); pr "const char *%s" n)
8314       | BufferIn n ->
8315           next ();
8316           pr "const char *%s" n;
8317           next ();
8318           pr "size_t %s_size" n
8319     ) (snd style);
8320     if is_RBufferOut then (next (); pr "size_t *size_r");
8321   );
8322   pr ")";
8323   if semicolon then pr ";";
8324   if newline then pr "\n"
8325
8326 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8327 and generate_c_call_args ?handle ?(decl = false) style =
8328   pr "(";
8329   let comma = ref false in
8330   let next () =
8331     if !comma then pr ", ";
8332     comma := true
8333   in
8334   (match handle with
8335    | None -> ()
8336    | Some handle -> pr "%s" handle; comma := true
8337   );
8338   List.iter (
8339     function
8340     | BufferIn n ->
8341         next ();
8342         pr "%s, %s_size" n n
8343     | arg ->
8344         next ();
8345         pr "%s" (name_of_argt arg)
8346   ) (snd style);
8347   (* For RBufferOut calls, add implicit &size parameter. *)
8348   if not decl then (
8349     match fst style with
8350     | RBufferOut _ ->
8351         next ();
8352         pr "&size"
8353     | _ -> ()
8354   );
8355   pr ")"
8356
8357 (* Generate the OCaml bindings interface. *)
8358 and generate_ocaml_mli () =
8359   generate_header OCamlStyle LGPLv2plus;
8360
8361   pr "\
8362 (** For API documentation you should refer to the C API
8363     in the guestfs(3) manual page.  The OCaml API uses almost
8364     exactly the same calls. *)
8365
8366 type t
8367 (** A [guestfs_h] handle. *)
8368
8369 exception Error of string
8370 (** This exception is raised when there is an error. *)
8371
8372 exception Handle_closed of string
8373 (** This exception is raised if you use a {!Guestfs.t} handle
8374     after calling {!close} on it.  The string is the name of
8375     the function. *)
8376
8377 val create : unit -> t
8378 (** Create a {!Guestfs.t} handle. *)
8379
8380 val close : t -> unit
8381 (** Close the {!Guestfs.t} handle and free up all resources used
8382     by it immediately.
8383
8384     Handles are closed by the garbage collector when they become
8385     unreferenced, but callers can call this in order to provide
8386     predictable cleanup. *)
8387
8388 ";
8389   generate_ocaml_structure_decls ();
8390
8391   (* The actions. *)
8392   List.iter (
8393     fun (name, style, _, _, _, shortdesc, _) ->
8394       generate_ocaml_prototype name style;
8395       pr "(** %s *)\n" shortdesc;
8396       pr "\n"
8397   ) all_functions_sorted
8398
8399 (* Generate the OCaml bindings implementation. *)
8400 and generate_ocaml_ml () =
8401   generate_header OCamlStyle LGPLv2plus;
8402
8403   pr "\
8404 type t
8405
8406 exception Error of string
8407 exception Handle_closed of string
8408
8409 external create : unit -> t = \"ocaml_guestfs_create\"
8410 external close : t -> unit = \"ocaml_guestfs_close\"
8411
8412 (* Give the exceptions names, so they can be raised from the C code. *)
8413 let () =
8414   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8415   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8416
8417 ";
8418
8419   generate_ocaml_structure_decls ();
8420
8421   (* The actions. *)
8422   List.iter (
8423     fun (name, style, _, _, _, shortdesc, _) ->
8424       generate_ocaml_prototype ~is_external:true name style;
8425   ) all_functions_sorted
8426
8427 (* Generate the OCaml bindings C implementation. *)
8428 and generate_ocaml_c () =
8429   generate_header CStyle LGPLv2plus;
8430
8431   pr "\
8432 #include <stdio.h>
8433 #include <stdlib.h>
8434 #include <string.h>
8435
8436 #include <caml/config.h>
8437 #include <caml/alloc.h>
8438 #include <caml/callback.h>
8439 #include <caml/fail.h>
8440 #include <caml/memory.h>
8441 #include <caml/mlvalues.h>
8442 #include <caml/signals.h>
8443
8444 #include \"guestfs.h\"
8445
8446 #include \"guestfs_c.h\"
8447
8448 /* Copy a hashtable of string pairs into an assoc-list.  We return
8449  * the list in reverse order, but hashtables aren't supposed to be
8450  * ordered anyway.
8451  */
8452 static CAMLprim value
8453 copy_table (char * const * argv)
8454 {
8455   CAMLparam0 ();
8456   CAMLlocal5 (rv, pairv, kv, vv, cons);
8457   size_t i;
8458
8459   rv = Val_int (0);
8460   for (i = 0; argv[i] != NULL; i += 2) {
8461     kv = caml_copy_string (argv[i]);
8462     vv = caml_copy_string (argv[i+1]);
8463     pairv = caml_alloc (2, 0);
8464     Store_field (pairv, 0, kv);
8465     Store_field (pairv, 1, vv);
8466     cons = caml_alloc (2, 0);
8467     Store_field (cons, 1, rv);
8468     rv = cons;
8469     Store_field (cons, 0, pairv);
8470   }
8471
8472   CAMLreturn (rv);
8473 }
8474
8475 ";
8476
8477   (* Struct copy functions. *)
8478
8479   let emit_ocaml_copy_list_function typ =
8480     pr "static CAMLprim value\n";
8481     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8482     pr "{\n";
8483     pr "  CAMLparam0 ();\n";
8484     pr "  CAMLlocal2 (rv, v);\n";
8485     pr "  unsigned int i;\n";
8486     pr "\n";
8487     pr "  if (%ss->len == 0)\n" typ;
8488     pr "    CAMLreturn (Atom (0));\n";
8489     pr "  else {\n";
8490     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8491     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8492     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8493     pr "      caml_modify (&Field (rv, i), v);\n";
8494     pr "    }\n";
8495     pr "    CAMLreturn (rv);\n";
8496     pr "  }\n";
8497     pr "}\n";
8498     pr "\n";
8499   in
8500
8501   List.iter (
8502     fun (typ, cols) ->
8503       let has_optpercent_col =
8504         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8505
8506       pr "static CAMLprim value\n";
8507       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8508       pr "{\n";
8509       pr "  CAMLparam0 ();\n";
8510       if has_optpercent_col then
8511         pr "  CAMLlocal3 (rv, v, v2);\n"
8512       else
8513         pr "  CAMLlocal2 (rv, v);\n";
8514       pr "\n";
8515       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8516       iteri (
8517         fun i col ->
8518           (match col with
8519            | name, FString ->
8520                pr "  v = caml_copy_string (%s->%s);\n" typ name
8521            | name, FBuffer ->
8522                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8523                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8524                  typ name typ name
8525            | name, FUUID ->
8526                pr "  v = caml_alloc_string (32);\n";
8527                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8528            | name, (FBytes|FInt64|FUInt64) ->
8529                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8530            | name, (FInt32|FUInt32) ->
8531                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8532            | name, FOptPercent ->
8533                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8534                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8535                pr "    v = caml_alloc (1, 0);\n";
8536                pr "    Store_field (v, 0, v2);\n";
8537                pr "  } else /* None */\n";
8538                pr "    v = Val_int (0);\n";
8539            | name, FChar ->
8540                pr "  v = Val_int (%s->%s);\n" typ name
8541           );
8542           pr "  Store_field (rv, %d, v);\n" i
8543       ) cols;
8544       pr "  CAMLreturn (rv);\n";
8545       pr "}\n";
8546       pr "\n";
8547   ) structs;
8548
8549   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8550   List.iter (
8551     function
8552     | typ, (RStructListOnly | RStructAndList) ->
8553         (* generate the function for typ *)
8554         emit_ocaml_copy_list_function typ
8555     | typ, _ -> () (* empty *)
8556   ) (rstructs_used_by all_functions);
8557
8558   (* The wrappers. *)
8559   List.iter (
8560     fun (name, style, _, _, _, _, _) ->
8561       pr "/* Automatically generated wrapper for function\n";
8562       pr " * ";
8563       generate_ocaml_prototype name style;
8564       pr " */\n";
8565       pr "\n";
8566
8567       let params =
8568         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8569
8570       let needs_extra_vs =
8571         match fst style with RConstOptString _ -> true | _ -> false in
8572
8573       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8574       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8575       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8576       pr "\n";
8577
8578       pr "CAMLprim value\n";
8579       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8580       List.iter (pr ", value %s") (List.tl params);
8581       pr ")\n";
8582       pr "{\n";
8583
8584       (match params with
8585        | [p1; p2; p3; p4; p5] ->
8586            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8587        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8588            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8589            pr "  CAMLxparam%d (%s);\n"
8590              (List.length rest) (String.concat ", " rest)
8591        | ps ->
8592            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8593       );
8594       if not needs_extra_vs then
8595         pr "  CAMLlocal1 (rv);\n"
8596       else
8597         pr "  CAMLlocal3 (rv, v, v2);\n";
8598       pr "\n";
8599
8600       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8601       pr "  if (g == NULL)\n";
8602       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8603       pr "\n";
8604
8605       List.iter (
8606         function
8607         | Pathname n
8608         | Device n | Dev_or_Path n
8609         | String n
8610         | FileIn n
8611         | FileOut n ->
8612             (* Copy strings in case the GC moves them: RHBZ#604691 *)
8613             pr "  char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8614         | OptString n ->
8615             pr "  char *%s =\n" n;
8616             pr "    %sv != Val_int (0) ?" n;
8617             pr "      guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8618         | BufferIn n ->
8619             pr "  size_t %s_size = caml_string_length (%sv);\n" n n;
8620             pr "  char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8621         | StringList n | DeviceList n ->
8622             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8623         | Bool n ->
8624             pr "  int %s = Bool_val (%sv);\n" n n
8625         | Int n ->
8626             pr "  int %s = Int_val (%sv);\n" n n
8627         | Int64 n ->
8628             pr "  int64_t %s = Int64_val (%sv);\n" n n
8629       ) (snd style);
8630       let error_code =
8631         match fst style with
8632         | RErr -> pr "  int r;\n"; "-1"
8633         | RInt _ -> pr "  int r;\n"; "-1"
8634         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8635         | RBool _ -> pr "  int r;\n"; "-1"
8636         | RConstString _ | RConstOptString _ ->
8637             pr "  const char *r;\n"; "NULL"
8638         | RString _ -> pr "  char *r;\n"; "NULL"
8639         | RStringList _ ->
8640             pr "  size_t i;\n";
8641             pr "  char **r;\n";
8642             "NULL"
8643         | RStruct (_, typ) ->
8644             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8645         | RStructList (_, typ) ->
8646             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8647         | RHashtable _ ->
8648             pr "  size_t i;\n";
8649             pr "  char **r;\n";
8650             "NULL"
8651         | RBufferOut _ ->
8652             pr "  char *r;\n";
8653             pr "  size_t size;\n";
8654             "NULL" in
8655       pr "\n";
8656
8657       pr "  caml_enter_blocking_section ();\n";
8658       pr "  r = guestfs_%s " name;
8659       generate_c_call_args ~handle:"g" style;
8660       pr ";\n";
8661       pr "  caml_leave_blocking_section ();\n";
8662
8663       (* Free strings if we copied them above. *)
8664       List.iter (
8665         function
8666         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8667         | FileIn n | FileOut n | BufferIn n ->
8668             pr "  free (%s);\n" n
8669         | StringList n | DeviceList n ->
8670             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8671         | Bool _ | Int _ | Int64 _ -> ()
8672       ) (snd style);
8673
8674       pr "  if (r == %s)\n" error_code;
8675       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8676       pr "\n";
8677
8678       (match fst style with
8679        | RErr -> pr "  rv = Val_unit;\n"
8680        | RInt _ -> pr "  rv = Val_int (r);\n"
8681        | RInt64 _ ->
8682            pr "  rv = caml_copy_int64 (r);\n"
8683        | RBool _ -> pr "  rv = Val_bool (r);\n"
8684        | RConstString _ ->
8685            pr "  rv = caml_copy_string (r);\n"
8686        | RConstOptString _ ->
8687            pr "  if (r) { /* Some string */\n";
8688            pr "    v = caml_alloc (1, 0);\n";
8689            pr "    v2 = caml_copy_string (r);\n";
8690            pr "    Store_field (v, 0, v2);\n";
8691            pr "  } else /* None */\n";
8692            pr "    v = Val_int (0);\n";
8693        | RString _ ->
8694            pr "  rv = caml_copy_string (r);\n";
8695            pr "  free (r);\n"
8696        | RStringList _ ->
8697            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8698            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8699            pr "  free (r);\n"
8700        | RStruct (_, typ) ->
8701            pr "  rv = copy_%s (r);\n" typ;
8702            pr "  guestfs_free_%s (r);\n" typ;
8703        | RStructList (_, typ) ->
8704            pr "  rv = copy_%s_list (r);\n" typ;
8705            pr "  guestfs_free_%s_list (r);\n" typ;
8706        | RHashtable _ ->
8707            pr "  rv = copy_table (r);\n";
8708            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8709            pr "  free (r);\n";
8710        | RBufferOut _ ->
8711            pr "  rv = caml_alloc_string (size);\n";
8712            pr "  memcpy (String_val (rv), r, size);\n";
8713       );
8714
8715       pr "  CAMLreturn (rv);\n";
8716       pr "}\n";
8717       pr "\n";
8718
8719       if List.length params > 5 then (
8720         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8721         pr "CAMLprim value ";
8722         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8723         pr "CAMLprim value\n";
8724         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8725         pr "{\n";
8726         pr "  return ocaml_guestfs_%s (argv[0]" name;
8727         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8728         pr ");\n";
8729         pr "}\n";
8730         pr "\n"
8731       )
8732   ) all_functions_sorted
8733
8734 and generate_ocaml_structure_decls () =
8735   List.iter (
8736     fun (typ, cols) ->
8737       pr "type %s = {\n" typ;
8738       List.iter (
8739         function
8740         | name, FString -> pr "  %s : string;\n" name
8741         | name, FBuffer -> pr "  %s : string;\n" name
8742         | name, FUUID -> pr "  %s : string;\n" name
8743         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8744         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8745         | name, FChar -> pr "  %s : char;\n" name
8746         | name, FOptPercent -> pr "  %s : float option;\n" name
8747       ) cols;
8748       pr "}\n";
8749       pr "\n"
8750   ) structs
8751
8752 and generate_ocaml_prototype ?(is_external = false) name style =
8753   if is_external then pr "external " else pr "val ";
8754   pr "%s : t -> " name;
8755   List.iter (
8756     function
8757     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8758     | BufferIn _ -> pr "string -> "
8759     | OptString _ -> pr "string option -> "
8760     | StringList _ | DeviceList _ -> pr "string array -> "
8761     | Bool _ -> pr "bool -> "
8762     | Int _ -> pr "int -> "
8763     | Int64 _ -> pr "int64 -> "
8764   ) (snd style);
8765   (match fst style with
8766    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8767    | RInt _ -> pr "int"
8768    | RInt64 _ -> pr "int64"
8769    | RBool _ -> pr "bool"
8770    | RConstString _ -> pr "string"
8771    | RConstOptString _ -> pr "string option"
8772    | RString _ | RBufferOut _ -> pr "string"
8773    | RStringList _ -> pr "string array"
8774    | RStruct (_, typ) -> pr "%s" typ
8775    | RStructList (_, typ) -> pr "%s array" typ
8776    | RHashtable _ -> pr "(string * string) list"
8777   );
8778   if is_external then (
8779     pr " = ";
8780     if List.length (snd style) + 1 > 5 then
8781       pr "\"ocaml_guestfs_%s_byte\" " name;
8782     pr "\"ocaml_guestfs_%s\"" name
8783   );
8784   pr "\n"
8785
8786 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8787 and generate_perl_xs () =
8788   generate_header CStyle LGPLv2plus;
8789
8790   pr "\
8791 #include \"EXTERN.h\"
8792 #include \"perl.h\"
8793 #include \"XSUB.h\"
8794
8795 #include <guestfs.h>
8796
8797 #ifndef PRId64
8798 #define PRId64 \"lld\"
8799 #endif
8800
8801 static SV *
8802 my_newSVll(long long val) {
8803 #ifdef USE_64_BIT_ALL
8804   return newSViv(val);
8805 #else
8806   char buf[100];
8807   int len;
8808   len = snprintf(buf, 100, \"%%\" PRId64, val);
8809   return newSVpv(buf, len);
8810 #endif
8811 }
8812
8813 #ifndef PRIu64
8814 #define PRIu64 \"llu\"
8815 #endif
8816
8817 static SV *
8818 my_newSVull(unsigned long long val) {
8819 #ifdef USE_64_BIT_ALL
8820   return newSVuv(val);
8821 #else
8822   char buf[100];
8823   int len;
8824   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8825   return newSVpv(buf, len);
8826 #endif
8827 }
8828
8829 /* http://www.perlmonks.org/?node_id=680842 */
8830 static char **
8831 XS_unpack_charPtrPtr (SV *arg) {
8832   char **ret;
8833   AV *av;
8834   I32 i;
8835
8836   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8837     croak (\"array reference expected\");
8838
8839   av = (AV *)SvRV (arg);
8840   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8841   if (!ret)
8842     croak (\"malloc failed\");
8843
8844   for (i = 0; i <= av_len (av); i++) {
8845     SV **elem = av_fetch (av, i, 0);
8846
8847     if (!elem || !*elem)
8848       croak (\"missing element in list\");
8849
8850     ret[i] = SvPV_nolen (*elem);
8851   }
8852
8853   ret[i] = NULL;
8854
8855   return ret;
8856 }
8857
8858 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8859
8860 PROTOTYPES: ENABLE
8861
8862 guestfs_h *
8863 _create ()
8864    CODE:
8865       RETVAL = guestfs_create ();
8866       if (!RETVAL)
8867         croak (\"could not create guestfs handle\");
8868       guestfs_set_error_handler (RETVAL, NULL, NULL);
8869  OUTPUT:
8870       RETVAL
8871
8872 void
8873 DESTROY (sv)
8874       SV *sv;
8875  PPCODE:
8876       /* For the 'g' argument above we do the conversion explicitly and
8877        * don't rely on the typemap, because if the handle has been
8878        * explicitly closed we don't want the typemap conversion to
8879        * display an error.
8880        */
8881       HV *hv = (HV *) SvRV (sv);
8882       SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8883       if (svp != NULL) {
8884         guestfs_h *g = (guestfs_h *) SvIV (*svp);
8885         assert (g != NULL);
8886         guestfs_close (g);
8887       }
8888
8889 void
8890 close (g)
8891       guestfs_h *g;
8892  PPCODE:
8893       guestfs_close (g);
8894       /* Avoid double-free in DESTROY method. */
8895       HV *hv = (HV *) SvRV (ST(0));
8896       (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
8897
8898 ";
8899
8900   List.iter (
8901     fun (name, style, _, _, _, _, _) ->
8902       (match fst style with
8903        | RErr -> pr "void\n"
8904        | RInt _ -> pr "SV *\n"
8905        | RInt64 _ -> pr "SV *\n"
8906        | RBool _ -> pr "SV *\n"
8907        | RConstString _ -> pr "SV *\n"
8908        | RConstOptString _ -> pr "SV *\n"
8909        | RString _ -> pr "SV *\n"
8910        | RBufferOut _ -> pr "SV *\n"
8911        | RStringList _
8912        | RStruct _ | RStructList _
8913        | RHashtable _ ->
8914            pr "void\n" (* all lists returned implictly on the stack *)
8915       );
8916       (* Call and arguments. *)
8917       pr "%s (g" name;
8918       List.iter (
8919         fun arg -> pr ", %s" (name_of_argt arg)
8920       ) (snd style);
8921       pr ")\n";
8922       pr "      guestfs_h *g;\n";
8923       iteri (
8924         fun i ->
8925           function
8926           | Pathname n | Device n | Dev_or_Path n | String n
8927           | FileIn n | FileOut n ->
8928               pr "      char *%s;\n" n
8929           | BufferIn n ->
8930               pr "      char *%s;\n" n;
8931               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8932           | OptString n ->
8933               (* http://www.perlmonks.org/?node_id=554277
8934                * Note that the implicit handle argument means we have
8935                * to add 1 to the ST(x) operator.
8936                *)
8937               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8938           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8939           | Bool n -> pr "      int %s;\n" n
8940           | Int n -> pr "      int %s;\n" n
8941           | Int64 n -> pr "      int64_t %s;\n" n
8942       ) (snd style);
8943
8944       let do_cleanups () =
8945         List.iter (
8946           function
8947           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8948           | Bool _ | Int _ | Int64 _
8949           | FileIn _ | FileOut _
8950           | BufferIn _ -> ()
8951           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8952         ) (snd style)
8953       in
8954
8955       (* Code. *)
8956       (match fst style with
8957        | RErr ->
8958            pr "PREINIT:\n";
8959            pr "      int r;\n";
8960            pr " PPCODE:\n";
8961            pr "      r = guestfs_%s " name;
8962            generate_c_call_args ~handle:"g" style;
8963            pr ";\n";
8964            do_cleanups ();
8965            pr "      if (r == -1)\n";
8966            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8967        | RInt n
8968        | RBool n ->
8969            pr "PREINIT:\n";
8970            pr "      int %s;\n" n;
8971            pr "   CODE:\n";
8972            pr "      %s = guestfs_%s " n name;
8973            generate_c_call_args ~handle:"g" style;
8974            pr ";\n";
8975            do_cleanups ();
8976            pr "      if (%s == -1)\n" n;
8977            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8978            pr "      RETVAL = newSViv (%s);\n" n;
8979            pr " OUTPUT:\n";
8980            pr "      RETVAL\n"
8981        | RInt64 n ->
8982            pr "PREINIT:\n";
8983            pr "      int64_t %s;\n" n;
8984            pr "   CODE:\n";
8985            pr "      %s = guestfs_%s " n name;
8986            generate_c_call_args ~handle:"g" style;
8987            pr ";\n";
8988            do_cleanups ();
8989            pr "      if (%s == -1)\n" n;
8990            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8991            pr "      RETVAL = my_newSVll (%s);\n" n;
8992            pr " OUTPUT:\n";
8993            pr "      RETVAL\n"
8994        | RConstString n ->
8995            pr "PREINIT:\n";
8996            pr "      const char *%s;\n" n;
8997            pr "   CODE:\n";
8998            pr "      %s = guestfs_%s " n name;
8999            generate_c_call_args ~handle:"g" style;
9000            pr ";\n";
9001            do_cleanups ();
9002            pr "      if (%s == NULL)\n" n;
9003            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9004            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9005            pr " OUTPUT:\n";
9006            pr "      RETVAL\n"
9007        | RConstOptString n ->
9008            pr "PREINIT:\n";
9009            pr "      const char *%s;\n" n;
9010            pr "   CODE:\n";
9011            pr "      %s = guestfs_%s " n name;
9012            generate_c_call_args ~handle:"g" style;
9013            pr ";\n";
9014            do_cleanups ();
9015            pr "      if (%s == NULL)\n" n;
9016            pr "        RETVAL = &PL_sv_undef;\n";
9017            pr "      else\n";
9018            pr "        RETVAL = newSVpv (%s, 0);\n" n;
9019            pr " OUTPUT:\n";
9020            pr "      RETVAL\n"
9021        | RString n ->
9022            pr "PREINIT:\n";
9023            pr "      char *%s;\n" n;
9024            pr "   CODE:\n";
9025            pr "      %s = guestfs_%s " n name;
9026            generate_c_call_args ~handle:"g" style;
9027            pr ";\n";
9028            do_cleanups ();
9029            pr "      if (%s == NULL)\n" n;
9030            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9031            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9032            pr "      free (%s);\n" n;
9033            pr " OUTPUT:\n";
9034            pr "      RETVAL\n"
9035        | RStringList n | RHashtable n ->
9036            pr "PREINIT:\n";
9037            pr "      char **%s;\n" n;
9038            pr "      size_t i, n;\n";
9039            pr " PPCODE:\n";
9040            pr "      %s = guestfs_%s " n name;
9041            generate_c_call_args ~handle:"g" style;
9042            pr ";\n";
9043            do_cleanups ();
9044            pr "      if (%s == NULL)\n" n;
9045            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9046            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9047            pr "      EXTEND (SP, n);\n";
9048            pr "      for (i = 0; i < n; ++i) {\n";
9049            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9050            pr "        free (%s[i]);\n" n;
9051            pr "      }\n";
9052            pr "      free (%s);\n" n;
9053        | RStruct (n, typ) ->
9054            let cols = cols_of_struct typ in
9055            generate_perl_struct_code typ cols name style n do_cleanups
9056        | RStructList (n, typ) ->
9057            let cols = cols_of_struct typ in
9058            generate_perl_struct_list_code typ cols name style n do_cleanups
9059        | RBufferOut n ->
9060            pr "PREINIT:\n";
9061            pr "      char *%s;\n" n;
9062            pr "      size_t size;\n";
9063            pr "   CODE:\n";
9064            pr "      %s = guestfs_%s " n name;
9065            generate_c_call_args ~handle:"g" style;
9066            pr ";\n";
9067            do_cleanups ();
9068            pr "      if (%s == NULL)\n" n;
9069            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9070            pr "      RETVAL = newSVpvn (%s, size);\n" n;
9071            pr "      free (%s);\n" n;
9072            pr " OUTPUT:\n";
9073            pr "      RETVAL\n"
9074       );
9075
9076       pr "\n"
9077   ) all_functions
9078
9079 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9080   pr "PREINIT:\n";
9081   pr "      struct guestfs_%s_list *%s;\n" typ n;
9082   pr "      size_t i;\n";
9083   pr "      HV *hv;\n";
9084   pr " PPCODE:\n";
9085   pr "      %s = guestfs_%s " n name;
9086   generate_c_call_args ~handle:"g" style;
9087   pr ";\n";
9088   do_cleanups ();
9089   pr "      if (%s == NULL)\n" n;
9090   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9091   pr "      EXTEND (SP, %s->len);\n" n;
9092   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
9093   pr "        hv = newHV ();\n";
9094   List.iter (
9095     function
9096     | name, FString ->
9097         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9098           name (String.length name) n name
9099     | name, FUUID ->
9100         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9101           name (String.length name) n name
9102     | name, FBuffer ->
9103         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9104           name (String.length name) n name n name
9105     | name, (FBytes|FUInt64) ->
9106         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9107           name (String.length name) n name
9108     | name, FInt64 ->
9109         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9110           name (String.length name) n name
9111     | name, (FInt32|FUInt32) ->
9112         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9113           name (String.length name) n name
9114     | name, FChar ->
9115         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9116           name (String.length name) n name
9117     | name, FOptPercent ->
9118         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9119           name (String.length name) n name
9120   ) cols;
9121   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9122   pr "      }\n";
9123   pr "      guestfs_free_%s_list (%s);\n" typ n
9124
9125 and generate_perl_struct_code typ cols name style n do_cleanups =
9126   pr "PREINIT:\n";
9127   pr "      struct guestfs_%s *%s;\n" typ n;
9128   pr " PPCODE:\n";
9129   pr "      %s = guestfs_%s " n name;
9130   generate_c_call_args ~handle:"g" style;
9131   pr ";\n";
9132   do_cleanups ();
9133   pr "      if (%s == NULL)\n" n;
9134   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9135   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9136   List.iter (
9137     fun ((name, _) as col) ->
9138       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9139
9140       match col with
9141       | name, FString ->
9142           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9143             n name
9144       | name, FBuffer ->
9145           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9146             n name n name
9147       | name, FUUID ->
9148           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9149             n name
9150       | name, (FBytes|FUInt64) ->
9151           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9152             n name
9153       | name, FInt64 ->
9154           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9155             n name
9156       | name, (FInt32|FUInt32) ->
9157           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9158             n name
9159       | name, FChar ->
9160           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9161             n name
9162       | name, FOptPercent ->
9163           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9164             n name
9165   ) cols;
9166   pr "      free (%s);\n" n
9167
9168 (* Generate Sys/Guestfs.pm. *)
9169 and generate_perl_pm () =
9170   generate_header HashStyle LGPLv2plus;
9171
9172   pr "\
9173 =pod
9174
9175 =head1 NAME
9176
9177 Sys::Guestfs - Perl bindings for libguestfs
9178
9179 =head1 SYNOPSIS
9180
9181  use Sys::Guestfs;
9182
9183  my $h = Sys::Guestfs->new ();
9184  $h->add_drive ('guest.img');
9185  $h->launch ();
9186  $h->mount ('/dev/sda1', '/');
9187  $h->touch ('/hello');
9188  $h->sync ();
9189
9190 =head1 DESCRIPTION
9191
9192 The C<Sys::Guestfs> module provides a Perl XS binding to the
9193 libguestfs API for examining and modifying virtual machine
9194 disk images.
9195
9196 Amongst the things this is good for: making batch configuration
9197 changes to guests, getting disk used/free statistics (see also:
9198 virt-df), migrating between virtualization systems (see also:
9199 virt-p2v), performing partial backups, performing partial guest
9200 clones, cloning guests and changing registry/UUID/hostname info, and
9201 much else besides.
9202
9203 Libguestfs uses Linux kernel and qemu code, and can access any type of
9204 guest filesystem that Linux and qemu can, including but not limited
9205 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9206 schemes, qcow, qcow2, vmdk.
9207
9208 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9209 LVs, what filesystem is in each LV, etc.).  It can also run commands
9210 in the context of the guest.  Also you can access filesystems over
9211 FUSE.
9212
9213 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9214 functions for using libguestfs from Perl, including integration
9215 with libvirt.
9216
9217 =head1 ERRORS
9218
9219 All errors turn into calls to C<croak> (see L<Carp(3)>).
9220
9221 =head1 METHODS
9222
9223 =over 4
9224
9225 =cut
9226
9227 package Sys::Guestfs;
9228
9229 use strict;
9230 use warnings;
9231
9232 # This version number changes whenever a new function
9233 # is added to the libguestfs API.  It is not directly
9234 # related to the libguestfs version number.
9235 use vars qw($VERSION);
9236 $VERSION = '0.%d';
9237
9238 require XSLoader;
9239 XSLoader::load ('Sys::Guestfs');
9240
9241 =item $h = Sys::Guestfs->new ();
9242
9243 Create a new guestfs handle.
9244
9245 =cut
9246
9247 sub new {
9248   my $proto = shift;
9249   my $class = ref ($proto) || $proto;
9250
9251   my $g = Sys::Guestfs::_create ();
9252   my $self = { _g => $g };
9253   bless $self, $class;
9254   return $self;
9255 }
9256
9257 =item $h->close ();
9258
9259 Explicitly close the guestfs handle.
9260
9261 B<Note:> You should not usually call this function.  The handle will
9262 be closed implicitly when its reference count goes to zero (eg.
9263 when it goes out of scope or the program ends).  This call is
9264 only required in some exceptional cases, such as where the program
9265 may contain cached references to the handle 'somewhere' and you
9266 really have to have the close happen right away.  After calling
9267 C<close> the program must not call any method (including C<close>)
9268 on the handle (but the implicit call to C<DESTROY> that happens
9269 when the final reference is cleaned up is OK).
9270
9271 =cut
9272
9273 " max_proc_nr;
9274
9275   (* Actions.  We only need to print documentation for these as
9276    * they are pulled in from the XS code automatically.
9277    *)
9278   List.iter (
9279     fun (name, style, _, flags, _, _, longdesc) ->
9280       if not (List.mem NotInDocs flags) then (
9281         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9282         pr "=item ";
9283         generate_perl_prototype name style;
9284         pr "\n\n";
9285         pr "%s\n\n" longdesc;
9286         if List.mem ProtocolLimitWarning flags then
9287           pr "%s\n\n" protocol_limit_warning;
9288         if List.mem DangerWillRobinson flags then
9289           pr "%s\n\n" danger_will_robinson;
9290         match deprecation_notice flags with
9291         | None -> ()
9292         | Some txt -> pr "%s\n\n" txt
9293       )
9294   ) all_functions_sorted;
9295
9296   (* End of file. *)
9297   pr "\
9298 =cut
9299
9300 1;
9301
9302 =back
9303
9304 =head1 COPYRIGHT
9305
9306 Copyright (C) %s Red Hat Inc.
9307
9308 =head1 LICENSE
9309
9310 Please see the file COPYING.LIB for the full license.
9311
9312 =head1 SEE ALSO
9313
9314 L<guestfs(3)>,
9315 L<guestfish(1)>,
9316 L<http://libguestfs.org>,
9317 L<Sys::Guestfs::Lib(3)>.
9318
9319 =cut
9320 " copyright_years
9321
9322 and generate_perl_prototype name style =
9323   (match fst style with
9324    | RErr -> ()
9325    | RBool n
9326    | RInt n
9327    | RInt64 n
9328    | RConstString n
9329    | RConstOptString n
9330    | RString n
9331    | RBufferOut n -> pr "$%s = " n
9332    | RStruct (n,_)
9333    | RHashtable n -> pr "%%%s = " n
9334    | RStringList n
9335    | RStructList (n,_) -> pr "@%s = " n
9336   );
9337   pr "$h->%s (" name;
9338   let comma = ref false in
9339   List.iter (
9340     fun arg ->
9341       if !comma then pr ", ";
9342       comma := true;
9343       match arg with
9344       | Pathname n | Device n | Dev_or_Path n | String n
9345       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9346       | BufferIn n ->
9347           pr "$%s" n
9348       | StringList n | DeviceList n ->
9349           pr "\\@%s" n
9350   ) (snd style);
9351   pr ");"
9352
9353 (* Generate Python C module. *)
9354 and generate_python_c () =
9355   generate_header CStyle LGPLv2plus;
9356
9357   pr "\
9358 #define PY_SSIZE_T_CLEAN 1
9359 #include <Python.h>
9360
9361 #if PY_VERSION_HEX < 0x02050000
9362 typedef int Py_ssize_t;
9363 #define PY_SSIZE_T_MAX INT_MAX
9364 #define PY_SSIZE_T_MIN INT_MIN
9365 #endif
9366
9367 #include <stdio.h>
9368 #include <stdlib.h>
9369 #include <assert.h>
9370
9371 #include \"guestfs.h\"
9372
9373 typedef struct {
9374   PyObject_HEAD
9375   guestfs_h *g;
9376 } Pyguestfs_Object;
9377
9378 static guestfs_h *
9379 get_handle (PyObject *obj)
9380 {
9381   assert (obj);
9382   assert (obj != Py_None);
9383   return ((Pyguestfs_Object *) obj)->g;
9384 }
9385
9386 static PyObject *
9387 put_handle (guestfs_h *g)
9388 {
9389   assert (g);
9390   return
9391     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9392 }
9393
9394 /* This list should be freed (but not the strings) after use. */
9395 static char **
9396 get_string_list (PyObject *obj)
9397 {
9398   size_t i, len;
9399   char **r;
9400
9401   assert (obj);
9402
9403   if (!PyList_Check (obj)) {
9404     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9405     return NULL;
9406   }
9407
9408   Py_ssize_t slen = PyList_Size (obj);
9409   if (slen == -1) {
9410     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9411     return NULL;
9412   }
9413   len = (size_t) slen;
9414   r = malloc (sizeof (char *) * (len+1));
9415   if (r == NULL) {
9416     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9417     return NULL;
9418   }
9419
9420   for (i = 0; i < len; ++i)
9421     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9422   r[len] = NULL;
9423
9424   return r;
9425 }
9426
9427 static PyObject *
9428 put_string_list (char * const * const argv)
9429 {
9430   PyObject *list;
9431   int argc, i;
9432
9433   for (argc = 0; argv[argc] != NULL; ++argc)
9434     ;
9435
9436   list = PyList_New (argc);
9437   for (i = 0; i < argc; ++i)
9438     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9439
9440   return list;
9441 }
9442
9443 static PyObject *
9444 put_table (char * const * const argv)
9445 {
9446   PyObject *list, *item;
9447   int argc, i;
9448
9449   for (argc = 0; argv[argc] != NULL; ++argc)
9450     ;
9451
9452   list = PyList_New (argc >> 1);
9453   for (i = 0; i < argc; i += 2) {
9454     item = PyTuple_New (2);
9455     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9456     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9457     PyList_SetItem (list, i >> 1, item);
9458   }
9459
9460   return list;
9461 }
9462
9463 static void
9464 free_strings (char **argv)
9465 {
9466   int argc;
9467
9468   for (argc = 0; argv[argc] != NULL; ++argc)
9469     free (argv[argc]);
9470   free (argv);
9471 }
9472
9473 static PyObject *
9474 py_guestfs_create (PyObject *self, PyObject *args)
9475 {
9476   guestfs_h *g;
9477
9478   g = guestfs_create ();
9479   if (g == NULL) {
9480     PyErr_SetString (PyExc_RuntimeError,
9481                      \"guestfs.create: failed to allocate handle\");
9482     return NULL;
9483   }
9484   guestfs_set_error_handler (g, NULL, NULL);
9485   return put_handle (g);
9486 }
9487
9488 static PyObject *
9489 py_guestfs_close (PyObject *self, PyObject *args)
9490 {
9491   PyObject *py_g;
9492   guestfs_h *g;
9493
9494   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9495     return NULL;
9496   g = get_handle (py_g);
9497
9498   guestfs_close (g);
9499
9500   Py_INCREF (Py_None);
9501   return Py_None;
9502 }
9503
9504 ";
9505
9506   let emit_put_list_function typ =
9507     pr "static PyObject *\n";
9508     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9509     pr "{\n";
9510     pr "  PyObject *list;\n";
9511     pr "  size_t i;\n";
9512     pr "\n";
9513     pr "  list = PyList_New (%ss->len);\n" typ;
9514     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9515     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9516     pr "  return list;\n";
9517     pr "};\n";
9518     pr "\n"
9519   in
9520
9521   (* Structures, turned into Python dictionaries. *)
9522   List.iter (
9523     fun (typ, cols) ->
9524       pr "static PyObject *\n";
9525       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9526       pr "{\n";
9527       pr "  PyObject *dict;\n";
9528       pr "\n";
9529       pr "  dict = PyDict_New ();\n";
9530       List.iter (
9531         function
9532         | name, FString ->
9533             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9534             pr "                        PyString_FromString (%s->%s));\n"
9535               typ name
9536         | name, FBuffer ->
9537             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9538             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9539               typ name typ name
9540         | name, FUUID ->
9541             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9542             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9543               typ name
9544         | name, (FBytes|FUInt64) ->
9545             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9546             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9547               typ name
9548         | name, FInt64 ->
9549             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9550             pr "                        PyLong_FromLongLong (%s->%s));\n"
9551               typ name
9552         | name, FUInt32 ->
9553             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9554             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9555               typ name
9556         | name, FInt32 ->
9557             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9558             pr "                        PyLong_FromLong (%s->%s));\n"
9559               typ name
9560         | name, FOptPercent ->
9561             pr "  if (%s->%s >= 0)\n" typ name;
9562             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9563             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9564               typ name;
9565             pr "  else {\n";
9566             pr "    Py_INCREF (Py_None);\n";
9567             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9568             pr "  }\n"
9569         | name, FChar ->
9570             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9571             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9572       ) cols;
9573       pr "  return dict;\n";
9574       pr "};\n";
9575       pr "\n";
9576
9577   ) structs;
9578
9579   (* Emit a put_TYPE_list function definition only if that function is used. *)
9580   List.iter (
9581     function
9582     | typ, (RStructListOnly | RStructAndList) ->
9583         (* generate the function for typ *)
9584         emit_put_list_function typ
9585     | typ, _ -> () (* empty *)
9586   ) (rstructs_used_by all_functions);
9587
9588   (* Python wrapper functions. *)
9589   List.iter (
9590     fun (name, style, _, _, _, _, _) ->
9591       pr "static PyObject *\n";
9592       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9593       pr "{\n";
9594
9595       pr "  PyObject *py_g;\n";
9596       pr "  guestfs_h *g;\n";
9597       pr "  PyObject *py_r;\n";
9598
9599       let error_code =
9600         match fst style with
9601         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9602         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9603         | RConstString _ | RConstOptString _ ->
9604             pr "  const char *r;\n"; "NULL"
9605         | RString _ -> pr "  char *r;\n"; "NULL"
9606         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9607         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9608         | RStructList (_, typ) ->
9609             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9610         | RBufferOut _ ->
9611             pr "  char *r;\n";
9612             pr "  size_t size;\n";
9613             "NULL" in
9614
9615       List.iter (
9616         function
9617         | Pathname n | Device n | Dev_or_Path n | String n
9618         | FileIn n | FileOut n ->
9619             pr "  const char *%s;\n" n
9620         | OptString n -> pr "  const char *%s;\n" n
9621         | BufferIn n ->
9622             pr "  const char *%s;\n" n;
9623             pr "  Py_ssize_t %s_size;\n" n
9624         | StringList n | DeviceList n ->
9625             pr "  PyObject *py_%s;\n" n;
9626             pr "  char **%s;\n" n
9627         | Bool n -> pr "  int %s;\n" n
9628         | Int n -> pr "  int %s;\n" n
9629         | Int64 n -> pr "  long long %s;\n" n
9630       ) (snd style);
9631
9632       pr "\n";
9633
9634       (* Convert the parameters. *)
9635       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9636       List.iter (
9637         function
9638         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9639         | OptString _ -> pr "z"
9640         | StringList _ | DeviceList _ -> pr "O"
9641         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9642         | Int _ -> pr "i"
9643         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9644                              * emulate C's int/long/long long in Python?
9645                              *)
9646         | BufferIn _ -> pr "s#"
9647       ) (snd style);
9648       pr ":guestfs_%s\",\n" name;
9649       pr "                         &py_g";
9650       List.iter (
9651         function
9652         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9653         | OptString n -> pr ", &%s" n
9654         | StringList n | DeviceList n -> pr ", &py_%s" n
9655         | Bool n -> pr ", &%s" n
9656         | Int n -> pr ", &%s" n
9657         | Int64 n -> pr ", &%s" n
9658         | BufferIn n -> pr ", &%s, &%s_size" n n
9659       ) (snd style);
9660
9661       pr "))\n";
9662       pr "    return NULL;\n";
9663
9664       pr "  g = get_handle (py_g);\n";
9665       List.iter (
9666         function
9667         | Pathname _ | Device _ | Dev_or_Path _ | String _
9668         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9669         | BufferIn _ -> ()
9670         | StringList n | DeviceList n ->
9671             pr "  %s = get_string_list (py_%s);\n" n n;
9672             pr "  if (!%s) return NULL;\n" n
9673       ) (snd style);
9674
9675       pr "\n";
9676
9677       pr "  r = guestfs_%s " name;
9678       generate_c_call_args ~handle:"g" style;
9679       pr ";\n";
9680
9681       List.iter (
9682         function
9683         | Pathname _ | Device _ | Dev_or_Path _ | String _
9684         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9685         | BufferIn _ -> ()
9686         | StringList n | DeviceList n ->
9687             pr "  free (%s);\n" n
9688       ) (snd style);
9689
9690       pr "  if (r == %s) {\n" error_code;
9691       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9692       pr "    return NULL;\n";
9693       pr "  }\n";
9694       pr "\n";
9695
9696       (match fst style with
9697        | RErr ->
9698            pr "  Py_INCREF (Py_None);\n";
9699            pr "  py_r = Py_None;\n"
9700        | RInt _
9701        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9702        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9703        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9704        | RConstOptString _ ->
9705            pr "  if (r)\n";
9706            pr "    py_r = PyString_FromString (r);\n";
9707            pr "  else {\n";
9708            pr "    Py_INCREF (Py_None);\n";
9709            pr "    py_r = Py_None;\n";
9710            pr "  }\n"
9711        | RString _ ->
9712            pr "  py_r = PyString_FromString (r);\n";
9713            pr "  free (r);\n"
9714        | RStringList _ ->
9715            pr "  py_r = put_string_list (r);\n";
9716            pr "  free_strings (r);\n"
9717        | RStruct (_, typ) ->
9718            pr "  py_r = put_%s (r);\n" typ;
9719            pr "  guestfs_free_%s (r);\n" typ
9720        | RStructList (_, typ) ->
9721            pr "  py_r = put_%s_list (r);\n" typ;
9722            pr "  guestfs_free_%s_list (r);\n" typ
9723        | RHashtable n ->
9724            pr "  py_r = put_table (r);\n";
9725            pr "  free_strings (r);\n"
9726        | RBufferOut _ ->
9727            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9728            pr "  free (r);\n"
9729       );
9730
9731       pr "  return py_r;\n";
9732       pr "}\n";
9733       pr "\n"
9734   ) all_functions;
9735
9736   (* Table of functions. *)
9737   pr "static PyMethodDef methods[] = {\n";
9738   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9739   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9740   List.iter (
9741     fun (name, _, _, _, _, _, _) ->
9742       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9743         name name
9744   ) all_functions;
9745   pr "  { NULL, NULL, 0, NULL }\n";
9746   pr "};\n";
9747   pr "\n";
9748
9749   (* Init function. *)
9750   pr "\
9751 void
9752 initlibguestfsmod (void)
9753 {
9754   static int initialized = 0;
9755
9756   if (initialized) return;
9757   Py_InitModule ((char *) \"libguestfsmod\", methods);
9758   initialized = 1;
9759 }
9760 "
9761
9762 (* Generate Python module. *)
9763 and generate_python_py () =
9764   generate_header HashStyle LGPLv2plus;
9765
9766   pr "\
9767 u\"\"\"Python bindings for libguestfs
9768
9769 import guestfs
9770 g = guestfs.GuestFS ()
9771 g.add_drive (\"guest.img\")
9772 g.launch ()
9773 parts = g.list_partitions ()
9774
9775 The guestfs module provides a Python binding to the libguestfs API
9776 for examining and modifying virtual machine disk images.
9777
9778 Amongst the things this is good for: making batch configuration
9779 changes to guests, getting disk used/free statistics (see also:
9780 virt-df), migrating between virtualization systems (see also:
9781 virt-p2v), performing partial backups, performing partial guest
9782 clones, cloning guests and changing registry/UUID/hostname info, and
9783 much else besides.
9784
9785 Libguestfs uses Linux kernel and qemu code, and can access any type of
9786 guest filesystem that Linux and qemu can, including but not limited
9787 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9788 schemes, qcow, qcow2, vmdk.
9789
9790 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9791 LVs, what filesystem is in each LV, etc.).  It can also run commands
9792 in the context of the guest.  Also you can access filesystems over
9793 FUSE.
9794
9795 Errors which happen while using the API are turned into Python
9796 RuntimeError exceptions.
9797
9798 To create a guestfs handle you usually have to perform the following
9799 sequence of calls:
9800
9801 # Create the handle, call add_drive at least once, and possibly
9802 # several times if the guest has multiple block devices:
9803 g = guestfs.GuestFS ()
9804 g.add_drive (\"guest.img\")
9805
9806 # Launch the qemu subprocess and wait for it to become ready:
9807 g.launch ()
9808
9809 # Now you can issue commands, for example:
9810 logvols = g.lvs ()
9811
9812 \"\"\"
9813
9814 import libguestfsmod
9815
9816 class GuestFS:
9817     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9818
9819     def __init__ (self):
9820         \"\"\"Create a new libguestfs handle.\"\"\"
9821         self._o = libguestfsmod.create ()
9822
9823     def __del__ (self):
9824         libguestfsmod.close (self._o)
9825
9826 ";
9827
9828   List.iter (
9829     fun (name, style, _, flags, _, _, longdesc) ->
9830       pr "    def %s " name;
9831       generate_py_call_args ~handle:"self" (snd style);
9832       pr ":\n";
9833
9834       if not (List.mem NotInDocs flags) then (
9835         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9836         let doc =
9837           match fst style with
9838           | RErr | RInt _ | RInt64 _ | RBool _
9839           | RConstOptString _ | RConstString _
9840           | RString _ | RBufferOut _ -> doc
9841           | RStringList _ ->
9842               doc ^ "\n\nThis function returns a list of strings."
9843           | RStruct (_, typ) ->
9844               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9845           | RStructList (_, typ) ->
9846               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9847           | RHashtable _ ->
9848               doc ^ "\n\nThis function returns a dictionary." in
9849         let doc =
9850           if List.mem ProtocolLimitWarning flags then
9851             doc ^ "\n\n" ^ protocol_limit_warning
9852           else doc in
9853         let doc =
9854           if List.mem DangerWillRobinson flags then
9855             doc ^ "\n\n" ^ danger_will_robinson
9856           else doc in
9857         let doc =
9858           match deprecation_notice flags with
9859           | None -> doc
9860           | Some txt -> doc ^ "\n\n" ^ txt in
9861         let doc = pod2text ~width:60 name doc in
9862         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9863         let doc = String.concat "\n        " doc in
9864         pr "        u\"\"\"%s\"\"\"\n" doc;
9865       );
9866       pr "        return libguestfsmod.%s " name;
9867       generate_py_call_args ~handle:"self._o" (snd style);
9868       pr "\n";
9869       pr "\n";
9870   ) all_functions
9871
9872 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9873 and generate_py_call_args ~handle args =
9874   pr "(%s" handle;
9875   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9876   pr ")"
9877
9878 (* Useful if you need the longdesc POD text as plain text.  Returns a
9879  * list of lines.
9880  *
9881  * Because this is very slow (the slowest part of autogeneration),
9882  * we memoize the results.
9883  *)
9884 and pod2text ~width name longdesc =
9885   let key = width, name, longdesc in
9886   try Hashtbl.find pod2text_memo key
9887   with Not_found ->
9888     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9889     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9890     close_out chan;
9891     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9892     let chan = open_process_in cmd in
9893     let lines = ref [] in
9894     let rec loop i =
9895       let line = input_line chan in
9896       if i = 1 then             (* discard the first line of output *)
9897         loop (i+1)
9898       else (
9899         let line = triml line in
9900         lines := line :: !lines;
9901         loop (i+1)
9902       ) in
9903     let lines = try loop 1 with End_of_file -> List.rev !lines in
9904     unlink filename;
9905     (match close_process_in chan with
9906      | WEXITED 0 -> ()
9907      | WEXITED i ->
9908          failwithf "pod2text: process exited with non-zero status (%d)" i
9909      | WSIGNALED i | WSTOPPED i ->
9910          failwithf "pod2text: process signalled or stopped by signal %d" i
9911     );
9912     Hashtbl.add pod2text_memo key lines;
9913     pod2text_memo_updated ();
9914     lines
9915
9916 (* Generate ruby bindings. *)
9917 and generate_ruby_c () =
9918   generate_header CStyle LGPLv2plus;
9919
9920   pr "\
9921 #include <stdio.h>
9922 #include <stdlib.h>
9923
9924 #include <ruby.h>
9925
9926 #include \"guestfs.h\"
9927
9928 #include \"extconf.h\"
9929
9930 /* For Ruby < 1.9 */
9931 #ifndef RARRAY_LEN
9932 #define RARRAY_LEN(r) (RARRAY((r))->len)
9933 #endif
9934
9935 static VALUE m_guestfs;                 /* guestfs module */
9936 static VALUE c_guestfs;                 /* guestfs_h handle */
9937 static VALUE e_Error;                   /* used for all errors */
9938
9939 static void ruby_guestfs_free (void *p)
9940 {
9941   if (!p) return;
9942   guestfs_close ((guestfs_h *) p);
9943 }
9944
9945 static VALUE ruby_guestfs_create (VALUE m)
9946 {
9947   guestfs_h *g;
9948
9949   g = guestfs_create ();
9950   if (!g)
9951     rb_raise (e_Error, \"failed to create guestfs handle\");
9952
9953   /* Don't print error messages to stderr by default. */
9954   guestfs_set_error_handler (g, NULL, NULL);
9955
9956   /* Wrap it, and make sure the close function is called when the
9957    * handle goes away.
9958    */
9959   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9960 }
9961
9962 static VALUE ruby_guestfs_close (VALUE gv)
9963 {
9964   guestfs_h *g;
9965   Data_Get_Struct (gv, guestfs_h, g);
9966
9967   ruby_guestfs_free (g);
9968   DATA_PTR (gv) = NULL;
9969
9970   return Qnil;
9971 }
9972
9973 ";
9974
9975   List.iter (
9976     fun (name, style, _, _, _, _, _) ->
9977       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9978       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9979       pr ")\n";
9980       pr "{\n";
9981       pr "  guestfs_h *g;\n";
9982       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9983       pr "  if (!g)\n";
9984       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9985         name;
9986       pr "\n";
9987
9988       List.iter (
9989         function
9990         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9991             pr "  Check_Type (%sv, T_STRING);\n" n;
9992             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9993             pr "  if (!%s)\n" n;
9994             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9995             pr "              \"%s\", \"%s\");\n" n name
9996         | BufferIn n ->
9997             pr "  Check_Type (%sv, T_STRING);\n" n;
9998             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
9999             pr "  if (!%s)\n" n;
10000             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10001             pr "              \"%s\", \"%s\");\n" n name;
10002             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
10003         | OptString n ->
10004             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
10005         | StringList n | DeviceList n ->
10006             pr "  char **%s;\n" n;
10007             pr "  Check_Type (%sv, T_ARRAY);\n" n;
10008             pr "  {\n";
10009             pr "    size_t i, len;\n";
10010             pr "    len = RARRAY_LEN (%sv);\n" n;
10011             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
10012               n;
10013             pr "    for (i = 0; i < len; ++i) {\n";
10014             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
10015             pr "      %s[i] = StringValueCStr (v);\n" n;
10016             pr "    }\n";
10017             pr "    %s[len] = NULL;\n" n;
10018             pr "  }\n";
10019         | Bool n ->
10020             pr "  int %s = RTEST (%sv);\n" n n
10021         | Int n ->
10022             pr "  int %s = NUM2INT (%sv);\n" n n
10023         | Int64 n ->
10024             pr "  long long %s = NUM2LL (%sv);\n" n n
10025       ) (snd style);
10026       pr "\n";
10027
10028       let error_code =
10029         match fst style with
10030         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
10031         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
10032         | RConstString _ | RConstOptString _ ->
10033             pr "  const char *r;\n"; "NULL"
10034         | RString _ -> pr "  char *r;\n"; "NULL"
10035         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
10036         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
10037         | RStructList (_, typ) ->
10038             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
10039         | RBufferOut _ ->
10040             pr "  char *r;\n";
10041             pr "  size_t size;\n";
10042             "NULL" in
10043       pr "\n";
10044
10045       pr "  r = guestfs_%s " name;
10046       generate_c_call_args ~handle:"g" style;
10047       pr ";\n";
10048
10049       List.iter (
10050         function
10051         | Pathname _ | Device _ | Dev_or_Path _ | String _
10052         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10053         | BufferIn _ -> ()
10054         | StringList n | DeviceList n ->
10055             pr "  free (%s);\n" n
10056       ) (snd style);
10057
10058       pr "  if (r == %s)\n" error_code;
10059       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10060       pr "\n";
10061
10062       (match fst style with
10063        | RErr ->
10064            pr "  return Qnil;\n"
10065        | RInt _ | RBool _ ->
10066            pr "  return INT2NUM (r);\n"
10067        | RInt64 _ ->
10068            pr "  return ULL2NUM (r);\n"
10069        | RConstString _ ->
10070            pr "  return rb_str_new2 (r);\n";
10071        | RConstOptString _ ->
10072            pr "  if (r)\n";
10073            pr "    return rb_str_new2 (r);\n";
10074            pr "  else\n";
10075            pr "    return Qnil;\n";
10076        | RString _ ->
10077            pr "  VALUE rv = rb_str_new2 (r);\n";
10078            pr "  free (r);\n";
10079            pr "  return rv;\n";
10080        | RStringList _ ->
10081            pr "  size_t i, len = 0;\n";
10082            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
10083            pr "  VALUE rv = rb_ary_new2 (len);\n";
10084            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
10085            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10086            pr "    free (r[i]);\n";
10087            pr "  }\n";
10088            pr "  free (r);\n";
10089            pr "  return rv;\n"
10090        | RStruct (_, typ) ->
10091            let cols = cols_of_struct typ in
10092            generate_ruby_struct_code typ cols
10093        | RStructList (_, typ) ->
10094            let cols = cols_of_struct typ in
10095            generate_ruby_struct_list_code typ cols
10096        | RHashtable _ ->
10097            pr "  VALUE rv = rb_hash_new ();\n";
10098            pr "  size_t i;\n";
10099            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
10100            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10101            pr "    free (r[i]);\n";
10102            pr "    free (r[i+1]);\n";
10103            pr "  }\n";
10104            pr "  free (r);\n";
10105            pr "  return rv;\n"
10106        | RBufferOut _ ->
10107            pr "  VALUE rv = rb_str_new (r, size);\n";
10108            pr "  free (r);\n";
10109            pr "  return rv;\n";
10110       );
10111
10112       pr "}\n";
10113       pr "\n"
10114   ) all_functions;
10115
10116   pr "\
10117 /* Initialize the module. */
10118 void Init__guestfs ()
10119 {
10120   m_guestfs = rb_define_module (\"Guestfs\");
10121   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10122   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10123
10124   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10125   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10126
10127 ";
10128   (* Define the rest of the methods. *)
10129   List.iter (
10130     fun (name, style, _, _, _, _, _) ->
10131       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10132       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10133   ) all_functions;
10134
10135   pr "}\n"
10136
10137 (* Ruby code to return a struct. *)
10138 and generate_ruby_struct_code typ cols =
10139   pr "  VALUE rv = rb_hash_new ();\n";
10140   List.iter (
10141     function
10142     | name, FString ->
10143         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10144     | name, FBuffer ->
10145         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10146     | name, FUUID ->
10147         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10148     | name, (FBytes|FUInt64) ->
10149         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10150     | name, FInt64 ->
10151         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10152     | name, FUInt32 ->
10153         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10154     | name, FInt32 ->
10155         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10156     | name, FOptPercent ->
10157         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10158     | name, FChar -> (* XXX wrong? *)
10159         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10160   ) cols;
10161   pr "  guestfs_free_%s (r);\n" typ;
10162   pr "  return rv;\n"
10163
10164 (* Ruby code to return a struct list. *)
10165 and generate_ruby_struct_list_code typ cols =
10166   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10167   pr "  size_t i;\n";
10168   pr "  for (i = 0; i < r->len; ++i) {\n";
10169   pr "    VALUE hv = rb_hash_new ();\n";
10170   List.iter (
10171     function
10172     | name, FString ->
10173         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10174     | name, FBuffer ->
10175         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
10176     | name, FUUID ->
10177         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10178     | name, (FBytes|FUInt64) ->
10179         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10180     | name, FInt64 ->
10181         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10182     | name, FUInt32 ->
10183         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10184     | name, FInt32 ->
10185         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10186     | name, FOptPercent ->
10187         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10188     | name, FChar -> (* XXX wrong? *)
10189         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10190   ) cols;
10191   pr "    rb_ary_push (rv, hv);\n";
10192   pr "  }\n";
10193   pr "  guestfs_free_%s_list (r);\n" typ;
10194   pr "  return rv;\n"
10195
10196 (* Generate Java bindings GuestFS.java file. *)
10197 and generate_java_java () =
10198   generate_header CStyle LGPLv2plus;
10199
10200   pr "\
10201 package com.redhat.et.libguestfs;
10202
10203 import java.util.HashMap;
10204 import com.redhat.et.libguestfs.LibGuestFSException;
10205 import com.redhat.et.libguestfs.PV;
10206 import com.redhat.et.libguestfs.VG;
10207 import com.redhat.et.libguestfs.LV;
10208 import com.redhat.et.libguestfs.Stat;
10209 import com.redhat.et.libguestfs.StatVFS;
10210 import com.redhat.et.libguestfs.IntBool;
10211 import com.redhat.et.libguestfs.Dirent;
10212
10213 /**
10214  * The GuestFS object is a libguestfs handle.
10215  *
10216  * @author rjones
10217  */
10218 public class GuestFS {
10219   // Load the native code.
10220   static {
10221     System.loadLibrary (\"guestfs_jni\");
10222   }
10223
10224   /**
10225    * The native guestfs_h pointer.
10226    */
10227   long g;
10228
10229   /**
10230    * Create a libguestfs handle.
10231    *
10232    * @throws LibGuestFSException
10233    */
10234   public GuestFS () throws LibGuestFSException
10235   {
10236     g = _create ();
10237   }
10238   private native long _create () throws LibGuestFSException;
10239
10240   /**
10241    * Close a libguestfs handle.
10242    *
10243    * You can also leave handles to be collected by the garbage
10244    * collector, but this method ensures that the resources used
10245    * by the handle are freed up immediately.  If you call any
10246    * other methods after closing the handle, you will get an
10247    * exception.
10248    *
10249    * @throws LibGuestFSException
10250    */
10251   public void close () throws LibGuestFSException
10252   {
10253     if (g != 0)
10254       _close (g);
10255     g = 0;
10256   }
10257   private native void _close (long g) throws LibGuestFSException;
10258
10259   public void finalize () throws LibGuestFSException
10260   {
10261     close ();
10262   }
10263
10264 ";
10265
10266   List.iter (
10267     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10268       if not (List.mem NotInDocs flags); then (
10269         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10270         let doc =
10271           if List.mem ProtocolLimitWarning flags then
10272             doc ^ "\n\n" ^ protocol_limit_warning
10273           else doc in
10274         let doc =
10275           if List.mem DangerWillRobinson flags then
10276             doc ^ "\n\n" ^ danger_will_robinson
10277           else doc in
10278         let doc =
10279           match deprecation_notice flags with
10280           | None -> doc
10281           | Some txt -> doc ^ "\n\n" ^ txt in
10282         let doc = pod2text ~width:60 name doc in
10283         let doc = List.map (            (* RHBZ#501883 *)
10284           function
10285           | "" -> "<p>"
10286           | nonempty -> nonempty
10287         ) doc in
10288         let doc = String.concat "\n   * " doc in
10289
10290         pr "  /**\n";
10291         pr "   * %s\n" shortdesc;
10292         pr "   * <p>\n";
10293         pr "   * %s\n" doc;
10294         pr "   * @throws LibGuestFSException\n";
10295         pr "   */\n";
10296         pr "  ";
10297       );
10298       generate_java_prototype ~public:true ~semicolon:false name style;
10299       pr "\n";
10300       pr "  {\n";
10301       pr "    if (g == 0)\n";
10302       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10303         name;
10304       pr "    ";
10305       if fst style <> RErr then pr "return ";
10306       pr "_%s " name;
10307       generate_java_call_args ~handle:"g" (snd style);
10308       pr ";\n";
10309       pr "  }\n";
10310       pr "  ";
10311       generate_java_prototype ~privat:true ~native:true name style;
10312       pr "\n";
10313       pr "\n";
10314   ) all_functions;
10315
10316   pr "}\n"
10317
10318 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10319 and generate_java_call_args ~handle args =
10320   pr "(%s" handle;
10321   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10322   pr ")"
10323
10324 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10325     ?(semicolon=true) name style =
10326   if privat then pr "private ";
10327   if public then pr "public ";
10328   if native then pr "native ";
10329
10330   (* return type *)
10331   (match fst style with
10332    | RErr -> pr "void ";
10333    | RInt _ -> pr "int ";
10334    | RInt64 _ -> pr "long ";
10335    | RBool _ -> pr "boolean ";
10336    | RConstString _ | RConstOptString _ | RString _
10337    | RBufferOut _ -> pr "String ";
10338    | RStringList _ -> pr "String[] ";
10339    | RStruct (_, typ) ->
10340        let name = java_name_of_struct typ in
10341        pr "%s " name;
10342    | RStructList (_, typ) ->
10343        let name = java_name_of_struct typ in
10344        pr "%s[] " name;
10345    | RHashtable _ -> pr "HashMap<String,String> ";
10346   );
10347
10348   if native then pr "_%s " name else pr "%s " name;
10349   pr "(";
10350   let needs_comma = ref false in
10351   if native then (
10352     pr "long g";
10353     needs_comma := true
10354   );
10355
10356   (* args *)
10357   List.iter (
10358     fun arg ->
10359       if !needs_comma then pr ", ";
10360       needs_comma := true;
10361
10362       match arg with
10363       | Pathname n
10364       | Device n | Dev_or_Path n
10365       | String n
10366       | OptString n
10367       | FileIn n
10368       | FileOut n ->
10369           pr "String %s" n
10370       | BufferIn n ->
10371           pr "byte[] %s" n
10372       | StringList n | DeviceList n ->
10373           pr "String[] %s" n
10374       | Bool n ->
10375           pr "boolean %s" n
10376       | Int n ->
10377           pr "int %s" n
10378       | Int64 n ->
10379           pr "long %s" n
10380   ) (snd style);
10381
10382   pr ")\n";
10383   pr "    throws LibGuestFSException";
10384   if semicolon then pr ";"
10385
10386 and generate_java_struct jtyp cols () =
10387   generate_header CStyle LGPLv2plus;
10388
10389   pr "\
10390 package com.redhat.et.libguestfs;
10391
10392 /**
10393  * Libguestfs %s structure.
10394  *
10395  * @author rjones
10396  * @see GuestFS
10397  */
10398 public class %s {
10399 " jtyp jtyp;
10400
10401   List.iter (
10402     function
10403     | name, FString
10404     | name, FUUID
10405     | name, FBuffer -> pr "  public String %s;\n" name
10406     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10407     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10408     | name, FChar -> pr "  public char %s;\n" name
10409     | name, FOptPercent ->
10410         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10411         pr "  public float %s;\n" name
10412   ) cols;
10413
10414   pr "}\n"
10415
10416 and generate_java_c () =
10417   generate_header CStyle LGPLv2plus;
10418
10419   pr "\
10420 #include <stdio.h>
10421 #include <stdlib.h>
10422 #include <string.h>
10423
10424 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10425 #include \"guestfs.h\"
10426
10427 /* Note that this function returns.  The exception is not thrown
10428  * until after the wrapper function returns.
10429  */
10430 static void
10431 throw_exception (JNIEnv *env, const char *msg)
10432 {
10433   jclass cl;
10434   cl = (*env)->FindClass (env,
10435                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10436   (*env)->ThrowNew (env, cl, msg);
10437 }
10438
10439 JNIEXPORT jlong JNICALL
10440 Java_com_redhat_et_libguestfs_GuestFS__1create
10441   (JNIEnv *env, jobject obj)
10442 {
10443   guestfs_h *g;
10444
10445   g = guestfs_create ();
10446   if (g == NULL) {
10447     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10448     return 0;
10449   }
10450   guestfs_set_error_handler (g, NULL, NULL);
10451   return (jlong) (long) g;
10452 }
10453
10454 JNIEXPORT void JNICALL
10455 Java_com_redhat_et_libguestfs_GuestFS__1close
10456   (JNIEnv *env, jobject obj, jlong jg)
10457 {
10458   guestfs_h *g = (guestfs_h *) (long) jg;
10459   guestfs_close (g);
10460 }
10461
10462 ";
10463
10464   List.iter (
10465     fun (name, style, _, _, _, _, _) ->
10466       pr "JNIEXPORT ";
10467       (match fst style with
10468        | RErr -> pr "void ";
10469        | RInt _ -> pr "jint ";
10470        | RInt64 _ -> pr "jlong ";
10471        | RBool _ -> pr "jboolean ";
10472        | RConstString _ | RConstOptString _ | RString _
10473        | RBufferOut _ -> pr "jstring ";
10474        | RStruct _ | RHashtable _ ->
10475            pr "jobject ";
10476        | RStringList _ | RStructList _ ->
10477            pr "jobjectArray ";
10478       );
10479       pr "JNICALL\n";
10480       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10481       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10482       pr "\n";
10483       pr "  (JNIEnv *env, jobject obj, jlong jg";
10484       List.iter (
10485         function
10486         | Pathname n
10487         | Device n | Dev_or_Path n
10488         | String n
10489         | OptString n
10490         | FileIn n
10491         | FileOut n ->
10492             pr ", jstring j%s" n
10493         | BufferIn n ->
10494             pr ", jbyteArray j%s" n
10495         | StringList n | DeviceList n ->
10496             pr ", jobjectArray j%s" n
10497         | Bool n ->
10498             pr ", jboolean j%s" n
10499         | Int n ->
10500             pr ", jint j%s" n
10501         | Int64 n ->
10502             pr ", jlong j%s" n
10503       ) (snd style);
10504       pr ")\n";
10505       pr "{\n";
10506       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10507       let error_code, no_ret =
10508         match fst style with
10509         | RErr -> pr "  int r;\n"; "-1", ""
10510         | RBool _
10511         | RInt _ -> pr "  int r;\n"; "-1", "0"
10512         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10513         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10514         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10515         | RString _ ->
10516             pr "  jstring jr;\n";
10517             pr "  char *r;\n"; "NULL", "NULL"
10518         | RStringList _ ->
10519             pr "  jobjectArray jr;\n";
10520             pr "  int r_len;\n";
10521             pr "  jclass cl;\n";
10522             pr "  jstring jstr;\n";
10523             pr "  char **r;\n"; "NULL", "NULL"
10524         | RStruct (_, typ) ->
10525             pr "  jobject jr;\n";
10526             pr "  jclass cl;\n";
10527             pr "  jfieldID fl;\n";
10528             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10529         | RStructList (_, typ) ->
10530             pr "  jobjectArray jr;\n";
10531             pr "  jclass cl;\n";
10532             pr "  jfieldID fl;\n";
10533             pr "  jobject jfl;\n";
10534             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10535         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10536         | RBufferOut _ ->
10537             pr "  jstring jr;\n";
10538             pr "  char *r;\n";
10539             pr "  size_t size;\n";
10540             "NULL", "NULL" in
10541       List.iter (
10542         function
10543         | Pathname n
10544         | Device n | Dev_or_Path n
10545         | String n
10546         | OptString n
10547         | FileIn n
10548         | FileOut n ->
10549             pr "  const char *%s;\n" n
10550         | BufferIn n ->
10551             pr "  jbyte *%s;\n" n;
10552             pr "  size_t %s_size;\n" n
10553         | StringList n | DeviceList n ->
10554             pr "  int %s_len;\n" n;
10555             pr "  const char **%s;\n" n
10556         | Bool n
10557         | Int n ->
10558             pr "  int %s;\n" n
10559         | Int64 n ->
10560             pr "  int64_t %s;\n" n
10561       ) (snd style);
10562
10563       let needs_i =
10564         (match fst style with
10565          | RStringList _ | RStructList _ -> true
10566          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10567          | RConstOptString _
10568          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10569           List.exists (function
10570                        | StringList _ -> true
10571                        | DeviceList _ -> true
10572                        | _ -> false) (snd style) in
10573       if needs_i then
10574         pr "  size_t i;\n";
10575
10576       pr "\n";
10577
10578       (* Get the parameters. *)
10579       List.iter (
10580         function
10581         | Pathname n
10582         | Device n | Dev_or_Path n
10583         | String n
10584         | FileIn n
10585         | FileOut n ->
10586             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10587         | OptString n ->
10588             (* This is completely undocumented, but Java null becomes
10589              * a NULL parameter.
10590              *)
10591             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10592         | BufferIn n ->
10593             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10594             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10595         | StringList n | DeviceList n ->
10596             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10597             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10598             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10599             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10600               n;
10601             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10602             pr "  }\n";
10603             pr "  %s[%s_len] = NULL;\n" n n;
10604         | Bool n
10605         | Int n
10606         | Int64 n ->
10607             pr "  %s = j%s;\n" n n
10608       ) (snd style);
10609
10610       (* Make the call. *)
10611       pr "  r = guestfs_%s " name;
10612       generate_c_call_args ~handle:"g" style;
10613       pr ";\n";
10614
10615       (* Release the parameters. *)
10616       List.iter (
10617         function
10618         | Pathname n
10619         | Device n | Dev_or_Path n
10620         | String n
10621         | FileIn n
10622         | FileOut n ->
10623             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10624         | OptString n ->
10625             pr "  if (j%s)\n" n;
10626             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10627         | BufferIn n ->
10628             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10629         | StringList n | DeviceList n ->
10630             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10631             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10632               n;
10633             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10634             pr "  }\n";
10635             pr "  free (%s);\n" n
10636         | Bool n
10637         | Int n
10638         | Int64 n -> ()
10639       ) (snd style);
10640
10641       (* Check for errors. *)
10642       pr "  if (r == %s) {\n" error_code;
10643       pr "    throw_exception (env, guestfs_last_error (g));\n";
10644       pr "    return %s;\n" no_ret;
10645       pr "  }\n";
10646
10647       (* Return value. *)
10648       (match fst style with
10649        | RErr -> ()
10650        | RInt _ -> pr "  return (jint) r;\n"
10651        | RBool _ -> pr "  return (jboolean) r;\n"
10652        | RInt64 _ -> pr "  return (jlong) r;\n"
10653        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10654        | RConstOptString _ ->
10655            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10656        | RString _ ->
10657            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10658            pr "  free (r);\n";
10659            pr "  return jr;\n"
10660        | RStringList _ ->
10661            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10662            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10663            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10664            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10665            pr "  for (i = 0; i < r_len; ++i) {\n";
10666            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10667            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10668            pr "    free (r[i]);\n";
10669            pr "  }\n";
10670            pr "  free (r);\n";
10671            pr "  return jr;\n"
10672        | RStruct (_, typ) ->
10673            let jtyp = java_name_of_struct typ in
10674            let cols = cols_of_struct typ in
10675            generate_java_struct_return typ jtyp cols
10676        | RStructList (_, typ) ->
10677            let jtyp = java_name_of_struct typ in
10678            let cols = cols_of_struct typ in
10679            generate_java_struct_list_return typ jtyp cols
10680        | RHashtable _ ->
10681            (* XXX *)
10682            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10683            pr "  return NULL;\n"
10684        | RBufferOut _ ->
10685            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10686            pr "  free (r);\n";
10687            pr "  return jr;\n"
10688       );
10689
10690       pr "}\n";
10691       pr "\n"
10692   ) all_functions
10693
10694 and generate_java_struct_return typ jtyp cols =
10695   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10696   pr "  jr = (*env)->AllocObject (env, cl);\n";
10697   List.iter (
10698     function
10699     | name, FString ->
10700         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10701         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10702     | name, FUUID ->
10703         pr "  {\n";
10704         pr "    char s[33];\n";
10705         pr "    memcpy (s, r->%s, 32);\n" name;
10706         pr "    s[32] = 0;\n";
10707         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10708         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10709         pr "  }\n";
10710     | name, FBuffer ->
10711         pr "  {\n";
10712         pr "    int len = r->%s_len;\n" name;
10713         pr "    char s[len+1];\n";
10714         pr "    memcpy (s, r->%s, len);\n" name;
10715         pr "    s[len] = 0;\n";
10716         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10717         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10718         pr "  }\n";
10719     | name, (FBytes|FUInt64|FInt64) ->
10720         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10721         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10722     | name, (FUInt32|FInt32) ->
10723         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10724         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10725     | name, FOptPercent ->
10726         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10727         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10728     | name, FChar ->
10729         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10730         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10731   ) cols;
10732   pr "  free (r);\n";
10733   pr "  return jr;\n"
10734
10735 and generate_java_struct_list_return typ jtyp cols =
10736   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10737   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10738   pr "  for (i = 0; i < r->len; ++i) {\n";
10739   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10740   List.iter (
10741     function
10742     | name, FString ->
10743         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10744         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10745     | name, FUUID ->
10746         pr "    {\n";
10747         pr "      char s[33];\n";
10748         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10749         pr "      s[32] = 0;\n";
10750         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10751         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10752         pr "    }\n";
10753     | name, FBuffer ->
10754         pr "    {\n";
10755         pr "      int len = r->val[i].%s_len;\n" name;
10756         pr "      char s[len+1];\n";
10757         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10758         pr "      s[len] = 0;\n";
10759         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10760         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10761         pr "    }\n";
10762     | name, (FBytes|FUInt64|FInt64) ->
10763         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10764         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10765     | name, (FUInt32|FInt32) ->
10766         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10767         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10768     | name, FOptPercent ->
10769         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10770         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10771     | name, FChar ->
10772         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10773         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10774   ) cols;
10775   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10776   pr "  }\n";
10777   pr "  guestfs_free_%s_list (r);\n" typ;
10778   pr "  return jr;\n"
10779
10780 and generate_java_makefile_inc () =
10781   generate_header HashStyle GPLv2plus;
10782
10783   pr "java_built_sources = \\\n";
10784   List.iter (
10785     fun (typ, jtyp) ->
10786         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10787   ) java_structs;
10788   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10789
10790 and generate_haskell_hs () =
10791   generate_header HaskellStyle LGPLv2plus;
10792
10793   (* XXX We only know how to generate partial FFI for Haskell
10794    * at the moment.  Please help out!
10795    *)
10796   let can_generate style =
10797     match style with
10798     | RErr, _
10799     | RInt _, _
10800     | RInt64 _, _ -> true
10801     | RBool _, _
10802     | RConstString _, _
10803     | RConstOptString _, _
10804     | RString _, _
10805     | RStringList _, _
10806     | RStruct _, _
10807     | RStructList _, _
10808     | RHashtable _, _
10809     | RBufferOut _, _ -> false in
10810
10811   pr "\
10812 {-# INCLUDE <guestfs.h> #-}
10813 {-# LANGUAGE ForeignFunctionInterface #-}
10814
10815 module Guestfs (
10816   create";
10817
10818   (* List out the names of the actions we want to export. *)
10819   List.iter (
10820     fun (name, style, _, _, _, _, _) ->
10821       if can_generate style then pr ",\n  %s" name
10822   ) all_functions;
10823
10824   pr "
10825   ) where
10826
10827 -- Unfortunately some symbols duplicate ones already present
10828 -- in Prelude.  We don't know which, so we hard-code a list
10829 -- here.
10830 import Prelude hiding (truncate)
10831
10832 import Foreign
10833 import Foreign.C
10834 import Foreign.C.Types
10835 import IO
10836 import Control.Exception
10837 import Data.Typeable
10838
10839 data GuestfsS = GuestfsS            -- represents the opaque C struct
10840 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10841 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10842
10843 -- XXX define properly later XXX
10844 data PV = PV
10845 data VG = VG
10846 data LV = LV
10847 data IntBool = IntBool
10848 data Stat = Stat
10849 data StatVFS = StatVFS
10850 data Hashtable = Hashtable
10851
10852 foreign import ccall unsafe \"guestfs_create\" c_create
10853   :: IO GuestfsP
10854 foreign import ccall unsafe \"&guestfs_close\" c_close
10855   :: FunPtr (GuestfsP -> IO ())
10856 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10857   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10858
10859 create :: IO GuestfsH
10860 create = do
10861   p <- c_create
10862   c_set_error_handler p nullPtr nullPtr
10863   h <- newForeignPtr c_close p
10864   return h
10865
10866 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10867   :: GuestfsP -> IO CString
10868
10869 -- last_error :: GuestfsH -> IO (Maybe String)
10870 -- last_error h = do
10871 --   str <- withForeignPtr h (\\p -> c_last_error p)
10872 --   maybePeek peekCString str
10873
10874 last_error :: GuestfsH -> IO (String)
10875 last_error h = do
10876   str <- withForeignPtr h (\\p -> c_last_error p)
10877   if (str == nullPtr)
10878     then return \"no error\"
10879     else peekCString str
10880
10881 ";
10882
10883   (* Generate wrappers for each foreign function. *)
10884   List.iter (
10885     fun (name, style, _, _, _, _, _) ->
10886       if can_generate style then (
10887         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10888         pr "  :: ";
10889         generate_haskell_prototype ~handle:"GuestfsP" style;
10890         pr "\n";
10891         pr "\n";
10892         pr "%s :: " name;
10893         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10894         pr "\n";
10895         pr "%s %s = do\n" name
10896           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10897         pr "  r <- ";
10898         (* Convert pointer arguments using with* functions. *)
10899         List.iter (
10900           function
10901           | FileIn n
10902           | FileOut n
10903           | Pathname n | Device n | Dev_or_Path n | String n ->
10904               pr "withCString %s $ \\%s -> " n n
10905           | BufferIn n ->
10906               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
10907           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10908           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10909           | Bool _ | Int _ | Int64 _ -> ()
10910         ) (snd style);
10911         (* Convert integer arguments. *)
10912         let args =
10913           List.map (
10914             function
10915             | Bool n -> sprintf "(fromBool %s)" n
10916             | Int n -> sprintf "(fromIntegral %s)" n
10917             | Int64 n -> sprintf "(fromIntegral %s)" n
10918             | FileIn n | FileOut n
10919             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10920             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
10921           ) (snd style) in
10922         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10923           (String.concat " " ("p" :: args));
10924         (match fst style with
10925          | RErr | RInt _ | RInt64 _ | RBool _ ->
10926              pr "  if (r == -1)\n";
10927              pr "    then do\n";
10928              pr "      err <- last_error h\n";
10929              pr "      fail err\n";
10930          | RConstString _ | RConstOptString _ | RString _
10931          | RStringList _ | RStruct _
10932          | RStructList _ | RHashtable _ | RBufferOut _ ->
10933              pr "  if (r == nullPtr)\n";
10934              pr "    then do\n";
10935              pr "      err <- last_error h\n";
10936              pr "      fail err\n";
10937         );
10938         (match fst style with
10939          | RErr ->
10940              pr "    else return ()\n"
10941          | RInt _ ->
10942              pr "    else return (fromIntegral r)\n"
10943          | RInt64 _ ->
10944              pr "    else return (fromIntegral r)\n"
10945          | RBool _ ->
10946              pr "    else return (toBool r)\n"
10947          | RConstString _
10948          | RConstOptString _
10949          | RString _
10950          | RStringList _
10951          | RStruct _
10952          | RStructList _
10953          | RHashtable _
10954          | RBufferOut _ ->
10955              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10956         );
10957         pr "\n";
10958       )
10959   ) all_functions
10960
10961 and generate_haskell_prototype ~handle ?(hs = false) style =
10962   pr "%s -> " handle;
10963   let string = if hs then "String" else "CString" in
10964   let int = if hs then "Int" else "CInt" in
10965   let bool = if hs then "Bool" else "CInt" in
10966   let int64 = if hs then "Integer" else "Int64" in
10967   List.iter (
10968     fun arg ->
10969       (match arg with
10970        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10971        | BufferIn _ ->
10972            if hs then pr "String"
10973            else pr "CString -> CInt"
10974        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10975        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10976        | Bool _ -> pr "%s" bool
10977        | Int _ -> pr "%s" int
10978        | Int64 _ -> pr "%s" int
10979        | FileIn _ -> pr "%s" string
10980        | FileOut _ -> pr "%s" string
10981       );
10982       pr " -> ";
10983   ) (snd style);
10984   pr "IO (";
10985   (match fst style with
10986    | RErr -> if not hs then pr "CInt"
10987    | RInt _ -> pr "%s" int
10988    | RInt64 _ -> pr "%s" int64
10989    | RBool _ -> pr "%s" bool
10990    | RConstString _ -> pr "%s" string
10991    | RConstOptString _ -> pr "Maybe %s" string
10992    | RString _ -> pr "%s" string
10993    | RStringList _ -> pr "[%s]" string
10994    | RStruct (_, typ) ->
10995        let name = java_name_of_struct typ in
10996        pr "%s" name
10997    | RStructList (_, typ) ->
10998        let name = java_name_of_struct typ in
10999        pr "[%s]" name
11000    | RHashtable _ -> pr "Hashtable"
11001    | RBufferOut _ -> pr "%s" string
11002   );
11003   pr ")"
11004
11005 and generate_csharp () =
11006   generate_header CPlusPlusStyle LGPLv2plus;
11007
11008   (* XXX Make this configurable by the C# assembly users. *)
11009   let library = "libguestfs.so.0" in
11010
11011   pr "\
11012 // These C# bindings are highly experimental at present.
11013 //
11014 // Firstly they only work on Linux (ie. Mono).  In order to get them
11015 // to work on Windows (ie. .Net) you would need to port the library
11016 // itself to Windows first.
11017 //
11018 // The second issue is that some calls are known to be incorrect and
11019 // can cause Mono to segfault.  Particularly: calls which pass or
11020 // return string[], or return any structure value.  This is because
11021 // we haven't worked out the correct way to do this from C#.
11022 //
11023 // The third issue is that when compiling you get a lot of warnings.
11024 // We are not sure whether the warnings are important or not.
11025 //
11026 // Fourthly we do not routinely build or test these bindings as part
11027 // of the make && make check cycle, which means that regressions might
11028 // go unnoticed.
11029 //
11030 // Suggestions and patches are welcome.
11031
11032 // To compile:
11033 //
11034 // gmcs Libguestfs.cs
11035 // mono Libguestfs.exe
11036 //
11037 // (You'll probably want to add a Test class / static main function
11038 // otherwise this won't do anything useful).
11039
11040 using System;
11041 using System.IO;
11042 using System.Runtime.InteropServices;
11043 using System.Runtime.Serialization;
11044 using System.Collections;
11045
11046 namespace Guestfs
11047 {
11048   class Error : System.ApplicationException
11049   {
11050     public Error (string message) : base (message) {}
11051     protected Error (SerializationInfo info, StreamingContext context) {}
11052   }
11053
11054   class Guestfs
11055   {
11056     IntPtr _handle;
11057
11058     [DllImport (\"%s\")]
11059     static extern IntPtr guestfs_create ();
11060
11061     public Guestfs ()
11062     {
11063       _handle = guestfs_create ();
11064       if (_handle == IntPtr.Zero)
11065         throw new Error (\"could not create guestfs handle\");
11066     }
11067
11068     [DllImport (\"%s\")]
11069     static extern void guestfs_close (IntPtr h);
11070
11071     ~Guestfs ()
11072     {
11073       guestfs_close (_handle);
11074     }
11075
11076     [DllImport (\"%s\")]
11077     static extern string guestfs_last_error (IntPtr h);
11078
11079 " library library library;
11080
11081   (* Generate C# structure bindings.  We prefix struct names with
11082    * underscore because C# cannot have conflicting struct names and
11083    * method names (eg. "class stat" and "stat").
11084    *)
11085   List.iter (
11086     fun (typ, cols) ->
11087       pr "    [StructLayout (LayoutKind.Sequential)]\n";
11088       pr "    public class _%s {\n" typ;
11089       List.iter (
11090         function
11091         | name, FChar -> pr "      char %s;\n" name
11092         | name, FString -> pr "      string %s;\n" name
11093         | name, FBuffer ->
11094             pr "      uint %s_len;\n" name;
11095             pr "      string %s;\n" name
11096         | name, FUUID ->
11097             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11098             pr "      string %s;\n" name
11099         | name, FUInt32 -> pr "      uint %s;\n" name
11100         | name, FInt32 -> pr "      int %s;\n" name
11101         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
11102         | name, FInt64 -> pr "      long %s;\n" name
11103         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
11104       ) cols;
11105       pr "    }\n";
11106       pr "\n"
11107   ) structs;
11108
11109   (* Generate C# function bindings. *)
11110   List.iter (
11111     fun (name, style, _, _, _, shortdesc, _) ->
11112       let rec csharp_return_type () =
11113         match fst style with
11114         | RErr -> "void"
11115         | RBool n -> "bool"
11116         | RInt n -> "int"
11117         | RInt64 n -> "long"
11118         | RConstString n
11119         | RConstOptString n
11120         | RString n
11121         | RBufferOut n -> "string"
11122         | RStruct (_,n) -> "_" ^ n
11123         | RHashtable n -> "Hashtable"
11124         | RStringList n -> "string[]"
11125         | RStructList (_,n) -> sprintf "_%s[]" n
11126
11127       and c_return_type () =
11128         match fst style with
11129         | RErr
11130         | RBool _
11131         | RInt _ -> "int"
11132         | RInt64 _ -> "long"
11133         | RConstString _
11134         | RConstOptString _
11135         | RString _
11136         | RBufferOut _ -> "string"
11137         | RStruct (_,n) -> "_" ^ n
11138         | RHashtable _
11139         | RStringList _ -> "string[]"
11140         | RStructList (_,n) -> sprintf "_%s[]" n
11141
11142       and c_error_comparison () =
11143         match fst style with
11144         | RErr
11145         | RBool _
11146         | RInt _
11147         | RInt64 _ -> "== -1"
11148         | RConstString _
11149         | RConstOptString _
11150         | RString _
11151         | RBufferOut _
11152         | RStruct (_,_)
11153         | RHashtable _
11154         | RStringList _
11155         | RStructList (_,_) -> "== null"
11156
11157       and generate_extern_prototype () =
11158         pr "    static extern %s guestfs_%s (IntPtr h"
11159           (c_return_type ()) name;
11160         List.iter (
11161           function
11162           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11163           | FileIn n | FileOut n
11164           | BufferIn n ->
11165               pr ", [In] string %s" n
11166           | StringList n | DeviceList n ->
11167               pr ", [In] string[] %s" n
11168           | Bool n ->
11169               pr ", bool %s" n
11170           | Int n ->
11171               pr ", int %s" n
11172           | Int64 n ->
11173               pr ", long %s" n
11174         ) (snd style);
11175         pr ");\n"
11176
11177       and generate_public_prototype () =
11178         pr "    public %s %s (" (csharp_return_type ()) name;
11179         let comma = ref false in
11180         let next () =
11181           if !comma then pr ", ";
11182           comma := true
11183         in
11184         List.iter (
11185           function
11186           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11187           | FileIn n | FileOut n
11188           | BufferIn n ->
11189               next (); pr "string %s" n
11190           | StringList n | DeviceList n ->
11191               next (); pr "string[] %s" n
11192           | Bool n ->
11193               next (); pr "bool %s" n
11194           | Int n ->
11195               next (); pr "int %s" n
11196           | Int64 n ->
11197               next (); pr "long %s" n
11198         ) (snd style);
11199         pr ")\n"
11200
11201       and generate_call () =
11202         pr "guestfs_%s (_handle" name;
11203         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11204         pr ");\n";
11205       in
11206
11207       pr "    [DllImport (\"%s\")]\n" library;
11208       generate_extern_prototype ();
11209       pr "\n";
11210       pr "    /// <summary>\n";
11211       pr "    /// %s\n" shortdesc;
11212       pr "    /// </summary>\n";
11213       generate_public_prototype ();
11214       pr "    {\n";
11215       pr "      %s r;\n" (c_return_type ());
11216       pr "      r = ";
11217       generate_call ();
11218       pr "      if (r %s)\n" (c_error_comparison ());
11219       pr "        throw new Error (guestfs_last_error (_handle));\n";
11220       (match fst style with
11221        | RErr -> ()
11222        | RBool _ ->
11223            pr "      return r != 0 ? true : false;\n"
11224        | RHashtable _ ->
11225            pr "      Hashtable rr = new Hashtable ();\n";
11226            pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
11227            pr "        rr.Add (r[i], r[i+1]);\n";
11228            pr "      return rr;\n"
11229        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11230        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11231        | RStructList _ ->
11232            pr "      return r;\n"
11233       );
11234       pr "    }\n";
11235       pr "\n";
11236   ) all_functions_sorted;
11237
11238   pr "  }
11239 }
11240 "
11241
11242 and generate_bindtests () =
11243   generate_header CStyle LGPLv2plus;
11244
11245   pr "\
11246 #include <stdio.h>
11247 #include <stdlib.h>
11248 #include <inttypes.h>
11249 #include <string.h>
11250
11251 #include \"guestfs.h\"
11252 #include \"guestfs-internal.h\"
11253 #include \"guestfs-internal-actions.h\"
11254 #include \"guestfs_protocol.h\"
11255
11256 #define error guestfs_error
11257 #define safe_calloc guestfs_safe_calloc
11258 #define safe_malloc guestfs_safe_malloc
11259
11260 static void
11261 print_strings (char *const *argv)
11262 {
11263   size_t argc;
11264
11265   printf (\"[\");
11266   for (argc = 0; argv[argc] != NULL; ++argc) {
11267     if (argc > 0) printf (\", \");
11268     printf (\"\\\"%%s\\\"\", argv[argc]);
11269   }
11270   printf (\"]\\n\");
11271 }
11272
11273 /* The test0 function prints its parameters to stdout. */
11274 ";
11275
11276   let test0, tests =
11277     match test_functions with
11278     | [] -> assert false
11279     | test0 :: tests -> test0, tests in
11280
11281   let () =
11282     let (name, style, _, _, _, _, _) = test0 in
11283     generate_prototype ~extern:false ~semicolon:false ~newline:true
11284       ~handle:"g" ~prefix:"guestfs__" name style;
11285     pr "{\n";
11286     List.iter (
11287       function
11288       | Pathname n
11289       | Device n | Dev_or_Path n
11290       | String n
11291       | FileIn n
11292       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11293       | BufferIn n ->
11294           pr "  {\n";
11295           pr "    size_t i;\n";
11296           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11297           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11298           pr "    printf (\"\\n\");\n";
11299           pr "  }\n";
11300       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11301       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11302       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11303       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11304       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11305     ) (snd style);
11306     pr "  /* Java changes stdout line buffering so we need this: */\n";
11307     pr "  fflush (stdout);\n";
11308     pr "  return 0;\n";
11309     pr "}\n";
11310     pr "\n" in
11311
11312   List.iter (
11313     fun (name, style, _, _, _, _, _) ->
11314       if String.sub name (String.length name - 3) 3 <> "err" then (
11315         pr "/* Test normal return. */\n";
11316         generate_prototype ~extern:false ~semicolon:false ~newline:true
11317           ~handle:"g" ~prefix:"guestfs__" name style;
11318         pr "{\n";
11319         (match fst style with
11320          | RErr ->
11321              pr "  return 0;\n"
11322          | RInt _ ->
11323              pr "  int r;\n";
11324              pr "  sscanf (val, \"%%d\", &r);\n";
11325              pr "  return r;\n"
11326          | RInt64 _ ->
11327              pr "  int64_t r;\n";
11328              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11329              pr "  return r;\n"
11330          | RBool _ ->
11331              pr "  return STREQ (val, \"true\");\n"
11332          | RConstString _
11333          | RConstOptString _ ->
11334              (* Can't return the input string here.  Return a static
11335               * string so we ensure we get a segfault if the caller
11336               * tries to free it.
11337               *)
11338              pr "  return \"static string\";\n"
11339          | RString _ ->
11340              pr "  return strdup (val);\n"
11341          | RStringList _ ->
11342              pr "  char **strs;\n";
11343              pr "  int n, i;\n";
11344              pr "  sscanf (val, \"%%d\", &n);\n";
11345              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11346              pr "  for (i = 0; i < n; ++i) {\n";
11347              pr "    strs[i] = safe_malloc (g, 16);\n";
11348              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11349              pr "  }\n";
11350              pr "  strs[n] = NULL;\n";
11351              pr "  return strs;\n"
11352          | RStruct (_, typ) ->
11353              pr "  struct guestfs_%s *r;\n" typ;
11354              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11355              pr "  return r;\n"
11356          | RStructList (_, typ) ->
11357              pr "  struct guestfs_%s_list *r;\n" typ;
11358              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11359              pr "  sscanf (val, \"%%d\", &r->len);\n";
11360              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11361              pr "  return r;\n"
11362          | RHashtable _ ->
11363              pr "  char **strs;\n";
11364              pr "  int n, i;\n";
11365              pr "  sscanf (val, \"%%d\", &n);\n";
11366              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11367              pr "  for (i = 0; i < n; ++i) {\n";
11368              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11369              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11370              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11371              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11372              pr "  }\n";
11373              pr "  strs[n*2] = NULL;\n";
11374              pr "  return strs;\n"
11375          | RBufferOut _ ->
11376              pr "  return strdup (val);\n"
11377         );
11378         pr "}\n";
11379         pr "\n"
11380       ) else (
11381         pr "/* Test error return. */\n";
11382         generate_prototype ~extern:false ~semicolon:false ~newline:true
11383           ~handle:"g" ~prefix:"guestfs__" name style;
11384         pr "{\n";
11385         pr "  error (g, \"error\");\n";
11386         (match fst style with
11387          | RErr | RInt _ | RInt64 _ | RBool _ ->
11388              pr "  return -1;\n"
11389          | RConstString _ | RConstOptString _
11390          | RString _ | RStringList _ | RStruct _
11391          | RStructList _
11392          | RHashtable _
11393          | RBufferOut _ ->
11394              pr "  return NULL;\n"
11395         );
11396         pr "}\n";
11397         pr "\n"
11398       )
11399   ) tests
11400
11401 and generate_ocaml_bindtests () =
11402   generate_header OCamlStyle GPLv2plus;
11403
11404   pr "\
11405 let () =
11406   let g = Guestfs.create () in
11407 ";
11408
11409   let mkargs args =
11410     String.concat " " (
11411       List.map (
11412         function
11413         | CallString s -> "\"" ^ s ^ "\""
11414         | CallOptString None -> "None"
11415         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11416         | CallStringList xs ->
11417             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11418         | CallInt i when i >= 0 -> string_of_int i
11419         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11420         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11421         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11422         | CallBool b -> string_of_bool b
11423         | CallBuffer s -> sprintf "%S" s
11424       ) args
11425     )
11426   in
11427
11428   generate_lang_bindtests (
11429     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11430   );
11431
11432   pr "print_endline \"EOF\"\n"
11433
11434 and generate_perl_bindtests () =
11435   pr "#!/usr/bin/perl -w\n";
11436   generate_header HashStyle GPLv2plus;
11437
11438   pr "\
11439 use strict;
11440
11441 use Sys::Guestfs;
11442
11443 my $g = Sys::Guestfs->new ();
11444 ";
11445
11446   let mkargs args =
11447     String.concat ", " (
11448       List.map (
11449         function
11450         | CallString s -> "\"" ^ s ^ "\""
11451         | CallOptString None -> "undef"
11452         | CallOptString (Some s) -> sprintf "\"%s\"" s
11453         | CallStringList xs ->
11454             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11455         | CallInt i -> string_of_int i
11456         | CallInt64 i -> Int64.to_string i
11457         | CallBool b -> if b then "1" else "0"
11458         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11459       ) args
11460     )
11461   in
11462
11463   generate_lang_bindtests (
11464     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11465   );
11466
11467   pr "print \"EOF\\n\"\n"
11468
11469 and generate_python_bindtests () =
11470   generate_header HashStyle GPLv2plus;
11471
11472   pr "\
11473 import guestfs
11474
11475 g = guestfs.GuestFS ()
11476 ";
11477
11478   let mkargs args =
11479     String.concat ", " (
11480       List.map (
11481         function
11482         | CallString s -> "\"" ^ s ^ "\""
11483         | CallOptString None -> "None"
11484         | CallOptString (Some s) -> sprintf "\"%s\"" s
11485         | CallStringList xs ->
11486             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11487         | CallInt i -> string_of_int i
11488         | CallInt64 i -> Int64.to_string i
11489         | CallBool b -> if b then "1" else "0"
11490         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11491       ) args
11492     )
11493   in
11494
11495   generate_lang_bindtests (
11496     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11497   );
11498
11499   pr "print \"EOF\"\n"
11500
11501 and generate_ruby_bindtests () =
11502   generate_header HashStyle GPLv2plus;
11503
11504   pr "\
11505 require 'guestfs'
11506
11507 g = Guestfs::create()
11508 ";
11509
11510   let mkargs args =
11511     String.concat ", " (
11512       List.map (
11513         function
11514         | CallString s -> "\"" ^ s ^ "\""
11515         | CallOptString None -> "nil"
11516         | CallOptString (Some s) -> sprintf "\"%s\"" s
11517         | CallStringList xs ->
11518             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11519         | CallInt i -> string_of_int i
11520         | CallInt64 i -> Int64.to_string i
11521         | CallBool b -> string_of_bool b
11522         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11523       ) args
11524     )
11525   in
11526
11527   generate_lang_bindtests (
11528     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11529   );
11530
11531   pr "print \"EOF\\n\"\n"
11532
11533 and generate_java_bindtests () =
11534   generate_header CStyle GPLv2plus;
11535
11536   pr "\
11537 import com.redhat.et.libguestfs.*;
11538
11539 public class Bindtests {
11540     public static void main (String[] argv)
11541     {
11542         try {
11543             GuestFS g = new GuestFS ();
11544 ";
11545
11546   let mkargs args =
11547     String.concat ", " (
11548       List.map (
11549         function
11550         | CallString s -> "\"" ^ s ^ "\""
11551         | CallOptString None -> "null"
11552         | CallOptString (Some s) -> sprintf "\"%s\"" s
11553         | CallStringList xs ->
11554             "new String[]{" ^
11555               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11556         | CallInt i -> string_of_int i
11557         | CallInt64 i -> Int64.to_string i
11558         | CallBool b -> string_of_bool b
11559         | CallBuffer s ->
11560             "new byte[] { " ^ String.concat "," (
11561               map_chars (fun c -> string_of_int (Char.code c)) s
11562             ) ^ " }"
11563       ) args
11564     )
11565   in
11566
11567   generate_lang_bindtests (
11568     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11569   );
11570
11571   pr "
11572             System.out.println (\"EOF\");
11573         }
11574         catch (Exception exn) {
11575             System.err.println (exn);
11576             System.exit (1);
11577         }
11578     }
11579 }
11580 "
11581
11582 and generate_haskell_bindtests () =
11583   generate_header HaskellStyle GPLv2plus;
11584
11585   pr "\
11586 module Bindtests where
11587 import qualified Guestfs
11588
11589 main = do
11590   g <- Guestfs.create
11591 ";
11592
11593   let mkargs args =
11594     String.concat " " (
11595       List.map (
11596         function
11597         | CallString s -> "\"" ^ s ^ "\""
11598         | CallOptString None -> "Nothing"
11599         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11600         | CallStringList xs ->
11601             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11602         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11603         | CallInt i -> string_of_int i
11604         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11605         | CallInt64 i -> Int64.to_string i
11606         | CallBool true -> "True"
11607         | CallBool false -> "False"
11608         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11609       ) args
11610     )
11611   in
11612
11613   generate_lang_bindtests (
11614     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11615   );
11616
11617   pr "  putStrLn \"EOF\"\n"
11618
11619 (* Language-independent bindings tests - we do it this way to
11620  * ensure there is parity in testing bindings across all languages.
11621  *)
11622 and generate_lang_bindtests call =
11623   call "test0" [CallString "abc"; CallOptString (Some "def");
11624                 CallStringList []; CallBool false;
11625                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11626                 CallBuffer "abc\000abc"];
11627   call "test0" [CallString "abc"; CallOptString None;
11628                 CallStringList []; CallBool false;
11629                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11630                 CallBuffer "abc\000abc"];
11631   call "test0" [CallString ""; CallOptString (Some "def");
11632                 CallStringList []; CallBool false;
11633                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11634                 CallBuffer "abc\000abc"];
11635   call "test0" [CallString ""; CallOptString (Some "");
11636                 CallStringList []; CallBool false;
11637                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11638                 CallBuffer "abc\000abc"];
11639   call "test0" [CallString "abc"; CallOptString (Some "def");
11640                 CallStringList ["1"]; CallBool false;
11641                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11642                 CallBuffer "abc\000abc"];
11643   call "test0" [CallString "abc"; CallOptString (Some "def");
11644                 CallStringList ["1"; "2"]; CallBool false;
11645                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11646                 CallBuffer "abc\000abc"];
11647   call "test0" [CallString "abc"; CallOptString (Some "def");
11648                 CallStringList ["1"]; CallBool true;
11649                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11650                 CallBuffer "abc\000abc"];
11651   call "test0" [CallString "abc"; CallOptString (Some "def");
11652                 CallStringList ["1"]; CallBool false;
11653                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11654                 CallBuffer "abc\000abc"];
11655   call "test0" [CallString "abc"; CallOptString (Some "def");
11656                 CallStringList ["1"]; CallBool false;
11657                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11658                 CallBuffer "abc\000abc"];
11659   call "test0" [CallString "abc"; CallOptString (Some "def");
11660                 CallStringList ["1"]; CallBool false;
11661                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11662                 CallBuffer "abc\000abc"];
11663   call "test0" [CallString "abc"; CallOptString (Some "def");
11664                 CallStringList ["1"]; CallBool false;
11665                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11666                 CallBuffer "abc\000abc"];
11667   call "test0" [CallString "abc"; CallOptString (Some "def");
11668                 CallStringList ["1"]; CallBool false;
11669                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11670                 CallBuffer "abc\000abc"];
11671   call "test0" [CallString "abc"; CallOptString (Some "def");
11672                 CallStringList ["1"]; CallBool false;
11673                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11674                 CallBuffer "abc\000abc"]
11675
11676 (* XXX Add here tests of the return and error functions. *)
11677
11678 (* Code to generator bindings for virt-inspector.  Currently only
11679  * implemented for OCaml code (for virt-p2v 2.0).
11680  *)
11681 let rng_input = "inspector/virt-inspector.rng"
11682
11683 (* Read the input file and parse it into internal structures.  This is
11684  * by no means a complete RELAX NG parser, but is just enough to be
11685  * able to parse the specific input file.
11686  *)
11687 type rng =
11688   | Element of string * rng list        (* <element name=name/> *)
11689   | Attribute of string * rng list        (* <attribute name=name/> *)
11690   | Interleave of rng list                (* <interleave/> *)
11691   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11692   | OneOrMore of rng                        (* <oneOrMore/> *)
11693   | Optional of rng                        (* <optional/> *)
11694   | Choice of string list                (* <choice><value/>*</choice> *)
11695   | Value of string                        (* <value>str</value> *)
11696   | Text                                (* <text/> *)
11697
11698 let rec string_of_rng = function
11699   | Element (name, xs) ->
11700       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11701   | Attribute (name, xs) ->
11702       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11703   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11704   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11705   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11706   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11707   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11708   | Value value -> "Value \"" ^ value ^ "\""
11709   | Text -> "Text"
11710
11711 and string_of_rng_list xs =
11712   String.concat ", " (List.map string_of_rng xs)
11713
11714 let rec parse_rng ?defines context = function
11715   | [] -> []
11716   | Xml.Element ("element", ["name", name], children) :: rest ->
11717       Element (name, parse_rng ?defines context children)
11718       :: parse_rng ?defines context rest
11719   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11720       Attribute (name, parse_rng ?defines context children)
11721       :: parse_rng ?defines context rest
11722   | Xml.Element ("interleave", [], children) :: rest ->
11723       Interleave (parse_rng ?defines context children)
11724       :: parse_rng ?defines context rest
11725   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11726       let rng = parse_rng ?defines context [child] in
11727       (match rng with
11728        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11729        | _ ->
11730            failwithf "%s: <zeroOrMore> contains more than one child element"
11731              context
11732       )
11733   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11734       let rng = parse_rng ?defines context [child] in
11735       (match rng with
11736        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11737        | _ ->
11738            failwithf "%s: <oneOrMore> contains more than one child element"
11739              context
11740       )
11741   | Xml.Element ("optional", [], [child]) :: rest ->
11742       let rng = parse_rng ?defines context [child] in
11743       (match rng with
11744        | [child] -> Optional child :: parse_rng ?defines context rest
11745        | _ ->
11746            failwithf "%s: <optional> contains more than one child element"
11747              context
11748       )
11749   | Xml.Element ("choice", [], children) :: rest ->
11750       let values = List.map (
11751         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11752         | _ ->
11753             failwithf "%s: can't handle anything except <value> in <choice>"
11754               context
11755       ) children in
11756       Choice values
11757       :: parse_rng ?defines context rest
11758   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11759       Value value :: parse_rng ?defines context rest
11760   | Xml.Element ("text", [], []) :: rest ->
11761       Text :: parse_rng ?defines context rest
11762   | Xml.Element ("ref", ["name", name], []) :: rest ->
11763       (* Look up the reference.  Because of limitations in this parser,
11764        * we can't handle arbitrarily nested <ref> yet.  You can only
11765        * use <ref> from inside <start>.
11766        *)
11767       (match defines with
11768        | None ->
11769            failwithf "%s: contains <ref>, but no refs are defined yet" context
11770        | Some map ->
11771            let rng = StringMap.find name map in
11772            rng @ parse_rng ?defines context rest
11773       )
11774   | x :: _ ->
11775       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11776
11777 let grammar =
11778   let xml = Xml.parse_file rng_input in
11779   match xml with
11780   | Xml.Element ("grammar", _,
11781                  Xml.Element ("start", _, gram) :: defines) ->
11782       (* The <define/> elements are referenced in the <start> section,
11783        * so build a map of those first.
11784        *)
11785       let defines = List.fold_left (
11786         fun map ->
11787           function Xml.Element ("define", ["name", name], defn) ->
11788             StringMap.add name defn map
11789           | _ ->
11790               failwithf "%s: expected <define name=name/>" rng_input
11791       ) StringMap.empty defines in
11792       let defines = StringMap.mapi parse_rng defines in
11793
11794       (* Parse the <start> clause, passing the defines. *)
11795       parse_rng ~defines "<start>" gram
11796   | _ ->
11797       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11798         rng_input
11799
11800 let name_of_field = function
11801   | Element (name, _) | Attribute (name, _)
11802   | ZeroOrMore (Element (name, _))
11803   | OneOrMore (Element (name, _))
11804   | Optional (Element (name, _)) -> name
11805   | Optional (Attribute (name, _)) -> name
11806   | Text -> (* an unnamed field in an element *)
11807       "data"
11808   | rng ->
11809       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11810
11811 (* At the moment this function only generates OCaml types.  However we
11812  * should parameterize it later so it can generate types/structs in a
11813  * variety of languages.
11814  *)
11815 let generate_types xs =
11816   (* A simple type is one that can be printed out directly, eg.
11817    * "string option".  A complex type is one which has a name and has
11818    * to be defined via another toplevel definition, eg. a struct.
11819    *
11820    * generate_type generates code for either simple or complex types.
11821    * In the simple case, it returns the string ("string option").  In
11822    * the complex case, it returns the name ("mountpoint").  In the
11823    * complex case it has to print out the definition before returning,
11824    * so it should only be called when we are at the beginning of a
11825    * new line (BOL context).
11826    *)
11827   let rec generate_type = function
11828     | Text ->                                (* string *)
11829         "string", true
11830     | Choice values ->                        (* [`val1|`val2|...] *)
11831         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11832     | ZeroOrMore rng ->                        (* <rng> list *)
11833         let t, is_simple = generate_type rng in
11834         t ^ " list (* 0 or more *)", is_simple
11835     | OneOrMore rng ->                        (* <rng> list *)
11836         let t, is_simple = generate_type rng in
11837         t ^ " list (* 1 or more *)", is_simple
11838                                         (* virt-inspector hack: bool *)
11839     | Optional (Attribute (name, [Value "1"])) ->
11840         "bool", true
11841     | Optional rng ->                        (* <rng> list *)
11842         let t, is_simple = generate_type rng in
11843         t ^ " option", is_simple
11844                                         (* type name = { fields ... } *)
11845     | Element (name, fields) when is_attrs_interleave fields ->
11846         generate_type_struct name (get_attrs_interleave fields)
11847     | Element (name, [field])                (* type name = field *)
11848     | Attribute (name, [field]) ->
11849         let t, is_simple = generate_type field in
11850         if is_simple then (t, true)
11851         else (
11852           pr "type %s = %s\n" name t;
11853           name, false
11854         )
11855     | Element (name, fields) ->              (* type name = { fields ... } *)
11856         generate_type_struct name fields
11857     | rng ->
11858         failwithf "generate_type failed at: %s" (string_of_rng rng)
11859
11860   and is_attrs_interleave = function
11861     | [Interleave _] -> true
11862     | Attribute _ :: fields -> is_attrs_interleave fields
11863     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11864     | _ -> false
11865
11866   and get_attrs_interleave = function
11867     | [Interleave fields] -> fields
11868     | ((Attribute _) as field) :: fields
11869     | ((Optional (Attribute _)) as field) :: fields ->
11870         field :: get_attrs_interleave fields
11871     | _ -> assert false
11872
11873   and generate_types xs =
11874     List.iter (fun x -> ignore (generate_type x)) xs
11875
11876   and generate_type_struct name fields =
11877     (* Calculate the types of the fields first.  We have to do this
11878      * before printing anything so we are still in BOL context.
11879      *)
11880     let types = List.map fst (List.map generate_type fields) in
11881
11882     (* Special case of a struct containing just a string and another
11883      * field.  Turn it into an assoc list.
11884      *)
11885     match types with
11886     | ["string"; other] ->
11887         let fname1, fname2 =
11888           match fields with
11889           | [f1; f2] -> name_of_field f1, name_of_field f2
11890           | _ -> assert false in
11891         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
11892         name, false
11893
11894     | types ->
11895         pr "type %s = {\n" name;
11896         List.iter (
11897           fun (field, ftype) ->
11898             let fname = name_of_field field in
11899             pr "  %s_%s : %s;\n" name fname ftype
11900         ) (List.combine fields types);
11901         pr "}\n";
11902         (* Return the name of this type, and
11903          * false because it's not a simple type.
11904          *)
11905         name, false
11906   in
11907
11908   generate_types xs
11909
11910 let generate_parsers xs =
11911   (* As for generate_type above, generate_parser makes a parser for
11912    * some type, and returns the name of the parser it has generated.
11913    * Because it (may) need to print something, it should always be
11914    * called in BOL context.
11915    *)
11916   let rec generate_parser = function
11917     | Text ->                                (* string *)
11918         "string_child_or_empty"
11919     | Choice values ->                        (* [`val1|`val2|...] *)
11920         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11921           (String.concat "|"
11922              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11923     | ZeroOrMore rng ->                        (* <rng> list *)
11924         let pa = generate_parser rng in
11925         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11926     | OneOrMore rng ->                        (* <rng> list *)
11927         let pa = generate_parser rng in
11928         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11929                                         (* virt-inspector hack: bool *)
11930     | Optional (Attribute (name, [Value "1"])) ->
11931         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11932     | Optional rng ->                        (* <rng> list *)
11933         let pa = generate_parser rng in
11934         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11935                                         (* type name = { fields ... } *)
11936     | Element (name, fields) when is_attrs_interleave fields ->
11937         generate_parser_struct name (get_attrs_interleave fields)
11938     | Element (name, [field]) ->        (* type name = field *)
11939         let pa = generate_parser field in
11940         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11941         pr "let %s =\n" parser_name;
11942         pr "  %s\n" pa;
11943         pr "let parse_%s = %s\n" name parser_name;
11944         parser_name
11945     | Attribute (name, [field]) ->
11946         let pa = generate_parser field in
11947         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11948         pr "let %s =\n" parser_name;
11949         pr "  %s\n" pa;
11950         pr "let parse_%s = %s\n" name parser_name;
11951         parser_name
11952     | Element (name, fields) ->              (* type name = { fields ... } *)
11953         generate_parser_struct name ([], fields)
11954     | rng ->
11955         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11956
11957   and is_attrs_interleave = function
11958     | [Interleave _] -> true
11959     | Attribute _ :: fields -> is_attrs_interleave fields
11960     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11961     | _ -> false
11962
11963   and get_attrs_interleave = function
11964     | [Interleave fields] -> [], fields
11965     | ((Attribute _) as field) :: fields
11966     | ((Optional (Attribute _)) as field) :: fields ->
11967         let attrs, interleaves = get_attrs_interleave fields in
11968         (field :: attrs), interleaves
11969     | _ -> assert false
11970
11971   and generate_parsers xs =
11972     List.iter (fun x -> ignore (generate_parser x)) xs
11973
11974   and generate_parser_struct name (attrs, interleaves) =
11975     (* Generate parsers for the fields first.  We have to do this
11976      * before printing anything so we are still in BOL context.
11977      *)
11978     let fields = attrs @ interleaves in
11979     let pas = List.map generate_parser fields in
11980
11981     (* Generate an intermediate tuple from all the fields first.
11982      * If the type is just a string + another field, then we will
11983      * return this directly, otherwise it is turned into a record.
11984      *
11985      * RELAX NG note: This code treats <interleave> and plain lists of
11986      * fields the same.  In other words, it doesn't bother enforcing
11987      * any ordering of fields in the XML.
11988      *)
11989     pr "let parse_%s x =\n" name;
11990     pr "  let t = (\n    ";
11991     let comma = ref false in
11992     List.iter (
11993       fun x ->
11994         if !comma then pr ",\n    ";
11995         comma := true;
11996         match x with
11997         | Optional (Attribute (fname, [field])), pa ->
11998             pr "%s x" pa
11999         | Optional (Element (fname, [field])), pa ->
12000             pr "%s (optional_child %S x)" pa fname
12001         | Attribute (fname, [Text]), _ ->
12002             pr "attribute %S x" fname
12003         | (ZeroOrMore _ | OneOrMore _), pa ->
12004             pr "%s x" pa
12005         | Text, pa ->
12006             pr "%s x" pa
12007         | (field, pa) ->
12008             let fname = name_of_field field in
12009             pr "%s (child %S x)" pa fname
12010     ) (List.combine fields pas);
12011     pr "\n  ) in\n";
12012
12013     (match fields with
12014      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
12015          pr "  t\n"
12016
12017      | _ ->
12018          pr "  (Obj.magic t : %s)\n" name
12019 (*
12020          List.iter (
12021            function
12022            | (Optional (Attribute (fname, [field])), pa) ->
12023                pr "  %s_%s =\n" name fname;
12024                pr "    %s x;\n" pa
12025            | (Optional (Element (fname, [field])), pa) ->
12026                pr "  %s_%s =\n" name fname;
12027                pr "    (let x = optional_child %S x in\n" fname;
12028                pr "     %s x);\n" pa
12029            | (field, pa) ->
12030                let fname = name_of_field field in
12031                pr "  %s_%s =\n" name fname;
12032                pr "    (let x = child %S x in\n" fname;
12033                pr "     %s x);\n" pa
12034          ) (List.combine fields pas);
12035          pr "}\n"
12036 *)
12037     );
12038     sprintf "parse_%s" name
12039   in
12040
12041   generate_parsers xs
12042
12043 (* Generate ocaml/guestfs_inspector.mli. *)
12044 let generate_ocaml_inspector_mli () =
12045   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12046
12047   pr "\
12048 (** This is an OCaml language binding to the external [virt-inspector]
12049     program.
12050
12051     For more information, please read the man page [virt-inspector(1)].
12052 *)
12053
12054 ";
12055
12056   generate_types grammar;
12057   pr "(** The nested information returned from the {!inspect} function. *)\n";
12058   pr "\n";
12059
12060   pr "\
12061 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12062 (** To inspect a libvirt domain called [name], pass a singleton
12063     list: [inspect [name]].  When using libvirt only, you may
12064     optionally pass a libvirt URI using [inspect ~connect:uri ...].
12065
12066     To inspect a disk image or images, pass a list of the filenames
12067     of the disk images: [inspect filenames]
12068
12069     This function inspects the given guest or disk images and
12070     returns a list of operating system(s) found and a large amount
12071     of information about them.  In the vast majority of cases,
12072     a virtual machine only contains a single operating system.
12073
12074     If the optional [~xml] parameter is given, then this function
12075     skips running the external virt-inspector program and just
12076     parses the given XML directly (which is expected to be XML
12077     produced from a previous run of virt-inspector).  The list of
12078     names and connect URI are ignored in this case.
12079
12080     This function can throw a wide variety of exceptions, for example
12081     if the external virt-inspector program cannot be found, or if
12082     it doesn't generate valid XML.
12083 *)
12084 "
12085
12086 (* Generate ocaml/guestfs_inspector.ml. *)
12087 let generate_ocaml_inspector_ml () =
12088   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12089
12090   pr "open Unix\n";
12091   pr "\n";
12092
12093   generate_types grammar;
12094   pr "\n";
12095
12096   pr "\
12097 (* Misc functions which are used by the parser code below. *)
12098 let first_child = function
12099   | Xml.Element (_, _, c::_) -> c
12100   | Xml.Element (name, _, []) ->
12101       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12102   | Xml.PCData str ->
12103       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12104
12105 let string_child_or_empty = function
12106   | Xml.Element (_, _, [Xml.PCData s]) -> s
12107   | Xml.Element (_, _, []) -> \"\"
12108   | Xml.Element (x, _, _) ->
12109       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12110                 x ^ \" instead\")
12111   | Xml.PCData str ->
12112       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12113
12114 let optional_child name xml =
12115   let children = Xml.children xml in
12116   try
12117     Some (List.find (function
12118                      | Xml.Element (n, _, _) when n = name -> true
12119                      | _ -> false) children)
12120   with
12121     Not_found -> None
12122
12123 let child name xml =
12124   match optional_child name xml with
12125   | Some c -> c
12126   | None ->
12127       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12128
12129 let attribute name xml =
12130   try Xml.attrib xml name
12131   with Xml.No_attribute _ ->
12132     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12133
12134 ";
12135
12136   generate_parsers grammar;
12137   pr "\n";
12138
12139   pr "\
12140 (* Run external virt-inspector, then use parser to parse the XML. *)
12141 let inspect ?connect ?xml names =
12142   let xml =
12143     match xml with
12144     | None ->
12145         if names = [] then invalid_arg \"inspect: no names given\";
12146         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12147           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12148           names in
12149         let cmd = List.map Filename.quote cmd in
12150         let cmd = String.concat \" \" cmd in
12151         let chan = open_process_in cmd in
12152         let xml = Xml.parse_in chan in
12153         (match close_process_in chan with
12154          | WEXITED 0 -> ()
12155          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12156          | WSIGNALED i | WSTOPPED i ->
12157              failwith (\"external virt-inspector command died or stopped on sig \" ^
12158                        string_of_int i)
12159         );
12160         xml
12161     | Some doc ->
12162         Xml.parse_string doc in
12163   parse_operatingsystems xml
12164 "
12165
12166 and generate_max_proc_nr () =
12167   pr "%d\n" max_proc_nr
12168
12169 let output_to filename k =
12170   let filename_new = filename ^ ".new" in
12171   chan := open_out filename_new;
12172   k ();
12173   close_out !chan;
12174   chan := Pervasives.stdout;
12175
12176   (* Is the new file different from the current file? *)
12177   if Sys.file_exists filename && files_equal filename filename_new then
12178     unlink filename_new                 (* same, so skip it *)
12179   else (
12180     (* different, overwrite old one *)
12181     (try chmod filename 0o644 with Unix_error _ -> ());
12182     rename filename_new filename;
12183     chmod filename 0o444;
12184     printf "written %s\n%!" filename;
12185   )
12186
12187 let perror msg = function
12188   | Unix_error (err, _, _) ->
12189       eprintf "%s: %s\n" msg (error_message err)
12190   | exn ->
12191       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12192
12193 (* Main program. *)
12194 let () =
12195   let lock_fd =
12196     try openfile "HACKING" [O_RDWR] 0
12197     with
12198     | Unix_error (ENOENT, _, _) ->
12199         eprintf "\
12200 You are probably running this from the wrong directory.
12201 Run it from the top source directory using the command
12202   src/generator.ml
12203 ";
12204         exit 1
12205     | exn ->
12206         perror "open: HACKING" exn;
12207         exit 1 in
12208
12209   (* Acquire a lock so parallel builds won't try to run the generator
12210    * twice at the same time.  Subsequent builds will wait for the first
12211    * one to finish.  Note the lock is released implicitly when the
12212    * program exits.
12213    *)
12214   (try lockf lock_fd F_LOCK 1
12215    with exn ->
12216      perror "lock: HACKING" exn;
12217      exit 1);
12218
12219   check_functions ();
12220
12221   output_to "src/guestfs_protocol.x" generate_xdr;
12222   output_to "src/guestfs-structs.h" generate_structs_h;
12223   output_to "src/guestfs-actions.h" generate_actions_h;
12224   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12225   output_to "src/guestfs-actions.c" generate_client_actions;
12226   output_to "src/guestfs-bindtests.c" generate_bindtests;
12227   output_to "src/guestfs-structs.pod" generate_structs_pod;
12228   output_to "src/guestfs-actions.pod" generate_actions_pod;
12229   output_to "src/guestfs-availability.pod" generate_availability_pod;
12230   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12231   output_to "src/libguestfs.syms" generate_linker_script;
12232   output_to "daemon/actions.h" generate_daemon_actions_h;
12233   output_to "daemon/stubs.c" generate_daemon_actions;
12234   output_to "daemon/names.c" generate_daemon_names;
12235   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12236   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12237   output_to "capitests/tests.c" generate_tests;
12238   output_to "fish/cmds.c" generate_fish_cmds;
12239   output_to "fish/completion.c" generate_fish_completion;
12240   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12241   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12242   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12243   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12244   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12245   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12246   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12247   output_to "perl/Guestfs.xs" generate_perl_xs;
12248   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12249   output_to "perl/bindtests.pl" generate_perl_bindtests;
12250   output_to "python/guestfs-py.c" generate_python_c;
12251   output_to "python/guestfs.py" generate_python_py;
12252   output_to "python/bindtests.py" generate_python_bindtests;
12253   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12254   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12255   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12256
12257   List.iter (
12258     fun (typ, jtyp) ->
12259       let cols = cols_of_struct typ in
12260       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12261       output_to filename (generate_java_struct jtyp cols);
12262   ) java_structs;
12263
12264   output_to "java/Makefile.inc" generate_java_makefile_inc;
12265   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12266   output_to "java/Bindtests.java" generate_java_bindtests;
12267   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12268   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12269   output_to "csharp/Libguestfs.cs" generate_csharp;
12270
12271   (* Always generate this file last, and unconditionally.  It's used
12272    * by the Makefile to know when we must re-run the generator.
12273    *)
12274   let chan = open_out "src/stamp-generator" in
12275   fprintf chan "1\n";
12276   close_out chan;
12277
12278   printf "generated %d lines of code\n" !lines