955569818d3505f99d3197ef1f58237763c3119e
[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,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 Note that this call checks for the existence of C<filename>.  This
562 stops you from specifying other types of drive which are supported
563 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
564 the general C<guestfs_config> call instead.");
565
566   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
567    [],
568    "add qemu parameters",
569    "\
570 This can be used to add arbitrary qemu command line parameters
571 of the form C<-param value>.  Actually it's not quite arbitrary - we
572 prevent you from setting some parameters which would interfere with
573 parameters that we use.
574
575 The first character of C<param> string must be a C<-> (dash).
576
577 C<value> can be NULL.");
578
579   ("set_qemu", (RErr, [OptString "qemu"]), -1, [FishAlias "qemu"],
580    [],
581    "set the qemu binary",
582    "\
583 Set the qemu binary that we will use.
584
585 The default is chosen when the library was compiled by the
586 configure script.
587
588 You can also override this by setting the C<LIBGUESTFS_QEMU>
589 environment variable.
590
591 Setting C<qemu> to C<NULL> restores the default qemu binary.
592
593 Note that you should call this function as early as possible
594 after creating the handle.  This is because some pre-launch
595 operations depend on testing qemu features (by running C<qemu -help>).
596 If the qemu binary changes, we don't retest features, and
597 so you might see inconsistent results.  Using the environment
598 variable C<LIBGUESTFS_QEMU> is safest of all since that picks
599 the qemu binary at the same time as the handle is created.");
600
601   ("get_qemu", (RConstString "qemu", []), -1, [],
602    [InitNone, Always, TestRun (
603       [["get_qemu"]])],
604    "get the qemu binary",
605    "\
606 Return the current qemu binary.
607
608 This is always non-NULL.  If it wasn't set already, then this will
609 return the default qemu binary name.");
610
611   ("set_path", (RErr, [OptString "searchpath"]), -1, [FishAlias "path"],
612    [],
613    "set the search path",
614    "\
615 Set the path that libguestfs searches for kernel and initrd.img.
616
617 The default is C<$libdir/guestfs> unless overridden by setting
618 C<LIBGUESTFS_PATH> environment variable.
619
620 Setting C<path> to C<NULL> restores the default path.");
621
622   ("get_path", (RConstString "path", []), -1, [],
623    [InitNone, Always, TestRun (
624       [["get_path"]])],
625    "get the search path",
626    "\
627 Return the current search path.
628
629 This is always non-NULL.  If it wasn't set already, then this will
630 return the default path.");
631
632   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
633    [],
634    "add options to kernel command line",
635    "\
636 This function is used to add additional options to the
637 guest kernel command line.
638
639 The default is C<NULL> unless overridden by setting
640 C<LIBGUESTFS_APPEND> environment variable.
641
642 Setting C<append> to C<NULL> means I<no> additional options
643 are passed (libguestfs always adds a few of its own).");
644
645   ("get_append", (RConstOptString "append", []), -1, [],
646    (* This cannot be tested with the current framework.  The
647     * function can return NULL in normal operations, which the
648     * test framework interprets as an error.
649     *)
650    [],
651    "get the additional kernel options",
652    "\
653 Return the additional kernel options which are added to the
654 guest kernel command line.
655
656 If C<NULL> then no options are added.");
657
658   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
659    [],
660    "set autosync mode",
661    "\
662 If C<autosync> is true, this enables autosync.  Libguestfs will make a
663 best effort attempt to run C<guestfs_umount_all> followed by
664 C<guestfs_sync> when the handle is closed
665 (also if the program exits without closing handles).
666
667 This is disabled by default (except in guestfish where it is
668 enabled by default).");
669
670   ("get_autosync", (RBool "autosync", []), -1, [],
671    [InitNone, Always, TestRun (
672       [["get_autosync"]])],
673    "get autosync mode",
674    "\
675 Get the autosync flag.");
676
677   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
678    [],
679    "set verbose mode",
680    "\
681 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
682
683 Verbose messages are disabled unless the environment variable
684 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
685
686   ("get_verbose", (RBool "verbose", []), -1, [],
687    [],
688    "get verbose mode",
689    "\
690 This returns the verbose messages flag.");
691
692   ("is_ready", (RBool "ready", []), -1, [],
693    [InitNone, Always, TestOutputTrue (
694       [["is_ready"]])],
695    "is ready to accept commands",
696    "\
697 This returns true iff this handle is ready to accept commands
698 (in the C<READY> state).
699
700 For more information on states, see L<guestfs(3)>.");
701
702   ("is_config", (RBool "config", []), -1, [],
703    [InitNone, Always, TestOutputFalse (
704       [["is_config"]])],
705    "is in configuration state",
706    "\
707 This returns true iff this handle is being configured
708 (in the C<CONFIG> state).
709
710 For more information on states, see L<guestfs(3)>.");
711
712   ("is_launching", (RBool "launching", []), -1, [],
713    [InitNone, Always, TestOutputFalse (
714       [["is_launching"]])],
715    "is launching subprocess",
716    "\
717 This returns true iff this handle is launching the subprocess
718 (in the C<LAUNCHING> state).
719
720 For more information on states, see L<guestfs(3)>.");
721
722   ("is_busy", (RBool "busy", []), -1, [],
723    [InitNone, Always, TestOutputFalse (
724       [["is_busy"]])],
725    "is busy processing a command",
726    "\
727 This returns true iff this handle is busy processing a command
728 (in the C<BUSY> state).
729
730 For more information on states, see L<guestfs(3)>.");
731
732   ("get_state", (RInt "state", []), -1, [],
733    [],
734    "get the current state",
735    "\
736 This returns the current state as an opaque integer.  This is
737 only useful for printing debug and internal error messages.
738
739 For more information on states, see L<guestfs(3)>.");
740
741   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
742    [InitNone, Always, TestOutputInt (
743       [["set_memsize"; "500"];
744        ["get_memsize"]], 500)],
745    "set memory allocated to the qemu subprocess",
746    "\
747 This sets the memory size in megabytes allocated to the
748 qemu subprocess.  This only has any effect if called before
749 C<guestfs_launch>.
750
751 You can also change this by setting the environment
752 variable C<LIBGUESTFS_MEMSIZE> before the handle is
753 created.
754
755 For more information on the architecture of libguestfs,
756 see L<guestfs(3)>.");
757
758   ("get_memsize", (RInt "memsize", []), -1, [],
759    [InitNone, Always, TestOutputIntOp (
760       [["get_memsize"]], ">=", 256)],
761    "get memory allocated to the qemu subprocess",
762    "\
763 This gets the memory size in megabytes allocated to the
764 qemu subprocess.
765
766 If C<guestfs_set_memsize> was not called
767 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
768 then this returns the compiled-in default value for memsize.
769
770 For more information on the architecture of libguestfs,
771 see L<guestfs(3)>.");
772
773   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
774    [InitNone, Always, TestOutputIntOp (
775       [["get_pid"]], ">=", 1)],
776    "get PID of qemu subprocess",
777    "\
778 Return the process ID of the qemu subprocess.  If there is no
779 qemu subprocess, then this will return an error.
780
781 This is an internal call used for debugging and testing.");
782
783   ("version", (RStruct ("version", "version"), []), -1, [],
784    [InitNone, Always, TestOutputStruct (
785       [["version"]], [CompareWithInt ("major", 1)])],
786    "get the library version number",
787    "\
788 Return the libguestfs version number that the program is linked
789 against.
790
791 Note that because of dynamic linking this is not necessarily
792 the version of libguestfs that you compiled against.  You can
793 compile the program, and then at runtime dynamically link
794 against a completely different C<libguestfs.so> library.
795
796 This call was added in version C<1.0.58>.  In previous
797 versions of libguestfs there was no way to get the version
798 number.  From C code you can use dynamic linker functions
799 to find out if this symbol exists (if it doesn't, then
800 it's an earlier version).
801
802 The call returns a structure with four elements.  The first
803 three (C<major>, C<minor> and C<release>) are numbers and
804 correspond to the usual version triplet.  The fourth element
805 (C<extra>) is a string and is normally empty, but may be
806 used for distro-specific information.
807
808 To construct the original version string:
809 C<$major.$minor.$release$extra>
810
811 See also: L<guestfs(3)/LIBGUESTFS VERSION NUMBERS>.
812
813 I<Note:> Don't use this call to test for availability
814 of features.  In enterprise distributions we backport
815 features from later versions into earlier versions,
816 making this an unreliable way to test for features.
817 Use C<guestfs_available> instead.");
818
819   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
820    [InitNone, Always, TestOutputTrue (
821       [["set_selinux"; "true"];
822        ["get_selinux"]])],
823    "set SELinux enabled or disabled at appliance boot",
824    "\
825 This sets the selinux flag that is passed to the appliance
826 at boot time.  The default is C<selinux=0> (disabled).
827
828 Note that if SELinux is enabled, it is always in
829 Permissive mode (C<enforcing=0>).
830
831 For more information on the architecture of libguestfs,
832 see L<guestfs(3)>.");
833
834   ("get_selinux", (RBool "selinux", []), -1, [],
835    [],
836    "get SELinux enabled flag",
837    "\
838 This returns the current setting of the selinux flag which
839 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
840
841 For more information on the architecture of libguestfs,
842 see L<guestfs(3)>.");
843
844   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
845    [InitNone, Always, TestOutputFalse (
846       [["set_trace"; "false"];
847        ["get_trace"]])],
848    "enable or disable command traces",
849    "\
850 If the command trace flag is set to 1, then commands are
851 printed on stdout before they are executed in a format
852 which is very similar to the one used by guestfish.  In
853 other words, you can run a program with this enabled, and
854 you will get out a script which you can feed to guestfish
855 to perform the same set of actions.
856
857 If you want to trace C API calls into libguestfs (and
858 other libraries) then possibly a better way is to use
859 the external ltrace(1) command.
860
861 Command traces are disabled unless the environment variable
862 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
863
864   ("get_trace", (RBool "trace", []), -1, [],
865    [],
866    "get command trace enabled flag",
867    "\
868 Return the command trace flag.");
869
870   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
871    [InitNone, Always, TestOutputFalse (
872       [["set_direct"; "false"];
873        ["get_direct"]])],
874    "enable or disable direct appliance mode",
875    "\
876 If the direct appliance mode flag is enabled, then stdin and
877 stdout are passed directly through to the appliance once it
878 is launched.
879
880 One consequence of this is that log messages aren't caught
881 by the library and handled by C<guestfs_set_log_message_callback>,
882 but go straight to stdout.
883
884 You probably don't want to use this unless you know what you
885 are doing.
886
887 The default is disabled.");
888
889   ("get_direct", (RBool "direct", []), -1, [],
890    [],
891    "get direct appliance mode flag",
892    "\
893 Return the direct appliance mode flag.");
894
895   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
896    [InitNone, Always, TestOutputTrue (
897       [["set_recovery_proc"; "true"];
898        ["get_recovery_proc"]])],
899    "enable or disable the recovery process",
900    "\
901 If this is called with the parameter C<false> then
902 C<guestfs_launch> does not create a recovery process.  The
903 purpose of the recovery process is to stop runaway qemu
904 processes in the case where the main program aborts abruptly.
905
906 This only has any effect if called before C<guestfs_launch>,
907 and the default is true.
908
909 About the only time when you would want to disable this is
910 if the main process will fork itself into the background
911 (\"daemonize\" itself).  In this case the recovery process
912 thinks that the main program has disappeared and so kills
913 qemu, which is not very helpful.");
914
915   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
916    [],
917    "get recovery process enabled flag",
918    "\
919 Return the recovery process enabled flag.");
920
921   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
922    [],
923    "add a drive specifying the QEMU block emulation to use",
924    "\
925 This is the same as C<guestfs_add_drive> but it allows you
926 to specify the QEMU interface emulation to use at run time.");
927
928   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
929    [],
930    "add a drive read-only specifying the QEMU block emulation to use",
931    "\
932 This is the same as C<guestfs_add_drive_ro> but it allows you
933 to specify the QEMU interface emulation to use at run time.");
934
935 ]
936
937 (* daemon_functions are any functions which cause some action
938  * to take place in the daemon.
939  *)
940
941 let daemon_functions = [
942   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
943    [InitEmpty, Always, TestOutput (
944       [["part_disk"; "/dev/sda"; "mbr"];
945        ["mkfs"; "ext2"; "/dev/sda1"];
946        ["mount"; "/dev/sda1"; "/"];
947        ["write"; "/new"; "new file contents"];
948        ["cat"; "/new"]], "new file contents")],
949    "mount a guest disk at a position in the filesystem",
950    "\
951 Mount a guest disk at a position in the filesystem.  Block devices
952 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
953 the guest.  If those block devices contain partitions, they will have
954 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
955 names can be used.
956
957 The rules are the same as for L<mount(2)>:  A filesystem must
958 first be mounted on C</> before others can be mounted.  Other
959 filesystems can only be mounted on directories which already
960 exist.
961
962 The mounted filesystem is writable, if we have sufficient permissions
963 on the underlying device.
964
965 B<Important note:>
966 When you use this call, the filesystem options C<sync> and C<noatime>
967 are set implicitly.  This was originally done because we thought it
968 would improve reliability, but it turns out that I<-o sync> has a
969 very large negative performance impact and negligible effect on
970 reliability.  Therefore we recommend that you avoid using
971 C<guestfs_mount> in any code that needs performance, and instead
972 use C<guestfs_mount_options> (use an empty string for the first
973 parameter if you don't want any options).");
974
975   ("sync", (RErr, []), 2, [],
976    [ InitEmpty, Always, TestRun [["sync"]]],
977    "sync disks, writes are flushed through to the disk image",
978    "\
979 This syncs the disk, so that any writes are flushed through to the
980 underlying disk image.
981
982 You should always call this if you have modified a disk image, before
983 closing the handle.");
984
985   ("touch", (RErr, [Pathname "path"]), 3, [],
986    [InitBasicFS, Always, TestOutputTrue (
987       [["touch"; "/new"];
988        ["exists"; "/new"]])],
989    "update file timestamps or create a new file",
990    "\
991 Touch acts like the L<touch(1)> command.  It can be used to
992 update the timestamps on a file, or, if the file does not exist,
993 to create a new zero-length file.
994
995 This command only works on regular files, and will fail on other
996 file types such as directories, symbolic links, block special etc.");
997
998   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
999    [InitISOFS, Always, TestOutput (
1000       [["cat"; "/known-2"]], "abcdef\n")],
1001    "list the contents of a file",
1002    "\
1003 Return the contents of the file named C<path>.
1004
1005 Note that this function cannot correctly handle binary files
1006 (specifically, files containing C<\\0> character which is treated
1007 as end of string).  For those you need to use the C<guestfs_read_file>
1008 or C<guestfs_download> functions which have a more complex interface.");
1009
1010   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
1011    [], (* XXX Tricky to test because it depends on the exact format
1012         * of the 'ls -l' command, which changes between F10 and F11.
1013         *)
1014    "list the files in a directory (long format)",
1015    "\
1016 List the files in C<directory> (relative to the root directory,
1017 there is no cwd) in the format of 'ls -la'.
1018
1019 This command is mostly useful for interactive sessions.  It
1020 is I<not> intended that you try to parse the output string.");
1021
1022   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
1023    [InitBasicFS, Always, TestOutputList (
1024       [["touch"; "/new"];
1025        ["touch"; "/newer"];
1026        ["touch"; "/newest"];
1027        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
1028    "list the files in a directory",
1029    "\
1030 List the files in C<directory> (relative to the root directory,
1031 there is no cwd).  The '.' and '..' entries are not returned, but
1032 hidden files are shown.
1033
1034 This command is mostly useful for interactive sessions.  Programs
1035 should probably use C<guestfs_readdir> instead.");
1036
1037   ("list_devices", (RStringList "devices", []), 7, [],
1038    [InitEmpty, Always, TestOutputListOfDevices (
1039       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1040    "list the block devices",
1041    "\
1042 List all the block devices.
1043
1044 The full block device names are returned, eg. C</dev/sda>");
1045
1046   ("list_partitions", (RStringList "partitions", []), 8, [],
1047    [InitBasicFS, Always, TestOutputListOfDevices (
1048       [["list_partitions"]], ["/dev/sda1"]);
1049     InitEmpty, Always, TestOutputListOfDevices (
1050       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1051        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1052    "list the partitions",
1053    "\
1054 List all the partitions detected on all block devices.
1055
1056 The full partition device names are returned, eg. C</dev/sda1>
1057
1058 This does not return logical volumes.  For that you will need to
1059 call C<guestfs_lvs>.");
1060
1061   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1062    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1063       [["pvs"]], ["/dev/sda1"]);
1064     InitEmpty, Always, TestOutputListOfDevices (
1065       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1066        ["pvcreate"; "/dev/sda1"];
1067        ["pvcreate"; "/dev/sda2"];
1068        ["pvcreate"; "/dev/sda3"];
1069        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1070    "list the LVM physical volumes (PVs)",
1071    "\
1072 List all the physical volumes detected.  This is the equivalent
1073 of the L<pvs(8)> command.
1074
1075 This returns a list of just the device names that contain
1076 PVs (eg. C</dev/sda2>).
1077
1078 See also C<guestfs_pvs_full>.");
1079
1080   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1081    [InitBasicFSonLVM, Always, TestOutputList (
1082       [["vgs"]], ["VG"]);
1083     InitEmpty, Always, TestOutputList (
1084       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1085        ["pvcreate"; "/dev/sda1"];
1086        ["pvcreate"; "/dev/sda2"];
1087        ["pvcreate"; "/dev/sda3"];
1088        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1089        ["vgcreate"; "VG2"; "/dev/sda3"];
1090        ["vgs"]], ["VG1"; "VG2"])],
1091    "list the LVM volume groups (VGs)",
1092    "\
1093 List all the volumes groups detected.  This is the equivalent
1094 of the L<vgs(8)> command.
1095
1096 This returns a list of just the volume group names that were
1097 detected (eg. C<VolGroup00>).
1098
1099 See also C<guestfs_vgs_full>.");
1100
1101   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1102    [InitBasicFSonLVM, Always, TestOutputList (
1103       [["lvs"]], ["/dev/VG/LV"]);
1104     InitEmpty, Always, TestOutputList (
1105       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1106        ["pvcreate"; "/dev/sda1"];
1107        ["pvcreate"; "/dev/sda2"];
1108        ["pvcreate"; "/dev/sda3"];
1109        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1110        ["vgcreate"; "VG2"; "/dev/sda3"];
1111        ["lvcreate"; "LV1"; "VG1"; "50"];
1112        ["lvcreate"; "LV2"; "VG1"; "50"];
1113        ["lvcreate"; "LV3"; "VG2"; "50"];
1114        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1115    "list the LVM logical volumes (LVs)",
1116    "\
1117 List all the logical volumes detected.  This is the equivalent
1118 of the L<lvs(8)> command.
1119
1120 This returns a list of the logical volume device names
1121 (eg. C</dev/VolGroup00/LogVol00>).
1122
1123 See also C<guestfs_lvs_full>.");
1124
1125   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1126    [], (* XXX how to test? *)
1127    "list the LVM physical volumes (PVs)",
1128    "\
1129 List all the physical volumes detected.  This is the equivalent
1130 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1131
1132   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1133    [], (* XXX how to test? *)
1134    "list the LVM volume groups (VGs)",
1135    "\
1136 List all the volumes groups detected.  This is the equivalent
1137 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1138
1139   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1140    [], (* XXX how to test? *)
1141    "list the LVM logical volumes (LVs)",
1142    "\
1143 List all the logical volumes detected.  This is the equivalent
1144 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1145
1146   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1147    [InitISOFS, Always, TestOutputList (
1148       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1149     InitISOFS, Always, TestOutputList (
1150       [["read_lines"; "/empty"]], [])],
1151    "read file as lines",
1152    "\
1153 Return the contents of the file named C<path>.
1154
1155 The file contents are returned as a list of lines.  Trailing
1156 C<LF> and C<CRLF> character sequences are I<not> returned.
1157
1158 Note that this function cannot correctly handle binary files
1159 (specifically, files containing C<\\0> character which is treated
1160 as end of line).  For those you need to use the C<guestfs_read_file>
1161 function which has a more complex interface.");
1162
1163   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1164    [], (* XXX Augeas code needs tests. *)
1165    "create a new Augeas handle",
1166    "\
1167 Create a new Augeas handle for editing configuration files.
1168 If there was any previous Augeas handle associated with this
1169 guestfs session, then it is closed.
1170
1171 You must call this before using any other C<guestfs_aug_*>
1172 commands.
1173
1174 C<root> is the filesystem root.  C<root> must not be NULL,
1175 use C</> instead.
1176
1177 The flags are the same as the flags defined in
1178 E<lt>augeas.hE<gt>, the logical I<or> of the following
1179 integers:
1180
1181 =over 4
1182
1183 =item C<AUG_SAVE_BACKUP> = 1
1184
1185 Keep the original file with a C<.augsave> extension.
1186
1187 =item C<AUG_SAVE_NEWFILE> = 2
1188
1189 Save changes into a file with extension C<.augnew>, and
1190 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1191
1192 =item C<AUG_TYPE_CHECK> = 4
1193
1194 Typecheck lenses (can be expensive).
1195
1196 =item C<AUG_NO_STDINC> = 8
1197
1198 Do not use standard load path for modules.
1199
1200 =item C<AUG_SAVE_NOOP> = 16
1201
1202 Make save a no-op, just record what would have been changed.
1203
1204 =item C<AUG_NO_LOAD> = 32
1205
1206 Do not load the tree in C<guestfs_aug_init>.
1207
1208 =back
1209
1210 To close the handle, you can call C<guestfs_aug_close>.
1211
1212 To find out more about Augeas, see L<http://augeas.net/>.");
1213
1214   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1215    [], (* XXX Augeas code needs tests. *)
1216    "close the current Augeas handle",
1217    "\
1218 Close the current Augeas handle and free up any resources
1219 used by it.  After calling this, you have to call
1220 C<guestfs_aug_init> again before you can use any other
1221 Augeas functions.");
1222
1223   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1224    [], (* XXX Augeas code needs tests. *)
1225    "define an Augeas variable",
1226    "\
1227 Defines an Augeas variable C<name> whose value is the result
1228 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1229 undefined.
1230
1231 On success this returns the number of nodes in C<expr>, or
1232 C<0> if C<expr> evaluates to something which is not a nodeset.");
1233
1234   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1235    [], (* XXX Augeas code needs tests. *)
1236    "define an Augeas node",
1237    "\
1238 Defines a variable C<name> whose value is the result of
1239 evaluating C<expr>.
1240
1241 If C<expr> evaluates to an empty nodeset, a node is created,
1242 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1243 C<name> will be the nodeset containing that single node.
1244
1245 On success this returns a pair containing the
1246 number of nodes in the nodeset, and a boolean flag
1247 if a node was created.");
1248
1249   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1250    [], (* XXX Augeas code needs tests. *)
1251    "look up the value of an Augeas path",
1252    "\
1253 Look up the value associated with C<path>.  If C<path>
1254 matches exactly one node, the C<value> is returned.");
1255
1256   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1257    [], (* XXX Augeas code needs tests. *)
1258    "set Augeas path to value",
1259    "\
1260 Set the value associated with C<path> to C<val>.
1261
1262 In the Augeas API, it is possible to clear a node by setting
1263 the value to NULL.  Due to an oversight in the libguestfs API
1264 you cannot do that with this call.  Instead you must use the
1265 C<guestfs_aug_clear> call.");
1266
1267   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1268    [], (* XXX Augeas code needs tests. *)
1269    "insert a sibling Augeas node",
1270    "\
1271 Create a new sibling C<label> for C<path>, inserting it into
1272 the tree before or after C<path> (depending on the boolean
1273 flag C<before>).
1274
1275 C<path> must match exactly one existing node in the tree, and
1276 C<label> must be a label, ie. not contain C</>, C<*> or end
1277 with a bracketed index C<[N]>.");
1278
1279   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1280    [], (* XXX Augeas code needs tests. *)
1281    "remove an Augeas path",
1282    "\
1283 Remove C<path> and all of its children.
1284
1285 On success this returns the number of entries which were removed.");
1286
1287   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1288    [], (* XXX Augeas code needs tests. *)
1289    "move Augeas node",
1290    "\
1291 Move the node C<src> to C<dest>.  C<src> must match exactly
1292 one node.  C<dest> is overwritten if it exists.");
1293
1294   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1295    [], (* XXX Augeas code needs tests. *)
1296    "return Augeas nodes which match augpath",
1297    "\
1298 Returns a list of paths which match the path expression C<path>.
1299 The returned paths are sufficiently qualified so that they match
1300 exactly one node in the current tree.");
1301
1302   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1303    [], (* XXX Augeas code needs tests. *)
1304    "write all pending Augeas changes to disk",
1305    "\
1306 This writes all pending changes to disk.
1307
1308 The flags which were passed to C<guestfs_aug_init> affect exactly
1309 how files are saved.");
1310
1311   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1312    [], (* XXX Augeas code needs tests. *)
1313    "load files into the tree",
1314    "\
1315 Load files into the tree.
1316
1317 See C<aug_load> in the Augeas documentation for the full gory
1318 details.");
1319
1320   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1321    [], (* XXX Augeas code needs tests. *)
1322    "list Augeas nodes under augpath",
1323    "\
1324 This is just a shortcut for listing C<guestfs_aug_match>
1325 C<path/*> and sorting the resulting nodes into alphabetical order.");
1326
1327   ("rm", (RErr, [Pathname "path"]), 29, [],
1328    [InitBasicFS, Always, TestRun
1329       [["touch"; "/new"];
1330        ["rm"; "/new"]];
1331     InitBasicFS, Always, TestLastFail
1332       [["rm"; "/new"]];
1333     InitBasicFS, Always, TestLastFail
1334       [["mkdir"; "/new"];
1335        ["rm"; "/new"]]],
1336    "remove a file",
1337    "\
1338 Remove the single file C<path>.");
1339
1340   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1341    [InitBasicFS, Always, TestRun
1342       [["mkdir"; "/new"];
1343        ["rmdir"; "/new"]];
1344     InitBasicFS, Always, TestLastFail
1345       [["rmdir"; "/new"]];
1346     InitBasicFS, Always, TestLastFail
1347       [["touch"; "/new"];
1348        ["rmdir"; "/new"]]],
1349    "remove a directory",
1350    "\
1351 Remove the single directory C<path>.");
1352
1353   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1354    [InitBasicFS, Always, TestOutputFalse
1355       [["mkdir"; "/new"];
1356        ["mkdir"; "/new/foo"];
1357        ["touch"; "/new/foo/bar"];
1358        ["rm_rf"; "/new"];
1359        ["exists"; "/new"]]],
1360    "remove a file or directory recursively",
1361    "\
1362 Remove the file or directory C<path>, recursively removing the
1363 contents if its a directory.  This is like the C<rm -rf> shell
1364 command.");
1365
1366   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1367    [InitBasicFS, Always, TestOutputTrue
1368       [["mkdir"; "/new"];
1369        ["is_dir"; "/new"]];
1370     InitBasicFS, Always, TestLastFail
1371       [["mkdir"; "/new/foo/bar"]]],
1372    "create a directory",
1373    "\
1374 Create a directory named C<path>.");
1375
1376   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1377    [InitBasicFS, Always, TestOutputTrue
1378       [["mkdir_p"; "/new/foo/bar"];
1379        ["is_dir"; "/new/foo/bar"]];
1380     InitBasicFS, Always, TestOutputTrue
1381       [["mkdir_p"; "/new/foo/bar"];
1382        ["is_dir"; "/new/foo"]];
1383     InitBasicFS, Always, TestOutputTrue
1384       [["mkdir_p"; "/new/foo/bar"];
1385        ["is_dir"; "/new"]];
1386     (* Regression tests for RHBZ#503133: *)
1387     InitBasicFS, Always, TestRun
1388       [["mkdir"; "/new"];
1389        ["mkdir_p"; "/new"]];
1390     InitBasicFS, Always, TestLastFail
1391       [["touch"; "/new"];
1392        ["mkdir_p"; "/new"]]],
1393    "create a directory and parents",
1394    "\
1395 Create a directory named C<path>, creating any parent directories
1396 as necessary.  This is like the C<mkdir -p> shell command.");
1397
1398   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1399    [], (* XXX Need stat command to test *)
1400    "change file mode",
1401    "\
1402 Change the mode (permissions) of C<path> to C<mode>.  Only
1403 numeric modes are supported.
1404
1405 I<Note>: When using this command from guestfish, C<mode>
1406 by default would be decimal, unless you prefix it with
1407 C<0> to get octal, ie. use C<0700> not C<700>.
1408
1409 The mode actually set is affected by the umask.");
1410
1411   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1412    [], (* XXX Need stat command to test *)
1413    "change file owner and group",
1414    "\
1415 Change the file owner to C<owner> and group to C<group>.
1416
1417 Only numeric uid and gid are supported.  If you want to use
1418 names, you will need to locate and parse the password file
1419 yourself (Augeas support makes this relatively easy).");
1420
1421   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1422    [InitISOFS, Always, TestOutputTrue (
1423       [["exists"; "/empty"]]);
1424     InitISOFS, Always, TestOutputTrue (
1425       [["exists"; "/directory"]])],
1426    "test if file or directory exists",
1427    "\
1428 This returns C<true> if and only if there is a file, directory
1429 (or anything) with the given C<path> name.
1430
1431 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1432
1433   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1434    [InitISOFS, Always, TestOutputTrue (
1435       [["is_file"; "/known-1"]]);
1436     InitISOFS, Always, TestOutputFalse (
1437       [["is_file"; "/directory"]])],
1438    "test if file exists",
1439    "\
1440 This returns C<true> if and only if there is a file
1441 with the given C<path> name.  Note that it returns false for
1442 other objects like directories.
1443
1444 See also C<guestfs_stat>.");
1445
1446   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1447    [InitISOFS, Always, TestOutputFalse (
1448       [["is_dir"; "/known-3"]]);
1449     InitISOFS, Always, TestOutputTrue (
1450       [["is_dir"; "/directory"]])],
1451    "test if file exists",
1452    "\
1453 This returns C<true> if and only if there is a directory
1454 with the given C<path> name.  Note that it returns false for
1455 other objects like files.
1456
1457 See also C<guestfs_stat>.");
1458
1459   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1460    [InitEmpty, Always, TestOutputListOfDevices (
1461       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1462        ["pvcreate"; "/dev/sda1"];
1463        ["pvcreate"; "/dev/sda2"];
1464        ["pvcreate"; "/dev/sda3"];
1465        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1466    "create an LVM physical volume",
1467    "\
1468 This creates an LVM physical volume on the named C<device>,
1469 where C<device> should usually be a partition name such
1470 as C</dev/sda1>.");
1471
1472   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1473    [InitEmpty, Always, TestOutputList (
1474       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1475        ["pvcreate"; "/dev/sda1"];
1476        ["pvcreate"; "/dev/sda2"];
1477        ["pvcreate"; "/dev/sda3"];
1478        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1479        ["vgcreate"; "VG2"; "/dev/sda3"];
1480        ["vgs"]], ["VG1"; "VG2"])],
1481    "create an LVM volume group",
1482    "\
1483 This creates an LVM volume group called C<volgroup>
1484 from the non-empty list of physical volumes C<physvols>.");
1485
1486   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1487    [InitEmpty, Always, TestOutputList (
1488       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1489        ["pvcreate"; "/dev/sda1"];
1490        ["pvcreate"; "/dev/sda2"];
1491        ["pvcreate"; "/dev/sda3"];
1492        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1493        ["vgcreate"; "VG2"; "/dev/sda3"];
1494        ["lvcreate"; "LV1"; "VG1"; "50"];
1495        ["lvcreate"; "LV2"; "VG1"; "50"];
1496        ["lvcreate"; "LV3"; "VG2"; "50"];
1497        ["lvcreate"; "LV4"; "VG2"; "50"];
1498        ["lvcreate"; "LV5"; "VG2"; "50"];
1499        ["lvs"]],
1500       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1501        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1502    "create an LVM logical volume",
1503    "\
1504 This creates an LVM logical volume called C<logvol>
1505 on the volume group C<volgroup>, with C<size> megabytes.");
1506
1507   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1508    [InitEmpty, Always, TestOutput (
1509       [["part_disk"; "/dev/sda"; "mbr"];
1510        ["mkfs"; "ext2"; "/dev/sda1"];
1511        ["mount_options"; ""; "/dev/sda1"; "/"];
1512        ["write"; "/new"; "new file contents"];
1513        ["cat"; "/new"]], "new file contents")],
1514    "make a filesystem",
1515    "\
1516 This creates a filesystem on C<device> (usually a partition
1517 or LVM logical volume).  The filesystem type is C<fstype>, for
1518 example C<ext3>.");
1519
1520   ("sfdisk", (RErr, [Device "device";
1521                      Int "cyls"; Int "heads"; Int "sectors";
1522                      StringList "lines"]), 43, [DangerWillRobinson],
1523    [],
1524    "create partitions on a block device",
1525    "\
1526 This is a direct interface to the L<sfdisk(8)> program for creating
1527 partitions on block devices.
1528
1529 C<device> should be a block device, for example C</dev/sda>.
1530
1531 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1532 and sectors on the device, which are passed directly to sfdisk as
1533 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1534 of these, then the corresponding parameter is omitted.  Usually for
1535 'large' disks, you can just pass C<0> for these, but for small
1536 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1537 out the right geometry and you will need to tell it.
1538
1539 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1540 information refer to the L<sfdisk(8)> manpage.
1541
1542 To create a single partition occupying the whole disk, you would
1543 pass C<lines> as a single element list, when the single element being
1544 the string C<,> (comma).
1545
1546 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1547 C<guestfs_part_init>");
1548
1549   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning; DeprecatedBy "write"],
1550    (* Regression test for RHBZ#597135. *)
1551    [InitBasicFS, Always, TestLastFail
1552       [["write_file"; "/new"; "abc"; "10000"]]],
1553    "create a file",
1554    "\
1555 This call creates a file called C<path>.  The contents of the
1556 file is the string C<content> (which can contain any 8 bit data),
1557 with length C<size>.
1558
1559 As a special case, if C<size> is C<0>
1560 then the length is calculated using C<strlen> (so in this case
1561 the content cannot contain embedded ASCII NULs).
1562
1563 I<NB.> Owing to a bug, writing content containing ASCII NUL
1564 characters does I<not> work, even if the length is specified.");
1565
1566   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1567    [InitEmpty, Always, TestOutputListOfDevices (
1568       [["part_disk"; "/dev/sda"; "mbr"];
1569        ["mkfs"; "ext2"; "/dev/sda1"];
1570        ["mount_options"; ""; "/dev/sda1"; "/"];
1571        ["mounts"]], ["/dev/sda1"]);
1572     InitEmpty, Always, TestOutputList (
1573       [["part_disk"; "/dev/sda"; "mbr"];
1574        ["mkfs"; "ext2"; "/dev/sda1"];
1575        ["mount_options"; ""; "/dev/sda1"; "/"];
1576        ["umount"; "/"];
1577        ["mounts"]], [])],
1578    "unmount a filesystem",
1579    "\
1580 This unmounts the given filesystem.  The filesystem may be
1581 specified either by its mountpoint (path) or the device which
1582 contains the filesystem.");
1583
1584   ("mounts", (RStringList "devices", []), 46, [],
1585    [InitBasicFS, Always, TestOutputListOfDevices (
1586       [["mounts"]], ["/dev/sda1"])],
1587    "show mounted filesystems",
1588    "\
1589 This returns the list of currently mounted filesystems.  It returns
1590 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1591
1592 Some internal mounts are not shown.
1593
1594 See also: C<guestfs_mountpoints>");
1595
1596   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1597    [InitBasicFS, Always, TestOutputList (
1598       [["umount_all"];
1599        ["mounts"]], []);
1600     (* check that umount_all can unmount nested mounts correctly: *)
1601     InitEmpty, Always, TestOutputList (
1602       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1603        ["mkfs"; "ext2"; "/dev/sda1"];
1604        ["mkfs"; "ext2"; "/dev/sda2"];
1605        ["mkfs"; "ext2"; "/dev/sda3"];
1606        ["mount_options"; ""; "/dev/sda1"; "/"];
1607        ["mkdir"; "/mp1"];
1608        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1609        ["mkdir"; "/mp1/mp2"];
1610        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1611        ["mkdir"; "/mp1/mp2/mp3"];
1612        ["umount_all"];
1613        ["mounts"]], [])],
1614    "unmount all filesystems",
1615    "\
1616 This unmounts all mounted filesystems.
1617
1618 Some internal mounts are not unmounted by this call.");
1619
1620   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1621    [],
1622    "remove all LVM LVs, VGs and PVs",
1623    "\
1624 This command removes all LVM logical volumes, volume groups
1625 and physical volumes.");
1626
1627   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1628    [InitISOFS, Always, TestOutput (
1629       [["file"; "/empty"]], "empty");
1630     InitISOFS, Always, TestOutput (
1631       [["file"; "/known-1"]], "ASCII text");
1632     InitISOFS, Always, TestLastFail (
1633       [["file"; "/notexists"]]);
1634     InitISOFS, Always, TestOutput (
1635       [["file"; "/abssymlink"]], "symbolic link");
1636     InitISOFS, Always, TestOutput (
1637       [["file"; "/directory"]], "directory")],
1638    "determine file type",
1639    "\
1640 This call uses the standard L<file(1)> command to determine
1641 the type or contents of the file.
1642
1643 This call will also transparently look inside various types
1644 of compressed file.
1645
1646 The exact command which runs is C<file -zb path>.  Note in
1647 particular that the filename is not prepended to the output
1648 (the C<-b> option).
1649
1650 This command can also be used on C</dev/> devices
1651 (and partitions, LV names).  You can for example use this
1652 to determine if a device contains a filesystem, although
1653 it's usually better to use C<guestfs_vfs_type>.
1654
1655 If the C<path> does not begin with C</dev/> then
1656 this command only works for the content of regular files.
1657 For other file types (directory, symbolic link etc) it
1658 will just return the string C<directory> etc.");
1659
1660   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1661    [InitBasicFS, Always, TestOutput (
1662       [["upload"; "test-command"; "/test-command"];
1663        ["chmod"; "0o755"; "/test-command"];
1664        ["command"; "/test-command 1"]], "Result1");
1665     InitBasicFS, Always, TestOutput (
1666       [["upload"; "test-command"; "/test-command"];
1667        ["chmod"; "0o755"; "/test-command"];
1668        ["command"; "/test-command 2"]], "Result2\n");
1669     InitBasicFS, Always, TestOutput (
1670       [["upload"; "test-command"; "/test-command"];
1671        ["chmod"; "0o755"; "/test-command"];
1672        ["command"; "/test-command 3"]], "\nResult3");
1673     InitBasicFS, Always, TestOutput (
1674       [["upload"; "test-command"; "/test-command"];
1675        ["chmod"; "0o755"; "/test-command"];
1676        ["command"; "/test-command 4"]], "\nResult4\n");
1677     InitBasicFS, Always, TestOutput (
1678       [["upload"; "test-command"; "/test-command"];
1679        ["chmod"; "0o755"; "/test-command"];
1680        ["command"; "/test-command 5"]], "\nResult5\n\n");
1681     InitBasicFS, Always, TestOutput (
1682       [["upload"; "test-command"; "/test-command"];
1683        ["chmod"; "0o755"; "/test-command"];
1684        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1685     InitBasicFS, Always, TestOutput (
1686       [["upload"; "test-command"; "/test-command"];
1687        ["chmod"; "0o755"; "/test-command"];
1688        ["command"; "/test-command 7"]], "");
1689     InitBasicFS, Always, TestOutput (
1690       [["upload"; "test-command"; "/test-command"];
1691        ["chmod"; "0o755"; "/test-command"];
1692        ["command"; "/test-command 8"]], "\n");
1693     InitBasicFS, Always, TestOutput (
1694       [["upload"; "test-command"; "/test-command"];
1695        ["chmod"; "0o755"; "/test-command"];
1696        ["command"; "/test-command 9"]], "\n\n");
1697     InitBasicFS, Always, TestOutput (
1698       [["upload"; "test-command"; "/test-command"];
1699        ["chmod"; "0o755"; "/test-command"];
1700        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1701     InitBasicFS, Always, TestOutput (
1702       [["upload"; "test-command"; "/test-command"];
1703        ["chmod"; "0o755"; "/test-command"];
1704        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1705     InitBasicFS, Always, TestLastFail (
1706       [["upload"; "test-command"; "/test-command"];
1707        ["chmod"; "0o755"; "/test-command"];
1708        ["command"; "/test-command"]])],
1709    "run a command from the guest filesystem",
1710    "\
1711 This call runs a command from the guest filesystem.  The
1712 filesystem must be mounted, and must contain a compatible
1713 operating system (ie. something Linux, with the same
1714 or compatible processor architecture).
1715
1716 The single parameter is an argv-style list of arguments.
1717 The first element is the name of the program to run.
1718 Subsequent elements are parameters.  The list must be
1719 non-empty (ie. must contain a program name).  Note that
1720 the command runs directly, and is I<not> invoked via
1721 the shell (see C<guestfs_sh>).
1722
1723 The return value is anything printed to I<stdout> by
1724 the command.
1725
1726 If the command returns a non-zero exit status, then
1727 this function returns an error message.  The error message
1728 string is the content of I<stderr> from the command.
1729
1730 The C<$PATH> environment variable will contain at least
1731 C</usr/bin> and C</bin>.  If you require a program from
1732 another location, you should provide the full path in the
1733 first parameter.
1734
1735 Shared libraries and data files required by the program
1736 must be available on filesystems which are mounted in the
1737 correct places.  It is the caller's responsibility to ensure
1738 all filesystems that are needed are mounted at the right
1739 locations.");
1740
1741   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1742    [InitBasicFS, Always, TestOutputList (
1743       [["upload"; "test-command"; "/test-command"];
1744        ["chmod"; "0o755"; "/test-command"];
1745        ["command_lines"; "/test-command 1"]], ["Result1"]);
1746     InitBasicFS, Always, TestOutputList (
1747       [["upload"; "test-command"; "/test-command"];
1748        ["chmod"; "0o755"; "/test-command"];
1749        ["command_lines"; "/test-command 2"]], ["Result2"]);
1750     InitBasicFS, Always, TestOutputList (
1751       [["upload"; "test-command"; "/test-command"];
1752        ["chmod"; "0o755"; "/test-command"];
1753        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1754     InitBasicFS, Always, TestOutputList (
1755       [["upload"; "test-command"; "/test-command"];
1756        ["chmod"; "0o755"; "/test-command"];
1757        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1758     InitBasicFS, Always, TestOutputList (
1759       [["upload"; "test-command"; "/test-command"];
1760        ["chmod"; "0o755"; "/test-command"];
1761        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1762     InitBasicFS, Always, TestOutputList (
1763       [["upload"; "test-command"; "/test-command"];
1764        ["chmod"; "0o755"; "/test-command"];
1765        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1766     InitBasicFS, Always, TestOutputList (
1767       [["upload"; "test-command"; "/test-command"];
1768        ["chmod"; "0o755"; "/test-command"];
1769        ["command_lines"; "/test-command 7"]], []);
1770     InitBasicFS, Always, TestOutputList (
1771       [["upload"; "test-command"; "/test-command"];
1772        ["chmod"; "0o755"; "/test-command"];
1773        ["command_lines"; "/test-command 8"]], [""]);
1774     InitBasicFS, Always, TestOutputList (
1775       [["upload"; "test-command"; "/test-command"];
1776        ["chmod"; "0o755"; "/test-command"];
1777        ["command_lines"; "/test-command 9"]], ["";""]);
1778     InitBasicFS, Always, TestOutputList (
1779       [["upload"; "test-command"; "/test-command"];
1780        ["chmod"; "0o755"; "/test-command"];
1781        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1782     InitBasicFS, Always, TestOutputList (
1783       [["upload"; "test-command"; "/test-command"];
1784        ["chmod"; "0o755"; "/test-command"];
1785        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1786    "run a command, returning lines",
1787    "\
1788 This is the same as C<guestfs_command>, but splits the
1789 result into a list of lines.
1790
1791 See also: C<guestfs_sh_lines>");
1792
1793   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1794    [InitISOFS, Always, TestOutputStruct (
1795       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1796    "get file information",
1797    "\
1798 Returns file information for the given C<path>.
1799
1800 This is the same as the C<stat(2)> system call.");
1801
1802   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1803    [InitISOFS, Always, TestOutputStruct (
1804       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1805    "get file information for a symbolic link",
1806    "\
1807 Returns file information for the given C<path>.
1808
1809 This is the same as C<guestfs_stat> except that if C<path>
1810 is a symbolic link, then the link is stat-ed, not the file it
1811 refers to.
1812
1813 This is the same as the C<lstat(2)> system call.");
1814
1815   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1816    [InitISOFS, Always, TestOutputStruct (
1817       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1818    "get file system statistics",
1819    "\
1820 Returns file system statistics for any mounted file system.
1821 C<path> should be a file or directory in the mounted file system
1822 (typically it is the mount point itself, but it doesn't need to be).
1823
1824 This is the same as the C<statvfs(2)> system call.");
1825
1826   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1827    [], (* XXX test *)
1828    "get ext2/ext3/ext4 superblock details",
1829    "\
1830 This returns the contents of the ext2, ext3 or ext4 filesystem
1831 superblock on C<device>.
1832
1833 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1834 manpage for more details.  The list of fields returned isn't
1835 clearly defined, and depends on both the version of C<tune2fs>
1836 that libguestfs was built against, and the filesystem itself.");
1837
1838   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1839    [InitEmpty, Always, TestOutputTrue (
1840       [["blockdev_setro"; "/dev/sda"];
1841        ["blockdev_getro"; "/dev/sda"]])],
1842    "set block device to read-only",
1843    "\
1844 Sets the block device named C<device> to read-only.
1845
1846 This uses the L<blockdev(8)> command.");
1847
1848   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1849    [InitEmpty, Always, TestOutputFalse (
1850       [["blockdev_setrw"; "/dev/sda"];
1851        ["blockdev_getro"; "/dev/sda"]])],
1852    "set block device to read-write",
1853    "\
1854 Sets the block device named C<device> to read-write.
1855
1856 This uses the L<blockdev(8)> command.");
1857
1858   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1859    [InitEmpty, Always, TestOutputTrue (
1860       [["blockdev_setro"; "/dev/sda"];
1861        ["blockdev_getro"; "/dev/sda"]])],
1862    "is block device set to read-only",
1863    "\
1864 Returns a boolean indicating if the block device is read-only
1865 (true if read-only, false if not).
1866
1867 This uses the L<blockdev(8)> command.");
1868
1869   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1870    [InitEmpty, Always, TestOutputInt (
1871       [["blockdev_getss"; "/dev/sda"]], 512)],
1872    "get sectorsize of block device",
1873    "\
1874 This returns the size of sectors on a block device.
1875 Usually 512, but can be larger for modern devices.
1876
1877 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1878 for that).
1879
1880 This uses the L<blockdev(8)> command.");
1881
1882   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1883    [InitEmpty, Always, TestOutputInt (
1884       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1885    "get blocksize of block device",
1886    "\
1887 This returns the block size of a device.
1888
1889 (Note this is different from both I<size in blocks> and
1890 I<filesystem block size>).
1891
1892 This uses the L<blockdev(8)> command.");
1893
1894   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1895    [], (* XXX test *)
1896    "set blocksize of block device",
1897    "\
1898 This sets the block size of a device.
1899
1900 (Note this is different from both I<size in blocks> and
1901 I<filesystem block size>).
1902
1903 This uses the L<blockdev(8)> command.");
1904
1905   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1906    [InitEmpty, Always, TestOutputInt (
1907       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1908    "get total size of device in 512-byte sectors",
1909    "\
1910 This returns the size of the device in units of 512-byte sectors
1911 (even if the sectorsize isn't 512 bytes ... weird).
1912
1913 See also C<guestfs_blockdev_getss> for the real sector size of
1914 the device, and C<guestfs_blockdev_getsize64> for the more
1915 useful I<size in bytes>.
1916
1917 This uses the L<blockdev(8)> command.");
1918
1919   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1920    [InitEmpty, Always, TestOutputInt (
1921       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1922    "get total size of device in bytes",
1923    "\
1924 This returns the size of the device in bytes.
1925
1926 See also C<guestfs_blockdev_getsz>.
1927
1928 This uses the L<blockdev(8)> command.");
1929
1930   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1931    [InitEmpty, Always, TestRun
1932       [["blockdev_flushbufs"; "/dev/sda"]]],
1933    "flush device buffers",
1934    "\
1935 This tells the kernel to flush internal buffers associated
1936 with C<device>.
1937
1938 This uses the L<blockdev(8)> command.");
1939
1940   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1941    [InitEmpty, Always, TestRun
1942       [["blockdev_rereadpt"; "/dev/sda"]]],
1943    "reread partition table",
1944    "\
1945 Reread the partition table on C<device>.
1946
1947 This uses the L<blockdev(8)> command.");
1948
1949   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1950    [InitBasicFS, Always, TestOutput (
1951       (* Pick a file from cwd which isn't likely to change. *)
1952       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1953        ["checksum"; "md5"; "/COPYING.LIB"]],
1954       Digest.to_hex (Digest.file "COPYING.LIB"))],
1955    "upload a file from the local machine",
1956    "\
1957 Upload local file C<filename> to C<remotefilename> on the
1958 filesystem.
1959
1960 C<filename> can also be a named pipe.
1961
1962 See also C<guestfs_download>.");
1963
1964   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1965    [InitBasicFS, Always, TestOutput (
1966       (* Pick a file from cwd which isn't likely to change. *)
1967       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1968        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1969        ["upload"; "testdownload.tmp"; "/upload"];
1970        ["checksum"; "md5"; "/upload"]],
1971       Digest.to_hex (Digest.file "COPYING.LIB"))],
1972    "download a file to the local machine",
1973    "\
1974 Download file C<remotefilename> and save it as C<filename>
1975 on the local machine.
1976
1977 C<filename> can also be a named pipe.
1978
1979 See also C<guestfs_upload>, C<guestfs_cat>.");
1980
1981   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1982    [InitISOFS, Always, TestOutput (
1983       [["checksum"; "crc"; "/known-3"]], "2891671662");
1984     InitISOFS, Always, TestLastFail (
1985       [["checksum"; "crc"; "/notexists"]]);
1986     InitISOFS, Always, TestOutput (
1987       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1988     InitISOFS, Always, TestOutput (
1989       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1990     InitISOFS, Always, TestOutput (
1991       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1992     InitISOFS, Always, TestOutput (
1993       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1994     InitISOFS, Always, TestOutput (
1995       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1996     InitISOFS, Always, TestOutput (
1997       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6");
1998     (* Test for RHBZ#579608, absolute symbolic links. *)
1999     InitISOFS, Always, TestOutput (
2000       [["checksum"; "sha512"; "/abssymlink"]], "5f57d0639bc95081c53afc63a449403883818edc64da48930ad6b1a4fb49be90404686877743fbcd7c99811f3def7df7bc22635c885c6a8cf79c806b43451c1a")],
2001    "compute MD5, SHAx or CRC checksum of file",
2002    "\
2003 This call computes the MD5, SHAx or CRC checksum of the
2004 file named C<path>.
2005
2006 The type of checksum to compute is given by the C<csumtype>
2007 parameter which must have one of the following values:
2008
2009 =over 4
2010
2011 =item C<crc>
2012
2013 Compute the cyclic redundancy check (CRC) specified by POSIX
2014 for the C<cksum> command.
2015
2016 =item C<md5>
2017
2018 Compute the MD5 hash (using the C<md5sum> program).
2019
2020 =item C<sha1>
2021
2022 Compute the SHA1 hash (using the C<sha1sum> program).
2023
2024 =item C<sha224>
2025
2026 Compute the SHA224 hash (using the C<sha224sum> program).
2027
2028 =item C<sha256>
2029
2030 Compute the SHA256 hash (using the C<sha256sum> program).
2031
2032 =item C<sha384>
2033
2034 Compute the SHA384 hash (using the C<sha384sum> program).
2035
2036 =item C<sha512>
2037
2038 Compute the SHA512 hash (using the C<sha512sum> program).
2039
2040 =back
2041
2042 The checksum is returned as a printable string.
2043
2044 To get the checksum for a device, use C<guestfs_checksum_device>.
2045
2046 To get the checksums for many files, use C<guestfs_checksums_out>.");
2047
2048   ("tar_in", (RErr, [FileIn "tarfile"; Pathname "directory"]), 69, [],
2049    [InitBasicFS, Always, TestOutput (
2050       [["tar_in"; "../images/helloworld.tar"; "/"];
2051        ["cat"; "/hello"]], "hello\n")],
2052    "unpack tarfile to directory",
2053    "\
2054 This command uploads and unpacks local file C<tarfile> (an
2055 I<uncompressed> tar file) into C<directory>.
2056
2057 To upload a compressed tarball, use C<guestfs_tgz_in>
2058 or C<guestfs_txz_in>.");
2059
2060   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2061    [],
2062    "pack directory into tarfile",
2063    "\
2064 This command packs the contents of C<directory> and downloads
2065 it to local file C<tarfile>.
2066
2067 To download a compressed tarball, use C<guestfs_tgz_out>
2068 or C<guestfs_txz_out>.");
2069
2070   ("tgz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 71, [],
2071    [InitBasicFS, Always, TestOutput (
2072       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2073        ["cat"; "/hello"]], "hello\n")],
2074    "unpack compressed tarball to directory",
2075    "\
2076 This command uploads and unpacks local file C<tarball> (a
2077 I<gzip compressed> tar file) into C<directory>.
2078
2079 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2080
2081   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2082    [],
2083    "pack directory into compressed tarball",
2084    "\
2085 This command packs the contents of C<directory> and downloads
2086 it to local file C<tarball>.
2087
2088 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2089
2090   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2091    [InitBasicFS, Always, TestLastFail (
2092       [["umount"; "/"];
2093        ["mount_ro"; "/dev/sda1"; "/"];
2094        ["touch"; "/new"]]);
2095     InitBasicFS, Always, TestOutput (
2096       [["write"; "/new"; "data"];
2097        ["umount"; "/"];
2098        ["mount_ro"; "/dev/sda1"; "/"];
2099        ["cat"; "/new"]], "data")],
2100    "mount a guest disk, read-only",
2101    "\
2102 This is the same as the C<guestfs_mount> command, but it
2103 mounts the filesystem with the read-only (I<-o ro>) flag.");
2104
2105   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2106    [],
2107    "mount a guest disk with mount options",
2108    "\
2109 This is the same as the C<guestfs_mount> command, but it
2110 allows you to set the mount options as for the
2111 L<mount(8)> I<-o> flag.
2112
2113 If the C<options> parameter is an empty string, then
2114 no options are passed (all options default to whatever
2115 the filesystem uses).");
2116
2117   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2118    [],
2119    "mount a guest disk with mount options and vfstype",
2120    "\
2121 This is the same as the C<guestfs_mount> command, but it
2122 allows you to set both the mount options and the vfstype
2123 as for the L<mount(8)> I<-o> and I<-t> flags.");
2124
2125   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2126    [],
2127    "debugging and internals",
2128    "\
2129 The C<guestfs_debug> command exposes some internals of
2130 C<guestfsd> (the guestfs daemon) that runs inside the
2131 qemu subprocess.
2132
2133 There is no comprehensive help for this command.  You have
2134 to look at the file C<daemon/debug.c> in the libguestfs source
2135 to find out what you can do.");
2136
2137   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2138    [InitEmpty, Always, TestOutputList (
2139       [["part_disk"; "/dev/sda"; "mbr"];
2140        ["pvcreate"; "/dev/sda1"];
2141        ["vgcreate"; "VG"; "/dev/sda1"];
2142        ["lvcreate"; "LV1"; "VG"; "50"];
2143        ["lvcreate"; "LV2"; "VG"; "50"];
2144        ["lvremove"; "/dev/VG/LV1"];
2145        ["lvs"]], ["/dev/VG/LV2"]);
2146     InitEmpty, Always, TestOutputList (
2147       [["part_disk"; "/dev/sda"; "mbr"];
2148        ["pvcreate"; "/dev/sda1"];
2149        ["vgcreate"; "VG"; "/dev/sda1"];
2150        ["lvcreate"; "LV1"; "VG"; "50"];
2151        ["lvcreate"; "LV2"; "VG"; "50"];
2152        ["lvremove"; "/dev/VG"];
2153        ["lvs"]], []);
2154     InitEmpty, Always, TestOutputList (
2155       [["part_disk"; "/dev/sda"; "mbr"];
2156        ["pvcreate"; "/dev/sda1"];
2157        ["vgcreate"; "VG"; "/dev/sda1"];
2158        ["lvcreate"; "LV1"; "VG"; "50"];
2159        ["lvcreate"; "LV2"; "VG"; "50"];
2160        ["lvremove"; "/dev/VG"];
2161        ["vgs"]], ["VG"])],
2162    "remove an LVM logical volume",
2163    "\
2164 Remove an LVM logical volume C<device>, where C<device> is
2165 the path to the LV, such as C</dev/VG/LV>.
2166
2167 You can also remove all LVs in a volume group by specifying
2168 the VG name, C</dev/VG>.");
2169
2170   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2171    [InitEmpty, Always, TestOutputList (
2172       [["part_disk"; "/dev/sda"; "mbr"];
2173        ["pvcreate"; "/dev/sda1"];
2174        ["vgcreate"; "VG"; "/dev/sda1"];
2175        ["lvcreate"; "LV1"; "VG"; "50"];
2176        ["lvcreate"; "LV2"; "VG"; "50"];
2177        ["vgremove"; "VG"];
2178        ["lvs"]], []);
2179     InitEmpty, Always, TestOutputList (
2180       [["part_disk"; "/dev/sda"; "mbr"];
2181        ["pvcreate"; "/dev/sda1"];
2182        ["vgcreate"; "VG"; "/dev/sda1"];
2183        ["lvcreate"; "LV1"; "VG"; "50"];
2184        ["lvcreate"; "LV2"; "VG"; "50"];
2185        ["vgremove"; "VG"];
2186        ["vgs"]], [])],
2187    "remove an LVM volume group",
2188    "\
2189 Remove an LVM volume group C<vgname>, (for example C<VG>).
2190
2191 This also forcibly removes all logical volumes in the volume
2192 group (if any).");
2193
2194   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2195    [InitEmpty, Always, TestOutputListOfDevices (
2196       [["part_disk"; "/dev/sda"; "mbr"];
2197        ["pvcreate"; "/dev/sda1"];
2198        ["vgcreate"; "VG"; "/dev/sda1"];
2199        ["lvcreate"; "LV1"; "VG"; "50"];
2200        ["lvcreate"; "LV2"; "VG"; "50"];
2201        ["vgremove"; "VG"];
2202        ["pvremove"; "/dev/sda1"];
2203        ["lvs"]], []);
2204     InitEmpty, Always, TestOutputListOfDevices (
2205       [["part_disk"; "/dev/sda"; "mbr"];
2206        ["pvcreate"; "/dev/sda1"];
2207        ["vgcreate"; "VG"; "/dev/sda1"];
2208        ["lvcreate"; "LV1"; "VG"; "50"];
2209        ["lvcreate"; "LV2"; "VG"; "50"];
2210        ["vgremove"; "VG"];
2211        ["pvremove"; "/dev/sda1"];
2212        ["vgs"]], []);
2213     InitEmpty, Always, TestOutputListOfDevices (
2214       [["part_disk"; "/dev/sda"; "mbr"];
2215        ["pvcreate"; "/dev/sda1"];
2216        ["vgcreate"; "VG"; "/dev/sda1"];
2217        ["lvcreate"; "LV1"; "VG"; "50"];
2218        ["lvcreate"; "LV2"; "VG"; "50"];
2219        ["vgremove"; "VG"];
2220        ["pvremove"; "/dev/sda1"];
2221        ["pvs"]], [])],
2222    "remove an LVM physical volume",
2223    "\
2224 This wipes a physical volume C<device> so that LVM will no longer
2225 recognise it.
2226
2227 The implementation uses the C<pvremove> command which refuses to
2228 wipe physical volumes that contain any volume groups, so you have
2229 to remove those first.");
2230
2231   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2232    [InitBasicFS, Always, TestOutput (
2233       [["set_e2label"; "/dev/sda1"; "testlabel"];
2234        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2235    "set the ext2/3/4 filesystem label",
2236    "\
2237 This sets the ext2/3/4 filesystem label of the filesystem on
2238 C<device> to C<label>.  Filesystem labels are limited to
2239 16 characters.
2240
2241 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2242 to return the existing label on a filesystem.");
2243
2244   ("get_e2label", (RString "label", [Device "device"]), 81, [DeprecatedBy "vfs_label"],
2245    [],
2246    "get the ext2/3/4 filesystem label",
2247    "\
2248 This returns the ext2/3/4 filesystem label of the filesystem on
2249 C<device>.");
2250
2251   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2252    (let uuid = uuidgen () in
2253     [InitBasicFS, Always, TestOutput (
2254        [["set_e2uuid"; "/dev/sda1"; uuid];
2255         ["get_e2uuid"; "/dev/sda1"]], uuid);
2256      InitBasicFS, Always, TestOutput (
2257        [["set_e2uuid"; "/dev/sda1"; "clear"];
2258         ["get_e2uuid"; "/dev/sda1"]], "");
2259      (* We can't predict what UUIDs will be, so just check the commands run. *)
2260      InitBasicFS, Always, TestRun (
2261        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2262      InitBasicFS, Always, TestRun (
2263        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2264    "set the ext2/3/4 filesystem UUID",
2265    "\
2266 This sets the ext2/3/4 filesystem UUID of the filesystem on
2267 C<device> to C<uuid>.  The format of the UUID and alternatives
2268 such as C<clear>, C<random> and C<time> are described in the
2269 L<tune2fs(8)> manpage.
2270
2271 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2272 to return the existing UUID of a filesystem.");
2273
2274   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [DeprecatedBy "vfs_uuid"],
2275    (* Regression test for RHBZ#597112. *)
2276    (let uuid = uuidgen () in
2277     [InitBasicFS, Always, TestOutput (
2278        [["mke2journal"; "1024"; "/dev/sdb"];
2279         ["set_e2uuid"; "/dev/sdb"; uuid];
2280         ["get_e2uuid"; "/dev/sdb"]], uuid)]),
2281    "get the ext2/3/4 filesystem UUID",
2282    "\
2283 This returns the ext2/3/4 filesystem UUID of the filesystem on
2284 C<device>.");
2285
2286   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [FishOutput FishOutputHexadecimal],
2287    [InitBasicFS, Always, TestOutputInt (
2288       [["umount"; "/dev/sda1"];
2289        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2290     InitBasicFS, Always, TestOutputInt (
2291       [["umount"; "/dev/sda1"];
2292        ["zero"; "/dev/sda1"];
2293        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2294    "run the filesystem checker",
2295    "\
2296 This runs the filesystem checker (fsck) on C<device> which
2297 should have filesystem type C<fstype>.
2298
2299 The returned integer is the status.  See L<fsck(8)> for the
2300 list of status codes from C<fsck>.
2301
2302 Notes:
2303
2304 =over 4
2305
2306 =item *
2307
2308 Multiple status codes can be summed together.
2309
2310 =item *
2311
2312 A non-zero return code can mean \"success\", for example if
2313 errors have been corrected on the filesystem.
2314
2315 =item *
2316
2317 Checking or repairing NTFS volumes is not supported
2318 (by linux-ntfs).
2319
2320 =back
2321
2322 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2323
2324   ("zero", (RErr, [Device "device"]), 85, [],
2325    [InitBasicFS, Always, TestOutput (
2326       [["umount"; "/dev/sda1"];
2327        ["zero"; "/dev/sda1"];
2328        ["file"; "/dev/sda1"]], "data")],
2329    "write zeroes to the device",
2330    "\
2331 This command writes zeroes over the first few blocks of C<device>.
2332
2333 How many blocks are zeroed isn't specified (but it's I<not> enough
2334 to securely wipe the device).  It should be sufficient to remove
2335 any partition tables, filesystem superblocks and so on.
2336
2337 See also: C<guestfs_zero_device>, C<guestfs_scrub_device>.");
2338
2339   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2340    (* See:
2341     * https://bugzilla.redhat.com/show_bug.cgi?id=484986
2342     * https://bugzilla.redhat.com/show_bug.cgi?id=479760
2343     *)
2344    [InitBasicFS, Always, TestOutputTrue (
2345       [["mkdir_p"; "/boot/grub"];
2346        ["write"; "/boot/grub/device.map"; "(hd0) /dev/vda"];
2347        ["grub_install"; "/"; "/dev/vda"];
2348        ["is_dir"; "/boot"]])],
2349    "install GRUB",
2350    "\
2351 This command installs GRUB (the Grand Unified Bootloader) on
2352 C<device>, with the root directory being C<root>.
2353
2354 Note: If grub-install reports the error
2355 \"No suitable drive was found in the generated device map.\"
2356 it may be that you need to create a C</boot/grub/device.map>
2357 file first that contains the mapping between grub device names
2358 and Linux device names.  It is usually sufficient to create
2359 a file containing:
2360
2361  (hd0) /dev/vda
2362
2363 replacing C</dev/vda> with the name of the installation device.");
2364
2365   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2366    [InitBasicFS, Always, TestOutput (
2367       [["write"; "/old"; "file content"];
2368        ["cp"; "/old"; "/new"];
2369        ["cat"; "/new"]], "file content");
2370     InitBasicFS, Always, TestOutputTrue (
2371       [["write"; "/old"; "file content"];
2372        ["cp"; "/old"; "/new"];
2373        ["is_file"; "/old"]]);
2374     InitBasicFS, Always, TestOutput (
2375       [["write"; "/old"; "file content"];
2376        ["mkdir"; "/dir"];
2377        ["cp"; "/old"; "/dir/new"];
2378        ["cat"; "/dir/new"]], "file content")],
2379    "copy a file",
2380    "\
2381 This copies a file from C<src> to C<dest> where C<dest> is
2382 either a destination filename or destination directory.");
2383
2384   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2385    [InitBasicFS, Always, TestOutput (
2386       [["mkdir"; "/olddir"];
2387        ["mkdir"; "/newdir"];
2388        ["write"; "/olddir/file"; "file content"];
2389        ["cp_a"; "/olddir"; "/newdir"];
2390        ["cat"; "/newdir/olddir/file"]], "file content")],
2391    "copy a file or directory recursively",
2392    "\
2393 This copies a file or directory from C<src> to C<dest>
2394 recursively using the C<cp -a> command.");
2395
2396   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2397    [InitBasicFS, Always, TestOutput (
2398       [["write"; "/old"; "file content"];
2399        ["mv"; "/old"; "/new"];
2400        ["cat"; "/new"]], "file content");
2401     InitBasicFS, Always, TestOutputFalse (
2402       [["write"; "/old"; "file content"];
2403        ["mv"; "/old"; "/new"];
2404        ["is_file"; "/old"]])],
2405    "move a file",
2406    "\
2407 This moves a file from C<src> to C<dest> where C<dest> is
2408 either a destination filename or destination directory.");
2409
2410   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2411    [InitEmpty, Always, TestRun (
2412       [["drop_caches"; "3"]])],
2413    "drop kernel page cache, dentries and inodes",
2414    "\
2415 This instructs the guest kernel to drop its page cache,
2416 and/or dentries and inode caches.  The parameter C<whattodrop>
2417 tells the kernel what precisely to drop, see
2418 L<http://linux-mm.org/Drop_Caches>
2419
2420 Setting C<whattodrop> to 3 should drop everything.
2421
2422 This automatically calls L<sync(2)> before the operation,
2423 so that the maximum guest memory is freed.");
2424
2425   ("dmesg", (RString "kmsgs", []), 91, [],
2426    [InitEmpty, Always, TestRun (
2427       [["dmesg"]])],
2428    "return kernel messages",
2429    "\
2430 This returns the kernel messages (C<dmesg> output) from
2431 the guest kernel.  This is sometimes useful for extended
2432 debugging of problems.
2433
2434 Another way to get the same information is to enable
2435 verbose messages with C<guestfs_set_verbose> or by setting
2436 the environment variable C<LIBGUESTFS_DEBUG=1> before
2437 running the program.");
2438
2439   ("ping_daemon", (RErr, []), 92, [],
2440    [InitEmpty, Always, TestRun (
2441       [["ping_daemon"]])],
2442    "ping the guest daemon",
2443    "\
2444 This is a test probe into the guestfs daemon running inside
2445 the qemu subprocess.  Calling this function checks that the
2446 daemon responds to the ping message, without affecting the daemon
2447 or attached block device(s) in any other way.");
2448
2449   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2450    [InitBasicFS, Always, TestOutputTrue (
2451       [["write"; "/file1"; "contents of a file"];
2452        ["cp"; "/file1"; "/file2"];
2453        ["equal"; "/file1"; "/file2"]]);
2454     InitBasicFS, Always, TestOutputFalse (
2455       [["write"; "/file1"; "contents of a file"];
2456        ["write"; "/file2"; "contents of another file"];
2457        ["equal"; "/file1"; "/file2"]]);
2458     InitBasicFS, Always, TestLastFail (
2459       [["equal"; "/file1"; "/file2"]])],
2460    "test if two files have equal contents",
2461    "\
2462 This compares the two files C<file1> and C<file2> and returns
2463 true if their content is exactly equal, or false otherwise.
2464
2465 The external L<cmp(1)> program is used for the comparison.");
2466
2467   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2468    [InitISOFS, Always, TestOutputList (
2469       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2470     InitISOFS, Always, TestOutputList (
2471       [["strings"; "/empty"]], []);
2472     (* Test for RHBZ#579608, absolute symbolic links. *)
2473     InitISOFS, Always, TestRun (
2474       [["strings"; "/abssymlink"]])],
2475    "print the printable strings in a file",
2476    "\
2477 This runs the L<strings(1)> command on a file and returns
2478 the list of printable strings found.");
2479
2480   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2481    [InitISOFS, Always, TestOutputList (
2482       [["strings_e"; "b"; "/known-5"]], []);
2483     InitBasicFS, Always, TestOutputList (
2484       [["write"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"];
2485        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2486    "print the printable strings in a file",
2487    "\
2488 This is like the C<guestfs_strings> command, but allows you to
2489 specify the encoding of strings that are looked for in
2490 the source file C<path>.
2491
2492 Allowed encodings are:
2493
2494 =over 4
2495
2496 =item s
2497
2498 Single 7-bit-byte characters like ASCII and the ASCII-compatible
2499 parts of ISO-8859-X (this is what C<guestfs_strings> uses).
2500
2501 =item S
2502
2503 Single 8-bit-byte characters.
2504
2505 =item b
2506
2507 16-bit big endian strings such as those encoded in
2508 UTF-16BE or UCS-2BE.
2509
2510 =item l (lower case letter L)
2511
2512 16-bit little endian such as UTF-16LE and UCS-2LE.
2513 This is useful for examining binaries in Windows guests.
2514
2515 =item B
2516
2517 32-bit big endian such as UCS-4BE.
2518
2519 =item L
2520
2521 32-bit little endian such as UCS-4LE.
2522
2523 =back
2524
2525 The returned strings are transcoded to UTF-8.");
2526
2527   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2528    [InitISOFS, Always, TestOutput (
2529       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2530     (* Test for RHBZ#501888c2 regression which caused large hexdump
2531      * commands to segfault.
2532      *)
2533     InitISOFS, Always, TestRun (
2534       [["hexdump"; "/100krandom"]]);
2535     (* Test for RHBZ#579608, absolute symbolic links. *)
2536     InitISOFS, Always, TestRun (
2537       [["hexdump"; "/abssymlink"]])],
2538    "dump a file in hexadecimal",
2539    "\
2540 This runs C<hexdump -C> on the given C<path>.  The result is
2541 the human-readable, canonical hex dump of the file.");
2542
2543   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2544    [InitNone, Always, TestOutput (
2545       [["part_disk"; "/dev/sda"; "mbr"];
2546        ["mkfs"; "ext3"; "/dev/sda1"];
2547        ["mount_options"; ""; "/dev/sda1"; "/"];
2548        ["write"; "/new"; "test file"];
2549        ["umount"; "/dev/sda1"];
2550        ["zerofree"; "/dev/sda1"];
2551        ["mount_options"; ""; "/dev/sda1"; "/"];
2552        ["cat"; "/new"]], "test file")],
2553    "zero unused inodes and disk blocks on ext2/3 filesystem",
2554    "\
2555 This runs the I<zerofree> program on C<device>.  This program
2556 claims to zero unused inodes and disk blocks on an ext2/3
2557 filesystem, thus making it possible to compress the filesystem
2558 more effectively.
2559
2560 You should B<not> run this program if the filesystem is
2561 mounted.
2562
2563 It is possible that using this program can damage the filesystem
2564 or data on the filesystem.");
2565
2566   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2567    [],
2568    "resize an LVM physical volume",
2569    "\
2570 This resizes (expands or shrinks) an existing LVM physical
2571 volume to match the new size of the underlying device.");
2572
2573   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2574                        Int "cyls"; Int "heads"; Int "sectors";
2575                        String "line"]), 99, [DangerWillRobinson],
2576    [],
2577    "modify a single partition on a block device",
2578    "\
2579 This runs L<sfdisk(8)> option to modify just the single
2580 partition C<n> (note: C<n> counts from 1).
2581
2582 For other parameters, see C<guestfs_sfdisk>.  You should usually
2583 pass C<0> for the cyls/heads/sectors parameters.
2584
2585 See also: C<guestfs_part_add>");
2586
2587   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2588    [],
2589    "display the partition table",
2590    "\
2591 This displays the partition table on C<device>, in the
2592 human-readable output of the L<sfdisk(8)> command.  It is
2593 not intended to be parsed.
2594
2595 See also: C<guestfs_part_list>");
2596
2597   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2598    [],
2599    "display the kernel geometry",
2600    "\
2601 This displays the kernel's idea of the geometry of C<device>.
2602
2603 The result is in human-readable format, and not designed to
2604 be parsed.");
2605
2606   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2607    [],
2608    "display the disk geometry from the partition table",
2609    "\
2610 This displays the disk geometry of C<device> read from the
2611 partition table.  Especially in the case where the underlying
2612 block device has been resized, this can be different from the
2613 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2614
2615 The result is in human-readable format, and not designed to
2616 be parsed.");
2617
2618   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2619    [],
2620    "activate or deactivate all volume groups",
2621    "\
2622 This command activates or (if C<activate> is false) deactivates
2623 all logical volumes in all volume groups.
2624 If activated, then they are made known to the
2625 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2626 then those devices disappear.
2627
2628 This command is the same as running C<vgchange -a y|n>");
2629
2630   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2631    [],
2632    "activate or deactivate some volume groups",
2633    "\
2634 This command activates or (if C<activate> is false) deactivates
2635 all logical volumes in the listed volume groups C<volgroups>.
2636 If activated, then they are made known to the
2637 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2638 then those devices disappear.
2639
2640 This command is the same as running C<vgchange -a y|n volgroups...>
2641
2642 Note that if C<volgroups> is an empty list then B<all> volume groups
2643 are activated or deactivated.");
2644
2645   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2646    [InitNone, Always, TestOutput (
2647       [["part_disk"; "/dev/sda"; "mbr"];
2648        ["pvcreate"; "/dev/sda1"];
2649        ["vgcreate"; "VG"; "/dev/sda1"];
2650        ["lvcreate"; "LV"; "VG"; "10"];
2651        ["mkfs"; "ext2"; "/dev/VG/LV"];
2652        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2653        ["write"; "/new"; "test content"];
2654        ["umount"; "/"];
2655        ["lvresize"; "/dev/VG/LV"; "20"];
2656        ["e2fsck_f"; "/dev/VG/LV"];
2657        ["resize2fs"; "/dev/VG/LV"];
2658        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2659        ["cat"; "/new"]], "test content");
2660     InitNone, Always, TestRun (
2661       (* Make an LV smaller to test RHBZ#587484. *)
2662       [["part_disk"; "/dev/sda"; "mbr"];
2663        ["pvcreate"; "/dev/sda1"];
2664        ["vgcreate"; "VG"; "/dev/sda1"];
2665        ["lvcreate"; "LV"; "VG"; "20"];
2666        ["lvresize"; "/dev/VG/LV"; "10"]])],
2667    "resize an LVM logical volume",
2668    "\
2669 This resizes (expands or shrinks) an existing LVM logical
2670 volume to C<mbytes>.  When reducing, data in the reduced part
2671 is lost.");
2672
2673   ("resize2fs", (RErr, [Device "device"]), 106, [],
2674    [], (* lvresize tests this *)
2675    "resize an ext2, ext3 or ext4 filesystem",
2676    "\
2677 This resizes an ext2, ext3 or ext4 filesystem to match the size of
2678 the underlying device.
2679
2680 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2681 on the C<device> before calling this command.  For unknown reasons
2682 C<resize2fs> sometimes gives an error about this and sometimes not.
2683 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2684 calling this function.");
2685
2686   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2687    [InitBasicFS, Always, TestOutputList (
2688       [["find"; "/"]], ["lost+found"]);
2689     InitBasicFS, Always, TestOutputList (
2690       [["touch"; "/a"];
2691        ["mkdir"; "/b"];
2692        ["touch"; "/b/c"];
2693        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2694     InitBasicFS, Always, TestOutputList (
2695       [["mkdir_p"; "/a/b/c"];
2696        ["touch"; "/a/b/c/d"];
2697        ["find"; "/a/b/"]], ["c"; "c/d"])],
2698    "find all files and directories",
2699    "\
2700 This command lists out all files and directories, recursively,
2701 starting at C<directory>.  It is essentially equivalent to
2702 running the shell command C<find directory -print> but some
2703 post-processing happens on the output, described below.
2704
2705 This returns a list of strings I<without any prefix>.  Thus
2706 if the directory structure was:
2707
2708  /tmp/a
2709  /tmp/b
2710  /tmp/c/d
2711
2712 then the returned list from C<guestfs_find> C</tmp> would be
2713 4 elements:
2714
2715  a
2716  b
2717  c
2718  c/d
2719
2720 If C<directory> is not a directory, then this command returns
2721 an error.
2722
2723 The returned list is sorted.
2724
2725 See also C<guestfs_find0>.");
2726
2727   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2728    [], (* lvresize tests this *)
2729    "check an ext2/ext3 filesystem",
2730    "\
2731 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2732 filesystem checker on C<device>, noninteractively (C<-p>),
2733 even if the filesystem appears to be clean (C<-f>).
2734
2735 This command is only needed because of C<guestfs_resize2fs>
2736 (q.v.).  Normally you should use C<guestfs_fsck>.");
2737
2738   ("sleep", (RErr, [Int "secs"]), 109, [],
2739    [InitNone, Always, TestRun (
2740       [["sleep"; "1"]])],
2741    "sleep for some seconds",
2742    "\
2743 Sleep for C<secs> seconds.");
2744
2745   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2746    [InitNone, Always, TestOutputInt (
2747       [["part_disk"; "/dev/sda"; "mbr"];
2748        ["mkfs"; "ntfs"; "/dev/sda1"];
2749        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2750     InitNone, Always, TestOutputInt (
2751       [["part_disk"; "/dev/sda"; "mbr"];
2752        ["mkfs"; "ext2"; "/dev/sda1"];
2753        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2754    "probe NTFS volume",
2755    "\
2756 This command runs the L<ntfs-3g.probe(8)> command which probes
2757 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2758 be mounted read-write, and some cannot be mounted at all).
2759
2760 C<rw> is a boolean flag.  Set it to true if you want to test
2761 if the volume can be mounted read-write.  Set it to false if
2762 you want to test if the volume can be mounted read-only.
2763
2764 The return value is an integer which C<0> if the operation
2765 would succeed, or some non-zero value documented in the
2766 L<ntfs-3g.probe(8)> manual page.");
2767
2768   ("sh", (RString "output", [String "command"]), 111, [],
2769    [], (* XXX needs tests *)
2770    "run a command via the shell",
2771    "\
2772 This call runs a command from the guest filesystem via the
2773 guest's C</bin/sh>.
2774
2775 This is like C<guestfs_command>, but passes the command to:
2776
2777  /bin/sh -c \"command\"
2778
2779 Depending on the guest's shell, this usually results in
2780 wildcards being expanded, shell expressions being interpolated
2781 and so on.
2782
2783 All the provisos about C<guestfs_command> apply to this call.");
2784
2785   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2786    [], (* XXX needs tests *)
2787    "run a command via the shell returning lines",
2788    "\
2789 This is the same as C<guestfs_sh>, but splits the result
2790 into a list of lines.
2791
2792 See also: C<guestfs_command_lines>");
2793
2794   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2795    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2796     * code in stubs.c, since all valid glob patterns must start with "/".
2797     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2798     *)
2799    [InitBasicFS, Always, TestOutputList (
2800       [["mkdir_p"; "/a/b/c"];
2801        ["touch"; "/a/b/c/d"];
2802        ["touch"; "/a/b/c/e"];
2803        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2804     InitBasicFS, Always, TestOutputList (
2805       [["mkdir_p"; "/a/b/c"];
2806        ["touch"; "/a/b/c/d"];
2807        ["touch"; "/a/b/c/e"];
2808        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2809     InitBasicFS, Always, TestOutputList (
2810       [["mkdir_p"; "/a/b/c"];
2811        ["touch"; "/a/b/c/d"];
2812        ["touch"; "/a/b/c/e"];
2813        ["glob_expand"; "/a/*/x/*"]], [])],
2814    "expand a wildcard path",
2815    "\
2816 This command searches for all the pathnames matching
2817 C<pattern> according to the wildcard expansion rules
2818 used by the shell.
2819
2820 If no paths match, then this returns an empty list
2821 (note: not an error).
2822
2823 It is just a wrapper around the C L<glob(3)> function
2824 with flags C<GLOB_MARK|GLOB_BRACE>.
2825 See that manual page for more details.");
2826
2827   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2828    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2829       [["scrub_device"; "/dev/sdc"]])],
2830    "scrub (securely wipe) a device",
2831    "\
2832 This command writes patterns over C<device> to make data retrieval
2833 more difficult.
2834
2835 It is an interface to the L<scrub(1)> program.  See that
2836 manual page for more details.");
2837
2838   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2839    [InitBasicFS, Always, TestRun (
2840       [["write"; "/file"; "content"];
2841        ["scrub_file"; "/file"]])],
2842    "scrub (securely wipe) a file",
2843    "\
2844 This command writes patterns over a file to make data retrieval
2845 more difficult.
2846
2847 The file is I<removed> after scrubbing.
2848
2849 It is an interface to the L<scrub(1)> program.  See that
2850 manual page for more details.");
2851
2852   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2853    [], (* XXX needs testing *)
2854    "scrub (securely wipe) free space",
2855    "\
2856 This command creates the directory C<dir> and then fills it
2857 with files until the filesystem is full, and scrubs the files
2858 as for C<guestfs_scrub_file>, and deletes them.
2859 The intention is to scrub any free space on the partition
2860 containing C<dir>.
2861
2862 It is an interface to the L<scrub(1)> program.  See that
2863 manual page for more details.");
2864
2865   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2866    [InitBasicFS, Always, TestRun (
2867       [["mkdir"; "/tmp"];
2868        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2869    "create a temporary directory",
2870    "\
2871 This command creates a temporary directory.  The
2872 C<template> parameter should be a full pathname for the
2873 temporary directory name with the final six characters being
2874 \"XXXXXX\".
2875
2876 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2877 the second one being suitable for Windows filesystems.
2878
2879 The name of the temporary directory that was created
2880 is returned.
2881
2882 The temporary directory is created with mode 0700
2883 and is owned by root.
2884
2885 The caller is responsible for deleting the temporary
2886 directory and its contents after use.
2887
2888 See also: L<mkdtemp(3)>");
2889
2890   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2891    [InitISOFS, Always, TestOutputInt (
2892       [["wc_l"; "/10klines"]], 10000);
2893     (* Test for RHBZ#579608, absolute symbolic links. *)
2894     InitISOFS, Always, TestOutputInt (
2895       [["wc_l"; "/abssymlink"]], 10000)],
2896    "count lines in a file",
2897    "\
2898 This command counts the lines in a file, using the
2899 C<wc -l> external command.");
2900
2901   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2902    [InitISOFS, Always, TestOutputInt (
2903       [["wc_w"; "/10klines"]], 10000)],
2904    "count words in a file",
2905    "\
2906 This command counts the words in a file, using the
2907 C<wc -w> external command.");
2908
2909   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2910    [InitISOFS, Always, TestOutputInt (
2911       [["wc_c"; "/100kallspaces"]], 102400)],
2912    "count characters in a file",
2913    "\
2914 This command counts the characters in a file, using the
2915 C<wc -c> external command.");
2916
2917   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2918    [InitISOFS, Always, TestOutputList (
2919       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"]);
2920     (* Test for RHBZ#579608, absolute symbolic links. *)
2921     InitISOFS, Always, TestOutputList (
2922       [["head"; "/abssymlink"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2923    "return first 10 lines of a file",
2924    "\
2925 This command returns up to the first 10 lines of a file as
2926 a list of strings.");
2927
2928   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2929    [InitISOFS, Always, TestOutputList (
2930       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2931     InitISOFS, Always, TestOutputList (
2932       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2933     InitISOFS, Always, TestOutputList (
2934       [["head_n"; "0"; "/10klines"]], [])],
2935    "return first N lines of a file",
2936    "\
2937 If the parameter C<nrlines> is a positive number, this returns the first
2938 C<nrlines> lines of the file C<path>.
2939
2940 If the parameter C<nrlines> is a negative number, this returns lines
2941 from the file C<path>, excluding the last C<nrlines> lines.
2942
2943 If the parameter C<nrlines> is zero, this returns an empty list.");
2944
2945   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2946    [InitISOFS, Always, TestOutputList (
2947       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2948    "return last 10 lines of a file",
2949    "\
2950 This command returns up to the last 10 lines of a file as
2951 a list of strings.");
2952
2953   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2954    [InitISOFS, Always, TestOutputList (
2955       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2956     InitISOFS, Always, TestOutputList (
2957       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2958     InitISOFS, Always, TestOutputList (
2959       [["tail_n"; "0"; "/10klines"]], [])],
2960    "return last N lines of a file",
2961    "\
2962 If the parameter C<nrlines> is a positive number, this returns the last
2963 C<nrlines> lines of the file C<path>.
2964
2965 If the parameter C<nrlines> is a negative number, this returns lines
2966 from the file C<path>, starting with the C<-nrlines>th line.
2967
2968 If the parameter C<nrlines> is zero, this returns an empty list.");
2969
2970   ("df", (RString "output", []), 125, [],
2971    [], (* XXX Tricky to test because it depends on the exact format
2972         * of the 'df' command and other imponderables.
2973         *)
2974    "report file system disk space usage",
2975    "\
2976 This command runs the C<df> command to report disk space used.
2977
2978 This command is mostly useful for interactive sessions.  It
2979 is I<not> intended that you try to parse the output string.
2980 Use C<statvfs> from programs.");
2981
2982   ("df_h", (RString "output", []), 126, [],
2983    [], (* XXX Tricky to test because it depends on the exact format
2984         * of the 'df' command and other imponderables.
2985         *)
2986    "report file system disk space usage (human readable)",
2987    "\
2988 This command runs the C<df -h> command to report disk space used
2989 in human-readable format.
2990
2991 This command is mostly useful for interactive sessions.  It
2992 is I<not> intended that you try to parse the output string.
2993 Use C<statvfs> from programs.");
2994
2995   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2996    [InitISOFS, Always, TestOutputInt (
2997       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2998    "estimate file space usage",
2999    "\
3000 This command runs the C<du -s> command to estimate file space
3001 usage for C<path>.
3002
3003 C<path> can be a file or a directory.  If C<path> is a directory
3004 then the estimate includes the contents of the directory and all
3005 subdirectories (recursively).
3006
3007 The result is the estimated size in I<kilobytes>
3008 (ie. units of 1024 bytes).");
3009
3010   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
3011    [InitISOFS, Always, TestOutputList (
3012       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
3013    "list files in an initrd",
3014    "\
3015 This command lists out files contained in an initrd.
3016
3017 The files are listed without any initial C</> character.  The
3018 files are listed in the order they appear (not necessarily
3019 alphabetical).  Directory names are listed as separate items.
3020
3021 Old Linux kernels (2.4 and earlier) used a compressed ext2
3022 filesystem as initrd.  We I<only> support the newer initramfs
3023 format (compressed cpio files).");
3024
3025   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
3026    [],
3027    "mount a file using the loop device",
3028    "\
3029 This command lets you mount C<file> (a filesystem image
3030 in a file) on a mount point.  It is entirely equivalent to
3031 the command C<mount -o loop file mountpoint>.");
3032
3033   ("mkswap", (RErr, [Device "device"]), 130, [],
3034    [InitEmpty, Always, TestRun (
3035       [["part_disk"; "/dev/sda"; "mbr"];
3036        ["mkswap"; "/dev/sda1"]])],
3037    "create a swap partition",
3038    "\
3039 Create a swap partition on C<device>.");
3040
3041   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
3042    [InitEmpty, Always, TestRun (
3043       [["part_disk"; "/dev/sda"; "mbr"];
3044        ["mkswap_L"; "hello"; "/dev/sda1"]])],
3045    "create a swap partition with a label",
3046    "\
3047 Create a swap partition on C<device> with label C<label>.
3048
3049 Note that you cannot attach a swap label to a block device
3050 (eg. C</dev/sda>), just to a partition.  This appears to be
3051 a limitation of the kernel or swap tools.");
3052
3053   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
3054    (let uuid = uuidgen () in
3055     [InitEmpty, Always, TestRun (
3056        [["part_disk"; "/dev/sda"; "mbr"];
3057         ["mkswap_U"; uuid; "/dev/sda1"]])]),
3058    "create a swap partition with an explicit UUID",
3059    "\
3060 Create a swap partition on C<device> with UUID C<uuid>.");
3061
3062   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
3063    [InitBasicFS, Always, TestOutputStruct (
3064       [["mknod"; "0o10777"; "0"; "0"; "/node"];
3065        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
3066        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
3067     InitBasicFS, Always, TestOutputStruct (
3068       [["mknod"; "0o60777"; "66"; "99"; "/node"];
3069        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3070    "make block, character or FIFO devices",
3071    "\
3072 This call creates block or character special devices, or
3073 named pipes (FIFOs).
3074
3075 The C<mode> parameter should be the mode, using the standard
3076 constants.  C<devmajor> and C<devminor> are the
3077 device major and minor numbers, only used when creating block
3078 and character special devices.
3079
3080 Note that, just like L<mknod(2)>, the mode must be bitwise
3081 OR'd with S_IFBLK, S_IFCHR, S_IFIFO or S_IFSOCK (otherwise this call
3082 just creates a regular file).  These constants are
3083 available in the standard Linux header files, or you can use
3084 C<guestfs_mknod_b>, C<guestfs_mknod_c> or C<guestfs_mkfifo>
3085 which are wrappers around this command which bitwise OR
3086 in the appropriate constant for you.
3087
3088 The mode actually set is affected by the umask.");
3089
3090   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
3091    [InitBasicFS, Always, TestOutputStruct (
3092       [["mkfifo"; "0o777"; "/node"];
3093        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
3094    "make FIFO (named pipe)",
3095    "\
3096 This call creates a FIFO (named pipe) called C<path> with
3097 mode C<mode>.  It is just a convenient wrapper around
3098 C<guestfs_mknod>.
3099
3100 The mode actually set is affected by the umask.");
3101
3102   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
3103    [InitBasicFS, Always, TestOutputStruct (
3104       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
3105        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
3106    "make block device node",
3107    "\
3108 This call creates a block device node called C<path> with
3109 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3110 It is just a convenient wrapper around C<guestfs_mknod>.
3111
3112 The mode actually set is affected by the umask.");
3113
3114   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
3115    [InitBasicFS, Always, TestOutputStruct (
3116       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
3117        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
3118    "make char device node",
3119    "\
3120 This call creates a char device node called C<path> with
3121 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
3122 It is just a convenient wrapper around C<guestfs_mknod>.
3123
3124 The mode actually set is affected by the umask.");
3125
3126   ("umask", (RInt "oldmask", [Int "mask"]), 137, [FishOutput FishOutputOctal],
3127    [InitEmpty, Always, TestOutputInt (
3128       [["umask"; "0o22"]], 0o22)],
3129    "set file mode creation mask (umask)",
3130    "\
3131 This function sets the mask used for creating new files and
3132 device nodes to C<mask & 0777>.
3133
3134 Typical umask values would be C<022> which creates new files
3135 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3136 C<002> which creates new files with permissions like
3137 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3138
3139 The default umask is C<022>.  This is important because it
3140 means that directories and device nodes will be created with
3141 C<0644> or C<0755> mode even if you specify C<0777>.
3142
3143 See also C<guestfs_get_umask>,
3144 L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3145
3146 This call returns the previous umask.");
3147
3148   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3149    [],
3150    "read directories entries",
3151    "\
3152 This returns the list of directory entries in directory C<dir>.
3153
3154 All entries in the directory are returned, including C<.> and
3155 C<..>.  The entries are I<not> sorted, but returned in the same
3156 order as the underlying filesystem.
3157
3158 Also this call returns basic file type information about each
3159 file.  The C<ftyp> field will contain one of the following characters:
3160
3161 =over 4
3162
3163 =item 'b'
3164
3165 Block special
3166
3167 =item 'c'
3168
3169 Char special
3170
3171 =item 'd'
3172
3173 Directory
3174
3175 =item 'f'
3176
3177 FIFO (named pipe)
3178
3179 =item 'l'
3180
3181 Symbolic link
3182
3183 =item 'r'
3184
3185 Regular file
3186
3187 =item 's'
3188
3189 Socket
3190
3191 =item 'u'
3192
3193 Unknown file type
3194
3195 =item '?'
3196
3197 The L<readdir(3)> call returned a C<d_type> field with an
3198 unexpected value
3199
3200 =back
3201
3202 This function is primarily intended for use by programs.  To
3203 get a simple list of names, use C<guestfs_ls>.  To get a printable
3204 directory for human consumption, use C<guestfs_ll>.");
3205
3206   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3207    [],
3208    "create partitions on a block device",
3209    "\
3210 This is a simplified interface to the C<guestfs_sfdisk>
3211 command, where partition sizes are specified in megabytes
3212 only (rounded to the nearest cylinder) and you don't need
3213 to specify the cyls, heads and sectors parameters which
3214 were rarely if ever used anyway.
3215
3216 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3217 and C<guestfs_part_disk>");
3218
3219   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3220    [],
3221    "determine file type inside a compressed file",
3222    "\
3223 This command runs C<file> after first decompressing C<path>
3224 using C<method>.
3225
3226 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3227
3228 Since 1.0.63, use C<guestfs_file> instead which can now
3229 process compressed files.");
3230
3231   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3232    [],
3233    "list extended attributes of a file or directory",
3234    "\
3235 This call lists the extended attributes of the file or directory
3236 C<path>.
3237
3238 At the system call level, this is a combination of the
3239 L<listxattr(2)> and L<getxattr(2)> calls.
3240
3241 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3242
3243   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3244    [],
3245    "list extended attributes of a file or directory",
3246    "\
3247 This is the same as C<guestfs_getxattrs>, but if C<path>
3248 is a symbolic link, then it returns the extended attributes
3249 of the link itself.");
3250
3251   ("setxattr", (RErr, [String "xattr";
3252                        String "val"; Int "vallen"; (* will be BufferIn *)
3253                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3254    [],
3255    "set extended attribute of a file or directory",
3256    "\
3257 This call sets the extended attribute named C<xattr>
3258 of the file C<path> to the value C<val> (of length C<vallen>).
3259 The value is arbitrary 8 bit data.
3260
3261 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3262
3263   ("lsetxattr", (RErr, [String "xattr";
3264                         String "val"; Int "vallen"; (* will be BufferIn *)
3265                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3266    [],
3267    "set extended attribute of a file or directory",
3268    "\
3269 This is the same as C<guestfs_setxattr>, but if C<path>
3270 is a symbolic link, then it sets an extended attribute
3271 of the link itself.");
3272
3273   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3274    [],
3275    "remove extended attribute of a file or directory",
3276    "\
3277 This call removes the extended attribute named C<xattr>
3278 of the file C<path>.
3279
3280 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3281
3282   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3283    [],
3284    "remove extended attribute of a file or directory",
3285    "\
3286 This is the same as C<guestfs_removexattr>, but if C<path>
3287 is a symbolic link, then it removes an extended attribute
3288 of the link itself.");
3289
3290   ("mountpoints", (RHashtable "mps", []), 147, [],
3291    [],
3292    "show mountpoints",
3293    "\
3294 This call is similar to C<guestfs_mounts>.  That call returns
3295 a list of devices.  This one returns a hash table (map) of
3296 device name to directory where the device is mounted.");
3297
3298   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3299    (* This is a special case: while you would expect a parameter
3300     * of type "Pathname", that doesn't work, because it implies
3301     * NEED_ROOT in the generated calling code in stubs.c, and
3302     * this function cannot use NEED_ROOT.
3303     *)
3304    [],
3305    "create a mountpoint",
3306    "\
3307 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3308 specialized calls that can be used to create extra mountpoints
3309 before mounting the first filesystem.
3310
3311 These calls are I<only> necessary in some very limited circumstances,
3312 mainly the case where you want to mount a mix of unrelated and/or
3313 read-only filesystems together.
3314
3315 For example, live CDs often contain a \"Russian doll\" nest of
3316 filesystems, an ISO outer layer, with a squashfs image inside, with
3317 an ext2/3 image inside that.  You can unpack this as follows
3318 in guestfish:
3319
3320  add-ro Fedora-11-i686-Live.iso
3321  run
3322  mkmountpoint /cd
3323  mkmountpoint /squash
3324  mkmountpoint /ext3
3325  mount /dev/sda /cd
3326  mount-loop /cd/LiveOS/squashfs.img /squash
3327  mount-loop /squash/LiveOS/ext3fs.img /ext3
3328
3329 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3330
3331   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3332    [],
3333    "remove a mountpoint",
3334    "\
3335 This calls removes a mountpoint that was previously created
3336 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3337 for full details.");
3338
3339   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3340    [InitISOFS, Always, TestOutputBuffer (
3341       [["read_file"; "/known-4"]], "abc\ndef\nghi");
3342     (* Test various near large, large and too large files (RHBZ#589039). *)
3343     InitBasicFS, Always, TestLastFail (
3344       [["touch"; "/a"];
3345        ["truncate_size"; "/a"; "4194303"]; (* GUESTFS_MESSAGE_MAX - 1 *)
3346        ["read_file"; "/a"]]);
3347     InitBasicFS, Always, TestLastFail (
3348       [["touch"; "/a"];
3349        ["truncate_size"; "/a"; "4194304"]; (* GUESTFS_MESSAGE_MAX *)
3350        ["read_file"; "/a"]]);
3351     InitBasicFS, Always, TestLastFail (
3352       [["touch"; "/a"];
3353        ["truncate_size"; "/a"; "41943040"]; (* GUESTFS_MESSAGE_MAX * 10 *)
3354        ["read_file"; "/a"]])],
3355    "read a file",
3356    "\
3357 This calls returns the contents of the file C<path> as a
3358 buffer.
3359
3360 Unlike C<guestfs_cat>, this function can correctly
3361 handle files that contain embedded ASCII NUL characters.
3362 However unlike C<guestfs_download>, this function is limited
3363 in the total size of file that can be handled.");
3364
3365   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3366    [InitISOFS, Always, TestOutputList (
3367       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3368     InitISOFS, Always, TestOutputList (
3369       [["grep"; "nomatch"; "/test-grep.txt"]], []);
3370     (* Test for RHBZ#579608, absolute symbolic links. *)
3371     InitISOFS, Always, TestOutputList (
3372       [["grep"; "nomatch"; "/abssymlink"]], [])],
3373    "return lines matching a pattern",
3374    "\
3375 This calls the external C<grep> program and returns the
3376 matching lines.");
3377
3378   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3379    [InitISOFS, Always, TestOutputList (
3380       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3381    "return lines matching a pattern",
3382    "\
3383 This calls the external C<egrep> program and returns the
3384 matching lines.");
3385
3386   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3387    [InitISOFS, Always, TestOutputList (
3388       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3389    "return lines matching a pattern",
3390    "\
3391 This calls the external C<fgrep> program and returns the
3392 matching lines.");
3393
3394   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3395    [InitISOFS, Always, TestOutputList (
3396       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3397    "return lines matching a pattern",
3398    "\
3399 This calls the external C<grep -i> program and returns the
3400 matching lines.");
3401
3402   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3403    [InitISOFS, Always, TestOutputList (
3404       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3405    "return lines matching a pattern",
3406    "\
3407 This calls the external C<egrep -i> program and returns the
3408 matching lines.");
3409
3410   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3411    [InitISOFS, Always, TestOutputList (
3412       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3413    "return lines matching a pattern",
3414    "\
3415 This calls the external C<fgrep -i> program and returns the
3416 matching lines.");
3417
3418   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3419    [InitISOFS, Always, TestOutputList (
3420       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3421    "return lines matching a pattern",
3422    "\
3423 This calls the external C<zgrep> program and returns the
3424 matching lines.");
3425
3426   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3427    [InitISOFS, Always, TestOutputList (
3428       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3429    "return lines matching a pattern",
3430    "\
3431 This calls the external C<zegrep> program and returns the
3432 matching lines.");
3433
3434   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3435    [InitISOFS, Always, TestOutputList (
3436       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3437    "return lines matching a pattern",
3438    "\
3439 This calls the external C<zfgrep> program and returns the
3440 matching lines.");
3441
3442   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3443    [InitISOFS, Always, TestOutputList (
3444       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3445    "return lines matching a pattern",
3446    "\
3447 This calls the external C<zgrep -i> program and returns the
3448 matching lines.");
3449
3450   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3451    [InitISOFS, Always, TestOutputList (
3452       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3453    "return lines matching a pattern",
3454    "\
3455 This calls the external C<zegrep -i> program and returns the
3456 matching lines.");
3457
3458   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3459    [InitISOFS, Always, TestOutputList (
3460       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3461    "return lines matching a pattern",
3462    "\
3463 This calls the external C<zfgrep -i> program and returns the
3464 matching lines.");
3465
3466   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3467    [InitISOFS, Always, TestOutput (
3468       [["realpath"; "/../directory"]], "/directory")],
3469    "canonicalized absolute pathname",
3470    "\
3471 Return the canonicalized absolute pathname of C<path>.  The
3472 returned path has no C<.>, C<..> or symbolic link path elements.");
3473
3474   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3475    [InitBasicFS, Always, TestOutputStruct (
3476       [["touch"; "/a"];
3477        ["ln"; "/a"; "/b"];
3478        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3479    "create a hard link",
3480    "\
3481 This command creates a hard link using the C<ln> command.");
3482
3483   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3484    [InitBasicFS, Always, TestOutputStruct (
3485       [["touch"; "/a"];
3486        ["touch"; "/b"];
3487        ["ln_f"; "/a"; "/b"];
3488        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3489    "create a hard link",
3490    "\
3491 This command creates a hard link using the C<ln -f> command.
3492 The C<-f> option removes the link (C<linkname>) if it exists already.");
3493
3494   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3495    [InitBasicFS, Always, TestOutputStruct (
3496       [["touch"; "/a"];
3497        ["ln_s"; "a"; "/b"];
3498        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3499    "create a symbolic link",
3500    "\
3501 This command creates a symbolic link using the C<ln -s> command.");
3502
3503   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3504    [InitBasicFS, Always, TestOutput (
3505       [["mkdir_p"; "/a/b"];
3506        ["touch"; "/a/b/c"];
3507        ["ln_sf"; "../d"; "/a/b/c"];
3508        ["readlink"; "/a/b/c"]], "../d")],
3509    "create a symbolic link",
3510    "\
3511 This command creates a symbolic link using the C<ln -sf> command,
3512 The C<-f> option removes the link (C<linkname>) if it exists already.");
3513
3514   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3515    [] (* XXX tested above *),
3516    "read the target of a symbolic link",
3517    "\
3518 This command reads the target of a symbolic link.");
3519
3520   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [DeprecatedBy "fallocate64"],
3521    [InitBasicFS, Always, TestOutputStruct (
3522       [["fallocate"; "/a"; "1000000"];
3523        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3524    "preallocate a file in the guest filesystem",
3525    "\
3526 This command preallocates a file (containing zero bytes) named
3527 C<path> of size C<len> bytes.  If the file exists already, it
3528 is overwritten.
3529
3530 Do not confuse this with the guestfish-specific
3531 C<alloc> command which allocates a file in the host and
3532 attaches it as a device.");
3533
3534   ("swapon_device", (RErr, [Device "device"]), 170, [],
3535    [InitPartition, Always, TestRun (
3536       [["mkswap"; "/dev/sda1"];
3537        ["swapon_device"; "/dev/sda1"];
3538        ["swapoff_device"; "/dev/sda1"]])],
3539    "enable swap on device",
3540    "\
3541 This command enables the libguestfs appliance to use the
3542 swap device or partition named C<device>.  The increased
3543 memory is made available for all commands, for example
3544 those run using C<guestfs_command> or C<guestfs_sh>.
3545
3546 Note that you should not swap to existing guest swap
3547 partitions unless you know what you are doing.  They may
3548 contain hibernation information, or other information that
3549 the guest doesn't want you to trash.  You also risk leaking
3550 information about the host to the guest this way.  Instead,
3551 attach a new host device to the guest and swap on that.");
3552
3553   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3554    [], (* XXX tested by swapon_device *)
3555    "disable swap on device",
3556    "\
3557 This command disables the libguestfs appliance swap
3558 device or partition named C<device>.
3559 See C<guestfs_swapon_device>.");
3560
3561   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3562    [InitBasicFS, Always, TestRun (
3563       [["fallocate"; "/swap"; "8388608"];
3564        ["mkswap_file"; "/swap"];
3565        ["swapon_file"; "/swap"];
3566        ["swapoff_file"; "/swap"]])],
3567    "enable swap on file",
3568    "\
3569 This command enables swap to a file.
3570 See C<guestfs_swapon_device> for other notes.");
3571
3572   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3573    [], (* XXX tested by swapon_file *)
3574    "disable swap on file",
3575    "\
3576 This command disables the libguestfs appliance swap on file.");
3577
3578   ("swapon_label", (RErr, [String "label"]), 174, [],
3579    [InitEmpty, Always, TestRun (
3580       [["part_disk"; "/dev/sdb"; "mbr"];
3581        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3582        ["swapon_label"; "swapit"];
3583        ["swapoff_label"; "swapit"];
3584        ["zero"; "/dev/sdb"];
3585        ["blockdev_rereadpt"; "/dev/sdb"]])],
3586    "enable swap on labeled swap partition",
3587    "\
3588 This command enables swap to a labeled swap partition.
3589 See C<guestfs_swapon_device> for other notes.");
3590
3591   ("swapoff_label", (RErr, [String "label"]), 175, [],
3592    [], (* XXX tested by swapon_label *)
3593    "disable swap on labeled swap partition",
3594    "\
3595 This command disables the libguestfs appliance swap on
3596 labeled swap partition.");
3597
3598   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3599    (let uuid = uuidgen () in
3600     [InitEmpty, Always, TestRun (
3601        [["mkswap_U"; uuid; "/dev/sdb"];
3602         ["swapon_uuid"; uuid];
3603         ["swapoff_uuid"; uuid]])]),
3604    "enable swap on swap partition by UUID",
3605    "\
3606 This command enables swap to a swap partition with the given UUID.
3607 See C<guestfs_swapon_device> for other notes.");
3608
3609   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3610    [], (* XXX tested by swapon_uuid *)
3611    "disable swap on swap partition by UUID",
3612    "\
3613 This command disables the libguestfs appliance swap partition
3614 with the given UUID.");
3615
3616   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3617    [InitBasicFS, Always, TestRun (
3618       [["fallocate"; "/swap"; "8388608"];
3619        ["mkswap_file"; "/swap"]])],
3620    "create a swap file",
3621    "\
3622 Create a swap file.
3623
3624 This command just writes a swap file signature to an existing
3625 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3626
3627   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3628    [InitISOFS, Always, TestRun (
3629       [["inotify_init"; "0"]])],
3630    "create an inotify handle",
3631    "\
3632 This command creates a new inotify handle.
3633 The inotify subsystem can be used to notify events which happen to
3634 objects in the guest filesystem.
3635
3636 C<maxevents> is the maximum number of events which will be
3637 queued up between calls to C<guestfs_inotify_read> or
3638 C<guestfs_inotify_files>.
3639 If this is passed as C<0>, then the kernel (or previously set)
3640 default is used.  For Linux 2.6.29 the default was 16384 events.
3641 Beyond this limit, the kernel throws away events, but records
3642 the fact that it threw them away by setting a flag
3643 C<IN_Q_OVERFLOW> in the returned structure list (see
3644 C<guestfs_inotify_read>).
3645
3646 Before any events are generated, you have to add some
3647 watches to the internal watch list.  See:
3648 C<guestfs_inotify_add_watch>,
3649 C<guestfs_inotify_rm_watch> and
3650 C<guestfs_inotify_watch_all>.
3651
3652 Queued up events should be read periodically by calling
3653 C<guestfs_inotify_read>
3654 (or C<guestfs_inotify_files> which is just a helpful
3655 wrapper around C<guestfs_inotify_read>).  If you don't
3656 read the events out often enough then you risk the internal
3657 queue overflowing.
3658
3659 The handle should be closed after use by calling
3660 C<guestfs_inotify_close>.  This also removes any
3661 watches automatically.
3662
3663 See also L<inotify(7)> for an overview of the inotify interface
3664 as exposed by the Linux kernel, which is roughly what we expose
3665 via libguestfs.  Note that there is one global inotify handle
3666 per libguestfs instance.");
3667
3668   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3669    [InitBasicFS, Always, TestOutputList (
3670       [["inotify_init"; "0"];
3671        ["inotify_add_watch"; "/"; "1073741823"];
3672        ["touch"; "/a"];
3673        ["touch"; "/b"];
3674        ["inotify_files"]], ["a"; "b"])],
3675    "add an inotify watch",
3676    "\
3677 Watch C<path> for the events listed in C<mask>.
3678
3679 Note that if C<path> is a directory then events within that
3680 directory are watched, but this does I<not> happen recursively
3681 (in subdirectories).
3682
3683 Note for non-C or non-Linux callers: the inotify events are
3684 defined by the Linux kernel ABI and are listed in
3685 C</usr/include/sys/inotify.h>.");
3686
3687   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3688    [],
3689    "remove an inotify watch",
3690    "\
3691 Remove a previously defined inotify watch.
3692 See C<guestfs_inotify_add_watch>.");
3693
3694   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3695    [],
3696    "return list of inotify events",
3697    "\
3698 Return the complete queue of events that have happened
3699 since the previous read call.
3700
3701 If no events have happened, this returns an empty list.
3702
3703 I<Note>: In order to make sure that all events have been
3704 read, you must call this function repeatedly until it
3705 returns an empty list.  The reason is that the call will
3706 read events up to the maximum appliance-to-host message
3707 size and leave remaining events in the queue.");
3708
3709   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3710    [],
3711    "return list of watched files that had events",
3712    "\
3713 This function is a helpful wrapper around C<guestfs_inotify_read>
3714 which just returns a list of pathnames of objects that were
3715 touched.  The returned pathnames are sorted and deduplicated.");
3716
3717   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3718    [],
3719    "close the inotify handle",
3720    "\
3721 This closes the inotify handle which was previously
3722 opened by inotify_init.  It removes all watches, throws
3723 away any pending events, and deallocates all resources.");
3724
3725   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3726    [],
3727    "set SELinux security context",
3728    "\
3729 This sets the SELinux security context of the daemon
3730 to the string C<context>.
3731
3732 See the documentation about SELINUX in L<guestfs(3)>.");
3733
3734   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3735    [],
3736    "get SELinux security context",
3737    "\
3738 This gets the SELinux security context of the daemon.
3739
3740 See the documentation about SELINUX in L<guestfs(3)>,
3741 and C<guestfs_setcon>");
3742
3743   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3744    [InitEmpty, Always, TestOutput (
3745       [["part_disk"; "/dev/sda"; "mbr"];
3746        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3747        ["mount_options"; ""; "/dev/sda1"; "/"];
3748        ["write"; "/new"; "new file contents"];
3749        ["cat"; "/new"]], "new file contents");
3750     InitEmpty, Always, TestRun (
3751       [["part_disk"; "/dev/sda"; "mbr"];
3752        ["mkfs_b"; "vfat"; "32768"; "/dev/sda1"]]);
3753     InitEmpty, Always, TestLastFail (
3754       [["part_disk"; "/dev/sda"; "mbr"];
3755        ["mkfs_b"; "vfat"; "32769"; "/dev/sda1"]]);
3756     InitEmpty, Always, TestLastFail (
3757       [["part_disk"; "/dev/sda"; "mbr"];
3758        ["mkfs_b"; "vfat"; "33280"; "/dev/sda1"]]);
3759     InitEmpty, IfAvailable "ntfsprogs", TestRun (
3760       [["part_disk"; "/dev/sda"; "mbr"];
3761        ["mkfs_b"; "ntfs"; "32768"; "/dev/sda1"]])],
3762    "make a filesystem with block size",
3763    "\
3764 This call is similar to C<guestfs_mkfs>, but it allows you to
3765 control the block size of the resulting filesystem.  Supported
3766 block sizes depend on the filesystem type, but typically they
3767 are C<1024>, C<2048> or C<4096> only.
3768
3769 For VFAT and NTFS the C<blocksize> parameter is treated as
3770 the requested cluster size.");
3771
3772   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3773    [InitEmpty, Always, TestOutput (
3774       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3775        ["mke2journal"; "4096"; "/dev/sda1"];
3776        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3777        ["mount_options"; ""; "/dev/sda2"; "/"];
3778        ["write"; "/new"; "new file contents"];
3779        ["cat"; "/new"]], "new file contents")],
3780    "make ext2/3/4 external journal",
3781    "\
3782 This creates an ext2 external journal on C<device>.  It is equivalent
3783 to the command:
3784
3785  mke2fs -O journal_dev -b blocksize device");
3786
3787   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3788    [InitEmpty, Always, TestOutput (
3789       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3790        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3791        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3792        ["mount_options"; ""; "/dev/sda2"; "/"];
3793        ["write"; "/new"; "new file contents"];
3794        ["cat"; "/new"]], "new file contents")],
3795    "make ext2/3/4 external journal with label",
3796    "\
3797 This creates an ext2 external journal on C<device> with label C<label>.");
3798
3799   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3800    (let uuid = uuidgen () in
3801     [InitEmpty, Always, TestOutput (
3802        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3803         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3804         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3805         ["mount_options"; ""; "/dev/sda2"; "/"];
3806         ["write"; "/new"; "new file contents"];
3807         ["cat"; "/new"]], "new file contents")]),
3808    "make ext2/3/4 external journal with UUID",
3809    "\
3810 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3811
3812   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3813    [],
3814    "make ext2/3/4 filesystem with external journal",
3815    "\
3816 This creates an ext2/3/4 filesystem on C<device> with
3817 an external journal on C<journal>.  It is equivalent
3818 to the command:
3819
3820  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3821
3822 See also C<guestfs_mke2journal>.");
3823
3824   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3825    [],
3826    "make ext2/3/4 filesystem with external journal",
3827    "\
3828 This creates an ext2/3/4 filesystem on C<device> with
3829 an external journal on the journal labeled C<label>.
3830
3831 See also C<guestfs_mke2journal_L>.");
3832
3833   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3834    [],
3835    "make ext2/3/4 filesystem with external journal",
3836    "\
3837 This creates an ext2/3/4 filesystem on C<device> with
3838 an external journal on the journal with UUID C<uuid>.
3839
3840 See also C<guestfs_mke2journal_U>.");
3841
3842   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3843    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3844    "load a kernel module",
3845    "\
3846 This loads a kernel module in the appliance.
3847
3848 The kernel module must have been whitelisted when libguestfs
3849 was built (see C<appliance/kmod.whitelist.in> in the source).");
3850
3851   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3852    [InitNone, Always, TestOutput (
3853       [["echo_daemon"; "This is a test"]], "This is a test"
3854     )],
3855    "echo arguments back to the client",
3856    "\
3857 This command concatenates the list of C<words> passed with single spaces
3858 between them and returns the resulting string.
3859
3860 You can use this command to test the connection through to the daemon.
3861
3862 See also C<guestfs_ping_daemon>.");
3863
3864   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3865    [], (* There is a regression test for this. *)
3866    "find all files and directories, returning NUL-separated list",
3867    "\
3868 This command lists out all files and directories, recursively,
3869 starting at C<directory>, placing the resulting list in the
3870 external file called C<files>.
3871
3872 This command works the same way as C<guestfs_find> with the
3873 following exceptions:
3874
3875 =over 4
3876
3877 =item *
3878
3879 The resulting list is written to an external file.
3880
3881 =item *
3882
3883 Items (filenames) in the result are separated
3884 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3885
3886 =item *
3887
3888 This command is not limited in the number of names that it
3889 can return.
3890
3891 =item *
3892
3893 The result list is not sorted.
3894
3895 =back");
3896
3897   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3898    [InitISOFS, Always, TestOutput (
3899       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3900     InitISOFS, Always, TestOutput (
3901       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3902     InitISOFS, Always, TestOutput (
3903       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3904     InitISOFS, Always, TestLastFail (
3905       [["case_sensitive_path"; "/Known-1/"]]);
3906     InitBasicFS, Always, TestOutput (
3907       [["mkdir"; "/a"];
3908        ["mkdir"; "/a/bbb"];
3909        ["touch"; "/a/bbb/c"];
3910        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3911     InitBasicFS, Always, TestOutput (
3912       [["mkdir"; "/a"];
3913        ["mkdir"; "/a/bbb"];
3914        ["touch"; "/a/bbb/c"];
3915        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3916     InitBasicFS, Always, TestLastFail (
3917       [["mkdir"; "/a"];
3918        ["mkdir"; "/a/bbb"];
3919        ["touch"; "/a/bbb/c"];
3920        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3921    "return true path on case-insensitive filesystem",
3922    "\
3923 This can be used to resolve case insensitive paths on
3924 a filesystem which is case sensitive.  The use case is
3925 to resolve paths which you have read from Windows configuration
3926 files or the Windows Registry, to the true path.
3927
3928 The command handles a peculiarity of the Linux ntfs-3g
3929 filesystem driver (and probably others), which is that although
3930 the underlying filesystem is case-insensitive, the driver
3931 exports the filesystem to Linux as case-sensitive.
3932
3933 One consequence of this is that special directories such
3934 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3935 (or other things) depending on the precise details of how
3936 they were created.  In Windows itself this would not be
3937 a problem.
3938
3939 Bug or feature?  You decide:
3940 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3941
3942 This function resolves the true case of each element in the
3943 path and returns the case-sensitive path.
3944
3945 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3946 might return C<\"/WINDOWS/system32\"> (the exact return value
3947 would depend on details of how the directories were originally
3948 created under Windows).
3949
3950 I<Note>:
3951 This function does not handle drive names, backslashes etc.
3952
3953 See also C<guestfs_realpath>.");
3954
3955   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3956    [InitBasicFS, Always, TestOutput (
3957       [["vfs_type"; "/dev/sda1"]], "ext2")],
3958    "get the Linux VFS type corresponding to a mounted device",
3959    "\
3960 This command gets the filesystem type corresponding to
3961 the filesystem on C<device>.
3962
3963 For most filesystems, the result is the name of the Linux
3964 VFS module which would be used to mount this filesystem
3965 if you mounted it without specifying the filesystem type.
3966 For example a string such as C<ext3> or C<ntfs>.");
3967
3968   ("truncate", (RErr, [Pathname "path"]), 199, [],
3969    [InitBasicFS, Always, TestOutputStruct (
3970       [["write"; "/test"; "some stuff so size is not zero"];
3971        ["truncate"; "/test"];
3972        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3973    "truncate a file to zero size",
3974    "\
3975 This command truncates C<path> to a zero-length file.  The
3976 file must exist already.");
3977
3978   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3979    [InitBasicFS, Always, TestOutputStruct (
3980       [["touch"; "/test"];
3981        ["truncate_size"; "/test"; "1000"];
3982        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3983    "truncate a file to a particular size",
3984    "\
3985 This command truncates C<path> to size C<size> bytes.  The file
3986 must exist already.
3987
3988 If the current file size is less than C<size> then
3989 the file is extended to the required size with zero bytes.
3990 This creates a sparse file (ie. disk blocks are not allocated
3991 for the file until you write to it).  To create a non-sparse
3992 file of zeroes, use C<guestfs_fallocate64> instead.");
3993
3994   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3995    [InitBasicFS, Always, TestOutputStruct (
3996       [["touch"; "/test"];
3997        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3998        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3999    "set timestamp of a file with nanosecond precision",
4000    "\
4001 This command sets the timestamps of a file with nanosecond
4002 precision.
4003
4004 C<atsecs, atnsecs> are the last access time (atime) in secs and
4005 nanoseconds from the epoch.
4006
4007 C<mtsecs, mtnsecs> are the last modification time (mtime) in
4008 secs and nanoseconds from the epoch.
4009
4010 If the C<*nsecs> field contains the special value C<-1> then
4011 the corresponding timestamp is set to the current time.  (The
4012 C<*secs> field is ignored in this case).
4013
4014 If the C<*nsecs> field contains the special value C<-2> then
4015 the corresponding timestamp is left unchanged.  (The
4016 C<*secs> field is ignored in this case).");
4017
4018   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
4019    [InitBasicFS, Always, TestOutputStruct (
4020       [["mkdir_mode"; "/test"; "0o111"];
4021        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
4022    "create a directory with a particular mode",
4023    "\
4024 This command creates a directory, setting the initial permissions
4025 of the directory to C<mode>.
4026
4027 For common Linux filesystems, the actual mode which is set will
4028 be C<mode & ~umask & 01777>.  Non-native-Linux filesystems may
4029 interpret the mode in other ways.
4030
4031 See also C<guestfs_mkdir>, C<guestfs_umask>");
4032
4033   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
4034    [], (* XXX *)
4035    "change file owner and group",
4036    "\
4037 Change the file owner to C<owner> and group to C<group>.
4038 This is like C<guestfs_chown> but if C<path> is a symlink then
4039 the link itself is changed, not the target.
4040
4041 Only numeric uid and gid are supported.  If you want to use
4042 names, you will need to locate and parse the password file
4043 yourself (Augeas support makes this relatively easy).");
4044
4045   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
4046    [], (* XXX *)
4047    "lstat on multiple files",
4048    "\
4049 This call allows you to perform the C<guestfs_lstat> operation
4050 on multiple files, where all files are in the directory C<path>.
4051 C<names> is the list of files from this directory.
4052
4053 On return you get a list of stat structs, with a one-to-one
4054 correspondence to the C<names> list.  If any name did not exist
4055 or could not be lstat'd, then the C<ino> field of that structure
4056 is set to C<-1>.
4057
4058 This call is intended for programs that want to efficiently
4059 list a directory contents without making many round-trips.
4060 See also C<guestfs_lxattrlist> for a similarly efficient call
4061 for getting extended attributes.  Very long directory listings
4062 might cause the protocol message size to be exceeded, causing
4063 this call to fail.  The caller must split up such requests
4064 into smaller groups of names.");
4065
4066   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
4067    [], (* XXX *)
4068    "lgetxattr on multiple files",
4069    "\
4070 This call allows you to get the extended attributes
4071 of multiple files, where all files are in the directory C<path>.
4072 C<names> is the list of files from this directory.
4073
4074 On return you get a flat list of xattr structs which must be
4075 interpreted sequentially.  The first xattr struct always has a zero-length
4076 C<attrname>.  C<attrval> in this struct is zero-length
4077 to indicate there was an error doing C<lgetxattr> for this
4078 file, I<or> is a C string which is a decimal number
4079 (the number of following attributes for this file, which could
4080 be C<\"0\">).  Then after the first xattr struct are the
4081 zero or more attributes for the first named file.
4082 This repeats for the second and subsequent files.
4083
4084 This call is intended for programs that want to efficiently
4085 list a directory contents without making many round-trips.
4086 See also C<guestfs_lstatlist> for a similarly efficient call
4087 for getting standard stats.  Very long directory listings
4088 might cause the protocol message size to be exceeded, causing
4089 this call to fail.  The caller must split up such requests
4090 into smaller groups of names.");
4091
4092   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
4093    [], (* XXX *)
4094    "readlink on multiple files",
4095    "\
4096 This call allows you to do a C<readlink> operation
4097 on multiple files, where all files are in the directory C<path>.
4098 C<names> is the list of files from this directory.
4099
4100 On return you get a list of strings, with a one-to-one
4101 correspondence to the C<names> list.  Each string is the
4102 value of the symbolic link.
4103
4104 If the C<readlink(2)> operation fails on any name, then
4105 the corresponding result string is the empty string C<\"\">.
4106 However the whole operation is completed even if there
4107 were C<readlink(2)> errors, and so you can call this
4108 function with names where you don't know if they are
4109 symbolic links already (albeit slightly less efficient).
4110
4111 This call is intended for programs that want to efficiently
4112 list a directory contents without making many round-trips.
4113 Very long directory listings might cause the protocol
4114 message size to be exceeded, causing
4115 this call to fail.  The caller must split up such requests
4116 into smaller groups of names.");
4117
4118   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
4119    [InitISOFS, Always, TestOutputBuffer (
4120       [["pread"; "/known-4"; "1"; "3"]], "\n");
4121     InitISOFS, Always, TestOutputBuffer (
4122       [["pread"; "/empty"; "0"; "100"]], "")],
4123    "read part of a file",
4124    "\
4125 This command lets you read part of a file.  It reads C<count>
4126 bytes of the file, starting at C<offset>, from file C<path>.
4127
4128 This may read fewer bytes than requested.  For further details
4129 see the L<pread(2)> system call.
4130
4131 See also C<guestfs_pwrite>.");
4132
4133   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
4134    [InitEmpty, Always, TestRun (
4135       [["part_init"; "/dev/sda"; "gpt"]])],
4136    "create an empty partition table",
4137    "\
4138 This creates an empty partition table on C<device> of one of the
4139 partition types listed below.  Usually C<parttype> should be
4140 either C<msdos> or C<gpt> (for large disks).
4141
4142 Initially there are no partitions.  Following this, you should
4143 call C<guestfs_part_add> for each partition required.
4144
4145 Possible values for C<parttype> are:
4146
4147 =over 4
4148
4149 =item B<efi> | B<gpt>
4150
4151 Intel EFI / GPT partition table.
4152
4153 This is recommended for >= 2 TB partitions that will be accessed
4154 from Linux and Intel-based Mac OS X.  It also has limited backwards
4155 compatibility with the C<mbr> format.
4156
4157 =item B<mbr> | B<msdos>
4158
4159 The standard PC \"Master Boot Record\" (MBR) format used
4160 by MS-DOS and Windows.  This partition type will B<only> work
4161 for device sizes up to 2 TB.  For large disks we recommend
4162 using C<gpt>.
4163
4164 =back
4165
4166 Other partition table types that may work but are not
4167 supported include:
4168
4169 =over 4
4170
4171 =item B<aix>
4172
4173 AIX disk labels.
4174
4175 =item B<amiga> | B<rdb>
4176
4177 Amiga \"Rigid Disk Block\" format.
4178
4179 =item B<bsd>
4180
4181 BSD disk labels.
4182
4183 =item B<dasd>
4184
4185 DASD, used on IBM mainframes.
4186
4187 =item B<dvh>
4188
4189 MIPS/SGI volumes.
4190
4191 =item B<mac>
4192
4193 Old Mac partition format.  Modern Macs use C<gpt>.
4194
4195 =item B<pc98>
4196
4197 NEC PC-98 format, common in Japan apparently.
4198
4199 =item B<sun>
4200
4201 Sun disk labels.
4202
4203 =back");
4204
4205   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4206    [InitEmpty, Always, TestRun (
4207       [["part_init"; "/dev/sda"; "mbr"];
4208        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4209     InitEmpty, Always, TestRun (
4210       [["part_init"; "/dev/sda"; "gpt"];
4211        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4212        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4213     InitEmpty, Always, TestRun (
4214       [["part_init"; "/dev/sda"; "mbr"];
4215        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4216        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4217        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4218        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4219    "add a partition to the device",
4220    "\
4221 This command adds a partition to C<device>.  If there is no partition
4222 table on the device, call C<guestfs_part_init> first.
4223
4224 The C<prlogex> parameter is the type of partition.  Normally you
4225 should pass C<p> or C<primary> here, but MBR partition tables also
4226 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4227 types.
4228
4229 C<startsect> and C<endsect> are the start and end of the partition
4230 in I<sectors>.  C<endsect> may be negative, which means it counts
4231 backwards from the end of the disk (C<-1> is the last sector).
4232
4233 Creating a partition which covers the whole disk is not so easy.
4234 Use C<guestfs_part_disk> to do that.");
4235
4236   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4237    [InitEmpty, Always, TestRun (
4238       [["part_disk"; "/dev/sda"; "mbr"]]);
4239     InitEmpty, Always, TestRun (
4240       [["part_disk"; "/dev/sda"; "gpt"]])],
4241    "partition whole disk with a single primary partition",
4242    "\
4243 This command is simply a combination of C<guestfs_part_init>
4244 followed by C<guestfs_part_add> to create a single primary partition
4245 covering the whole disk.
4246
4247 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4248 but other possible values are described in C<guestfs_part_init>.");
4249
4250   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4251    [InitEmpty, Always, TestRun (
4252       [["part_disk"; "/dev/sda"; "mbr"];
4253        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4254    "make a partition bootable",
4255    "\
4256 This sets the bootable flag on partition numbered C<partnum> on
4257 device C<device>.  Note that partitions are numbered from 1.
4258
4259 The bootable flag is used by some operating systems (notably
4260 Windows) to determine which partition to boot from.  It is by
4261 no means universally recognized.");
4262
4263   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4264    [InitEmpty, Always, TestRun (
4265       [["part_disk"; "/dev/sda"; "gpt"];
4266        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4267    "set partition name",
4268    "\
4269 This sets the partition name on partition numbered C<partnum> on
4270 device C<device>.  Note that partitions are numbered from 1.
4271
4272 The partition name can only be set on certain types of partition
4273 table.  This works on C<gpt> but not on C<mbr> partitions.");
4274
4275   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4276    [], (* XXX Add a regression test for this. *)
4277    "list partitions on a device",
4278    "\
4279 This command parses the partition table on C<device> and
4280 returns the list of partitions found.
4281
4282 The fields in the returned structure are:
4283
4284 =over 4
4285
4286 =item B<part_num>
4287
4288 Partition number, counting from 1.
4289
4290 =item B<part_start>
4291
4292 Start of the partition I<in bytes>.  To get sectors you have to
4293 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4294
4295 =item B<part_end>
4296
4297 End of the partition in bytes.
4298
4299 =item B<part_size>
4300
4301 Size of the partition in bytes.
4302
4303 =back");
4304
4305   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4306    [InitEmpty, Always, TestOutput (
4307       [["part_disk"; "/dev/sda"; "gpt"];
4308        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4309    "get the partition table type",
4310    "\
4311 This command examines the partition table on C<device> and
4312 returns the partition table type (format) being used.
4313
4314 Common return values include: C<msdos> (a DOS/Windows style MBR
4315 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4316 values are possible, although unusual.  See C<guestfs_part_init>
4317 for a full list.");
4318
4319   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4320    [InitBasicFS, Always, TestOutputBuffer (
4321       [["fill"; "0x63"; "10"; "/test"];
4322        ["read_file"; "/test"]], "cccccccccc")],
4323    "fill a file with octets",
4324    "\
4325 This command creates a new file called C<path>.  The initial
4326 content of the file is C<len> octets of C<c>, where C<c>
4327 must be a number in the range C<[0..255]>.
4328
4329 To fill a file with zero bytes (sparsely), it is
4330 much more efficient to use C<guestfs_truncate_size>.
4331 To create a file with a pattern of repeating bytes
4332 use C<guestfs_fill_pattern>.");
4333
4334   ("available", (RErr, [StringList "groups"]), 216, [],
4335    [InitNone, Always, TestRun [["available"; ""]]],
4336    "test availability of some parts of the API",
4337    "\
4338 This command is used to check the availability of some
4339 groups of functionality in the appliance, which not all builds of
4340 the libguestfs appliance will be able to provide.
4341
4342 The libguestfs groups, and the functions that those
4343 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4344 You can also fetch this list at runtime by calling
4345 C<guestfs_available_all_groups>.
4346
4347 The argument C<groups> is a list of group names, eg:
4348 C<[\"inotify\", \"augeas\"]> would check for the availability of
4349 the Linux inotify functions and Augeas (configuration file
4350 editing) functions.
4351
4352 The command returns no error if I<all> requested groups are available.
4353
4354 It fails with an error if one or more of the requested
4355 groups is unavailable in the appliance.
4356
4357 If an unknown group name is included in the
4358 list of groups then an error is always returned.
4359
4360 I<Notes:>
4361
4362 =over 4
4363
4364 =item *
4365
4366 You must call C<guestfs_launch> before calling this function.
4367
4368 The reason is because we don't know what groups are
4369 supported by the appliance/daemon until it is running and can
4370 be queried.
4371
4372 =item *
4373
4374 If a group of functions is available, this does not necessarily
4375 mean that they will work.  You still have to check for errors
4376 when calling individual API functions even if they are
4377 available.
4378
4379 =item *
4380
4381 It is usually the job of distro packagers to build
4382 complete functionality into the libguestfs appliance.
4383 Upstream libguestfs, if built from source with all
4384 requirements satisfied, will support everything.
4385
4386 =item *
4387
4388 This call was added in version C<1.0.80>.  In previous
4389 versions of libguestfs all you could do would be to speculatively
4390 execute a command to find out if the daemon implemented it.
4391 See also C<guestfs_version>.
4392
4393 =back");
4394
4395   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4396    [InitBasicFS, Always, TestOutputBuffer (
4397       [["write"; "/src"; "hello, world"];
4398        ["dd"; "/src"; "/dest"];
4399        ["read_file"; "/dest"]], "hello, world")],
4400    "copy from source to destination using dd",
4401    "\
4402 This command copies from one source device or file C<src>
4403 to another destination device or file C<dest>.  Normally you
4404 would use this to copy to or from a device or partition, for
4405 example to duplicate a filesystem.
4406
4407 If the destination is a device, it must be as large or larger
4408 than the source file or device, otherwise the copy will fail.
4409 This command cannot do partial copies (see C<guestfs_copy_size>).");
4410
4411   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4412    [InitBasicFS, Always, TestOutputInt (
4413       [["write"; "/file"; "hello, world"];
4414        ["filesize"; "/file"]], 12)],
4415    "return the size of the file in bytes",
4416    "\
4417 This command returns the size of C<file> in bytes.
4418
4419 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4420 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4421 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4422
4423   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4424    [InitBasicFSonLVM, Always, TestOutputList (
4425       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4426        ["lvs"]], ["/dev/VG/LV2"])],
4427    "rename an LVM logical volume",
4428    "\
4429 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4430
4431   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4432    [InitBasicFSonLVM, Always, TestOutputList (
4433       [["umount"; "/"];
4434        ["vg_activate"; "false"; "VG"];
4435        ["vgrename"; "VG"; "VG2"];
4436        ["vg_activate"; "true"; "VG2"];
4437        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4438        ["vgs"]], ["VG2"])],
4439    "rename an LVM volume group",
4440    "\
4441 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4442
4443   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4444    [InitISOFS, Always, TestOutputBuffer (
4445       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4446    "list the contents of a single file in an initrd",
4447    "\
4448 This command unpacks the file C<filename> from the initrd file
4449 called C<initrdpath>.  The filename must be given I<without> the
4450 initial C</> character.
4451
4452 For example, in guestfish you could use the following command
4453 to examine the boot script (usually called C</init>)
4454 contained in a Linux initrd or initramfs image:
4455
4456  initrd-cat /boot/initrd-<version>.img init
4457
4458 See also C<guestfs_initrd_list>.");
4459
4460   ("pvuuid", (RString "uuid", [Device "device"]), 222, [],
4461    [],
4462    "get the UUID of a physical volume",
4463    "\
4464 This command returns the UUID of the LVM PV C<device>.");
4465
4466   ("vguuid", (RString "uuid", [String "vgname"]), 223, [],
4467    [],
4468    "get the UUID of a volume group",
4469    "\
4470 This command returns the UUID of the LVM VG named C<vgname>.");
4471
4472   ("lvuuid", (RString "uuid", [Device "device"]), 224, [],
4473    [],
4474    "get the UUID of a logical volume",
4475    "\
4476 This command returns the UUID of the LVM LV C<device>.");
4477
4478   ("vgpvuuids", (RStringList "uuids", [String "vgname"]), 225, [],
4479    [],
4480    "get the PV UUIDs containing the volume group",
4481    "\
4482 Given a VG called C<vgname>, this returns the UUIDs of all
4483 the physical volumes that this volume group resides on.
4484
4485 You can use this along with C<guestfs_pvs> and C<guestfs_pvuuid>
4486 calls to associate physical volumes and volume groups.
4487
4488 See also C<guestfs_vglvuuids>.");
4489
4490   ("vglvuuids", (RStringList "uuids", [String "vgname"]), 226, [],
4491    [],
4492    "get the LV UUIDs of all LVs in the volume group",
4493    "\
4494 Given a VG called C<vgname>, this returns the UUIDs of all
4495 the logical volumes created in this volume group.
4496
4497 You can use this along with C<guestfs_lvs> and C<guestfs_lvuuid>
4498 calls to associate logical volumes and volume groups.
4499
4500 See also C<guestfs_vgpvuuids>.");
4501
4502   ("copy_size", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"; Int64 "size"]), 227, [],
4503    [InitBasicFS, Always, TestOutputBuffer (
4504       [["write"; "/src"; "hello, world"];
4505        ["copy_size"; "/src"; "/dest"; "5"];
4506        ["read_file"; "/dest"]], "hello")],
4507    "copy size bytes from source to destination using dd",
4508    "\
4509 This command copies exactly C<size> bytes from one source device
4510 or file C<src> to another destination device or file C<dest>.
4511
4512 Note this will fail if the source is too short or if the destination
4513 is not large enough.");
4514
4515   ("zero_device", (RErr, [Device "device"]), 228, [DangerWillRobinson],
4516    [InitBasicFSonLVM, Always, TestRun (
4517       [["zero_device"; "/dev/VG/LV"]])],
4518    "write zeroes to an entire device",
4519    "\
4520 This command writes zeroes over the entire C<device>.  Compare
4521 with C<guestfs_zero> which just zeroes the first few blocks of
4522 a device.");
4523
4524   ("txz_in", (RErr, [FileIn "tarball"; Pathname "directory"]), 229, [Optional "xz"],
4525    [InitBasicFS, Always, TestOutput (
4526       [["txz_in"; "../images/helloworld.tar.xz"; "/"];
4527        ["cat"; "/hello"]], "hello\n")],
4528    "unpack compressed tarball to directory",
4529    "\
4530 This command uploads and unpacks local file C<tarball> (an
4531 I<xz compressed> tar file) into C<directory>.");
4532
4533   ("txz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 230, [Optional "xz"],
4534    [],
4535    "pack directory into compressed tarball",
4536    "\
4537 This command packs the contents of C<directory> and downloads
4538 it to local file C<tarball> (as an xz compressed tar archive).");
4539
4540   ("ntfsresize", (RErr, [Device "device"]), 231, [Optional "ntfsprogs"],
4541    [],
4542    "resize an NTFS filesystem",
4543    "\
4544 This command resizes an NTFS filesystem, expanding or
4545 shrinking it to the size of the underlying device.
4546 See also L<ntfsresize(8)>.");
4547
4548   ("vgscan", (RErr, []), 232, [],
4549    [InitEmpty, Always, TestRun (
4550       [["vgscan"]])],
4551    "rescan for LVM physical volumes, volume groups and logical volumes",
4552    "\
4553 This rescans all block devices and rebuilds the list of LVM
4554 physical volumes, volume groups and logical volumes.");
4555
4556   ("part_del", (RErr, [Device "device"; Int "partnum"]), 233, [],
4557    [InitEmpty, Always, TestRun (
4558       [["part_init"; "/dev/sda"; "mbr"];
4559        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4560        ["part_del"; "/dev/sda"; "1"]])],
4561    "delete a partition",
4562    "\
4563 This command deletes the partition numbered C<partnum> on C<device>.
4564
4565 Note that in the case of MBR partitioning, deleting an
4566 extended partition also deletes any logical partitions
4567 it contains.");
4568
4569   ("part_get_bootable", (RBool "bootable", [Device "device"; Int "partnum"]), 234, [],
4570    [InitEmpty, Always, TestOutputTrue (
4571       [["part_init"; "/dev/sda"; "mbr"];
4572        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4573        ["part_set_bootable"; "/dev/sda"; "1"; "true"];
4574        ["part_get_bootable"; "/dev/sda"; "1"]])],
4575    "return true if a partition is bootable",
4576    "\
4577 This command returns true if the partition C<partnum> on
4578 C<device> has the bootable flag set.
4579
4580 See also C<guestfs_part_set_bootable>.");
4581
4582   ("part_get_mbr_id", (RInt "idbyte", [Device "device"; Int "partnum"]), 235, [FishOutput FishOutputHexadecimal],
4583    [InitEmpty, Always, TestOutputInt (
4584       [["part_init"; "/dev/sda"; "mbr"];
4585        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"];
4586        ["part_set_mbr_id"; "/dev/sda"; "1"; "0x7f"];
4587        ["part_get_mbr_id"; "/dev/sda"; "1"]], 0x7f)],
4588    "get the MBR type byte (ID byte) from a partition",
4589    "\
4590 Returns the MBR type byte (also known as the ID byte) from
4591 the numbered partition C<partnum>.
4592
4593 Note that only MBR (old DOS-style) partitions have type bytes.
4594 You will get undefined results for other partition table
4595 types (see C<guestfs_part_get_parttype>).");
4596
4597   ("part_set_mbr_id", (RErr, [Device "device"; Int "partnum"; Int "idbyte"]), 236, [],
4598    [], (* tested by part_get_mbr_id *)
4599    "set the MBR type byte (ID byte) of a partition",
4600    "\
4601 Sets the MBR type byte (also known as the ID byte) of
4602 the numbered partition C<partnum> to C<idbyte>.  Note
4603 that the type bytes quoted in most documentation are
4604 in fact hexadecimal numbers, but usually documented
4605 without any leading \"0x\" which might be confusing.
4606
4607 Note that only MBR (old DOS-style) partitions have type bytes.
4608 You will get undefined results for other partition table
4609 types (see C<guestfs_part_get_parttype>).");
4610
4611   ("checksum_device", (RString "checksum", [String "csumtype"; Device "device"]), 237, [],
4612    [InitISOFS, Always, TestOutput (
4613       [["checksum_device"; "md5"; "/dev/sdd"]],
4614       (Digest.to_hex (Digest.file "images/test.iso")))],
4615    "compute MD5, SHAx or CRC checksum of the contents of a device",
4616    "\
4617 This call computes the MD5, SHAx or CRC checksum of the
4618 contents of the device named C<device>.  For the types of
4619 checksums supported see the C<guestfs_checksum> command.");
4620
4621   ("lvresize_free", (RErr, [Device "lv"; Int "percent"]), 238, [Optional "lvm2"],
4622    [InitNone, Always, TestRun (
4623       [["part_disk"; "/dev/sda"; "mbr"];
4624        ["pvcreate"; "/dev/sda1"];
4625        ["vgcreate"; "VG"; "/dev/sda1"];
4626        ["lvcreate"; "LV"; "VG"; "10"];
4627        ["lvresize_free"; "/dev/VG/LV"; "100"]])],
4628    "expand an LV to fill free space",
4629    "\
4630 This expands an existing logical volume C<lv> so that it fills
4631 C<pc>% of the remaining free space in the volume group.  Commonly
4632 you would call this with pc = 100 which expands the logical volume
4633 as much as possible, using all remaining free space in the volume
4634 group.");
4635
4636   ("aug_clear", (RErr, [String "augpath"]), 239, [Optional "augeas"],
4637    [], (* XXX Augeas code needs tests. *)
4638    "clear Augeas path",
4639    "\
4640 Set the value associated with C<path> to C<NULL>.  This
4641 is the same as the L<augtool(1)> C<clear> command.");
4642
4643   ("get_umask", (RInt "mask", []), 240, [FishOutput FishOutputOctal],
4644    [InitEmpty, Always, TestOutputInt (
4645       [["get_umask"]], 0o22)],
4646    "get the current umask",
4647    "\
4648 Return the current umask.  By default the umask is C<022>
4649 unless it has been set by calling C<guestfs_umask>.");
4650
4651   ("debug_upload", (RErr, [FileIn "filename"; String "tmpname"; Int "mode"]), 241, [],
4652    [],
4653    "upload a file to the appliance (internal use only)",
4654    "\
4655 The C<guestfs_debug_upload> command uploads a file to
4656 the libguestfs appliance.
4657
4658 There is no comprehensive help for this command.  You have
4659 to look at the file C<daemon/debug.c> in the libguestfs source
4660 to find out what it is for.");
4661
4662   ("base64_in", (RErr, [FileIn "base64file"; Pathname "filename"]), 242, [],
4663    [InitBasicFS, Always, TestOutput (
4664       [["base64_in"; "../images/hello.b64"; "/hello"];
4665        ["cat"; "/hello"]], "hello\n")],
4666    "upload base64-encoded data to file",
4667    "\
4668 This command uploads base64-encoded data from C<base64file>
4669 to C<filename>.");
4670
4671   ("base64_out", (RErr, [Pathname "filename"; FileOut "base64file"]), 243, [],
4672    [],
4673    "download file and encode as base64",
4674    "\
4675 This command downloads the contents of C<filename>, writing
4676 it out to local file C<base64file> encoded as base64.");
4677
4678   ("checksums_out", (RErr, [String "csumtype"; Pathname "directory"; FileOut "sumsfile"]), 244, [],
4679    [],
4680    "compute MD5, SHAx or CRC checksum of files in a directory",
4681    "\
4682 This command computes the checksums of all regular files in
4683 C<directory> and then emits a list of those checksums to
4684 the local output file C<sumsfile>.
4685
4686 This can be used for verifying the integrity of a virtual
4687 machine.  However to be properly secure you should pay
4688 attention to the output of the checksum command (it uses
4689 the ones from GNU coreutils).  In particular when the
4690 filename is not printable, coreutils uses a special
4691 backslash syntax.  For more information, see the GNU
4692 coreutils info file.");
4693
4694   ("fill_pattern", (RErr, [String "pattern"; Int "len"; Pathname "path"]), 245, [],
4695    [InitBasicFS, Always, TestOutputBuffer (
4696       [["fill_pattern"; "abcdefghijklmnopqrstuvwxyz"; "28"; "/test"];
4697        ["read_file"; "/test"]], "abcdefghijklmnopqrstuvwxyzab")],
4698    "fill a file with a repeating pattern of bytes",
4699    "\
4700 This function is like C<guestfs_fill> except that it creates
4701 a new file of length C<len> containing the repeating pattern
4702 of bytes in C<pattern>.  The pattern is truncated if necessary
4703 to ensure the length of the file is exactly C<len> bytes.");
4704
4705   ("write", (RErr, [Pathname "path"; BufferIn "content"]), 246, [ProtocolLimitWarning],
4706    [InitBasicFS, Always, TestOutput (
4707       [["write"; "/new"; "new file contents"];
4708        ["cat"; "/new"]], "new file contents");
4709     InitBasicFS, Always, TestOutput (
4710       [["write"; "/new"; "\nnew file contents\n"];
4711        ["cat"; "/new"]], "\nnew file contents\n");
4712     InitBasicFS, Always, TestOutput (
4713       [["write"; "/new"; "\n\n"];
4714        ["cat"; "/new"]], "\n\n");
4715     InitBasicFS, Always, TestOutput (
4716       [["write"; "/new"; ""];
4717        ["cat"; "/new"]], "");
4718     InitBasicFS, Always, TestOutput (
4719       [["write"; "/new"; "\n\n\n"];
4720        ["cat"; "/new"]], "\n\n\n");
4721     InitBasicFS, Always, TestOutput (
4722       [["write"; "/new"; "\n"];
4723        ["cat"; "/new"]], "\n")],
4724    "create a new file",
4725    "\
4726 This call creates a file called C<path>.  The content of the
4727 file is the string C<content> (which can contain any 8 bit data).");
4728
4729   ("pwrite", (RInt "nbytes", [Pathname "path"; BufferIn "content"; Int64 "offset"]), 247, [ProtocolLimitWarning],
4730    [InitBasicFS, Always, TestOutput (
4731       [["write"; "/new"; "new file contents"];
4732        ["pwrite"; "/new"; "data"; "4"];
4733        ["cat"; "/new"]], "new data contents");
4734     InitBasicFS, Always, TestOutput (
4735       [["write"; "/new"; "new file contents"];
4736        ["pwrite"; "/new"; "is extended"; "9"];
4737        ["cat"; "/new"]], "new file is extended");
4738     InitBasicFS, Always, TestOutput (
4739       [["write"; "/new"; "new file contents"];
4740        ["pwrite"; "/new"; ""; "4"];
4741        ["cat"; "/new"]], "new file contents")],
4742    "write to part of a file",
4743    "\
4744 This command writes to part of a file.  It writes the data
4745 buffer C<content> to the file C<path> starting at offset C<offset>.
4746
4747 This command implements the L<pwrite(2)> system call, and like
4748 that system call it may not write the full data requested.  The
4749 return value is the number of bytes that were actually written
4750 to the file.  This could even be 0, although short writes are
4751 unlikely for regular files in ordinary circumstances.
4752
4753 See also C<guestfs_pread>.");
4754
4755   ("resize2fs_size", (RErr, [Device "device"; Int64 "size"]), 248, [],
4756    [],
4757    "resize an ext2, ext3 or ext4 filesystem (with size)",
4758    "\
4759 This command is the same as C<guestfs_resize2fs> except that it
4760 allows you to specify the new size (in bytes) explicitly.");
4761
4762   ("pvresize_size", (RErr, [Device "device"; Int64 "size"]), 249, [Optional "lvm2"],
4763    [],
4764    "resize an LVM physical volume (with size)",
4765    "\
4766 This command is the same as C<guestfs_pvresize> except that it
4767 allows you to specify the new size (in bytes) explicitly.");
4768
4769   ("ntfsresize_size", (RErr, [Device "device"; Int64 "size"]), 250, [Optional "ntfsprogs"],
4770    [],
4771    "resize an NTFS filesystem (with size)",
4772    "\
4773 This command is the same as C<guestfs_ntfsresize> except that it
4774 allows you to specify the new size (in bytes) explicitly.");
4775
4776   ("available_all_groups", (RStringList "groups", []), 251, [],
4777    [InitNone, Always, TestRun [["available_all_groups"]]],
4778    "return a list of all optional groups",
4779    "\
4780 This command returns a list of all optional groups that this
4781 daemon knows about.  Note this returns both supported and unsupported
4782 groups.  To find out which ones the daemon can actually support
4783 you have to call C<guestfs_available> on each member of the
4784 returned list.
4785
4786 See also C<guestfs_available> and L<guestfs(3)/AVAILABILITY>.");
4787
4788   ("fallocate64", (RErr, [Pathname "path"; Int64 "len"]), 252, [],
4789    [InitBasicFS, Always, TestOutputStruct (
4790       [["fallocate64"; "/a"; "1000000"];
4791        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
4792    "preallocate a file in the guest filesystem",
4793    "\
4794 This command preallocates a file (containing zero bytes) named
4795 C<path> of size C<len> bytes.  If the file exists already, it
4796 is overwritten.
4797
4798 Note that this call allocates disk blocks for the file.
4799 To create a sparse file use C<guestfs_truncate_size> instead.
4800
4801 The deprecated call C<guestfs_fallocate> does the same,
4802 but owing to an oversight it only allowed 30 bit lengths
4803 to be specified, effectively limiting the maximum size
4804 of files created through that call to 1GB.
4805
4806 Do not confuse this with the guestfish-specific
4807 C<alloc> and C<sparse> commands which create
4808 a file in the host and attach it as a device.");
4809
4810   ("vfs_label", (RString "label", [Device "device"]), 253, [],
4811    [InitBasicFS, Always, TestOutput (
4812        [["set_e2label"; "/dev/sda1"; "LTEST"];
4813         ["vfs_label"; "/dev/sda1"]], "LTEST")],
4814    "get the filesystem label",
4815    "\
4816 This returns the filesystem label of the filesystem on
4817 C<device>.
4818
4819 If the filesystem is unlabeled, this returns the empty string.");
4820
4821   ("vfs_uuid", (RString "uuid", [Device "device"]), 254, [],
4822    (let uuid = uuidgen () in
4823     [InitBasicFS, Always, TestOutput (
4824        [["set_e2uuid"; "/dev/sda1"; uuid];
4825         ["vfs_uuid"; "/dev/sda1"]], uuid)]),
4826    "get the filesystem UUID",
4827    "\
4828 This returns the filesystem UUID of the filesystem on
4829 C<device>.
4830
4831 If the filesystem does not have a UUID, this returns the empty string.");
4832
4833 ]
4834
4835 let all_functions = non_daemon_functions @ daemon_functions
4836
4837 (* In some places we want the functions to be displayed sorted
4838  * alphabetically, so this is useful:
4839  *)
4840 let all_functions_sorted =
4841   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4842                compare n1 n2) all_functions
4843
4844 (* This is used to generate the src/MAX_PROC_NR file which
4845  * contains the maximum procedure number, a surrogate for the
4846  * ABI version number.  See src/Makefile.am for the details.
4847  *)
4848 let max_proc_nr =
4849   let proc_nrs = List.map (
4850     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
4851   ) daemon_functions in
4852   List.fold_left max 0 proc_nrs
4853
4854 (* Field types for structures. *)
4855 type field =
4856   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4857   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4858   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4859   | FUInt32
4860   | FInt32
4861   | FUInt64
4862   | FInt64
4863   | FBytes                      (* Any int measure that counts bytes. *)
4864   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4865   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4866
4867 (* Because we generate extra parsing code for LVM command line tools,
4868  * we have to pull out the LVM columns separately here.
4869  *)
4870 let lvm_pv_cols = [
4871   "pv_name", FString;
4872   "pv_uuid", FUUID;
4873   "pv_fmt", FString;
4874   "pv_size", FBytes;
4875   "dev_size", FBytes;
4876   "pv_free", FBytes;
4877   "pv_used", FBytes;
4878   "pv_attr", FString (* XXX *);
4879   "pv_pe_count", FInt64;
4880   "pv_pe_alloc_count", FInt64;
4881   "pv_tags", FString;
4882   "pe_start", FBytes;
4883   "pv_mda_count", FInt64;
4884   "pv_mda_free", FBytes;
4885   (* Not in Fedora 10:
4886      "pv_mda_size", FBytes;
4887   *)
4888 ]
4889 let lvm_vg_cols = [
4890   "vg_name", FString;
4891   "vg_uuid", FUUID;
4892   "vg_fmt", FString;
4893   "vg_attr", FString (* XXX *);
4894   "vg_size", FBytes;
4895   "vg_free", FBytes;
4896   "vg_sysid", FString;
4897   "vg_extent_size", FBytes;
4898   "vg_extent_count", FInt64;
4899   "vg_free_count", FInt64;
4900   "max_lv", FInt64;
4901   "max_pv", FInt64;
4902   "pv_count", FInt64;
4903   "lv_count", FInt64;
4904   "snap_count", FInt64;
4905   "vg_seqno", FInt64;
4906   "vg_tags", FString;
4907   "vg_mda_count", FInt64;
4908   "vg_mda_free", FBytes;
4909   (* Not in Fedora 10:
4910      "vg_mda_size", FBytes;
4911   *)
4912 ]
4913 let lvm_lv_cols = [
4914   "lv_name", FString;
4915   "lv_uuid", FUUID;
4916   "lv_attr", FString (* XXX *);
4917   "lv_major", FInt64;
4918   "lv_minor", FInt64;
4919   "lv_kernel_major", FInt64;
4920   "lv_kernel_minor", FInt64;
4921   "lv_size", FBytes;
4922   "seg_count", FInt64;
4923   "origin", FString;
4924   "snap_percent", FOptPercent;
4925   "copy_percent", FOptPercent;
4926   "move_pv", FString;
4927   "lv_tags", FString;
4928   "mirror_log", FString;
4929   "modules", FString;
4930 ]
4931
4932 (* Names and fields in all structures (in RStruct and RStructList)
4933  * that we support.
4934  *)
4935 let structs = [
4936   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4937    * not use this struct in any new code.
4938    *)
4939   "int_bool", [
4940     "i", FInt32;                (* for historical compatibility *)
4941     "b", FInt32;                (* for historical compatibility *)
4942   ];
4943
4944   (* LVM PVs, VGs, LVs. *)
4945   "lvm_pv", lvm_pv_cols;
4946   "lvm_vg", lvm_vg_cols;
4947   "lvm_lv", lvm_lv_cols;
4948
4949   (* Column names and types from stat structures.
4950    * NB. Can't use things like 'st_atime' because glibc header files
4951    * define some of these as macros.  Ugh.
4952    *)
4953   "stat", [
4954     "dev", FInt64;
4955     "ino", FInt64;
4956     "mode", FInt64;
4957     "nlink", FInt64;
4958     "uid", FInt64;
4959     "gid", FInt64;
4960     "rdev", FInt64;
4961     "size", FInt64;
4962     "blksize", FInt64;
4963     "blocks", FInt64;
4964     "atime", FInt64;
4965     "mtime", FInt64;
4966     "ctime", FInt64;
4967   ];
4968   "statvfs", [
4969     "bsize", FInt64;
4970     "frsize", FInt64;
4971     "blocks", FInt64;
4972     "bfree", FInt64;
4973     "bavail", FInt64;
4974     "files", FInt64;
4975     "ffree", FInt64;
4976     "favail", FInt64;
4977     "fsid", FInt64;
4978     "flag", FInt64;
4979     "namemax", FInt64;
4980   ];
4981
4982   (* Column names in dirent structure. *)
4983   "dirent", [
4984     "ino", FInt64;
4985     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4986     "ftyp", FChar;
4987     "name", FString;
4988   ];
4989
4990   (* Version numbers. *)
4991   "version", [
4992     "major", FInt64;
4993     "minor", FInt64;
4994     "release", FInt64;
4995     "extra", FString;
4996   ];
4997
4998   (* Extended attribute. *)
4999   "xattr", [
5000     "attrname", FString;
5001     "attrval", FBuffer;
5002   ];
5003
5004   (* Inotify events. *)
5005   "inotify_event", [
5006     "in_wd", FInt64;
5007     "in_mask", FUInt32;
5008     "in_cookie", FUInt32;
5009     "in_name", FString;
5010   ];
5011
5012   (* Partition table entry. *)
5013   "partition", [
5014     "part_num", FInt32;
5015     "part_start", FBytes;
5016     "part_end", FBytes;
5017     "part_size", FBytes;
5018   ];
5019 ] (* end of structs *)
5020
5021 (* Ugh, Java has to be different ..
5022  * These names are also used by the Haskell bindings.
5023  *)
5024 let java_structs = [
5025   "int_bool", "IntBool";
5026   "lvm_pv", "PV";
5027   "lvm_vg", "VG";
5028   "lvm_lv", "LV";
5029   "stat", "Stat";
5030   "statvfs", "StatVFS";
5031   "dirent", "Dirent";
5032   "version", "Version";
5033   "xattr", "XAttr";
5034   "inotify_event", "INotifyEvent";
5035   "partition", "Partition";
5036 ]
5037
5038 (* What structs are actually returned. *)
5039 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
5040
5041 (* Returns a list of RStruct/RStructList structs that are returned
5042  * by any function.  Each element of returned list is a pair:
5043  *
5044  * (structname, RStructOnly)
5045  *    == there exists function which returns RStruct (_, structname)
5046  * (structname, RStructListOnly)
5047  *    == there exists function which returns RStructList (_, structname)
5048  * (structname, RStructAndList)
5049  *    == there are functions returning both RStruct (_, structname)
5050  *                                      and RStructList (_, structname)
5051  *)
5052 let rstructs_used_by functions =
5053   (* ||| is a "logical OR" for rstructs_used_t *)
5054   let (|||) a b =
5055     match a, b with
5056     | RStructAndList, _
5057     | _, RStructAndList -> RStructAndList
5058     | RStructOnly, RStructListOnly
5059     | RStructListOnly, RStructOnly -> RStructAndList
5060     | RStructOnly, RStructOnly -> RStructOnly
5061     | RStructListOnly, RStructListOnly -> RStructListOnly
5062   in
5063
5064   let h = Hashtbl.create 13 in
5065
5066   (* if elem->oldv exists, update entry using ||| operator,
5067    * else just add elem->newv to the hash
5068    *)
5069   let update elem newv =
5070     try  let oldv = Hashtbl.find h elem in
5071          Hashtbl.replace h elem (newv ||| oldv)
5072     with Not_found -> Hashtbl.add h elem newv
5073   in
5074
5075   List.iter (
5076     fun (_, style, _, _, _, _, _) ->
5077       match fst style with
5078       | RStruct (_, structname) -> update structname RStructOnly
5079       | RStructList (_, structname) -> update structname RStructListOnly
5080       | _ -> ()
5081   ) functions;
5082
5083   (* return key->values as a list of (key,value) *)
5084   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
5085
5086 (* Used for testing language bindings. *)
5087 type callt =
5088   | CallString of string
5089   | CallOptString of string option
5090   | CallStringList of string list
5091   | CallInt of int
5092   | CallInt64 of int64
5093   | CallBool of bool
5094   | CallBuffer of string
5095
5096 (* Used for the guestfish -N (prepared disk images) option.
5097  * Note that the longdescs are indented by 2 spaces.
5098  *)
5099 let prepopts = [
5100   ("disk",
5101    "create a blank disk",
5102    [ "size", "100M", "the size of the disk image" ],
5103    "  Create a blank disk, size 100MB (by default).
5104
5105   The default size can be changed by supplying an optional parameter.");
5106
5107   ("part",
5108    "create a partitioned disk",
5109    [ "size", "100M", "the size of the disk image";
5110      "partition", "mbr", "partition table type" ],
5111    "  Create a disk with a single partition.  By default the size of the disk
5112   is 100MB (the available space in the partition will be a tiny bit smaller)
5113   and the partition table will be MBR (old DOS-style).
5114
5115   These defaults can be changed by supplying optional parameters.");
5116
5117   ("fs",
5118    "create a filesystem",
5119    [ "filesystem", "ext2", "the type of filesystem to use";
5120      "size", "100M", "the size of the disk image";
5121      "partition", "mbr", "partition table type" ],
5122    "  Create a disk with a single partition, with the partition containing
5123   an empty filesystem.  This defaults to creating a 100MB disk (the available
5124   space in the filesystem will be a tiny bit smaller) with an MBR (old
5125   DOS-style) partition table and an ext2 filesystem.
5126
5127   These defaults can be changed by supplying optional parameters.");
5128 ]
5129
5130 (* Used to memoize the result of pod2text. *)
5131 let pod2text_memo_filename = "src/.pod2text.data"
5132 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
5133   try
5134     let chan = open_in pod2text_memo_filename in
5135     let v = input_value chan in
5136     close_in chan;
5137     v
5138   with
5139     _ -> Hashtbl.create 13
5140 let pod2text_memo_updated () =
5141   let chan = open_out pod2text_memo_filename in
5142   output_value chan pod2text_memo;
5143   close_out chan
5144
5145 (* Useful functions.
5146  * Note we don't want to use any external OCaml libraries which
5147  * makes this a bit harder than it should be.
5148  *)
5149 module StringMap = Map.Make (String)
5150
5151 let failwithf fs = ksprintf failwith fs
5152
5153 let unique = let i = ref 0 in fun () -> incr i; !i
5154
5155 let replace_char s c1 c2 =
5156   let s2 = String.copy s in
5157   let r = ref false in
5158   for i = 0 to String.length s2 - 1 do
5159     if String.unsafe_get s2 i = c1 then (
5160       String.unsafe_set s2 i c2;
5161       r := true
5162     )
5163   done;
5164   if not !r then s else s2
5165
5166 let isspace c =
5167   c = ' '
5168   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
5169
5170 let triml ?(test = isspace) str =
5171   let i = ref 0 in
5172   let n = ref (String.length str) in
5173   while !n > 0 && test str.[!i]; do
5174     decr n;
5175     incr i
5176   done;
5177   if !i = 0 then str
5178   else String.sub str !i !n
5179
5180 let trimr ?(test = isspace) str =
5181   let n = ref (String.length str) in
5182   while !n > 0 && test str.[!n-1]; do
5183     decr n
5184   done;
5185   if !n = String.length str then str
5186   else String.sub str 0 !n
5187
5188 let trim ?(test = isspace) str =
5189   trimr ~test (triml ~test str)
5190
5191 let rec find s sub =
5192   let len = String.length s in
5193   let sublen = String.length sub in
5194   let rec loop i =
5195     if i <= len-sublen then (
5196       let rec loop2 j =
5197         if j < sublen then (
5198           if s.[i+j] = sub.[j] then loop2 (j+1)
5199           else -1
5200         ) else
5201           i (* found *)
5202       in
5203       let r = loop2 0 in
5204       if r = -1 then loop (i+1) else r
5205     ) else
5206       -1 (* not found *)
5207   in
5208   loop 0
5209
5210 let rec replace_str s s1 s2 =
5211   let len = String.length s in
5212   let sublen = String.length s1 in
5213   let i = find s s1 in
5214   if i = -1 then s
5215   else (
5216     let s' = String.sub s 0 i in
5217     let s'' = String.sub s (i+sublen) (len-i-sublen) in
5218     s' ^ s2 ^ replace_str s'' s1 s2
5219   )
5220
5221 let rec string_split sep str =
5222   let len = String.length str in
5223   let seplen = String.length sep in
5224   let i = find str sep in
5225   if i = -1 then [str]
5226   else (
5227     let s' = String.sub str 0 i in
5228     let s'' = String.sub str (i+seplen) (len-i-seplen) in
5229     s' :: string_split sep s''
5230   )
5231
5232 let files_equal n1 n2 =
5233   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
5234   match Sys.command cmd with
5235   | 0 -> true
5236   | 1 -> false
5237   | i -> failwithf "%s: failed with error code %d" cmd i
5238
5239 let rec filter_map f = function
5240   | [] -> []
5241   | x :: xs ->
5242       match f x with
5243       | Some y -> y :: filter_map f xs
5244       | None -> filter_map f xs
5245
5246 let rec find_map f = function
5247   | [] -> raise Not_found
5248   | x :: xs ->
5249       match f x with
5250       | Some y -> y
5251       | None -> find_map f xs
5252
5253 let iteri f xs =
5254   let rec loop i = function
5255     | [] -> ()
5256     | x :: xs -> f i x; loop (i+1) xs
5257   in
5258   loop 0 xs
5259
5260 let mapi f xs =
5261   let rec loop i = function
5262     | [] -> []
5263     | x :: xs -> let r = f i x in r :: loop (i+1) xs
5264   in
5265   loop 0 xs
5266
5267 let count_chars c str =
5268   let count = ref 0 in
5269   for i = 0 to String.length str - 1 do
5270     if c = String.unsafe_get str i then incr count
5271   done;
5272   !count
5273
5274 let explode str =
5275   let r = ref [] in
5276   for i = 0 to String.length str - 1 do
5277     let c = String.unsafe_get str i in
5278     r := c :: !r;
5279   done;
5280   List.rev !r
5281
5282 let map_chars f str =
5283   List.map f (explode str)
5284
5285 let name_of_argt = function
5286   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
5287   | StringList n | DeviceList n | Bool n | Int n | Int64 n
5288   | FileIn n | FileOut n | BufferIn n -> n
5289
5290 let java_name_of_struct typ =
5291   try List.assoc typ java_structs
5292   with Not_found ->
5293     failwithf
5294       "java_name_of_struct: no java_structs entry corresponding to %s" typ
5295
5296 let cols_of_struct typ =
5297   try List.assoc typ structs
5298   with Not_found ->
5299     failwithf "cols_of_struct: unknown struct %s" typ
5300
5301 let seq_of_test = function
5302   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
5303   | TestOutputListOfDevices (s, _)
5304   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
5305   | TestOutputTrue s | TestOutputFalse s
5306   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
5307   | TestOutputStruct (s, _)
5308   | TestLastFail s -> s
5309
5310 (* Handling for function flags. *)
5311 let protocol_limit_warning =
5312   "Because of the message protocol, there is a transfer limit
5313 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
5314
5315 let danger_will_robinson =
5316   "B<This command is dangerous.  Without careful use you
5317 can easily destroy all your data>."
5318
5319 let deprecation_notice flags =
5320   try
5321     let alt =
5322       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
5323     let txt =
5324       sprintf "This function is deprecated.
5325 In new code, use the C<%s> call instead.
5326
5327 Deprecated functions will not be removed from the API, but the
5328 fact that they are deprecated indicates that there are problems
5329 with correct use of these functions." alt in
5330     Some txt
5331   with
5332     Not_found -> None
5333
5334 (* Create list of optional groups. *)
5335 let optgroups =
5336   let h = Hashtbl.create 13 in
5337   List.iter (
5338     fun (name, _, _, flags, _, _, _) ->
5339       List.iter (
5340         function
5341         | Optional group ->
5342             let names = try Hashtbl.find h group with Not_found -> [] in
5343             Hashtbl.replace h group (name :: names)
5344         | _ -> ()
5345       ) flags
5346   ) daemon_functions;
5347   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
5348   let groups =
5349     List.map (
5350       fun group -> group, List.sort compare (Hashtbl.find h group)
5351     ) groups in
5352   List.sort (fun x y -> compare (fst x) (fst y)) groups
5353
5354 (* Check function names etc. for consistency. *)
5355 let check_functions () =
5356   let contains_uppercase str =
5357     let len = String.length str in
5358     let rec loop i =
5359       if i >= len then false
5360       else (
5361         let c = str.[i] in
5362         if c >= 'A' && c <= 'Z' then true
5363         else loop (i+1)
5364       )
5365     in
5366     loop 0
5367   in
5368
5369   (* Check function names. *)
5370   List.iter (
5371     fun (name, _, _, _, _, _, _) ->
5372       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
5373         failwithf "function name %s does not need 'guestfs' prefix" name;
5374       if name = "" then
5375         failwithf "function name is empty";
5376       if name.[0] < 'a' || name.[0] > 'z' then
5377         failwithf "function name %s must start with lowercase a-z" name;
5378       if String.contains name '-' then
5379         failwithf "function name %s should not contain '-', use '_' instead."
5380           name
5381   ) all_functions;
5382
5383   (* Check function parameter/return names. *)
5384   List.iter (
5385     fun (name, style, _, _, _, _, _) ->
5386       let check_arg_ret_name n =
5387         if contains_uppercase n then
5388           failwithf "%s param/ret %s should not contain uppercase chars"
5389             name n;
5390         if String.contains n '-' || String.contains n '_' then
5391           failwithf "%s param/ret %s should not contain '-' or '_'"
5392             name n;
5393         if n = "value" then
5394           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;
5395         if n = "int" || n = "char" || n = "short" || n = "long" then
5396           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
5397         if n = "i" || n = "n" then
5398           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
5399         if n = "argv" || n = "args" then
5400           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
5401
5402         (* List Haskell, OCaml and C keywords here.
5403          * http://www.haskell.org/haskellwiki/Keywords
5404          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
5405          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
5406          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
5407          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
5408          * Omitting _-containing words, since they're handled above.
5409          * Omitting the OCaml reserved word, "val", is ok,
5410          * and saves us from renaming several parameters.
5411          *)
5412         let reserved = [
5413           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
5414           "char"; "class"; "const"; "constraint"; "continue"; "data";
5415           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
5416           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
5417           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
5418           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
5419           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
5420           "interface";
5421           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
5422           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
5423           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
5424           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
5425           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
5426           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
5427           "volatile"; "when"; "where"; "while";
5428           ] in
5429         if List.mem n reserved then
5430           failwithf "%s has param/ret using reserved word %s" name n;
5431       in
5432
5433       (match fst style with
5434        | RErr -> ()
5435        | RInt n | RInt64 n | RBool n
5436        | RConstString n | RConstOptString n | RString n
5437        | RStringList n | RStruct (n, _) | RStructList (n, _)
5438        | RHashtable n | RBufferOut n ->
5439            check_arg_ret_name n
5440       );
5441       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
5442   ) all_functions;
5443
5444   (* Check short descriptions. *)
5445   List.iter (
5446     fun (name, _, _, _, _, shortdesc, _) ->
5447       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
5448         failwithf "short description of %s should begin with lowercase." name;
5449       let c = shortdesc.[String.length shortdesc-1] in
5450       if c = '\n' || c = '.' then
5451         failwithf "short description of %s should not end with . or \\n." name
5452   ) all_functions;
5453
5454   (* Check long descriptions. *)
5455   List.iter (
5456     fun (name, _, _, _, _, _, longdesc) ->
5457       if longdesc.[String.length longdesc-1] = '\n' then
5458         failwithf "long description of %s should not end with \\n." name
5459   ) all_functions;
5460
5461   (* Check proc_nrs. *)
5462   List.iter (
5463     fun (name, _, proc_nr, _, _, _, _) ->
5464       if proc_nr <= 0 then
5465         failwithf "daemon function %s should have proc_nr > 0" name
5466   ) daemon_functions;
5467
5468   List.iter (
5469     fun (name, _, proc_nr, _, _, _, _) ->
5470       if proc_nr <> -1 then
5471         failwithf "non-daemon function %s should have proc_nr -1" name
5472   ) non_daemon_functions;
5473
5474   let proc_nrs =
5475     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
5476       daemon_functions in
5477   let proc_nrs =
5478     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
5479   let rec loop = function
5480     | [] -> ()
5481     | [_] -> ()
5482     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
5483         loop rest
5484     | (name1,nr1) :: (name2,nr2) :: _ ->
5485         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
5486           name1 name2 nr1 nr2
5487   in
5488   loop proc_nrs;
5489
5490   (* Check tests. *)
5491   List.iter (
5492     function
5493       (* Ignore functions that have no tests.  We generate a
5494        * warning when the user does 'make check' instead.
5495        *)
5496     | name, _, _, _, [], _, _ -> ()
5497     | name, _, _, _, tests, _, _ ->
5498         let funcs =
5499           List.map (
5500             fun (_, _, test) ->
5501               match seq_of_test test with
5502               | [] ->
5503                   failwithf "%s has a test containing an empty sequence" name
5504               | cmds -> List.map List.hd cmds
5505           ) tests in
5506         let funcs = List.flatten funcs in
5507
5508         let tested = List.mem name funcs in
5509
5510         if not tested then
5511           failwithf "function %s has tests but does not test itself" name
5512   ) all_functions
5513
5514 (* 'pr' prints to the current output file. *)
5515 let chan = ref Pervasives.stdout
5516 let lines = ref 0
5517 let pr fs =
5518   ksprintf
5519     (fun str ->
5520        let i = count_chars '\n' str in
5521        lines := !lines + i;
5522        output_string !chan str
5523     ) fs
5524
5525 let copyright_years =
5526   let this_year = 1900 + (localtime (time ())).tm_year in
5527   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
5528
5529 (* Generate a header block in a number of standard styles. *)
5530 type comment_style =
5531     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
5532 type license = GPLv2plus | LGPLv2plus
5533
5534 let generate_header ?(extra_inputs = []) comment license =
5535   let inputs = "src/generator.ml" :: extra_inputs in
5536   let c = match comment with
5537     | CStyle ->         pr "/* "; " *"
5538     | CPlusPlusStyle -> pr "// "; "//"
5539     | HashStyle ->      pr "# ";  "#"
5540     | OCamlStyle ->     pr "(* "; " *"
5541     | HaskellStyle ->   pr "{- "; "  " in
5542   pr "libguestfs generated file\n";
5543   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
5544   List.iter (pr "%s   %s\n" c) inputs;
5545   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
5546   pr "%s\n" c;
5547   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
5548   pr "%s\n" c;
5549   (match license with
5550    | GPLv2plus ->
5551        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
5552        pr "%s it under the terms of the GNU General Public License as published by\n" c;
5553        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
5554        pr "%s (at your option) any later version.\n" c;
5555        pr "%s\n" c;
5556        pr "%s This program is distributed in the hope that it will be useful,\n" c;
5557        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5558        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
5559        pr "%s GNU General Public License for more details.\n" c;
5560        pr "%s\n" c;
5561        pr "%s You should have received a copy of the GNU General Public License along\n" c;
5562        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
5563        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
5564
5565    | LGPLv2plus ->
5566        pr "%s This library is free software; you can redistribute it and/or\n" c;
5567        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
5568        pr "%s License as published by the Free Software Foundation; either\n" c;
5569        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
5570        pr "%s\n" c;
5571        pr "%s This library is distributed in the hope that it will be useful,\n" c;
5572        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
5573        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
5574        pr "%s Lesser General Public License for more details.\n" c;
5575        pr "%s\n" c;
5576        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
5577        pr "%s License along with this library; if not, write to the Free Software\n" c;
5578        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
5579   );
5580   (match comment with
5581    | CStyle -> pr " */\n"
5582    | CPlusPlusStyle
5583    | HashStyle -> ()
5584    | OCamlStyle -> pr " *)\n"
5585    | HaskellStyle -> pr "-}\n"
5586   );
5587   pr "\n"
5588
5589 (* Start of main code generation functions below this line. *)
5590
5591 (* Generate the pod documentation for the C API. *)
5592 let rec generate_actions_pod () =
5593   List.iter (
5594     fun (shortname, style, _, flags, _, _, longdesc) ->
5595       if not (List.mem NotInDocs flags) then (
5596         let name = "guestfs_" ^ shortname in
5597         pr "=head2 %s\n\n" name;
5598         pr " ";
5599         generate_prototype ~extern:false ~handle:"g" name style;
5600         pr "\n\n";
5601         pr "%s\n\n" longdesc;
5602         (match fst style with
5603          | RErr ->
5604              pr "This function returns 0 on success or -1 on error.\n\n"
5605          | RInt _ ->
5606              pr "On error this function returns -1.\n\n"
5607          | RInt64 _ ->
5608              pr "On error this function returns -1.\n\n"
5609          | RBool _ ->
5610              pr "This function returns a C truth value on success or -1 on error.\n\n"
5611          | RConstString _ ->
5612              pr "This function returns a string, or NULL on error.
5613 The string is owned by the guest handle and must I<not> be freed.\n\n"
5614          | RConstOptString _ ->
5615              pr "This function returns a string which may be NULL.
5616 There is no way to return an error from this function.
5617 The string is owned by the guest handle and must I<not> be freed.\n\n"
5618          | RString _ ->
5619              pr "This function returns a string, or NULL on error.
5620 I<The caller must free the returned string after use>.\n\n"
5621          | RStringList _ ->
5622              pr "This function returns a NULL-terminated array of strings
5623 (like L<environ(3)>), or NULL if there was an error.
5624 I<The caller must free the strings and the array after use>.\n\n"
5625          | RStruct (_, typ) ->
5626              pr "This function returns a C<struct guestfs_%s *>,
5627 or NULL if there was an error.
5628 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5629          | RStructList (_, typ) ->
5630              pr "This function returns a C<struct guestfs_%s_list *>
5631 (see E<lt>guestfs-structs.hE<gt>),
5632 or NULL if there was an error.
5633 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5634          | RHashtable _ ->
5635              pr "This function returns a NULL-terminated array of
5636 strings, or NULL if there was an error.
5637 The array of strings will always have length C<2n+1>, where
5638 C<n> keys and values alternate, followed by the trailing NULL entry.
5639 I<The caller must free the strings and the array after use>.\n\n"
5640          | RBufferOut _ ->
5641              pr "This function returns a buffer, or NULL on error.
5642 The size of the returned buffer is written to C<*size_r>.
5643 I<The caller must free the returned buffer after use>.\n\n"
5644         );
5645         if List.mem ProtocolLimitWarning flags then
5646           pr "%s\n\n" protocol_limit_warning;
5647         if List.mem DangerWillRobinson flags then
5648           pr "%s\n\n" danger_will_robinson;
5649         match deprecation_notice flags with
5650         | None -> ()
5651         | Some txt -> pr "%s\n\n" txt
5652       )
5653   ) all_functions_sorted
5654
5655 and generate_structs_pod () =
5656   (* Structs documentation. *)
5657   List.iter (
5658     fun (typ, cols) ->
5659       pr "=head2 guestfs_%s\n" typ;
5660       pr "\n";
5661       pr " struct guestfs_%s {\n" typ;
5662       List.iter (
5663         function
5664         | name, FChar -> pr "   char %s;\n" name
5665         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5666         | name, FInt32 -> pr "   int32_t %s;\n" name
5667         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5668         | name, FInt64 -> pr "   int64_t %s;\n" name
5669         | name, FString -> pr "   char *%s;\n" name
5670         | name, FBuffer ->
5671             pr "   /* The next two fields describe a byte array. */\n";
5672             pr "   uint32_t %s_len;\n" name;
5673             pr "   char *%s;\n" name
5674         | name, FUUID ->
5675             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5676             pr "   char %s[32];\n" name
5677         | name, FOptPercent ->
5678             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5679             pr "   float %s;\n" name
5680       ) cols;
5681       pr " };\n";
5682       pr " \n";
5683       pr " struct guestfs_%s_list {\n" typ;
5684       pr "   uint32_t len; /* Number of elements in list. */\n";
5685       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5686       pr " };\n";
5687       pr " \n";
5688       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5689       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5690         typ typ;
5691       pr "\n"
5692   ) structs
5693
5694 and generate_availability_pod () =
5695   (* Availability documentation. *)
5696   pr "=over 4\n";
5697   pr "\n";
5698   List.iter (
5699     fun (group, functions) ->
5700       pr "=item B<%s>\n" group;
5701       pr "\n";
5702       pr "The following functions:\n";
5703       List.iter (pr "L</guestfs_%s>\n") functions;
5704       pr "\n"
5705   ) optgroups;
5706   pr "=back\n";
5707   pr "\n"
5708
5709 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5710  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5711  *
5712  * We have to use an underscore instead of a dash because otherwise
5713  * rpcgen generates incorrect code.
5714  *
5715  * This header is NOT exported to clients, but see also generate_structs_h.
5716  *)
5717 and generate_xdr () =
5718   generate_header CStyle LGPLv2plus;
5719
5720   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5721   pr "typedef string guestfs_str<>;\n";
5722   pr "\n";
5723
5724   (* Internal structures. *)
5725   List.iter (
5726     function
5727     | typ, cols ->
5728         pr "struct guestfs_int_%s {\n" typ;
5729         List.iter (function
5730                    | name, FChar -> pr "  char %s;\n" name
5731                    | name, FString -> pr "  string %s<>;\n" name
5732                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5733                    | name, FUUID -> pr "  opaque %s[32];\n" name
5734                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5735                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5736                    | name, FOptPercent -> pr "  float %s;\n" name
5737                   ) cols;
5738         pr "};\n";
5739         pr "\n";
5740         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5741         pr "\n";
5742   ) structs;
5743
5744   List.iter (
5745     fun (shortname, style, _, _, _, _, _) ->
5746       let name = "guestfs_" ^ shortname in
5747
5748       (match snd style with
5749        | [] -> ()
5750        | args ->
5751            pr "struct %s_args {\n" name;
5752            List.iter (
5753              function
5754              | Pathname n | Device n | Dev_or_Path n | String n ->
5755                  pr "  string %s<>;\n" n
5756              | OptString n -> pr "  guestfs_str *%s;\n" n
5757              | StringList n | DeviceList n -> pr "  guestfs_str %s<>;\n" n
5758              | Bool n -> pr "  bool %s;\n" n
5759              | Int n -> pr "  int %s;\n" n
5760              | Int64 n -> pr "  hyper %s;\n" n
5761              | BufferIn n ->
5762                  pr "  opaque %s<>;\n" n
5763              | FileIn _ | FileOut _ -> ()
5764            ) args;
5765            pr "};\n\n"
5766       );
5767       (match fst style with
5768        | RErr -> ()
5769        | RInt n ->
5770            pr "struct %s_ret {\n" name;
5771            pr "  int %s;\n" n;
5772            pr "};\n\n"
5773        | RInt64 n ->
5774            pr "struct %s_ret {\n" name;
5775            pr "  hyper %s;\n" n;
5776            pr "};\n\n"
5777        | RBool n ->
5778            pr "struct %s_ret {\n" name;
5779            pr "  bool %s;\n" n;
5780            pr "};\n\n"
5781        | RConstString _ | RConstOptString _ ->
5782            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5783        | RString n ->
5784            pr "struct %s_ret {\n" name;
5785            pr "  string %s<>;\n" n;
5786            pr "};\n\n"
5787        | RStringList n ->
5788            pr "struct %s_ret {\n" name;
5789            pr "  guestfs_str %s<>;\n" n;
5790            pr "};\n\n"
5791        | RStruct (n, typ) ->
5792            pr "struct %s_ret {\n" name;
5793            pr "  guestfs_int_%s %s;\n" typ n;
5794            pr "};\n\n"
5795        | RStructList (n, typ) ->
5796            pr "struct %s_ret {\n" name;
5797            pr "  guestfs_int_%s_list %s;\n" typ n;
5798            pr "};\n\n"
5799        | RHashtable n ->
5800            pr "struct %s_ret {\n" name;
5801            pr "  guestfs_str %s<>;\n" n;
5802            pr "};\n\n"
5803        | RBufferOut n ->
5804            pr "struct %s_ret {\n" name;
5805            pr "  opaque %s<>;\n" n;
5806            pr "};\n\n"
5807       );
5808   ) daemon_functions;
5809
5810   (* Table of procedure numbers. *)
5811   pr "enum guestfs_procedure {\n";
5812   List.iter (
5813     fun (shortname, _, proc_nr, _, _, _, _) ->
5814       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5815   ) daemon_functions;
5816   pr "  GUESTFS_PROC_NR_PROCS\n";
5817   pr "};\n";
5818   pr "\n";
5819
5820   (* Having to choose a maximum message size is annoying for several
5821    * reasons (it limits what we can do in the API), but it (a) makes
5822    * the protocol a lot simpler, and (b) provides a bound on the size
5823    * of the daemon which operates in limited memory space.
5824    *)
5825   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5826   pr "\n";
5827
5828   (* Message header, etc. *)
5829   pr "\
5830 /* The communication protocol is now documented in the guestfs(3)
5831  * manpage.
5832  */
5833
5834 const GUESTFS_PROGRAM = 0x2000F5F5;
5835 const GUESTFS_PROTOCOL_VERSION = 1;
5836
5837 /* These constants must be larger than any possible message length. */
5838 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5839 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5840
5841 enum guestfs_message_direction {
5842   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5843   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5844 };
5845
5846 enum guestfs_message_status {
5847   GUESTFS_STATUS_OK = 0,
5848   GUESTFS_STATUS_ERROR = 1
5849 };
5850
5851 const GUESTFS_ERROR_LEN = 256;
5852
5853 struct guestfs_message_error {
5854   string error_message<GUESTFS_ERROR_LEN>;
5855 };
5856
5857 struct guestfs_message_header {
5858   unsigned prog;                     /* GUESTFS_PROGRAM */
5859   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5860   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5861   guestfs_message_direction direction;
5862   unsigned serial;                   /* message serial number */
5863   guestfs_message_status status;
5864 };
5865
5866 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5867
5868 struct guestfs_chunk {
5869   int cancel;                        /* if non-zero, transfer is cancelled */
5870   /* data size is 0 bytes if the transfer has finished successfully */
5871   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5872 };
5873 "
5874
5875 (* Generate the guestfs-structs.h file. *)
5876 and generate_structs_h () =
5877   generate_header CStyle LGPLv2plus;
5878
5879   (* This is a public exported header file containing various
5880    * structures.  The structures are carefully written to have
5881    * exactly the same in-memory format as the XDR structures that
5882    * we use on the wire to the daemon.  The reason for creating
5883    * copies of these structures here is just so we don't have to
5884    * export the whole of guestfs_protocol.h (which includes much
5885    * unrelated and XDR-dependent stuff that we don't want to be
5886    * public, or required by clients).
5887    *
5888    * To reiterate, we will pass these structures to and from the
5889    * client with a simple assignment or memcpy, so the format
5890    * must be identical to what rpcgen / the RFC defines.
5891    *)
5892
5893   (* Public structures. *)
5894   List.iter (
5895     fun (typ, cols) ->
5896       pr "struct guestfs_%s {\n" typ;
5897       List.iter (
5898         function
5899         | name, FChar -> pr "  char %s;\n" name
5900         | name, FString -> pr "  char *%s;\n" name
5901         | name, FBuffer ->
5902             pr "  uint32_t %s_len;\n" name;
5903             pr "  char *%s;\n" name
5904         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5905         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5906         | name, FInt32 -> pr "  int32_t %s;\n" name
5907         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5908         | name, FInt64 -> pr "  int64_t %s;\n" name
5909         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5910       ) cols;
5911       pr "};\n";
5912       pr "\n";
5913       pr "struct guestfs_%s_list {\n" typ;
5914       pr "  uint32_t len;\n";
5915       pr "  struct guestfs_%s *val;\n" typ;
5916       pr "};\n";
5917       pr "\n";
5918       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5919       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5920       pr "\n"
5921   ) structs
5922
5923 (* Generate the guestfs-actions.h file. *)
5924 and generate_actions_h () =
5925   generate_header CStyle LGPLv2plus;
5926   List.iter (
5927     fun (shortname, style, _, _, _, _, _) ->
5928       let name = "guestfs_" ^ shortname in
5929       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5930         name style
5931   ) all_functions
5932
5933 (* Generate the guestfs-internal-actions.h file. *)
5934 and generate_internal_actions_h () =
5935   generate_header CStyle LGPLv2plus;
5936   List.iter (
5937     fun (shortname, style, _, _, _, _, _) ->
5938       let name = "guestfs__" ^ shortname in
5939       generate_prototype ~single_line:true ~newline:true ~handle:"g"
5940         name style
5941   ) non_daemon_functions
5942
5943 (* Generate the client-side dispatch stubs. *)
5944 and generate_client_actions () =
5945   generate_header CStyle LGPLv2plus;
5946
5947   pr "\
5948 #include <stdio.h>
5949 #include <stdlib.h>
5950 #include <stdint.h>
5951 #include <string.h>
5952 #include <inttypes.h>
5953
5954 #include \"guestfs.h\"
5955 #include \"guestfs-internal.h\"
5956 #include \"guestfs-internal-actions.h\"
5957 #include \"guestfs_protocol.h\"
5958
5959 /* Check the return message from a call for validity. */
5960 static int
5961 check_reply_header (guestfs_h *g,
5962                     const struct guestfs_message_header *hdr,
5963                     unsigned int proc_nr, unsigned int serial)
5964 {
5965   if (hdr->prog != GUESTFS_PROGRAM) {
5966     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5967     return -1;
5968   }
5969   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5970     error (g, \"wrong protocol version (%%d/%%d)\",
5971            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5972     return -1;
5973   }
5974   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5975     error (g, \"unexpected message direction (%%d/%%d)\",
5976            hdr->direction, GUESTFS_DIRECTION_REPLY);
5977     return -1;
5978   }
5979   if (hdr->proc != proc_nr) {
5980     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5981     return -1;
5982   }
5983   if (hdr->serial != serial) {
5984     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5985     return -1;
5986   }
5987
5988   return 0;
5989 }
5990
5991 /* Check we are in the right state to run a high-level action. */
5992 static int
5993 check_state (guestfs_h *g, const char *caller)
5994 {
5995   if (!guestfs__is_ready (g)) {
5996     if (guestfs__is_config (g) || guestfs__is_launching (g))
5997       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5998         caller);
5999     else
6000       error (g, \"%%s called from the wrong state, %%d != READY\",
6001         caller, guestfs__get_state (g));
6002     return -1;
6003   }
6004   return 0;
6005 }
6006
6007 ";
6008
6009   let error_code_of = function
6010     | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
6011     | RConstString _ | RConstOptString _
6012     | RString _ | RStringList _
6013     | RStruct _ | RStructList _
6014     | RHashtable _ | RBufferOut _ -> "NULL"
6015   in
6016
6017   (* Generate code to check String-like parameters are not passed in
6018    * as NULL (returning an error if they are).
6019    *)
6020   let check_null_strings shortname style =
6021     let pr_newline = ref false in
6022     List.iter (
6023       function
6024       (* parameters which should not be NULL *)
6025       | String n
6026       | Device n
6027       | Pathname n
6028       | Dev_or_Path n
6029       | FileIn n
6030       | FileOut n
6031       | BufferIn n
6032       | StringList n
6033       | DeviceList n ->
6034           pr "  if (%s == NULL) {\n" n;
6035           pr "    error (g, \"%%s: %%s: parameter cannot be NULL\",\n";
6036           pr "           \"%s\", \"%s\");\n" shortname n;
6037           pr "    return %s;\n" (error_code_of (fst style));
6038           pr "  }\n";
6039           pr_newline := true
6040
6041       (* can be NULL *)
6042       | OptString _
6043
6044       (* not applicable *)
6045       | Bool _
6046       | Int _
6047       | Int64 _ -> ()
6048     ) (snd style);
6049
6050     if !pr_newline then pr "\n";
6051   in
6052
6053   (* Generate code to generate guestfish call traces. *)
6054   let trace_call shortname style =
6055     pr "  if (guestfs__get_trace (g)) {\n";
6056
6057     let needs_i =
6058       List.exists (function
6059                    | StringList _ | DeviceList _ -> true
6060                    | _ -> false) (snd style) in
6061     if needs_i then (
6062       pr "    size_t i;\n";
6063       pr "\n"
6064     );
6065
6066     pr "    printf (\"%s\");\n" shortname;
6067     List.iter (
6068       function
6069       | String n                        (* strings *)
6070       | Device n
6071       | Pathname n
6072       | Dev_or_Path n
6073       | FileIn n
6074       | FileOut n
6075       | BufferIn n ->
6076           (* guestfish doesn't support string escaping, so neither do we *)
6077           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
6078       | OptString n ->                  (* string option *)
6079           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
6080           pr "    else printf (\" null\");\n"
6081       | StringList n
6082       | DeviceList n ->                 (* string list *)
6083           pr "    putchar (' ');\n";
6084           pr "    putchar ('\"');\n";
6085           pr "    for (i = 0; %s[i]; ++i) {\n" n;
6086           pr "      if (i > 0) putchar (' ');\n";
6087           pr "      fputs (%s[i], stdout);\n" n;
6088           pr "    }\n";
6089           pr "    putchar ('\"');\n";
6090       | Bool n ->                       (* boolean *)
6091           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
6092       | Int n ->                        (* int *)
6093           pr "    printf (\" %%d\", %s);\n" n
6094       | Int64 n ->
6095           pr "    printf (\" %%\" PRIi64, %s);\n" n
6096     ) (snd style);
6097     pr "    putchar ('\\n');\n";
6098     pr "  }\n";
6099     pr "\n";
6100   in
6101
6102   (* For non-daemon functions, generate a wrapper around each function. *)
6103   List.iter (
6104     fun (shortname, style, _, _, _, _, _) ->
6105       let name = "guestfs_" ^ shortname in
6106
6107       generate_prototype ~extern:false ~semicolon:false ~newline:true
6108         ~handle:"g" name style;
6109       pr "{\n";
6110       check_null_strings shortname style;
6111       trace_call shortname style;
6112       pr "  return guestfs__%s " shortname;
6113       generate_c_call_args ~handle:"g" style;
6114       pr ";\n";
6115       pr "}\n";
6116       pr "\n"
6117   ) non_daemon_functions;
6118
6119   (* Client-side stubs for each function. *)
6120   List.iter (
6121     fun (shortname, style, _, _, _, _, _) ->
6122       let name = "guestfs_" ^ shortname in
6123       let error_code = error_code_of (fst style) in
6124
6125       (* Generate the action stub. *)
6126       generate_prototype ~extern:false ~semicolon:false ~newline:true
6127         ~handle:"g" name style;
6128
6129       pr "{\n";
6130
6131       (match snd style with
6132        | [] -> ()
6133        | _ -> pr "  struct %s_args args;\n" name
6134       );
6135
6136       pr "  guestfs_message_header hdr;\n";
6137       pr "  guestfs_message_error err;\n";
6138       let has_ret =
6139         match fst style with
6140         | RErr -> false
6141         | RConstString _ | RConstOptString _ ->
6142             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6143         | RInt _ | RInt64 _
6144         | RBool _ | RString _ | RStringList _
6145         | RStruct _ | RStructList _
6146         | RHashtable _ | RBufferOut _ ->
6147             pr "  struct %s_ret ret;\n" name;
6148             true in
6149
6150       pr "  int serial;\n";
6151       pr "  int r;\n";
6152       pr "\n";
6153       check_null_strings shortname style;
6154       trace_call shortname style;
6155       pr "  if (check_state (g, \"%s\") == -1) return %s;\n"
6156         shortname error_code;
6157       pr "  guestfs___set_busy (g);\n";
6158       pr "\n";
6159
6160       (* Send the main header and arguments. *)
6161       (match snd style with
6162        | [] ->
6163            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
6164              (String.uppercase shortname)
6165        | args ->
6166            List.iter (
6167              function
6168              | Pathname n | Device n | Dev_or_Path n | String n ->
6169                  pr "  args.%s = (char *) %s;\n" n n
6170              | OptString n ->
6171                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
6172              | StringList n | DeviceList n ->
6173                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
6174                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
6175              | Bool n ->
6176                  pr "  args.%s = %s;\n" n n
6177              | Int n ->
6178                  pr "  args.%s = %s;\n" n n
6179              | Int64 n ->
6180                  pr "  args.%s = %s;\n" n n
6181              | FileIn _ | FileOut _ -> ()
6182              | BufferIn n ->
6183                  pr "  /* Just catch grossly large sizes. XDR encoding will make this precise. */\n";
6184                  pr "  if (%s_size >= GUESTFS_MESSAGE_MAX) {\n" n;
6185                  pr "    error (g, \"%%s: size of input buffer too large\", \"%s\");\n"
6186                    shortname;
6187                  pr "    guestfs___end_busy (g);\n";
6188                  pr "    return %s;\n" error_code;
6189                  pr "  }\n";
6190                  pr "  args.%s.%s_val = (char *) %s;\n" n n n;
6191                  pr "  args.%s.%s_len = %s_size;\n" n n n
6192            ) args;
6193            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
6194              (String.uppercase shortname);
6195            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
6196              name;
6197       );
6198       pr "  if (serial == -1) {\n";
6199       pr "    guestfs___end_busy (g);\n";
6200       pr "    return %s;\n" error_code;
6201       pr "  }\n";
6202       pr "\n";
6203
6204       (* Send any additional files (FileIn) requested. *)
6205       let need_read_reply_label = ref false in
6206       List.iter (
6207         function
6208         | FileIn n ->
6209             pr "  r = guestfs___send_file (g, %s);\n" n;
6210             pr "  if (r == -1) {\n";
6211             pr "    guestfs___end_busy (g);\n";
6212             pr "    return %s;\n" error_code;
6213             pr "  }\n";
6214             pr "  if (r == -2) /* daemon cancelled */\n";
6215             pr "    goto read_reply;\n";
6216             need_read_reply_label := true;
6217             pr "\n";
6218         | _ -> ()
6219       ) (snd style);
6220
6221       (* Wait for the reply from the remote end. *)
6222       if !need_read_reply_label then pr " read_reply:\n";
6223       pr "  memset (&hdr, 0, sizeof hdr);\n";
6224       pr "  memset (&err, 0, sizeof err);\n";
6225       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
6226       pr "\n";
6227       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
6228       if not has_ret then
6229         pr "NULL, NULL"
6230       else
6231         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
6232       pr ");\n";
6233
6234       pr "  if (r == -1) {\n";
6235       pr "    guestfs___end_busy (g);\n";
6236       pr "    return %s;\n" error_code;
6237       pr "  }\n";
6238       pr "\n";
6239
6240       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
6241         (String.uppercase shortname);
6242       pr "    guestfs___end_busy (g);\n";
6243       pr "    return %s;\n" error_code;
6244       pr "  }\n";
6245       pr "\n";
6246
6247       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
6248       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
6249       pr "    free (err.error_message);\n";
6250       pr "    guestfs___end_busy (g);\n";
6251       pr "    return %s;\n" error_code;
6252       pr "  }\n";
6253       pr "\n";
6254
6255       (* Expecting to receive further files (FileOut)? *)
6256       List.iter (
6257         function
6258         | FileOut n ->
6259             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
6260             pr "    guestfs___end_busy (g);\n";
6261             pr "    return %s;\n" error_code;
6262             pr "  }\n";
6263             pr "\n";
6264         | _ -> ()
6265       ) (snd style);
6266
6267       pr "  guestfs___end_busy (g);\n";
6268
6269       (match fst style with
6270        | RErr -> pr "  return 0;\n"
6271        | RInt n | RInt64 n | RBool n ->
6272            pr "  return ret.%s;\n" n
6273        | RConstString _ | RConstOptString _ ->
6274            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6275        | RString n ->
6276            pr "  return ret.%s; /* caller will free */\n" n
6277        | RStringList n | RHashtable n ->
6278            pr "  /* caller will free this, but we need to add a NULL entry */\n";
6279            pr "  ret.%s.%s_val =\n" n n;
6280            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
6281            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
6282              n n;
6283            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
6284            pr "  return ret.%s.%s_val;\n" n n
6285        | RStruct (n, _) ->
6286            pr "  /* caller will free this */\n";
6287            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6288        | RStructList (n, _) ->
6289            pr "  /* caller will free this */\n";
6290            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
6291        | RBufferOut n ->
6292            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
6293            pr "   * _val might be NULL here.  To make the API saner for\n";
6294            pr "   * callers, we turn this case into a unique pointer (using\n";
6295            pr "   * malloc(1)).\n";
6296            pr "   */\n";
6297            pr "  if (ret.%s.%s_len > 0) {\n" n n;
6298            pr "    *size_r = ret.%s.%s_len;\n" n n;
6299            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
6300            pr "  } else {\n";
6301            pr "    free (ret.%s.%s_val);\n" n n;
6302            pr "    char *p = safe_malloc (g, 1);\n";
6303            pr "    *size_r = ret.%s.%s_len;\n" n n;
6304            pr "    return p;\n";
6305            pr "  }\n";
6306       );
6307
6308       pr "}\n\n"
6309   ) daemon_functions;
6310
6311   (* Functions to free structures. *)
6312   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
6313   pr " * structure format is identical to the XDR format.  See note in\n";
6314   pr " * generator.ml.\n";
6315   pr " */\n";
6316   pr "\n";
6317
6318   List.iter (
6319     fun (typ, _) ->
6320       pr "void\n";
6321       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
6322       pr "{\n";
6323       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
6324       pr "  free (x);\n";
6325       pr "}\n";
6326       pr "\n";
6327
6328       pr "void\n";
6329       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
6330       pr "{\n";
6331       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
6332       pr "  free (x);\n";
6333       pr "}\n";
6334       pr "\n";
6335
6336   ) structs;
6337
6338 (* Generate daemon/actions.h. *)
6339 and generate_daemon_actions_h () =
6340   generate_header CStyle GPLv2plus;
6341
6342   pr "#include \"../src/guestfs_protocol.h\"\n";
6343   pr "\n";
6344
6345   List.iter (
6346     fun (name, style, _, _, _, _, _) ->
6347       generate_prototype
6348         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
6349         name style;
6350   ) daemon_functions
6351
6352 (* Generate the linker script which controls the visibility of
6353  * symbols in the public ABI and ensures no other symbols get
6354  * exported accidentally.
6355  *)
6356 and generate_linker_script () =
6357   generate_header HashStyle GPLv2plus;
6358
6359   let globals = [
6360     "guestfs_create";
6361     "guestfs_close";
6362     "guestfs_get_error_handler";
6363     "guestfs_get_out_of_memory_handler";
6364     "guestfs_last_error";
6365     "guestfs_set_close_callback";
6366     "guestfs_set_error_handler";
6367     "guestfs_set_launch_done_callback";
6368     "guestfs_set_log_message_callback";
6369     "guestfs_set_out_of_memory_handler";
6370     "guestfs_set_subprocess_quit_callback";
6371
6372     (* Unofficial parts of the API: the bindings code use these
6373      * functions, so it is useful to export them.
6374      *)
6375     "guestfs_safe_calloc";
6376     "guestfs_safe_malloc";
6377     "guestfs_safe_strdup";
6378     "guestfs_safe_memdup";
6379   ] in
6380   let functions =
6381     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
6382       all_functions in
6383   let structs =
6384     List.concat (
6385       List.map (fun (typ, _) ->
6386                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
6387         structs
6388     ) in
6389   let globals = List.sort compare (globals @ functions @ structs) in
6390
6391   pr "{\n";
6392   pr "    global:\n";
6393   List.iter (pr "        %s;\n") globals;
6394   pr "\n";
6395
6396   pr "    local:\n";
6397   pr "        *;\n";
6398   pr "};\n"
6399
6400 (* Generate the server-side stubs. *)
6401 and generate_daemon_actions () =
6402   generate_header CStyle GPLv2plus;
6403
6404   pr "#include <config.h>\n";
6405   pr "\n";
6406   pr "#include <stdio.h>\n";
6407   pr "#include <stdlib.h>\n";
6408   pr "#include <string.h>\n";
6409   pr "#include <inttypes.h>\n";
6410   pr "#include <rpc/types.h>\n";
6411   pr "#include <rpc/xdr.h>\n";
6412   pr "\n";
6413   pr "#include \"daemon.h\"\n";
6414   pr "#include \"c-ctype.h\"\n";
6415   pr "#include \"../src/guestfs_protocol.h\"\n";
6416   pr "#include \"actions.h\"\n";
6417   pr "\n";
6418
6419   List.iter (
6420     fun (name, style, _, _, _, _, _) ->
6421       (* Generate server-side stubs. *)
6422       pr "static void %s_stub (XDR *xdr_in)\n" name;
6423       pr "{\n";
6424       let error_code =
6425         match fst style with
6426         | RErr | RInt _ -> pr "  int r;\n"; "-1"
6427         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
6428         | RBool _ -> pr "  int r;\n"; "-1"
6429         | RConstString _ | RConstOptString _ ->
6430             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6431         | RString _ -> pr "  char *r;\n"; "NULL"
6432         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
6433         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
6434         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
6435         | RBufferOut _ ->
6436             pr "  size_t size = 1;\n";
6437             pr "  char *r;\n";
6438             "NULL" in
6439
6440       (match snd style with
6441        | [] -> ()
6442        | args ->
6443            pr "  struct guestfs_%s_args args;\n" name;
6444            List.iter (
6445              function
6446              | Device n | Dev_or_Path n
6447              | Pathname n
6448              | String n -> ()
6449              | OptString n -> pr "  char *%s;\n" n
6450              | StringList n | DeviceList n -> pr "  char **%s;\n" n
6451              | Bool n -> pr "  int %s;\n" n
6452              | Int n -> pr "  int %s;\n" n
6453              | Int64 n -> pr "  int64_t %s;\n" n
6454              | FileIn _ | FileOut _ -> ()
6455              | BufferIn n ->
6456                  pr "  const char *%s;\n" n;
6457                  pr "  size_t %s_size;\n" n
6458            ) args
6459       );
6460       pr "\n";
6461
6462       let is_filein =
6463         List.exists (function FileIn _ -> true | _ -> false) (snd style) in
6464
6465       (match snd style with
6466        | [] -> ()
6467        | args ->
6468            pr "  memset (&args, 0, sizeof args);\n";
6469            pr "\n";
6470            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
6471            if is_filein then
6472              pr "    if (cancel_receive () != -2)\n";
6473            pr "      reply_with_error (\"daemon failed to decode procedure arguments\");\n";
6474            pr "    goto done;\n";
6475            pr "  }\n";
6476            let pr_args n =
6477              pr "  char *%s = args.%s;\n" n n
6478            in
6479            let pr_list_handling_code n =
6480              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
6481              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
6482              pr "  if (%s == NULL) {\n" n;
6483              if is_filein then
6484                pr "    if (cancel_receive () != -2)\n";
6485              pr "      reply_with_perror (\"realloc\");\n";
6486              pr "    goto done;\n";
6487              pr "  }\n";
6488              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
6489              pr "  args.%s.%s_val = %s;\n" n n n;
6490            in
6491            List.iter (
6492              function
6493              | Pathname n ->
6494                  pr_args n;
6495                  pr "  ABS_PATH (%s, %s, goto done);\n"
6496                    n (if is_filein then "cancel_receive ()" else "0");
6497              | Device n ->
6498                  pr_args n;
6499                  pr "  RESOLVE_DEVICE (%s, %s, goto done);\n"
6500                    n (if is_filein then "cancel_receive ()" else "0");
6501              | Dev_or_Path n ->
6502                  pr_args n;
6503                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, %s, goto done);\n"
6504                    n (if is_filein then "cancel_receive ()" else "0");
6505              | String n -> pr_args n
6506              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
6507              | StringList n ->
6508                  pr_list_handling_code n;
6509              | DeviceList n ->
6510                  pr_list_handling_code n;
6511                  pr "  /* Ensure that each is a device,\n";
6512                  pr "   * and perform device name translation.\n";
6513                  pr "   */\n";
6514                  pr "  {\n";
6515                  pr "    size_t i;\n";
6516                  pr "    for (i = 0; %s[i] != NULL; ++i)\n" n;
6517                  pr "      RESOLVE_DEVICE (%s[i], %s, goto done);\n" n
6518                    (if is_filein then "cancel_receive ()" else "0");
6519                  pr "  }\n";
6520              | Bool n -> pr "  %s = args.%s;\n" n n
6521              | Int n -> pr "  %s = args.%s;\n" n n
6522              | Int64 n -> pr "  %s = args.%s;\n" n n
6523              | FileIn _ | FileOut _ -> ()
6524              | BufferIn n ->
6525                  pr "  %s = args.%s.%s_val;\n" n n n;
6526                  pr "  %s_size = args.%s.%s_len;\n" n n n
6527            ) args;
6528            pr "\n"
6529       );
6530
6531       (* this is used at least for do_equal *)
6532       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
6533         (* Emit NEED_ROOT just once, even when there are two or
6534            more Pathname args *)
6535         pr "  NEED_ROOT (%s, goto done);\n"
6536           (if is_filein then "cancel_receive ()" else "0");
6537       );
6538
6539       (* Don't want to call the impl with any FileIn or FileOut
6540        * parameters, since these go "outside" the RPC protocol.
6541        *)
6542       let args' =
6543         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
6544           (snd style) in
6545       pr "  r = do_%s " name;
6546       generate_c_call_args (fst style, args');
6547       pr ";\n";
6548
6549       (match fst style with
6550        | RErr | RInt _ | RInt64 _ | RBool _
6551        | RConstString _ | RConstOptString _
6552        | RString _ | RStringList _ | RHashtable _
6553        | RStruct (_, _) | RStructList (_, _) ->
6554            pr "  if (r == %s)\n" error_code;
6555            pr "    /* do_%s has already called reply_with_error */\n" name;
6556            pr "    goto done;\n";
6557            pr "\n"
6558        | RBufferOut _ ->
6559            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
6560            pr "   * an ordinary zero-length buffer), so be careful ...\n";
6561            pr "   */\n";
6562            pr "  if (size == 1 && r == %s)\n" error_code;
6563            pr "    /* do_%s has already called reply_with_error */\n" name;
6564            pr "    goto done;\n";
6565            pr "\n"
6566       );
6567
6568       (* If there are any FileOut parameters, then the impl must
6569        * send its own reply.
6570        *)
6571       let no_reply =
6572         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
6573       if no_reply then
6574         pr "  /* do_%s has already sent a reply */\n" name
6575       else (
6576         match fst style with
6577         | RErr -> pr "  reply (NULL, NULL);\n"
6578         | RInt n | RInt64 n | RBool n ->
6579             pr "  struct guestfs_%s_ret ret;\n" name;
6580             pr "  ret.%s = r;\n" n;
6581             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6582               name
6583         | RConstString _ | RConstOptString _ ->
6584             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
6585         | RString n ->
6586             pr "  struct guestfs_%s_ret ret;\n" name;
6587             pr "  ret.%s = r;\n" n;
6588             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6589               name;
6590             pr "  free (r);\n"
6591         | RStringList n | RHashtable n ->
6592             pr "  struct guestfs_%s_ret ret;\n" name;
6593             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
6594             pr "  ret.%s.%s_val = r;\n" n n;
6595             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6596               name;
6597             pr "  free_strings (r);\n"
6598         | RStruct (n, _) ->
6599             pr "  struct guestfs_%s_ret ret;\n" name;
6600             pr "  ret.%s = *r;\n" n;
6601             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6602               name;
6603             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6604               name
6605         | RStructList (n, _) ->
6606             pr "  struct guestfs_%s_ret ret;\n" name;
6607             pr "  ret.%s = *r;\n" n;
6608             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6609               name;
6610             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
6611               name
6612         | RBufferOut n ->
6613             pr "  struct guestfs_%s_ret ret;\n" name;
6614             pr "  ret.%s.%s_val = r;\n" n n;
6615             pr "  ret.%s.%s_len = size;\n" n n;
6616             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
6617               name;
6618             pr "  free (r);\n"
6619       );
6620
6621       (* Free the args. *)
6622       pr "done:\n";
6623       (match snd style with
6624        | [] -> ()
6625        | _ ->
6626            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
6627              name
6628       );
6629       pr "  return;\n";
6630       pr "}\n\n";
6631   ) daemon_functions;
6632
6633   (* Dispatch function. *)
6634   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
6635   pr "{\n";
6636   pr "  switch (proc_nr) {\n";
6637
6638   List.iter (
6639     fun (name, style, _, _, _, _, _) ->
6640       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
6641       pr "      %s_stub (xdr_in);\n" name;
6642       pr "      break;\n"
6643   ) daemon_functions;
6644
6645   pr "    default:\n";
6646   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";
6647   pr "  }\n";
6648   pr "}\n";
6649   pr "\n";
6650
6651   (* LVM columns and tokenization functions. *)
6652   (* XXX This generates crap code.  We should rethink how we
6653    * do this parsing.
6654    *)
6655   List.iter (
6656     function
6657     | typ, cols ->
6658         pr "static const char *lvm_%s_cols = \"%s\";\n"
6659           typ (String.concat "," (List.map fst cols));
6660         pr "\n";
6661
6662         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
6663         pr "{\n";
6664         pr "  char *tok, *p, *next;\n";
6665         pr "  size_t i, j;\n";
6666         pr "\n";
6667         (*
6668           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
6669           pr "\n";
6670         *)
6671         pr "  if (!str) {\n";
6672         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6673         pr "    return -1;\n";
6674         pr "  }\n";
6675         pr "  if (!*str || c_isspace (*str)) {\n";
6676         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6677         pr "    return -1;\n";
6678         pr "  }\n";
6679         pr "  tok = str;\n";
6680         List.iter (
6681           fun (name, coltype) ->
6682             pr "  if (!tok) {\n";
6683             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6684             pr "    return -1;\n";
6685             pr "  }\n";
6686             pr "  p = strchrnul (tok, ',');\n";
6687             pr "  if (*p) next = p+1; else next = NULL;\n";
6688             pr "  *p = '\\0';\n";
6689             (match coltype with
6690              | FString ->
6691                  pr "  r->%s = strdup (tok);\n" name;
6692                  pr "  if (r->%s == NULL) {\n" name;
6693                  pr "    perror (\"strdup\");\n";
6694                  pr "    return -1;\n";
6695                  pr "  }\n"
6696              | FUUID ->
6697                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6698                  pr "    if (tok[j] == '\\0') {\n";
6699                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6700                  pr "      return -1;\n";
6701                  pr "    } else if (tok[j] != '-')\n";
6702                  pr "      r->%s[i++] = tok[j];\n" name;
6703                  pr "  }\n";
6704              | FBytes ->
6705                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6706                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6707                  pr "    return -1;\n";
6708                  pr "  }\n";
6709              | FInt64 ->
6710                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6711                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6712                  pr "    return -1;\n";
6713                  pr "  }\n";
6714              | FOptPercent ->
6715                  pr "  if (tok[0] == '\\0')\n";
6716                  pr "    r->%s = -1;\n" name;
6717                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6718                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6719                  pr "    return -1;\n";
6720                  pr "  }\n";
6721              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6722                  assert false (* can never be an LVM column *)
6723             );
6724             pr "  tok = next;\n";
6725         ) cols;
6726
6727         pr "  if (tok != NULL) {\n";
6728         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6729         pr "    return -1;\n";
6730         pr "  }\n";
6731         pr "  return 0;\n";
6732         pr "}\n";
6733         pr "\n";
6734
6735         pr "guestfs_int_lvm_%s_list *\n" typ;
6736         pr "parse_command_line_%ss (void)\n" typ;
6737         pr "{\n";
6738         pr "  char *out, *err;\n";
6739         pr "  char *p, *pend;\n";
6740         pr "  int r, i;\n";
6741         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6742         pr "  void *newp;\n";
6743         pr "\n";
6744         pr "  ret = malloc (sizeof *ret);\n";
6745         pr "  if (!ret) {\n";
6746         pr "    reply_with_perror (\"malloc\");\n";
6747         pr "    return NULL;\n";
6748         pr "  }\n";
6749         pr "\n";
6750         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6751         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6752         pr "\n";
6753         pr "  r = command (&out, &err,\n";
6754         pr "           \"lvm\", \"%ss\",\n" typ;
6755         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6756         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6757         pr "  if (r == -1) {\n";
6758         pr "    reply_with_error (\"%%s\", err);\n";
6759         pr "    free (out);\n";
6760         pr "    free (err);\n";
6761         pr "    free (ret);\n";
6762         pr "    return NULL;\n";
6763         pr "  }\n";
6764         pr "\n";
6765         pr "  free (err);\n";
6766         pr "\n";
6767         pr "  /* Tokenize each line of the output. */\n";
6768         pr "  p = out;\n";
6769         pr "  i = 0;\n";
6770         pr "  while (p) {\n";
6771         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6772         pr "    if (pend) {\n";
6773         pr "      *pend = '\\0';\n";
6774         pr "      pend++;\n";
6775         pr "    }\n";
6776         pr "\n";
6777         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6778         pr "      p++;\n";
6779         pr "\n";
6780         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6781         pr "      p = pend;\n";
6782         pr "      continue;\n";
6783         pr "    }\n";
6784         pr "\n";
6785         pr "    /* Allocate some space to store this next entry. */\n";
6786         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6787         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6788         pr "    if (newp == NULL) {\n";
6789         pr "      reply_with_perror (\"realloc\");\n";
6790         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6791         pr "      free (ret);\n";
6792         pr "      free (out);\n";
6793         pr "      return NULL;\n";
6794         pr "    }\n";
6795         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6796         pr "\n";
6797         pr "    /* Tokenize the next entry. */\n";
6798         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6799         pr "    if (r == -1) {\n";
6800         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6801         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6802         pr "      free (ret);\n";
6803         pr "      free (out);\n";
6804         pr "      return NULL;\n";
6805         pr "    }\n";
6806         pr "\n";
6807         pr "    ++i;\n";
6808         pr "    p = pend;\n";
6809         pr "  }\n";
6810         pr "\n";
6811         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6812         pr "\n";
6813         pr "  free (out);\n";
6814         pr "  return ret;\n";
6815         pr "}\n"
6816
6817   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6818
6819 (* Generate a list of function names, for debugging in the daemon.. *)
6820 and generate_daemon_names () =
6821   generate_header CStyle GPLv2plus;
6822
6823   pr "#include <config.h>\n";
6824   pr "\n";
6825   pr "#include \"daemon.h\"\n";
6826   pr "\n";
6827
6828   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6829   pr "const char *function_names[] = {\n";
6830   List.iter (
6831     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6832   ) daemon_functions;
6833   pr "};\n";
6834
6835 (* Generate the optional groups for the daemon to implement
6836  * guestfs_available.
6837  *)
6838 and generate_daemon_optgroups_c () =
6839   generate_header CStyle GPLv2plus;
6840
6841   pr "#include <config.h>\n";
6842   pr "\n";
6843   pr "#include \"daemon.h\"\n";
6844   pr "#include \"optgroups.h\"\n";
6845   pr "\n";
6846
6847   pr "struct optgroup optgroups[] = {\n";
6848   List.iter (
6849     fun (group, _) ->
6850       pr "  { \"%s\", optgroup_%s_available },\n" group group
6851   ) optgroups;
6852   pr "  { NULL, NULL }\n";
6853   pr "};\n"
6854
6855 and generate_daemon_optgroups_h () =
6856   generate_header CStyle GPLv2plus;
6857
6858   List.iter (
6859     fun (group, _) ->
6860       pr "extern int optgroup_%s_available (void);\n" group
6861   ) optgroups
6862
6863 (* Generate the tests. *)
6864 and generate_tests () =
6865   generate_header CStyle GPLv2plus;
6866
6867   pr "\
6868 #include <stdio.h>
6869 #include <stdlib.h>
6870 #include <string.h>
6871 #include <unistd.h>
6872 #include <sys/types.h>
6873 #include <fcntl.h>
6874
6875 #include \"guestfs.h\"
6876 #include \"guestfs-internal.h\"
6877
6878 static guestfs_h *g;
6879 static int suppress_error = 0;
6880
6881 static void print_error (guestfs_h *g, void *data, const char *msg)
6882 {
6883   if (!suppress_error)
6884     fprintf (stderr, \"%%s\\n\", msg);
6885 }
6886
6887 /* FIXME: nearly identical code appears in fish.c */
6888 static void print_strings (char *const *argv)
6889 {
6890   size_t argc;
6891
6892   for (argc = 0; argv[argc] != NULL; ++argc)
6893     printf (\"\\t%%s\\n\", argv[argc]);
6894 }
6895
6896 /*
6897 static void print_table (char const *const *argv)
6898 {
6899   size_t i;
6900
6901   for (i = 0; argv[i] != NULL; i += 2)
6902     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6903 }
6904 */
6905
6906 static int
6907 is_available (const char *group)
6908 {
6909   const char *groups[] = { group, NULL };
6910   int r;
6911
6912   suppress_error = 1;
6913   r = guestfs_available (g, (char **) groups);
6914   suppress_error = 0;
6915
6916   return r == 0;
6917 }
6918
6919 static void
6920 incr (guestfs_h *g, void *iv)
6921 {
6922   int *i = (int *) iv;
6923   (*i)++;
6924 }
6925
6926 ";
6927
6928   (* Generate a list of commands which are not tested anywhere. *)
6929   pr "static void no_test_warnings (void)\n";
6930   pr "{\n";
6931
6932   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6933   List.iter (
6934     fun (_, _, _, _, tests, _, _) ->
6935       let tests = filter_map (
6936         function
6937         | (_, (Always|If _|Unless _|IfAvailable _), test) -> Some test
6938         | (_, Disabled, _) -> None
6939       ) tests in
6940       let seq = List.concat (List.map seq_of_test tests) in
6941       let cmds_tested = List.map List.hd seq in
6942       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6943   ) all_functions;
6944
6945   List.iter (
6946     fun (name, _, _, _, _, _, _) ->
6947       if not (Hashtbl.mem hash name) then
6948         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6949   ) all_functions;
6950
6951   pr "}\n";
6952   pr "\n";
6953
6954   (* Generate the actual tests.  Note that we generate the tests
6955    * in reverse order, deliberately, so that (in general) the
6956    * newest tests run first.  This makes it quicker and easier to
6957    * debug them.
6958    *)
6959   let test_names =
6960     List.map (
6961       fun (name, _, _, flags, tests, _, _) ->
6962         mapi (generate_one_test name flags) tests
6963     ) (List.rev all_functions) in
6964   let test_names = List.concat test_names in
6965   let nr_tests = List.length test_names in
6966
6967   pr "\
6968 int main (int argc, char *argv[])
6969 {
6970   char c = 0;
6971   unsigned long int n_failed = 0;
6972   const char *filename;
6973   int fd;
6974   int nr_tests, test_num = 0;
6975
6976   setbuf (stdout, NULL);
6977
6978   no_test_warnings ();
6979
6980   g = guestfs_create ();
6981   if (g == NULL) {
6982     printf (\"guestfs_create FAILED\\n\");
6983     exit (EXIT_FAILURE);
6984   }
6985
6986   guestfs_set_error_handler (g, print_error, NULL);
6987
6988   guestfs_set_path (g, \"../appliance\");
6989
6990   filename = \"test1.img\";
6991   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6992   if (fd == -1) {
6993     perror (filename);
6994     exit (EXIT_FAILURE);
6995   }
6996   if (lseek (fd, %d, SEEK_SET) == -1) {
6997     perror (\"lseek\");
6998     close (fd);
6999     unlink (filename);
7000     exit (EXIT_FAILURE);
7001   }
7002   if (write (fd, &c, 1) == -1) {
7003     perror (\"write\");
7004     close (fd);
7005     unlink (filename);
7006     exit (EXIT_FAILURE);
7007   }
7008   if (close (fd) == -1) {
7009     perror (filename);
7010     unlink (filename);
7011     exit (EXIT_FAILURE);
7012   }
7013   if (guestfs_add_drive (g, filename) == -1) {
7014     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7015     exit (EXIT_FAILURE);
7016   }
7017
7018   filename = \"test2.img\";
7019   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7020   if (fd == -1) {
7021     perror (filename);
7022     exit (EXIT_FAILURE);
7023   }
7024   if (lseek (fd, %d, SEEK_SET) == -1) {
7025     perror (\"lseek\");
7026     close (fd);
7027     unlink (filename);
7028     exit (EXIT_FAILURE);
7029   }
7030   if (write (fd, &c, 1) == -1) {
7031     perror (\"write\");
7032     close (fd);
7033     unlink (filename);
7034     exit (EXIT_FAILURE);
7035   }
7036   if (close (fd) == -1) {
7037     perror (filename);
7038     unlink (filename);
7039     exit (EXIT_FAILURE);
7040   }
7041   if (guestfs_add_drive (g, filename) == -1) {
7042     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7043     exit (EXIT_FAILURE);
7044   }
7045
7046   filename = \"test3.img\";
7047   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
7048   if (fd == -1) {
7049     perror (filename);
7050     exit (EXIT_FAILURE);
7051   }
7052   if (lseek (fd, %d, SEEK_SET) == -1) {
7053     perror (\"lseek\");
7054     close (fd);
7055     unlink (filename);
7056     exit (EXIT_FAILURE);
7057   }
7058   if (write (fd, &c, 1) == -1) {
7059     perror (\"write\");
7060     close (fd);
7061     unlink (filename);
7062     exit (EXIT_FAILURE);
7063   }
7064   if (close (fd) == -1) {
7065     perror (filename);
7066     unlink (filename);
7067     exit (EXIT_FAILURE);
7068   }
7069   if (guestfs_add_drive (g, filename) == -1) {
7070     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
7071     exit (EXIT_FAILURE);
7072   }
7073
7074   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
7075     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
7076     exit (EXIT_FAILURE);
7077   }
7078
7079   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
7080   alarm (600);
7081
7082   if (guestfs_launch (g) == -1) {
7083     printf (\"guestfs_launch FAILED\\n\");
7084     exit (EXIT_FAILURE);
7085   }
7086
7087   /* Cancel previous alarm. */
7088   alarm (0);
7089
7090   nr_tests = %d;
7091
7092 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
7093
7094   iteri (
7095     fun i test_name ->
7096       pr "  test_num++;\n";
7097       pr "  if (guestfs_get_verbose (g))\n";
7098       pr "    printf (\"-------------------------------------------------------------------------------\\n\");\n";
7099       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
7100       pr "  if (%s () == -1) {\n" test_name;
7101       pr "    printf (\"%s FAILED\\n\");\n" test_name;
7102       pr "    n_failed++;\n";
7103       pr "  }\n";
7104   ) test_names;
7105   pr "\n";
7106
7107   pr "  /* Check close callback is called. */
7108   int close_sentinel = 1;
7109   guestfs_set_close_callback (g, incr, &close_sentinel);
7110
7111   guestfs_close (g);
7112
7113   if (close_sentinel != 2) {
7114     fprintf (stderr, \"close callback was not called\\n\");
7115     exit (EXIT_FAILURE);
7116   }
7117
7118   unlink (\"test1.img\");
7119   unlink (\"test2.img\");
7120   unlink (\"test3.img\");
7121
7122 ";
7123
7124   pr "  if (n_failed > 0) {\n";
7125   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
7126   pr "    exit (EXIT_FAILURE);\n";
7127   pr "  }\n";
7128   pr "\n";
7129
7130   pr "  exit (EXIT_SUCCESS);\n";
7131   pr "}\n"
7132
7133 and generate_one_test name flags i (init, prereq, test) =
7134   let test_name = sprintf "test_%s_%d" name i in
7135
7136   pr "\
7137 static int %s_skip (void)
7138 {
7139   const char *str;
7140
7141   str = getenv (\"TEST_ONLY\");
7142   if (str)
7143     return strstr (str, \"%s\") == NULL;
7144   str = getenv (\"SKIP_%s\");
7145   if (str && STREQ (str, \"1\")) return 1;
7146   str = getenv (\"SKIP_TEST_%s\");
7147   if (str && STREQ (str, \"1\")) return 1;
7148   return 0;
7149 }
7150
7151 " test_name name (String.uppercase test_name) (String.uppercase name);
7152
7153   (match prereq with
7154    | Disabled | Always | IfAvailable _ -> ()
7155    | If code | Unless code ->
7156        pr "static int %s_prereq (void)\n" test_name;
7157        pr "{\n";
7158        pr "  %s\n" code;
7159        pr "}\n";
7160        pr "\n";
7161   );
7162
7163   pr "\
7164 static int %s (void)
7165 {
7166   if (%s_skip ()) {
7167     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
7168     return 0;
7169   }
7170
7171 " test_name test_name test_name;
7172
7173   (* Optional functions should only be tested if the relevant
7174    * support is available in the daemon.
7175    *)
7176   List.iter (
7177     function
7178     | Optional group ->
7179         pr "  if (!is_available (\"%s\")) {\n" group;
7180         pr "    printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", \"%s\");\n" test_name group;
7181         pr "    return 0;\n";
7182         pr "  }\n";
7183     | _ -> ()
7184   ) flags;
7185
7186   (match prereq with
7187    | Disabled ->
7188        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
7189    | If _ ->
7190        pr "  if (! %s_prereq ()) {\n" test_name;
7191        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7192        pr "    return 0;\n";
7193        pr "  }\n";
7194        pr "\n";
7195        generate_one_test_body name i test_name init test;
7196    | Unless _ ->
7197        pr "  if (%s_prereq ()) {\n" test_name;
7198        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
7199        pr "    return 0;\n";
7200        pr "  }\n";
7201        pr "\n";
7202        generate_one_test_body name i test_name init test;
7203    | IfAvailable group ->
7204        pr "  if (!is_available (\"%s\")) {\n" group;
7205        pr "    printf (\"        %%s skipped (reason: %%s not available)\\n\", \"%s\", \"%s\");\n" test_name group;
7206        pr "    return 0;\n";
7207        pr "  }\n";
7208        pr "\n";
7209        generate_one_test_body name i test_name init test;
7210    | Always ->
7211        generate_one_test_body name i test_name init test
7212   );
7213
7214   pr "  return 0;\n";
7215   pr "}\n";
7216   pr "\n";
7217   test_name
7218
7219 and generate_one_test_body name i test_name init test =
7220   (match init with
7221    | InitNone (* XXX at some point, InitNone and InitEmpty became
7222                * folded together as the same thing.  Really we should
7223                * make InitNone do nothing at all, but the tests may
7224                * need to be checked to make sure this is OK.
7225                *)
7226    | InitEmpty ->
7227        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
7228        List.iter (generate_test_command_call test_name)
7229          [["blockdev_setrw"; "/dev/sda"];
7230           ["umount_all"];
7231           ["lvm_remove_all"]]
7232    | InitPartition ->
7233        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
7234        List.iter (generate_test_command_call test_name)
7235          [["blockdev_setrw"; "/dev/sda"];
7236           ["umount_all"];
7237           ["lvm_remove_all"];
7238           ["part_disk"; "/dev/sda"; "mbr"]]
7239    | InitBasicFS ->
7240        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
7241        List.iter (generate_test_command_call test_name)
7242          [["blockdev_setrw"; "/dev/sda"];
7243           ["umount_all"];
7244           ["lvm_remove_all"];
7245           ["part_disk"; "/dev/sda"; "mbr"];
7246           ["mkfs"; "ext2"; "/dev/sda1"];
7247           ["mount_options"; ""; "/dev/sda1"; "/"]]
7248    | InitBasicFSonLVM ->
7249        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
7250          test_name;
7251        List.iter (generate_test_command_call test_name)
7252          [["blockdev_setrw"; "/dev/sda"];
7253           ["umount_all"];
7254           ["lvm_remove_all"];
7255           ["part_disk"; "/dev/sda"; "mbr"];
7256           ["pvcreate"; "/dev/sda1"];
7257           ["vgcreate"; "VG"; "/dev/sda1"];
7258           ["lvcreate"; "LV"; "VG"; "8"];
7259           ["mkfs"; "ext2"; "/dev/VG/LV"];
7260           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
7261    | InitISOFS ->
7262        pr "  /* InitISOFS for %s */\n" test_name;
7263        List.iter (generate_test_command_call test_name)
7264          [["blockdev_setrw"; "/dev/sda"];
7265           ["umount_all"];
7266           ["lvm_remove_all"];
7267           ["mount_ro"; "/dev/sdd"; "/"]]
7268   );
7269
7270   let get_seq_last = function
7271     | [] ->
7272         failwithf "%s: you cannot use [] (empty list) when expecting a command"
7273           test_name
7274     | seq ->
7275         let seq = List.rev seq in
7276         List.rev (List.tl seq), List.hd seq
7277   in
7278
7279   match test with
7280   | TestRun seq ->
7281       pr "  /* TestRun for %s (%d) */\n" name i;
7282       List.iter (generate_test_command_call test_name) seq
7283   | TestOutput (seq, expected) ->
7284       pr "  /* TestOutput for %s (%d) */\n" name i;
7285       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7286       let seq, last = get_seq_last seq in
7287       let test () =
7288         pr "    if (STRNEQ (r, expected)) {\n";
7289         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7290         pr "      return -1;\n";
7291         pr "    }\n"
7292       in
7293       List.iter (generate_test_command_call test_name) seq;
7294       generate_test_command_call ~test test_name last
7295   | TestOutputList (seq, expected) ->
7296       pr "  /* TestOutputList for %s (%d) */\n" name i;
7297       let seq, last = get_seq_last seq in
7298       let test () =
7299         iteri (
7300           fun i str ->
7301             pr "    if (!r[%d]) {\n" i;
7302             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7303             pr "      print_strings (r);\n";
7304             pr "      return -1;\n";
7305             pr "    }\n";
7306             pr "    {\n";
7307             pr "      const char *expected = \"%s\";\n" (c_quote str);
7308             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7309             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7310             pr "        return -1;\n";
7311             pr "      }\n";
7312             pr "    }\n"
7313         ) expected;
7314         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7315         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7316           test_name;
7317         pr "      print_strings (r);\n";
7318         pr "      return -1;\n";
7319         pr "    }\n"
7320       in
7321       List.iter (generate_test_command_call test_name) seq;
7322       generate_test_command_call ~test test_name last
7323   | TestOutputListOfDevices (seq, expected) ->
7324       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
7325       let seq, last = get_seq_last seq in
7326       let test () =
7327         iteri (
7328           fun i str ->
7329             pr "    if (!r[%d]) {\n" i;
7330             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
7331             pr "      print_strings (r);\n";
7332             pr "      return -1;\n";
7333             pr "    }\n";
7334             pr "    {\n";
7335             pr "      const char *expected = \"%s\";\n" (c_quote str);
7336             pr "      r[%d][5] = 's';\n" i;
7337             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
7338             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
7339             pr "        return -1;\n";
7340             pr "      }\n";
7341             pr "    }\n"
7342         ) expected;
7343         pr "    if (r[%d] != NULL) {\n" (List.length expected);
7344         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
7345           test_name;
7346         pr "      print_strings (r);\n";
7347         pr "      return -1;\n";
7348         pr "    }\n"
7349       in
7350       List.iter (generate_test_command_call test_name) seq;
7351       generate_test_command_call ~test test_name last
7352   | TestOutputInt (seq, expected) ->
7353       pr "  /* TestOutputInt for %s (%d) */\n" name i;
7354       let seq, last = get_seq_last seq in
7355       let test () =
7356         pr "    if (r != %d) {\n" expected;
7357         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
7358           test_name expected;
7359         pr "               (int) r);\n";
7360         pr "      return -1;\n";
7361         pr "    }\n"
7362       in
7363       List.iter (generate_test_command_call test_name) seq;
7364       generate_test_command_call ~test test_name last
7365   | TestOutputIntOp (seq, op, expected) ->
7366       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
7367       let seq, last = get_seq_last seq in
7368       let test () =
7369         pr "    if (! (r %s %d)) {\n" op expected;
7370         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
7371           test_name op expected;
7372         pr "               (int) r);\n";
7373         pr "      return -1;\n";
7374         pr "    }\n"
7375       in
7376       List.iter (generate_test_command_call test_name) seq;
7377       generate_test_command_call ~test test_name last
7378   | TestOutputTrue seq ->
7379       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
7380       let seq, last = get_seq_last seq in
7381       let test () =
7382         pr "    if (!r) {\n";
7383         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
7384           test_name;
7385         pr "      return -1;\n";
7386         pr "    }\n"
7387       in
7388       List.iter (generate_test_command_call test_name) seq;
7389       generate_test_command_call ~test test_name last
7390   | TestOutputFalse seq ->
7391       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
7392       let seq, last = get_seq_last seq in
7393       let test () =
7394         pr "    if (r) {\n";
7395         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
7396           test_name;
7397         pr "      return -1;\n";
7398         pr "    }\n"
7399       in
7400       List.iter (generate_test_command_call test_name) seq;
7401       generate_test_command_call ~test test_name last
7402   | TestOutputLength (seq, expected) ->
7403       pr "  /* TestOutputLength for %s (%d) */\n" name i;
7404       let seq, last = get_seq_last seq in
7405       let test () =
7406         pr "    int j;\n";
7407         pr "    for (j = 0; j < %d; ++j)\n" expected;
7408         pr "      if (r[j] == NULL) {\n";
7409         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
7410           test_name;
7411         pr "        print_strings (r);\n";
7412         pr "        return -1;\n";
7413         pr "      }\n";
7414         pr "    if (r[j] != NULL) {\n";
7415         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
7416           test_name;
7417         pr "      print_strings (r);\n";
7418         pr "      return -1;\n";
7419         pr "    }\n"
7420       in
7421       List.iter (generate_test_command_call test_name) seq;
7422       generate_test_command_call ~test test_name last
7423   | TestOutputBuffer (seq, expected) ->
7424       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
7425       pr "  const char *expected = \"%s\";\n" (c_quote expected);
7426       let seq, last = get_seq_last seq in
7427       let len = String.length expected in
7428       let test () =
7429         pr "    if (size != %d) {\n" len;
7430         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
7431         pr "      return -1;\n";
7432         pr "    }\n";
7433         pr "    if (STRNEQLEN (r, expected, size)) {\n";
7434         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
7435         pr "      return -1;\n";
7436         pr "    }\n"
7437       in
7438       List.iter (generate_test_command_call test_name) seq;
7439       generate_test_command_call ~test test_name last
7440   | TestOutputStruct (seq, checks) ->
7441       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
7442       let seq, last = get_seq_last seq in
7443       let test () =
7444         List.iter (
7445           function
7446           | CompareWithInt (field, expected) ->
7447               pr "    if (r->%s != %d) {\n" field expected;
7448               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
7449                 test_name field expected;
7450               pr "               (int) r->%s);\n" field;
7451               pr "      return -1;\n";
7452               pr "    }\n"
7453           | CompareWithIntOp (field, op, expected) ->
7454               pr "    if (!(r->%s %s %d)) {\n" field op expected;
7455               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
7456                 test_name field op expected;
7457               pr "               (int) r->%s);\n" field;
7458               pr "      return -1;\n";
7459               pr "    }\n"
7460           | CompareWithString (field, expected) ->
7461               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
7462               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
7463                 test_name field expected;
7464               pr "               r->%s);\n" field;
7465               pr "      return -1;\n";
7466               pr "    }\n"
7467           | CompareFieldsIntEq (field1, field2) ->
7468               pr "    if (r->%s != r->%s) {\n" field1 field2;
7469               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
7470                 test_name field1 field2;
7471               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
7472               pr "      return -1;\n";
7473               pr "    }\n"
7474           | CompareFieldsStrEq (field1, field2) ->
7475               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
7476               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
7477                 test_name field1 field2;
7478               pr "               r->%s, r->%s);\n" field1 field2;
7479               pr "      return -1;\n";
7480               pr "    }\n"
7481         ) checks
7482       in
7483       List.iter (generate_test_command_call test_name) seq;
7484       generate_test_command_call ~test test_name last
7485   | TestLastFail seq ->
7486       pr "  /* TestLastFail for %s (%d) */\n" name i;
7487       let seq, last = get_seq_last seq in
7488       List.iter (generate_test_command_call test_name) seq;
7489       generate_test_command_call test_name ~expect_error:true last
7490
7491 (* Generate the code to run a command, leaving the result in 'r'.
7492  * If you expect to get an error then you should set expect_error:true.
7493  *)
7494 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
7495   match cmd with
7496   | [] -> assert false
7497   | name :: args ->
7498       (* Look up the command to find out what args/ret it has. *)
7499       let style =
7500         try
7501           let _, style, _, _, _, _, _ =
7502             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
7503           style
7504         with Not_found ->
7505           failwithf "%s: in test, command %s was not found" test_name name in
7506
7507       if List.length (snd style) <> List.length args then
7508         failwithf "%s: in test, wrong number of args given to %s"
7509           test_name name;
7510
7511       pr "  {\n";
7512
7513       List.iter (
7514         function
7515         | OptString n, "NULL" -> ()
7516         | Pathname n, arg
7517         | Device n, arg
7518         | Dev_or_Path n, arg
7519         | String n, arg
7520         | OptString n, arg ->
7521             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7522         | BufferIn n, arg ->
7523             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
7524             pr "    size_t %s_size = %d;\n" n (String.length arg)
7525         | Int _, _
7526         | Int64 _, _
7527         | Bool _, _
7528         | FileIn _, _ | FileOut _, _ -> ()
7529         | StringList n, "" | DeviceList n, "" ->
7530             pr "    const char *const %s[1] = { NULL };\n" n
7531         | StringList n, arg | DeviceList n, arg ->
7532             let strs = string_split " " arg in
7533             iteri (
7534               fun i str ->
7535                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
7536             ) strs;
7537             pr "    const char *const %s[] = {\n" n;
7538             iteri (
7539               fun i _ -> pr "      %s_%d,\n" n i
7540             ) strs;
7541             pr "      NULL\n";
7542             pr "    };\n";
7543       ) (List.combine (snd style) args);
7544
7545       let error_code =
7546         match fst style with
7547         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
7548         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
7549         | RConstString _ | RConstOptString _ ->
7550             pr "    const char *r;\n"; "NULL"
7551         | RString _ -> pr "    char *r;\n"; "NULL"
7552         | RStringList _ | RHashtable _ ->
7553             pr "    char **r;\n";
7554             pr "    size_t i;\n";
7555             "NULL"
7556         | RStruct (_, typ) ->
7557             pr "    struct guestfs_%s *r;\n" typ; "NULL"
7558         | RStructList (_, typ) ->
7559             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
7560         | RBufferOut _ ->
7561             pr "    char *r;\n";
7562             pr "    size_t size;\n";
7563             "NULL" in
7564
7565       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
7566       pr "    r = guestfs_%s (g" name;
7567
7568       (* Generate the parameters. *)
7569       List.iter (
7570         function
7571         | OptString _, "NULL" -> pr ", NULL"
7572         | Pathname n, _
7573         | Device n, _ | Dev_or_Path n, _
7574         | String n, _
7575         | OptString n, _ ->
7576             pr ", %s" n
7577         | BufferIn n, _ ->
7578             pr ", %s, %s_size" n n
7579         | FileIn _, arg | FileOut _, arg ->
7580             pr ", \"%s\"" (c_quote arg)
7581         | StringList n, _ | DeviceList n, _ ->
7582             pr ", (char **) %s" n
7583         | Int _, arg ->
7584             let i =
7585               try int_of_string arg
7586               with Failure "int_of_string" ->
7587                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
7588             pr ", %d" i
7589         | Int64 _, arg ->
7590             let i =
7591               try Int64.of_string arg
7592               with Failure "int_of_string" ->
7593                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
7594             pr ", %Ld" i
7595         | Bool _, arg ->
7596             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
7597       ) (List.combine (snd style) args);
7598
7599       (match fst style with
7600        | RBufferOut _ -> pr ", &size"
7601        | _ -> ()
7602       );
7603
7604       pr ");\n";
7605
7606       if not expect_error then
7607         pr "    if (r == %s)\n" error_code
7608       else
7609         pr "    if (r != %s)\n" error_code;
7610       pr "      return -1;\n";
7611
7612       (* Insert the test code. *)
7613       (match test with
7614        | None -> ()
7615        | Some f -> f ()
7616       );
7617
7618       (match fst style with
7619        | RErr | RInt _ | RInt64 _ | RBool _
7620        | RConstString _ | RConstOptString _ -> ()
7621        | RString _ | RBufferOut _ -> pr "    free (r);\n"
7622        | RStringList _ | RHashtable _ ->
7623            pr "    for (i = 0; r[i] != NULL; ++i)\n";
7624            pr "      free (r[i]);\n";
7625            pr "    free (r);\n"
7626        | RStruct (_, typ) ->
7627            pr "    guestfs_free_%s (r);\n" typ
7628        | RStructList (_, typ) ->
7629            pr "    guestfs_free_%s_list (r);\n" typ
7630       );
7631
7632       pr "  }\n"
7633
7634 and c_quote str =
7635   let str = replace_str str "\r" "\\r" in
7636   let str = replace_str str "\n" "\\n" in
7637   let str = replace_str str "\t" "\\t" in
7638   let str = replace_str str "\000" "\\0" in
7639   str
7640
7641 (* Generate a lot of different functions for guestfish. *)
7642 and generate_fish_cmds () =
7643   generate_header CStyle GPLv2plus;
7644
7645   let all_functions =
7646     List.filter (
7647       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7648     ) all_functions in
7649   let all_functions_sorted =
7650     List.filter (
7651       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7652     ) all_functions_sorted in
7653
7654   pr "#include <config.h>\n";
7655   pr "\n";
7656   pr "#include <stdio.h>\n";
7657   pr "#include <stdlib.h>\n";
7658   pr "#include <string.h>\n";
7659   pr "#include <inttypes.h>\n";
7660   pr "\n";
7661   pr "#include <guestfs.h>\n";
7662   pr "#include \"c-ctype.h\"\n";
7663   pr "#include \"full-write.h\"\n";
7664   pr "#include \"xstrtol.h\"\n";
7665   pr "#include \"fish.h\"\n";
7666   pr "\n";
7667   pr "/* Valid suffixes allowed for numbers.  See Gnulib xstrtol function. */\n";
7668   pr "static const char *xstrtol_suffixes = \"0kKMGTPEZY\";\n";
7669   pr "\n";
7670
7671   (* list_commands function, which implements guestfish -h *)
7672   pr "void list_commands (void)\n";
7673   pr "{\n";
7674   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
7675   pr "  list_builtin_commands ();\n";
7676   List.iter (
7677     fun (name, _, _, flags, _, shortdesc, _) ->
7678       let name = replace_char name '_' '-' in
7679       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
7680         name shortdesc
7681   ) all_functions_sorted;
7682   pr "  printf (\"    %%s\\n\",";
7683   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
7684   pr "}\n";
7685   pr "\n";
7686
7687   (* display_command function, which implements guestfish -h cmd *)
7688   pr "int display_command (const char *cmd)\n";
7689   pr "{\n";
7690   List.iter (
7691     fun (name, style, _, flags, _, shortdesc, longdesc) ->
7692       let name2 = replace_char name '_' '-' in
7693       let alias =
7694         try find_map (function FishAlias n -> Some n | _ -> None) flags
7695         with Not_found -> name in
7696       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
7697       let synopsis =
7698         match snd style with
7699         | [] -> name2
7700         | args ->
7701             sprintf "%s %s"
7702               name2 (String.concat " " (List.map name_of_argt args)) in
7703
7704       let warnings =
7705         if List.mem ProtocolLimitWarning flags then
7706           ("\n\n" ^ protocol_limit_warning)
7707         else "" in
7708
7709       (* For DangerWillRobinson commands, we should probably have
7710        * guestfish prompt before allowing you to use them (especially
7711        * in interactive mode). XXX
7712        *)
7713       let warnings =
7714         warnings ^
7715           if List.mem DangerWillRobinson flags then
7716             ("\n\n" ^ danger_will_robinson)
7717           else "" in
7718
7719       let warnings =
7720         warnings ^
7721           match deprecation_notice flags with
7722           | None -> ""
7723           | Some txt -> "\n\n" ^ txt in
7724
7725       let describe_alias =
7726         if name <> alias then
7727           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7728         else "" in
7729
7730       pr "  if (";
7731       pr "STRCASEEQ (cmd, \"%s\")" name;
7732       if name <> name2 then
7733         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7734       if name <> alias then
7735         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7736       pr ") {\n";
7737       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7738         name2 shortdesc
7739         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7740          "=head1 DESCRIPTION\n\n" ^
7741          longdesc ^ warnings ^ describe_alias);
7742       pr "    return 0;\n";
7743       pr "  }\n";
7744       pr "  else\n"
7745   ) all_functions;
7746   pr "    return display_builtin_command (cmd);\n";
7747   pr "}\n";
7748   pr "\n";
7749
7750   let emit_print_list_function typ =
7751     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7752       typ typ typ;
7753     pr "{\n";
7754     pr "  unsigned int i;\n";
7755     pr "\n";
7756     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7757     pr "    printf (\"[%%d] = {\\n\", i);\n";
7758     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7759     pr "    printf (\"}\\n\");\n";
7760     pr "  }\n";
7761     pr "}\n";
7762     pr "\n";
7763   in
7764
7765   (* print_* functions *)
7766   List.iter (
7767     fun (typ, cols) ->
7768       let needs_i =
7769         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7770
7771       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7772       pr "{\n";
7773       if needs_i then (
7774         pr "  unsigned int i;\n";
7775         pr "\n"
7776       );
7777       List.iter (
7778         function
7779         | name, FString ->
7780             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7781         | name, FUUID ->
7782             pr "  printf (\"%%s%s: \", indent);\n" name;
7783             pr "  for (i = 0; i < 32; ++i)\n";
7784             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7785             pr "  printf (\"\\n\");\n"
7786         | name, FBuffer ->
7787             pr "  printf (\"%%s%s: \", indent);\n" name;
7788             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7789             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7790             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7791             pr "    else\n";
7792             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7793             pr "  printf (\"\\n\");\n"
7794         | name, (FUInt64|FBytes) ->
7795             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7796               name typ name
7797         | name, FInt64 ->
7798             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7799               name typ name
7800         | name, FUInt32 ->
7801             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7802               name typ name
7803         | name, FInt32 ->
7804             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7805               name typ name
7806         | name, FChar ->
7807             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7808               name typ name
7809         | name, FOptPercent ->
7810             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7811               typ name name typ name;
7812             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7813       ) cols;
7814       pr "}\n";
7815       pr "\n";
7816   ) structs;
7817
7818   (* Emit a print_TYPE_list function definition only if that function is used. *)
7819   List.iter (
7820     function
7821     | typ, (RStructListOnly | RStructAndList) ->
7822         (* generate the function for typ *)
7823         emit_print_list_function typ
7824     | typ, _ -> () (* empty *)
7825   ) (rstructs_used_by all_functions);
7826
7827   (* Emit a print_TYPE function definition only if that function is used. *)
7828   List.iter (
7829     function
7830     | typ, (RStructOnly | RStructAndList) ->
7831         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7832         pr "{\n";
7833         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7834         pr "}\n";
7835         pr "\n";
7836     | typ, _ -> () (* empty *)
7837   ) (rstructs_used_by all_functions);
7838
7839   (* run_<action> actions *)
7840   List.iter (
7841     fun (name, style, _, flags, _, _, _) ->
7842       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7843       pr "{\n";
7844       (match fst style with
7845        | RErr
7846        | RInt _
7847        | RBool _ -> pr "  int r;\n"
7848        | RInt64 _ -> pr "  int64_t r;\n"
7849        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7850        | RString _ -> pr "  char *r;\n"
7851        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7852        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7853        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7854        | RBufferOut _ ->
7855            pr "  char *r;\n";
7856            pr "  size_t size;\n";
7857       );
7858       List.iter (
7859         function
7860         | Device n
7861         | String n
7862         | OptString n -> pr "  const char *%s;\n" n
7863         | Pathname n
7864         | Dev_or_Path n
7865         | FileIn n
7866         | FileOut n -> pr "  char *%s;\n" n
7867         | BufferIn n ->
7868             pr "  const char *%s;\n" n;
7869             pr "  size_t %s_size;\n" n
7870         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7871         | Bool n -> pr "  int %s;\n" n
7872         | Int n -> pr "  int %s;\n" n
7873         | Int64 n -> pr "  int64_t %s;\n" n
7874       ) (snd style);
7875
7876       (* Check and convert parameters. *)
7877       let argc_expected = List.length (snd style) in
7878       pr "  if (argc != %d) {\n" argc_expected;
7879       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7880         argc_expected;
7881       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7882       pr "    return -1;\n";
7883       pr "  }\n";
7884
7885       let parse_integer fn fntyp rtyp range name i =
7886         pr "  {\n";
7887         pr "    strtol_error xerr;\n";
7888         pr "    %s r;\n" fntyp;
7889         pr "\n";
7890         pr "    xerr = %s (argv[%d], NULL, 0, &r, xstrtol_suffixes);\n" fn i;
7891         pr "    if (xerr != LONGINT_OK) {\n";
7892         pr "      fprintf (stderr,\n";
7893         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7894         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7895         pr "      return -1;\n";
7896         pr "    }\n";
7897         (match range with
7898          | None -> ()
7899          | Some (min, max, comment) ->
7900              pr "    /* %s */\n" comment;
7901              pr "    if (r < %s || r > %s) {\n" min max;
7902              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7903                name;
7904              pr "      return -1;\n";
7905              pr "    }\n";
7906              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7907         );
7908         pr "    %s = r;\n" name;
7909         pr "  }\n";
7910       in
7911
7912       iteri (
7913         fun i ->
7914           function
7915           | Device name
7916           | String name ->
7917               pr "  %s = argv[%d];\n" name i
7918           | Pathname name
7919           | Dev_or_Path name ->
7920               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7921               pr "  if (%s == NULL) return -1;\n" name
7922           | OptString name ->
7923               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7924                 name i i
7925           | BufferIn name ->
7926               pr "  %s = argv[%d];\n" name i;
7927               pr "  %s_size = strlen (argv[%d]);\n" name i
7928           | FileIn name ->
7929               pr "  %s = file_in (argv[%d]);\n" name i;
7930               pr "  if (%s == NULL) return -1;\n" name
7931           | FileOut name ->
7932               pr "  %s = file_out (argv[%d]);\n" name i;
7933               pr "  if (%s == NULL) return -1;\n" name
7934           | StringList name | DeviceList name ->
7935               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7936               pr "  if (%s == NULL) return -1;\n" name;
7937           | Bool name ->
7938               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7939           | Int name ->
7940               let range =
7941                 let min = "(-(2LL<<30))"
7942                 and max = "((2LL<<30)-1)"
7943                 and comment =
7944                   "The Int type in the generator is a signed 31 bit int." in
7945                 Some (min, max, comment) in
7946               parse_integer "xstrtoll" "long long" "int" range name i
7947           | Int64 name ->
7948               parse_integer "xstrtoll" "long long" "int64_t" None name i
7949       ) (snd style);
7950
7951       (* Call C API function. *)
7952       pr "  r = guestfs_%s " name;
7953       generate_c_call_args ~handle:"g" style;
7954       pr ";\n";
7955
7956       List.iter (
7957         function
7958         | Device _ | String _
7959         | OptString _ | Bool _
7960         | Int _ | Int64 _
7961         | BufferIn _ -> ()
7962         | Pathname name | Dev_or_Path name | FileOut name ->
7963             pr "  free (%s);\n" name
7964         | FileIn name ->
7965             pr "  free_file_in (%s);\n" name
7966         | StringList name | DeviceList name ->
7967             pr "  free_strings (%s);\n" name
7968       ) (snd style);
7969
7970       (* Any output flags? *)
7971       let fish_output =
7972         let flags = filter_map (
7973           function FishOutput flag -> Some flag | _ -> None
7974         ) flags in
7975         match flags with
7976         | [] -> None
7977         | [f] -> Some f
7978         | _ ->
7979             failwithf "%s: more than one FishOutput flag is not allowed" name in
7980
7981       (* Check return value for errors and display command results. *)
7982       (match fst style with
7983        | RErr -> pr "  return r;\n"
7984        | RInt _ ->
7985            pr "  if (r == -1) return -1;\n";
7986            (match fish_output with
7987             | None ->
7988                 pr "  printf (\"%%d\\n\", r);\n";
7989             | Some FishOutputOctal ->
7990                 pr "  printf (\"%%s%%o\\n\", r != 0 ? \"0\" : \"\", r);\n";
7991             | Some FishOutputHexadecimal ->
7992                 pr "  printf (\"%%s%%x\\n\", r != 0 ? \"0x\" : \"\", r);\n");
7993            pr "  return 0;\n"
7994        | RInt64 _ ->
7995            pr "  if (r == -1) return -1;\n";
7996            (match fish_output with
7997             | None ->
7998                 pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7999             | Some FishOutputOctal ->
8000                 pr "  printf (\"%%s%%\" PRIo64 \"\\n\", r != 0 ? \"0\" : \"\", r);\n";
8001             | Some FishOutputHexadecimal ->
8002                 pr "  printf (\"%%s%%\" PRIx64 \"\\n\", r != 0 ? \"0x\" : \"\", r);\n");
8003            pr "  return 0;\n"
8004        | RBool _ ->
8005            pr "  if (r == -1) return -1;\n";
8006            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
8007            pr "  return 0;\n"
8008        | RConstString _ ->
8009            pr "  if (r == NULL) return -1;\n";
8010            pr "  printf (\"%%s\\n\", r);\n";
8011            pr "  return 0;\n"
8012        | RConstOptString _ ->
8013            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
8014            pr "  return 0;\n"
8015        | RString _ ->
8016            pr "  if (r == NULL) return -1;\n";
8017            pr "  printf (\"%%s\\n\", r);\n";
8018            pr "  free (r);\n";
8019            pr "  return 0;\n"
8020        | RStringList _ ->
8021            pr "  if (r == NULL) return -1;\n";
8022            pr "  print_strings (r);\n";
8023            pr "  free_strings (r);\n";
8024            pr "  return 0;\n"
8025        | RStruct (_, typ) ->
8026            pr "  if (r == NULL) return -1;\n";
8027            pr "  print_%s (r);\n" typ;
8028            pr "  guestfs_free_%s (r);\n" typ;
8029            pr "  return 0;\n"
8030        | RStructList (_, typ) ->
8031            pr "  if (r == NULL) return -1;\n";
8032            pr "  print_%s_list (r);\n" typ;
8033            pr "  guestfs_free_%s_list (r);\n" typ;
8034            pr "  return 0;\n"
8035        | RHashtable _ ->
8036            pr "  if (r == NULL) return -1;\n";
8037            pr "  print_table (r);\n";
8038            pr "  free_strings (r);\n";
8039            pr "  return 0;\n"
8040        | RBufferOut _ ->
8041            pr "  if (r == NULL) return -1;\n";
8042            pr "  if (full_write (1, r, size) != size) {\n";
8043            pr "    perror (\"write\");\n";
8044            pr "    free (r);\n";
8045            pr "    return -1;\n";
8046            pr "  }\n";
8047            pr "  free (r);\n";
8048            pr "  return 0;\n"
8049       );
8050       pr "}\n";
8051       pr "\n"
8052   ) all_functions;
8053
8054   (* run_action function *)
8055   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
8056   pr "{\n";
8057   List.iter (
8058     fun (name, _, _, flags, _, _, _) ->
8059       let name2 = replace_char name '_' '-' in
8060       let alias =
8061         try find_map (function FishAlias n -> Some n | _ -> None) flags
8062         with Not_found -> name in
8063       pr "  if (";
8064       pr "STRCASEEQ (cmd, \"%s\")" name;
8065       if name <> name2 then
8066         pr " || STRCASEEQ (cmd, \"%s\")" name2;
8067       if name <> alias then
8068         pr " || STRCASEEQ (cmd, \"%s\")" alias;
8069       pr ")\n";
8070       pr "    return run_%s (cmd, argc, argv);\n" name;
8071       pr "  else\n";
8072   ) all_functions;
8073   pr "    {\n";
8074   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
8075   pr "      if (command_num == 1)\n";
8076   pr "        extended_help_message ();\n";
8077   pr "      return -1;\n";
8078   pr "    }\n";
8079   pr "  return 0;\n";
8080   pr "}\n";
8081   pr "\n"
8082
8083 (* Readline completion for guestfish. *)
8084 and generate_fish_completion () =
8085   generate_header CStyle GPLv2plus;
8086
8087   let all_functions =
8088     List.filter (
8089       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
8090     ) all_functions in
8091
8092   pr "\
8093 #include <config.h>
8094
8095 #include <stdio.h>
8096 #include <stdlib.h>
8097 #include <string.h>
8098
8099 #ifdef HAVE_LIBREADLINE
8100 #include <readline/readline.h>
8101 #endif
8102
8103 #include \"fish.h\"
8104
8105 #ifdef HAVE_LIBREADLINE
8106
8107 static const char *const commands[] = {
8108   BUILTIN_COMMANDS_FOR_COMPLETION,
8109 ";
8110
8111   (* Get the commands, including the aliases.  They don't need to be
8112    * sorted - the generator() function just does a dumb linear search.
8113    *)
8114   let commands =
8115     List.map (
8116       fun (name, _, _, flags, _, _, _) ->
8117         let name2 = replace_char name '_' '-' in
8118         let alias =
8119           try find_map (function FishAlias n -> Some n | _ -> None) flags
8120           with Not_found -> name in
8121
8122         if name <> alias then [name2; alias] else [name2]
8123     ) all_functions in
8124   let commands = List.flatten commands in
8125
8126   List.iter (pr "  \"%s\",\n") commands;
8127
8128   pr "  NULL
8129 };
8130
8131 static char *
8132 generator (const char *text, int state)
8133 {
8134   static size_t index, len;
8135   const char *name;
8136
8137   if (!state) {
8138     index = 0;
8139     len = strlen (text);
8140   }
8141
8142   rl_attempted_completion_over = 1;
8143
8144   while ((name = commands[index]) != NULL) {
8145     index++;
8146     if (STRCASEEQLEN (name, text, len))
8147       return strdup (name);
8148   }
8149
8150   return NULL;
8151 }
8152
8153 #endif /* HAVE_LIBREADLINE */
8154
8155 #ifdef HAVE_RL_COMPLETION_MATCHES
8156 #define RL_COMPLETION_MATCHES rl_completion_matches
8157 #else
8158 #ifdef HAVE_COMPLETION_MATCHES
8159 #define RL_COMPLETION_MATCHES completion_matches
8160 #endif
8161 #endif /* else just fail if we don't have either symbol */
8162
8163 char **
8164 do_completion (const char *text, int start, int end)
8165 {
8166   char **matches = NULL;
8167
8168 #ifdef HAVE_LIBREADLINE
8169   rl_completion_append_character = ' ';
8170
8171   if (start == 0)
8172     matches = RL_COMPLETION_MATCHES (text, generator);
8173   else if (complete_dest_paths)
8174     matches = RL_COMPLETION_MATCHES (text, complete_dest_paths_generator);
8175 #endif
8176
8177   return matches;
8178 }
8179 ";
8180
8181 (* Generate the POD documentation for guestfish. *)
8182 and generate_fish_actions_pod () =
8183   let all_functions_sorted =
8184     List.filter (
8185       fun (_, _, _, flags, _, _, _) ->
8186         not (List.mem NotInFish flags || List.mem NotInDocs flags)
8187     ) all_functions_sorted in
8188
8189   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
8190
8191   List.iter (
8192     fun (name, style, _, flags, _, _, longdesc) ->
8193       let longdesc =
8194         Str.global_substitute rex (
8195           fun s ->
8196             let sub =
8197               try Str.matched_group 1 s
8198               with Not_found ->
8199                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
8200             "C<" ^ replace_char sub '_' '-' ^ ">"
8201         ) longdesc in
8202       let name = replace_char name '_' '-' in
8203       let alias =
8204         try find_map (function FishAlias n -> Some n | _ -> None) flags
8205         with Not_found -> name in
8206
8207       pr "=head2 %s" name;
8208       if name <> alias then
8209         pr " | %s" alias;
8210       pr "\n";
8211       pr "\n";
8212       pr " %s" name;
8213       List.iter (
8214         function
8215         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
8216         | OptString n -> pr " %s" n
8217         | StringList n | DeviceList n -> pr " '%s ...'" n
8218         | Bool _ -> pr " true|false"
8219         | Int n -> pr " %s" n
8220         | Int64 n -> pr " %s" n
8221         | FileIn n | FileOut n -> pr " (%s|-)" n
8222         | BufferIn n -> pr " %s" n
8223       ) (snd style);
8224       pr "\n";
8225       pr "\n";
8226       pr "%s\n\n" longdesc;
8227
8228       if List.exists (function FileIn _ | FileOut _ -> true
8229                       | _ -> false) (snd style) then
8230         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
8231
8232       if List.mem ProtocolLimitWarning flags then
8233         pr "%s\n\n" protocol_limit_warning;
8234
8235       if List.mem DangerWillRobinson flags then
8236         pr "%s\n\n" danger_will_robinson;
8237
8238       match deprecation_notice flags with
8239       | None -> ()
8240       | Some txt -> pr "%s\n\n" txt
8241   ) all_functions_sorted
8242
8243 and generate_fish_prep_options_h () =
8244   generate_header CStyle GPLv2plus;
8245
8246   pr "#ifndef PREPOPTS_H\n";
8247   pr "\n";
8248
8249   pr "\
8250 struct prep {
8251   const char *name;             /* eg. \"fs\" */
8252
8253   size_t nr_params;             /* optional parameters */
8254   struct prep_param *params;
8255
8256   const char *shortdesc;        /* short description */
8257   const char *longdesc;         /* long description */
8258
8259                                 /* functions to implement it */
8260   void (*prelaunch) (const char *filename, prep_data *);
8261   void (*postlaunch) (const char *filename, prep_data *, const char *device);
8262 };
8263
8264 struct prep_param {
8265   const char *pname;            /* parameter name */
8266   const char *pdefault;         /* parameter default */
8267   const char *pdesc;            /* parameter description */
8268 };
8269
8270 extern const struct prep preps[];
8271 #define NR_PREPS %d
8272
8273 " (List.length prepopts);
8274
8275   List.iter (
8276     fun (name, shortdesc, args, longdesc) ->
8277       pr "\
8278 extern void prep_prelaunch_%s (const char *filename, prep_data *data);
8279 extern void prep_postlaunch_%s (const char *filename, prep_data *data, const char *device);
8280
8281 " name name;
8282   ) prepopts;
8283
8284   pr "\n";
8285   pr "#endif /* PREPOPTS_H */\n"
8286
8287 and generate_fish_prep_options_c () =
8288   generate_header CStyle GPLv2plus;
8289
8290   pr "\
8291 #include \"fish.h\"
8292 #include \"prepopts.h\"
8293
8294 ";
8295
8296   List.iter (
8297     fun (name, shortdesc, args, longdesc) ->
8298       pr "static struct prep_param %s_args[] = {\n" name;
8299       List.iter (
8300         fun (n, default, desc) ->
8301           pr "  { \"%s\", \"%s\", \"%s\" },\n" n default desc
8302       ) args;
8303       pr "};\n";
8304       pr "\n";
8305   ) prepopts;
8306
8307   pr "const struct prep preps[] = {\n";
8308   List.iter (
8309     fun (name, shortdesc, args, longdesc) ->
8310       pr "  { \"%s\", %d, %s_args,
8311     \"%s\",
8312     \"%s\",
8313     prep_prelaunch_%s, prep_postlaunch_%s },
8314 "
8315         name (List.length args) name
8316         (c_quote shortdesc) (c_quote longdesc)
8317         name name;
8318   ) prepopts;
8319   pr "};\n"
8320
8321 (* Generate a C function prototype. *)
8322 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
8323     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
8324     ?(prefix = "")
8325     ?handle name style =
8326   if extern then pr "extern ";
8327   if static then pr "static ";
8328   (match fst style with
8329    | RErr -> pr "int "
8330    | RInt _ -> pr "int "
8331    | RInt64 _ -> pr "int64_t "
8332    | RBool _ -> pr "int "
8333    | RConstString _ | RConstOptString _ -> pr "const char *"
8334    | RString _ | RBufferOut _ -> pr "char *"
8335    | RStringList _ | RHashtable _ -> pr "char **"
8336    | RStruct (_, typ) ->
8337        if not in_daemon then pr "struct guestfs_%s *" typ
8338        else pr "guestfs_int_%s *" typ
8339    | RStructList (_, typ) ->
8340        if not in_daemon then pr "struct guestfs_%s_list *" typ
8341        else pr "guestfs_int_%s_list *" typ
8342   );
8343   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
8344   pr "%s%s (" prefix name;
8345   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
8346     pr "void"
8347   else (
8348     let comma = ref false in
8349     (match handle with
8350      | None -> ()
8351      | Some handle -> pr "guestfs_h *%s" handle; comma := true
8352     );
8353     let next () =
8354       if !comma then (
8355         if single_line then pr ", " else pr ",\n\t\t"
8356       );
8357       comma := true
8358     in
8359     List.iter (
8360       function
8361       | Pathname n
8362       | Device n | Dev_or_Path n
8363       | String n
8364       | OptString n ->
8365           next ();
8366           pr "const char *%s" n
8367       | StringList n | DeviceList n ->
8368           next ();
8369           pr "char *const *%s" n
8370       | Bool n -> next (); pr "int %s" n
8371       | Int n -> next (); pr "int %s" n
8372       | Int64 n -> next (); pr "int64_t %s" n
8373       | FileIn n
8374       | FileOut n ->
8375           if not in_daemon then (next (); pr "const char *%s" n)
8376       | BufferIn n ->
8377           next ();
8378           pr "const char *%s" n;
8379           next ();
8380           pr "size_t %s_size" n
8381     ) (snd style);
8382     if is_RBufferOut then (next (); pr "size_t *size_r");
8383   );
8384   pr ")";
8385   if semicolon then pr ";";
8386   if newline then pr "\n"
8387
8388 (* Generate C call arguments, eg "(handle, foo, bar)" *)
8389 and generate_c_call_args ?handle ?(decl = false) style =
8390   pr "(";
8391   let comma = ref false in
8392   let next () =
8393     if !comma then pr ", ";
8394     comma := true
8395   in
8396   (match handle with
8397    | None -> ()
8398    | Some handle -> pr "%s" handle; comma := true
8399   );
8400   List.iter (
8401     function
8402     | BufferIn n ->
8403         next ();
8404         pr "%s, %s_size" n n
8405     | arg ->
8406         next ();
8407         pr "%s" (name_of_argt arg)
8408   ) (snd style);
8409   (* For RBufferOut calls, add implicit &size parameter. *)
8410   if not decl then (
8411     match fst style with
8412     | RBufferOut _ ->
8413         next ();
8414         pr "&size"
8415     | _ -> ()
8416   );
8417   pr ")"
8418
8419 (* Generate the OCaml bindings interface. *)
8420 and generate_ocaml_mli () =
8421   generate_header OCamlStyle LGPLv2plus;
8422
8423   pr "\
8424 (** For API documentation you should refer to the C API
8425     in the guestfs(3) manual page.  The OCaml API uses almost
8426     exactly the same calls. *)
8427
8428 type t
8429 (** A [guestfs_h] handle. *)
8430
8431 exception Error of string
8432 (** This exception is raised when there is an error. *)
8433
8434 exception Handle_closed of string
8435 (** This exception is raised if you use a {!Guestfs.t} handle
8436     after calling {!close} on it.  The string is the name of
8437     the function. *)
8438
8439 val create : unit -> t
8440 (** Create a {!Guestfs.t} handle. *)
8441
8442 val close : t -> unit
8443 (** Close the {!Guestfs.t} handle and free up all resources used
8444     by it immediately.
8445
8446     Handles are closed by the garbage collector when they become
8447     unreferenced, but callers can call this in order to provide
8448     predictable cleanup. *)
8449
8450 ";
8451   generate_ocaml_structure_decls ();
8452
8453   (* The actions. *)
8454   List.iter (
8455     fun (name, style, _, _, _, shortdesc, _) ->
8456       generate_ocaml_prototype name style;
8457       pr "(** %s *)\n" shortdesc;
8458       pr "\n"
8459   ) all_functions_sorted
8460
8461 (* Generate the OCaml bindings implementation. *)
8462 and generate_ocaml_ml () =
8463   generate_header OCamlStyle LGPLv2plus;
8464
8465   pr "\
8466 type t
8467
8468 exception Error of string
8469 exception Handle_closed of string
8470
8471 external create : unit -> t = \"ocaml_guestfs_create\"
8472 external close : t -> unit = \"ocaml_guestfs_close\"
8473
8474 (* Give the exceptions names, so they can be raised from the C code. *)
8475 let () =
8476   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
8477   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
8478
8479 ";
8480
8481   generate_ocaml_structure_decls ();
8482
8483   (* The actions. *)
8484   List.iter (
8485     fun (name, style, _, _, _, shortdesc, _) ->
8486       generate_ocaml_prototype ~is_external:true name style;
8487   ) all_functions_sorted
8488
8489 (* Generate the OCaml bindings C implementation. *)
8490 and generate_ocaml_c () =
8491   generate_header CStyle LGPLv2plus;
8492
8493   pr "\
8494 #include <stdio.h>
8495 #include <stdlib.h>
8496 #include <string.h>
8497
8498 #include <caml/config.h>
8499 #include <caml/alloc.h>
8500 #include <caml/callback.h>
8501 #include <caml/fail.h>
8502 #include <caml/memory.h>
8503 #include <caml/mlvalues.h>
8504 #include <caml/signals.h>
8505
8506 #include \"guestfs.h\"
8507
8508 #include \"guestfs_c.h\"
8509
8510 /* Copy a hashtable of string pairs into an assoc-list.  We return
8511  * the list in reverse order, but hashtables aren't supposed to be
8512  * ordered anyway.
8513  */
8514 static CAMLprim value
8515 copy_table (char * const * argv)
8516 {
8517   CAMLparam0 ();
8518   CAMLlocal5 (rv, pairv, kv, vv, cons);
8519   size_t i;
8520
8521   rv = Val_int (0);
8522   for (i = 0; argv[i] != NULL; i += 2) {
8523     kv = caml_copy_string (argv[i]);
8524     vv = caml_copy_string (argv[i+1]);
8525     pairv = caml_alloc (2, 0);
8526     Store_field (pairv, 0, kv);
8527     Store_field (pairv, 1, vv);
8528     cons = caml_alloc (2, 0);
8529     Store_field (cons, 1, rv);
8530     rv = cons;
8531     Store_field (cons, 0, pairv);
8532   }
8533
8534   CAMLreturn (rv);
8535 }
8536
8537 ";
8538
8539   (* Struct copy functions. *)
8540
8541   let emit_ocaml_copy_list_function typ =
8542     pr "static CAMLprim value\n";
8543     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
8544     pr "{\n";
8545     pr "  CAMLparam0 ();\n";
8546     pr "  CAMLlocal2 (rv, v);\n";
8547     pr "  unsigned int i;\n";
8548     pr "\n";
8549     pr "  if (%ss->len == 0)\n" typ;
8550     pr "    CAMLreturn (Atom (0));\n";
8551     pr "  else {\n";
8552     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
8553     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
8554     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
8555     pr "      caml_modify (&Field (rv, i), v);\n";
8556     pr "    }\n";
8557     pr "    CAMLreturn (rv);\n";
8558     pr "  }\n";
8559     pr "}\n";
8560     pr "\n";
8561   in
8562
8563   List.iter (
8564     fun (typ, cols) ->
8565       let has_optpercent_col =
8566         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
8567
8568       pr "static CAMLprim value\n";
8569       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
8570       pr "{\n";
8571       pr "  CAMLparam0 ();\n";
8572       if has_optpercent_col then
8573         pr "  CAMLlocal3 (rv, v, v2);\n"
8574       else
8575         pr "  CAMLlocal2 (rv, v);\n";
8576       pr "\n";
8577       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
8578       iteri (
8579         fun i col ->
8580           (match col with
8581            | name, FString ->
8582                pr "  v = caml_copy_string (%s->%s);\n" typ name
8583            | name, FBuffer ->
8584                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
8585                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
8586                  typ name typ name
8587            | name, FUUID ->
8588                pr "  v = caml_alloc_string (32);\n";
8589                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
8590            | name, (FBytes|FInt64|FUInt64) ->
8591                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
8592            | name, (FInt32|FUInt32) ->
8593                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
8594            | name, FOptPercent ->
8595                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
8596                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
8597                pr "    v = caml_alloc (1, 0);\n";
8598                pr "    Store_field (v, 0, v2);\n";
8599                pr "  } else /* None */\n";
8600                pr "    v = Val_int (0);\n";
8601            | name, FChar ->
8602                pr "  v = Val_int (%s->%s);\n" typ name
8603           );
8604           pr "  Store_field (rv, %d, v);\n" i
8605       ) cols;
8606       pr "  CAMLreturn (rv);\n";
8607       pr "}\n";
8608       pr "\n";
8609   ) structs;
8610
8611   (* Emit a copy_TYPE_list function definition only if that function is used. *)
8612   List.iter (
8613     function
8614     | typ, (RStructListOnly | RStructAndList) ->
8615         (* generate the function for typ *)
8616         emit_ocaml_copy_list_function typ
8617     | typ, _ -> () (* empty *)
8618   ) (rstructs_used_by all_functions);
8619
8620   (* The wrappers. *)
8621   List.iter (
8622     fun (name, style, _, _, _, _, _) ->
8623       pr "/* Automatically generated wrapper for function\n";
8624       pr " * ";
8625       generate_ocaml_prototype name style;
8626       pr " */\n";
8627       pr "\n";
8628
8629       let params =
8630         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
8631
8632       let needs_extra_vs =
8633         match fst style with RConstOptString _ -> true | _ -> false in
8634
8635       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8636       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
8637       List.iter (pr ", value %s") (List.tl params); pr ");\n";
8638       pr "\n";
8639
8640       pr "CAMLprim value\n";
8641       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
8642       List.iter (pr ", value %s") (List.tl params);
8643       pr ")\n";
8644       pr "{\n";
8645
8646       (match params with
8647        | [p1; p2; p3; p4; p5] ->
8648            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
8649        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
8650            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
8651            pr "  CAMLxparam%d (%s);\n"
8652              (List.length rest) (String.concat ", " rest)
8653        | ps ->
8654            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
8655       );
8656       if not needs_extra_vs then
8657         pr "  CAMLlocal1 (rv);\n"
8658       else
8659         pr "  CAMLlocal3 (rv, v, v2);\n";
8660       pr "\n";
8661
8662       pr "  guestfs_h *g = Guestfs_val (gv);\n";
8663       pr "  if (g == NULL)\n";
8664       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
8665       pr "\n";
8666
8667       List.iter (
8668         function
8669         | Pathname n
8670         | Device n | Dev_or_Path n
8671         | String n
8672         | FileIn n
8673         | FileOut n ->
8674             (* Copy strings in case the GC moves them: RHBZ#604691 *)
8675             pr "  char *%s = guestfs_safe_strdup (g, String_val (%sv));\n" n n
8676         | OptString n ->
8677             pr "  char *%s =\n" n;
8678             pr "    %sv != Val_int (0) ?" n;
8679             pr "      guestfs_safe_strdup (g, String_val (Field (%sv, 0))) : NULL;\n" n
8680         | BufferIn n ->
8681             pr "  size_t %s_size = caml_string_length (%sv);\n" n n;
8682             pr "  char *%s = guestfs_safe_memdup (g, String_val (%sv), %s_size);\n" n n n
8683         | StringList n | DeviceList n ->
8684             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
8685         | Bool n ->
8686             pr "  int %s = Bool_val (%sv);\n" n n
8687         | Int n ->
8688             pr "  int %s = Int_val (%sv);\n" n n
8689         | Int64 n ->
8690             pr "  int64_t %s = Int64_val (%sv);\n" n n
8691       ) (snd style);
8692       let error_code =
8693         match fst style with
8694         | RErr -> pr "  int r;\n"; "-1"
8695         | RInt _ -> pr "  int r;\n"; "-1"
8696         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8697         | RBool _ -> pr "  int r;\n"; "-1"
8698         | RConstString _ | RConstOptString _ ->
8699             pr "  const char *r;\n"; "NULL"
8700         | RString _ -> pr "  char *r;\n"; "NULL"
8701         | RStringList _ ->
8702             pr "  size_t i;\n";
8703             pr "  char **r;\n";
8704             "NULL"
8705         | RStruct (_, typ) ->
8706             pr "  struct guestfs_%s *r;\n" typ; "NULL"
8707         | RStructList (_, typ) ->
8708             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8709         | RHashtable _ ->
8710             pr "  size_t i;\n";
8711             pr "  char **r;\n";
8712             "NULL"
8713         | RBufferOut _ ->
8714             pr "  char *r;\n";
8715             pr "  size_t size;\n";
8716             "NULL" in
8717       pr "\n";
8718
8719       pr "  caml_enter_blocking_section ();\n";
8720       pr "  r = guestfs_%s " name;
8721       generate_c_call_args ~handle:"g" style;
8722       pr ";\n";
8723       pr "  caml_leave_blocking_section ();\n";
8724
8725       (* Free strings if we copied them above. *)
8726       List.iter (
8727         function
8728         | Pathname n | Device n | Dev_or_Path n | String n | OptString n
8729         | FileIn n | FileOut n | BufferIn n ->
8730             pr "  free (%s);\n" n
8731         | StringList n | DeviceList n ->
8732             pr "  ocaml_guestfs_free_strings (%s);\n" n;
8733         | Bool _ | Int _ | Int64 _ -> ()
8734       ) (snd style);
8735
8736       pr "  if (r == %s)\n" error_code;
8737       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
8738       pr "\n";
8739
8740       (match fst style with
8741        | RErr -> pr "  rv = Val_unit;\n"
8742        | RInt _ -> pr "  rv = Val_int (r);\n"
8743        | RInt64 _ ->
8744            pr "  rv = caml_copy_int64 (r);\n"
8745        | RBool _ -> pr "  rv = Val_bool (r);\n"
8746        | RConstString _ ->
8747            pr "  rv = caml_copy_string (r);\n"
8748        | RConstOptString _ ->
8749            pr "  if (r) { /* Some string */\n";
8750            pr "    v = caml_alloc (1, 0);\n";
8751            pr "    v2 = caml_copy_string (r);\n";
8752            pr "    Store_field (v, 0, v2);\n";
8753            pr "  } else /* None */\n";
8754            pr "    v = Val_int (0);\n";
8755        | RString _ ->
8756            pr "  rv = caml_copy_string (r);\n";
8757            pr "  free (r);\n"
8758        | RStringList _ ->
8759            pr "  rv = caml_copy_string_array ((const char **) r);\n";
8760            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8761            pr "  free (r);\n"
8762        | RStruct (_, typ) ->
8763            pr "  rv = copy_%s (r);\n" typ;
8764            pr "  guestfs_free_%s (r);\n" typ;
8765        | RStructList (_, typ) ->
8766            pr "  rv = copy_%s_list (r);\n" typ;
8767            pr "  guestfs_free_%s_list (r);\n" typ;
8768        | RHashtable _ ->
8769            pr "  rv = copy_table (r);\n";
8770            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
8771            pr "  free (r);\n";
8772        | RBufferOut _ ->
8773            pr "  rv = caml_alloc_string (size);\n";
8774            pr "  memcpy (String_val (rv), r, size);\n";
8775       );
8776
8777       pr "  CAMLreturn (rv);\n";
8778       pr "}\n";
8779       pr "\n";
8780
8781       if List.length params > 5 then (
8782         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
8783         pr "CAMLprim value ";
8784         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
8785         pr "CAMLprim value\n";
8786         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
8787         pr "{\n";
8788         pr "  return ocaml_guestfs_%s (argv[0]" name;
8789         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
8790         pr ");\n";
8791         pr "}\n";
8792         pr "\n"
8793       )
8794   ) all_functions_sorted
8795
8796 and generate_ocaml_structure_decls () =
8797   List.iter (
8798     fun (typ, cols) ->
8799       pr "type %s = {\n" typ;
8800       List.iter (
8801         function
8802         | name, FString -> pr "  %s : string;\n" name
8803         | name, FBuffer -> pr "  %s : string;\n" name
8804         | name, FUUID -> pr "  %s : string;\n" name
8805         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
8806         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
8807         | name, FChar -> pr "  %s : char;\n" name
8808         | name, FOptPercent -> pr "  %s : float option;\n" name
8809       ) cols;
8810       pr "}\n";
8811       pr "\n"
8812   ) structs
8813
8814 and generate_ocaml_prototype ?(is_external = false) name style =
8815   if is_external then pr "external " else pr "val ";
8816   pr "%s : t -> " name;
8817   List.iter (
8818     function
8819     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _
8820     | BufferIn _ -> pr "string -> "
8821     | OptString _ -> pr "string option -> "
8822     | StringList _ | DeviceList _ -> pr "string array -> "
8823     | Bool _ -> pr "bool -> "
8824     | Int _ -> pr "int -> "
8825     | Int64 _ -> pr "int64 -> "
8826   ) (snd style);
8827   (match fst style with
8828    | RErr -> pr "unit" (* all errors are turned into exceptions *)
8829    | RInt _ -> pr "int"
8830    | RInt64 _ -> pr "int64"
8831    | RBool _ -> pr "bool"
8832    | RConstString _ -> pr "string"
8833    | RConstOptString _ -> pr "string option"
8834    | RString _ | RBufferOut _ -> pr "string"
8835    | RStringList _ -> pr "string array"
8836    | RStruct (_, typ) -> pr "%s" typ
8837    | RStructList (_, typ) -> pr "%s array" typ
8838    | RHashtable _ -> pr "(string * string) list"
8839   );
8840   if is_external then (
8841     pr " = ";
8842     if List.length (snd style) + 1 > 5 then
8843       pr "\"ocaml_guestfs_%s_byte\" " name;
8844     pr "\"ocaml_guestfs_%s\"" name
8845   );
8846   pr "\n"
8847
8848 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
8849 and generate_perl_xs () =
8850   generate_header CStyle LGPLv2plus;
8851
8852   pr "\
8853 #include \"EXTERN.h\"
8854 #include \"perl.h\"
8855 #include \"XSUB.h\"
8856
8857 #include <guestfs.h>
8858
8859 #ifndef PRId64
8860 #define PRId64 \"lld\"
8861 #endif
8862
8863 static SV *
8864 my_newSVll(long long val) {
8865 #ifdef USE_64_BIT_ALL
8866   return newSViv(val);
8867 #else
8868   char buf[100];
8869   int len;
8870   len = snprintf(buf, 100, \"%%\" PRId64, val);
8871   return newSVpv(buf, len);
8872 #endif
8873 }
8874
8875 #ifndef PRIu64
8876 #define PRIu64 \"llu\"
8877 #endif
8878
8879 static SV *
8880 my_newSVull(unsigned long long val) {
8881 #ifdef USE_64_BIT_ALL
8882   return newSVuv(val);
8883 #else
8884   char buf[100];
8885   int len;
8886   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8887   return newSVpv(buf, len);
8888 #endif
8889 }
8890
8891 /* http://www.perlmonks.org/?node_id=680842 */
8892 static char **
8893 XS_unpack_charPtrPtr (SV *arg) {
8894   char **ret;
8895   AV *av;
8896   I32 i;
8897
8898   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8899     croak (\"array reference expected\");
8900
8901   av = (AV *)SvRV (arg);
8902   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8903   if (!ret)
8904     croak (\"malloc failed\");
8905
8906   for (i = 0; i <= av_len (av); i++) {
8907     SV **elem = av_fetch (av, i, 0);
8908
8909     if (!elem || !*elem)
8910       croak (\"missing element in list\");
8911
8912     ret[i] = SvPV_nolen (*elem);
8913   }
8914
8915   ret[i] = NULL;
8916
8917   return ret;
8918 }
8919
8920 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8921
8922 PROTOTYPES: ENABLE
8923
8924 guestfs_h *
8925 _create ()
8926    CODE:
8927       RETVAL = guestfs_create ();
8928       if (!RETVAL)
8929         croak (\"could not create guestfs handle\");
8930       guestfs_set_error_handler (RETVAL, NULL, NULL);
8931  OUTPUT:
8932       RETVAL
8933
8934 void
8935 DESTROY (sv)
8936       SV *sv;
8937  PPCODE:
8938       /* For the 'g' argument above we do the conversion explicitly and
8939        * don't rely on the typemap, because if the handle has been
8940        * explicitly closed we don't want the typemap conversion to
8941        * display an error.
8942        */
8943       HV *hv = (HV *) SvRV (sv);
8944       SV **svp = hv_fetch (hv, \"_g\", 2, 0);
8945       if (svp != NULL) {
8946         guestfs_h *g = (guestfs_h *) SvIV (*svp);
8947         assert (g != NULL);
8948         guestfs_close (g);
8949       }
8950
8951 void
8952 close (g)
8953       guestfs_h *g;
8954  PPCODE:
8955       guestfs_close (g);
8956       /* Avoid double-free in DESTROY method. */
8957       HV *hv = (HV *) SvRV (ST(0));
8958       (void) hv_delete (hv, \"_g\", 2, G_DISCARD);
8959
8960 ";
8961
8962   List.iter (
8963     fun (name, style, _, _, _, _, _) ->
8964       (match fst style with
8965        | RErr -> pr "void\n"
8966        | RInt _ -> pr "SV *\n"
8967        | RInt64 _ -> pr "SV *\n"
8968        | RBool _ -> pr "SV *\n"
8969        | RConstString _ -> pr "SV *\n"
8970        | RConstOptString _ -> pr "SV *\n"
8971        | RString _ -> pr "SV *\n"
8972        | RBufferOut _ -> pr "SV *\n"
8973        | RStringList _
8974        | RStruct _ | RStructList _
8975        | RHashtable _ ->
8976            pr "void\n" (* all lists returned implictly on the stack *)
8977       );
8978       (* Call and arguments. *)
8979       pr "%s (g" name;
8980       List.iter (
8981         fun arg -> pr ", %s" (name_of_argt arg)
8982       ) (snd style);
8983       pr ")\n";
8984       pr "      guestfs_h *g;\n";
8985       iteri (
8986         fun i ->
8987           function
8988           | Pathname n | Device n | Dev_or_Path n | String n
8989           | FileIn n | FileOut n ->
8990               pr "      char *%s;\n" n
8991           | BufferIn n ->
8992               pr "      char *%s;\n" n;
8993               pr "      size_t %s_size = SvCUR (ST(%d));\n" n (i+1)
8994           | OptString n ->
8995               (* http://www.perlmonks.org/?node_id=554277
8996                * Note that the implicit handle argument means we have
8997                * to add 1 to the ST(x) operator.
8998                *)
8999               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
9000           | StringList n | DeviceList n -> pr "      char **%s;\n" n
9001           | Bool n -> pr "      int %s;\n" n
9002           | Int n -> pr "      int %s;\n" n
9003           | Int64 n -> pr "      int64_t %s;\n" n
9004       ) (snd style);
9005
9006       let do_cleanups () =
9007         List.iter (
9008           function
9009           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
9010           | Bool _ | Int _ | Int64 _
9011           | FileIn _ | FileOut _
9012           | BufferIn _ -> ()
9013           | StringList n | DeviceList n -> pr "      free (%s);\n" n
9014         ) (snd style)
9015       in
9016
9017       (* Code. *)
9018       (match fst style with
9019        | RErr ->
9020            pr "PREINIT:\n";
9021            pr "      int r;\n";
9022            pr " PPCODE:\n";
9023            pr "      r = guestfs_%s " name;
9024            generate_c_call_args ~handle:"g" style;
9025            pr ";\n";
9026            do_cleanups ();
9027            pr "      if (r == -1)\n";
9028            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9029        | RInt n
9030        | RBool n ->
9031            pr "PREINIT:\n";
9032            pr "      int %s;\n" n;
9033            pr "   CODE:\n";
9034            pr "      %s = guestfs_%s " n name;
9035            generate_c_call_args ~handle:"g" style;
9036            pr ";\n";
9037            do_cleanups ();
9038            pr "      if (%s == -1)\n" n;
9039            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9040            pr "      RETVAL = newSViv (%s);\n" n;
9041            pr " OUTPUT:\n";
9042            pr "      RETVAL\n"
9043        | RInt64 n ->
9044            pr "PREINIT:\n";
9045            pr "      int64_t %s;\n" n;
9046            pr "   CODE:\n";
9047            pr "      %s = guestfs_%s " n name;
9048            generate_c_call_args ~handle:"g" style;
9049            pr ";\n";
9050            do_cleanups ();
9051            pr "      if (%s == -1)\n" n;
9052            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9053            pr "      RETVAL = my_newSVll (%s);\n" n;
9054            pr " OUTPUT:\n";
9055            pr "      RETVAL\n"
9056        | RConstString n ->
9057            pr "PREINIT:\n";
9058            pr "      const char *%s;\n" n;
9059            pr "   CODE:\n";
9060            pr "      %s = guestfs_%s " n name;
9061            generate_c_call_args ~handle:"g" style;
9062            pr ";\n";
9063            do_cleanups ();
9064            pr "      if (%s == NULL)\n" n;
9065            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9066            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9067            pr " OUTPUT:\n";
9068            pr "      RETVAL\n"
9069        | RConstOptString n ->
9070            pr "PREINIT:\n";
9071            pr "      const char *%s;\n" n;
9072            pr "   CODE:\n";
9073            pr "      %s = guestfs_%s " n name;
9074            generate_c_call_args ~handle:"g" style;
9075            pr ";\n";
9076            do_cleanups ();
9077            pr "      if (%s == NULL)\n" n;
9078            pr "        RETVAL = &PL_sv_undef;\n";
9079            pr "      else\n";
9080            pr "        RETVAL = newSVpv (%s, 0);\n" n;
9081            pr " OUTPUT:\n";
9082            pr "      RETVAL\n"
9083        | RString n ->
9084            pr "PREINIT:\n";
9085            pr "      char *%s;\n" n;
9086            pr "   CODE:\n";
9087            pr "      %s = guestfs_%s " n name;
9088            generate_c_call_args ~handle:"g" style;
9089            pr ";\n";
9090            do_cleanups ();
9091            pr "      if (%s == NULL)\n" n;
9092            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9093            pr "      RETVAL = newSVpv (%s, 0);\n" n;
9094            pr "      free (%s);\n" n;
9095            pr " OUTPUT:\n";
9096            pr "      RETVAL\n"
9097        | RStringList n | RHashtable n ->
9098            pr "PREINIT:\n";
9099            pr "      char **%s;\n" n;
9100            pr "      size_t i, n;\n";
9101            pr " PPCODE:\n";
9102            pr "      %s = guestfs_%s " n name;
9103            generate_c_call_args ~handle:"g" style;
9104            pr ";\n";
9105            do_cleanups ();
9106            pr "      if (%s == NULL)\n" n;
9107            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9108            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
9109            pr "      EXTEND (SP, n);\n";
9110            pr "      for (i = 0; i < n; ++i) {\n";
9111            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
9112            pr "        free (%s[i]);\n" n;
9113            pr "      }\n";
9114            pr "      free (%s);\n" n;
9115        | RStruct (n, typ) ->
9116            let cols = cols_of_struct typ in
9117            generate_perl_struct_code typ cols name style n do_cleanups
9118        | RStructList (n, typ) ->
9119            let cols = cols_of_struct typ in
9120            generate_perl_struct_list_code typ cols name style n do_cleanups
9121        | RBufferOut n ->
9122            pr "PREINIT:\n";
9123            pr "      char *%s;\n" n;
9124            pr "      size_t size;\n";
9125            pr "   CODE:\n";
9126            pr "      %s = guestfs_%s " n name;
9127            generate_c_call_args ~handle:"g" style;
9128            pr ";\n";
9129            do_cleanups ();
9130            pr "      if (%s == NULL)\n" n;
9131            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9132            pr "      RETVAL = newSVpvn (%s, size);\n" n;
9133            pr "      free (%s);\n" n;
9134            pr " OUTPUT:\n";
9135            pr "      RETVAL\n"
9136       );
9137
9138       pr "\n"
9139   ) all_functions
9140
9141 and generate_perl_struct_list_code typ cols name style n do_cleanups =
9142   pr "PREINIT:\n";
9143   pr "      struct guestfs_%s_list *%s;\n" typ n;
9144   pr "      size_t i;\n";
9145   pr "      HV *hv;\n";
9146   pr " PPCODE:\n";
9147   pr "      %s = guestfs_%s " n name;
9148   generate_c_call_args ~handle:"g" style;
9149   pr ";\n";
9150   do_cleanups ();
9151   pr "      if (%s == NULL)\n" n;
9152   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9153   pr "      EXTEND (SP, %s->len);\n" n;
9154   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
9155   pr "        hv = newHV ();\n";
9156   List.iter (
9157     function
9158     | name, FString ->
9159         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
9160           name (String.length name) n name
9161     | name, FUUID ->
9162         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
9163           name (String.length name) n name
9164     | name, FBuffer ->
9165         pr "        (void) hv_store (hv, \"%s\", %d, newSVpvn (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
9166           name (String.length name) n name n name
9167     | name, (FBytes|FUInt64) ->
9168         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
9169           name (String.length name) n name
9170     | name, FInt64 ->
9171         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
9172           name (String.length name) n name
9173     | name, (FInt32|FUInt32) ->
9174         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9175           name (String.length name) n name
9176     | name, FChar ->
9177         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
9178           name (String.length name) n name
9179     | name, FOptPercent ->
9180         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
9181           name (String.length name) n name
9182   ) cols;
9183   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
9184   pr "      }\n";
9185   pr "      guestfs_free_%s_list (%s);\n" typ n
9186
9187 and generate_perl_struct_code typ cols name style n do_cleanups =
9188   pr "PREINIT:\n";
9189   pr "      struct guestfs_%s *%s;\n" typ n;
9190   pr " PPCODE:\n";
9191   pr "      %s = guestfs_%s " n name;
9192   generate_c_call_args ~handle:"g" style;
9193   pr ";\n";
9194   do_cleanups ();
9195   pr "      if (%s == NULL)\n" n;
9196   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
9197   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
9198   List.iter (
9199     fun ((name, _) as col) ->
9200       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
9201
9202       match col with
9203       | name, FString ->
9204           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
9205             n name
9206       | name, FBuffer ->
9207           pr "      PUSHs (sv_2mortal (newSVpvn (%s->%s, %s->%s_len)));\n"
9208             n name n name
9209       | name, FUUID ->
9210           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
9211             n name
9212       | name, (FBytes|FUInt64) ->
9213           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
9214             n name
9215       | name, FInt64 ->
9216           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
9217             n name
9218       | name, (FInt32|FUInt32) ->
9219           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9220             n name
9221       | name, FChar ->
9222           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
9223             n name
9224       | name, FOptPercent ->
9225           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
9226             n name
9227   ) cols;
9228   pr "      free (%s);\n" n
9229
9230 (* Generate Sys/Guestfs.pm. *)
9231 and generate_perl_pm () =
9232   generate_header HashStyle LGPLv2plus;
9233
9234   pr "\
9235 =pod
9236
9237 =head1 NAME
9238
9239 Sys::Guestfs - Perl bindings for libguestfs
9240
9241 =head1 SYNOPSIS
9242
9243  use Sys::Guestfs;
9244
9245  my $h = Sys::Guestfs->new ();
9246  $h->add_drive ('guest.img');
9247  $h->launch ();
9248  $h->mount ('/dev/sda1', '/');
9249  $h->touch ('/hello');
9250  $h->sync ();
9251
9252 =head1 DESCRIPTION
9253
9254 The C<Sys::Guestfs> module provides a Perl XS binding to the
9255 libguestfs API for examining and modifying virtual machine
9256 disk images.
9257
9258 Amongst the things this is good for: making batch configuration
9259 changes to guests, getting disk used/free statistics (see also:
9260 virt-df), migrating between virtualization systems (see also:
9261 virt-p2v), performing partial backups, performing partial guest
9262 clones, cloning guests and changing registry/UUID/hostname info, and
9263 much else besides.
9264
9265 Libguestfs uses Linux kernel and qemu code, and can access any type of
9266 guest filesystem that Linux and qemu can, including but not limited
9267 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9268 schemes, qcow, qcow2, vmdk.
9269
9270 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9271 LVs, what filesystem is in each LV, etc.).  It can also run commands
9272 in the context of the guest.  Also you can access filesystems over
9273 FUSE.
9274
9275 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
9276 functions for using libguestfs from Perl, including integration
9277 with libvirt.
9278
9279 =head1 ERRORS
9280
9281 All errors turn into calls to C<croak> (see L<Carp(3)>).
9282
9283 =head1 METHODS
9284
9285 =over 4
9286
9287 =cut
9288
9289 package Sys::Guestfs;
9290
9291 use strict;
9292 use warnings;
9293
9294 # This version number changes whenever a new function
9295 # is added to the libguestfs API.  It is not directly
9296 # related to the libguestfs version number.
9297 use vars qw($VERSION);
9298 $VERSION = '0.%d';
9299
9300 require XSLoader;
9301 XSLoader::load ('Sys::Guestfs');
9302
9303 =item $h = Sys::Guestfs->new ();
9304
9305 Create a new guestfs handle.
9306
9307 =cut
9308
9309 sub new {
9310   my $proto = shift;
9311   my $class = ref ($proto) || $proto;
9312
9313   my $g = Sys::Guestfs::_create ();
9314   my $self = { _g => $g };
9315   bless $self, $class;
9316   return $self;
9317 }
9318
9319 =item $h->close ();
9320
9321 Explicitly close the guestfs handle.
9322
9323 B<Note:> You should not usually call this function.  The handle will
9324 be closed implicitly when its reference count goes to zero (eg.
9325 when it goes out of scope or the program ends).  This call is
9326 only required in some exceptional cases, such as where the program
9327 may contain cached references to the handle 'somewhere' and you
9328 really have to have the close happen right away.  After calling
9329 C<close> the program must not call any method (including C<close>)
9330 on the handle (but the implicit call to C<DESTROY> that happens
9331 when the final reference is cleaned up is OK).
9332
9333 =cut
9334
9335 " max_proc_nr;
9336
9337   (* Actions.  We only need to print documentation for these as
9338    * they are pulled in from the XS code automatically.
9339    *)
9340   List.iter (
9341     fun (name, style, _, flags, _, _, longdesc) ->
9342       if not (List.mem NotInDocs flags) then (
9343         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
9344         pr "=item ";
9345         generate_perl_prototype name style;
9346         pr "\n\n";
9347         pr "%s\n\n" longdesc;
9348         if List.mem ProtocolLimitWarning flags then
9349           pr "%s\n\n" protocol_limit_warning;
9350         if List.mem DangerWillRobinson flags then
9351           pr "%s\n\n" danger_will_robinson;
9352         match deprecation_notice flags with
9353         | None -> ()
9354         | Some txt -> pr "%s\n\n" txt
9355       )
9356   ) all_functions_sorted;
9357
9358   (* End of file. *)
9359   pr "\
9360 =cut
9361
9362 1;
9363
9364 =back
9365
9366 =head1 AVAILABILITY
9367
9368 From time to time we add new libguestfs APIs.  Also some libguestfs
9369 APIs won't be available in all builds of libguestfs (the Fedora
9370 build is full-featured, but other builds may disable features).
9371 How do you test whether the APIs that your Perl program needs are
9372 available in the version of C<Sys::Guestfs> that you are using?
9373
9374 To test if a particular function is available in the C<Sys::Guestfs>
9375 class, use the ordinary Perl UNIVERSAL method C<can(METHOD)>
9376 (see L<perlobj(1)>).  For example:
9377
9378  use Sys::Guestfs;
9379  if (defined (Sys::Guestfs->can (\"set_verbose\"))) {
9380    print \"\\$h->set_verbose is available\\n\";
9381  }
9382
9383 To test if particular features are supported by the current
9384 build, use the L</available> method like the example below.  Note
9385 that the appliance must be launched first.
9386
9387  $h->available ( [\"augeas\"] );
9388
9389 Since the L</available> method croaks if the feature is not supported,
9390 you might also want to wrap this in an eval and return a boolean.
9391 In fact this has already been done for you: use
9392 L<Sys::Guestfs::Lib(3)/feature_available>.
9393
9394 For further discussion on this topic, refer to
9395 L<guestfs(3)/AVAILABILITY>.
9396
9397 =head1 STORING DATA IN THE HANDLE
9398
9399 The handle returned from L</new> is a hash reference.  The hash
9400 normally contains a single element:
9401
9402  {
9403    _g => [private data used by libguestfs]
9404  }
9405
9406 Callers can add other elements to this hash to store data for their own
9407 purposes.  The data lasts for the lifetime of the handle.
9408
9409 Any fields whose names begin with an underscore are reserved
9410 for private use by libguestfs.  We may add more in future.
9411
9412 It is recommended that callers prefix the name of their field(s)
9413 with some unique string, to avoid conflicts with other users.
9414
9415 =head1 COPYRIGHT
9416
9417 Copyright (C) %s Red Hat Inc.
9418
9419 =head1 LICENSE
9420
9421 Please see the file COPYING.LIB for the full license.
9422
9423 =head1 SEE ALSO
9424
9425 L<guestfs(3)>,
9426 L<guestfish(1)>,
9427 L<http://libguestfs.org>,
9428 L<Sys::Guestfs::Lib(3)>.
9429
9430 =cut
9431 " copyright_years
9432
9433 and generate_perl_prototype name style =
9434   (match fst style with
9435    | RErr -> ()
9436    | RBool n
9437    | RInt n
9438    | RInt64 n
9439    | RConstString n
9440    | RConstOptString n
9441    | RString n
9442    | RBufferOut n -> pr "$%s = " n
9443    | RStruct (n,_)
9444    | RHashtable n -> pr "%%%s = " n
9445    | RStringList n
9446    | RStructList (n,_) -> pr "@%s = " n
9447   );
9448   pr "$h->%s (" name;
9449   let comma = ref false in
9450   List.iter (
9451     fun arg ->
9452       if !comma then pr ", ";
9453       comma := true;
9454       match arg with
9455       | Pathname n | Device n | Dev_or_Path n | String n
9456       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n
9457       | BufferIn n ->
9458           pr "$%s" n
9459       | StringList n | DeviceList n ->
9460           pr "\\@%s" n
9461   ) (snd style);
9462   pr ");"
9463
9464 (* Generate Python C module. *)
9465 and generate_python_c () =
9466   generate_header CStyle LGPLv2plus;
9467
9468   pr "\
9469 #define PY_SSIZE_T_CLEAN 1
9470 #include <Python.h>
9471
9472 #if PY_VERSION_HEX < 0x02050000
9473 typedef int Py_ssize_t;
9474 #define PY_SSIZE_T_MAX INT_MAX
9475 #define PY_SSIZE_T_MIN INT_MIN
9476 #endif
9477
9478 #include <stdio.h>
9479 #include <stdlib.h>
9480 #include <assert.h>
9481
9482 #include \"guestfs.h\"
9483
9484 typedef struct {
9485   PyObject_HEAD
9486   guestfs_h *g;
9487 } Pyguestfs_Object;
9488
9489 static guestfs_h *
9490 get_handle (PyObject *obj)
9491 {
9492   assert (obj);
9493   assert (obj != Py_None);
9494   return ((Pyguestfs_Object *) obj)->g;
9495 }
9496
9497 static PyObject *
9498 put_handle (guestfs_h *g)
9499 {
9500   assert (g);
9501   return
9502     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
9503 }
9504
9505 /* This list should be freed (but not the strings) after use. */
9506 static char **
9507 get_string_list (PyObject *obj)
9508 {
9509   size_t i, len;
9510   char **r;
9511
9512   assert (obj);
9513
9514   if (!PyList_Check (obj)) {
9515     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
9516     return NULL;
9517   }
9518
9519   Py_ssize_t slen = PyList_Size (obj);
9520   if (slen == -1) {
9521     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: PyList_Size failure\");
9522     return NULL;
9523   }
9524   len = (size_t) slen;
9525   r = malloc (sizeof (char *) * (len+1));
9526   if (r == NULL) {
9527     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
9528     return NULL;
9529   }
9530
9531   for (i = 0; i < len; ++i)
9532     r[i] = PyString_AsString (PyList_GetItem (obj, i));
9533   r[len] = NULL;
9534
9535   return r;
9536 }
9537
9538 static PyObject *
9539 put_string_list (char * const * const argv)
9540 {
9541   PyObject *list;
9542   int argc, i;
9543
9544   for (argc = 0; argv[argc] != NULL; ++argc)
9545     ;
9546
9547   list = PyList_New (argc);
9548   for (i = 0; i < argc; ++i)
9549     PyList_SetItem (list, i, PyString_FromString (argv[i]));
9550
9551   return list;
9552 }
9553
9554 static PyObject *
9555 put_table (char * const * const argv)
9556 {
9557   PyObject *list, *item;
9558   int argc, i;
9559
9560   for (argc = 0; argv[argc] != NULL; ++argc)
9561     ;
9562
9563   list = PyList_New (argc >> 1);
9564   for (i = 0; i < argc; i += 2) {
9565     item = PyTuple_New (2);
9566     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
9567     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
9568     PyList_SetItem (list, i >> 1, item);
9569   }
9570
9571   return list;
9572 }
9573
9574 static void
9575 free_strings (char **argv)
9576 {
9577   int argc;
9578
9579   for (argc = 0; argv[argc] != NULL; ++argc)
9580     free (argv[argc]);
9581   free (argv);
9582 }
9583
9584 static PyObject *
9585 py_guestfs_create (PyObject *self, PyObject *args)
9586 {
9587   guestfs_h *g;
9588
9589   g = guestfs_create ();
9590   if (g == NULL) {
9591     PyErr_SetString (PyExc_RuntimeError,
9592                      \"guestfs.create: failed to allocate handle\");
9593     return NULL;
9594   }
9595   guestfs_set_error_handler (g, NULL, NULL);
9596   return put_handle (g);
9597 }
9598
9599 static PyObject *
9600 py_guestfs_close (PyObject *self, PyObject *args)
9601 {
9602   PyObject *py_g;
9603   guestfs_h *g;
9604
9605   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
9606     return NULL;
9607   g = get_handle (py_g);
9608
9609   guestfs_close (g);
9610
9611   Py_INCREF (Py_None);
9612   return Py_None;
9613 }
9614
9615 ";
9616
9617   let emit_put_list_function typ =
9618     pr "static PyObject *\n";
9619     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
9620     pr "{\n";
9621     pr "  PyObject *list;\n";
9622     pr "  size_t i;\n";
9623     pr "\n";
9624     pr "  list = PyList_New (%ss->len);\n" typ;
9625     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
9626     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
9627     pr "  return list;\n";
9628     pr "};\n";
9629     pr "\n"
9630   in
9631
9632   (* Structures, turned into Python dictionaries. *)
9633   List.iter (
9634     fun (typ, cols) ->
9635       pr "static PyObject *\n";
9636       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
9637       pr "{\n";
9638       pr "  PyObject *dict;\n";
9639       pr "\n";
9640       pr "  dict = PyDict_New ();\n";
9641       List.iter (
9642         function
9643         | name, FString ->
9644             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9645             pr "                        PyString_FromString (%s->%s));\n"
9646               typ name
9647         | name, FBuffer ->
9648             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9649             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
9650               typ name typ name
9651         | name, FUUID ->
9652             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9653             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
9654               typ name
9655         | name, (FBytes|FUInt64) ->
9656             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9657             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
9658               typ name
9659         | name, FInt64 ->
9660             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9661             pr "                        PyLong_FromLongLong (%s->%s));\n"
9662               typ name
9663         | name, FUInt32 ->
9664             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9665             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
9666               typ name
9667         | name, FInt32 ->
9668             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9669             pr "                        PyLong_FromLong (%s->%s));\n"
9670               typ name
9671         | name, FOptPercent ->
9672             pr "  if (%s->%s >= 0)\n" typ name;
9673             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
9674             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
9675               typ name;
9676             pr "  else {\n";
9677             pr "    Py_INCREF (Py_None);\n";
9678             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
9679             pr "  }\n"
9680         | name, FChar ->
9681             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
9682             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
9683       ) cols;
9684       pr "  return dict;\n";
9685       pr "};\n";
9686       pr "\n";
9687
9688   ) structs;
9689
9690   (* Emit a put_TYPE_list function definition only if that function is used. *)
9691   List.iter (
9692     function
9693     | typ, (RStructListOnly | RStructAndList) ->
9694         (* generate the function for typ *)
9695         emit_put_list_function typ
9696     | typ, _ -> () (* empty *)
9697   ) (rstructs_used_by all_functions);
9698
9699   (* Python wrapper functions. *)
9700   List.iter (
9701     fun (name, style, _, _, _, _, _) ->
9702       pr "static PyObject *\n";
9703       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
9704       pr "{\n";
9705
9706       pr "  PyObject *py_g;\n";
9707       pr "  guestfs_h *g;\n";
9708       pr "  PyObject *py_r;\n";
9709
9710       let error_code =
9711         match fst style with
9712         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9713         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9714         | RConstString _ | RConstOptString _ ->
9715             pr "  const char *r;\n"; "NULL"
9716         | RString _ -> pr "  char *r;\n"; "NULL"
9717         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9718         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9719         | RStructList (_, typ) ->
9720             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9721         | RBufferOut _ ->
9722             pr "  char *r;\n";
9723             pr "  size_t size;\n";
9724             "NULL" in
9725
9726       List.iter (
9727         function
9728         | Pathname n | Device n | Dev_or_Path n | String n
9729         | FileIn n | FileOut n ->
9730             pr "  const char *%s;\n" n
9731         | OptString n -> pr "  const char *%s;\n" n
9732         | BufferIn n ->
9733             pr "  const char *%s;\n" n;
9734             pr "  Py_ssize_t %s_size;\n" n
9735         | StringList n | DeviceList n ->
9736             pr "  PyObject *py_%s;\n" n;
9737             pr "  char **%s;\n" n
9738         | Bool n -> pr "  int %s;\n" n
9739         | Int n -> pr "  int %s;\n" n
9740         | Int64 n -> pr "  long long %s;\n" n
9741       ) (snd style);
9742
9743       pr "\n";
9744
9745       (* Convert the parameters. *)
9746       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
9747       List.iter (
9748         function
9749         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
9750         | OptString _ -> pr "z"
9751         | StringList _ | DeviceList _ -> pr "O"
9752         | Bool _ -> pr "i" (* XXX Python has booleans? *)
9753         | Int _ -> pr "i"
9754         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
9755                              * emulate C's int/long/long long in Python?
9756                              *)
9757         | BufferIn _ -> pr "s#"
9758       ) (snd style);
9759       pr ":guestfs_%s\",\n" name;
9760       pr "                         &py_g";
9761       List.iter (
9762         function
9763         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
9764         | OptString n -> pr ", &%s" n
9765         | StringList n | DeviceList n -> pr ", &py_%s" n
9766         | Bool n -> pr ", &%s" n
9767         | Int n -> pr ", &%s" n
9768         | Int64 n -> pr ", &%s" n
9769         | BufferIn n -> pr ", &%s, &%s_size" n n
9770       ) (snd style);
9771
9772       pr "))\n";
9773       pr "    return NULL;\n";
9774
9775       pr "  g = get_handle (py_g);\n";
9776       List.iter (
9777         function
9778         | Pathname _ | Device _ | Dev_or_Path _ | String _
9779         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9780         | BufferIn _ -> ()
9781         | StringList n | DeviceList n ->
9782             pr "  %s = get_string_list (py_%s);\n" n n;
9783             pr "  if (!%s) return NULL;\n" n
9784       ) (snd style);
9785
9786       pr "\n";
9787
9788       pr "  r = guestfs_%s " name;
9789       generate_c_call_args ~handle:"g" style;
9790       pr ";\n";
9791
9792       List.iter (
9793         function
9794         | Pathname _ | Device _ | Dev_or_Path _ | String _
9795         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
9796         | BufferIn _ -> ()
9797         | StringList n | DeviceList n ->
9798             pr "  free (%s);\n" n
9799       ) (snd style);
9800
9801       pr "  if (r == %s) {\n" error_code;
9802       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
9803       pr "    return NULL;\n";
9804       pr "  }\n";
9805       pr "\n";
9806
9807       (match fst style with
9808        | RErr ->
9809            pr "  Py_INCREF (Py_None);\n";
9810            pr "  py_r = Py_None;\n"
9811        | RInt _
9812        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
9813        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
9814        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
9815        | RConstOptString _ ->
9816            pr "  if (r)\n";
9817            pr "    py_r = PyString_FromString (r);\n";
9818            pr "  else {\n";
9819            pr "    Py_INCREF (Py_None);\n";
9820            pr "    py_r = Py_None;\n";
9821            pr "  }\n"
9822        | RString _ ->
9823            pr "  py_r = PyString_FromString (r);\n";
9824            pr "  free (r);\n"
9825        | RStringList _ ->
9826            pr "  py_r = put_string_list (r);\n";
9827            pr "  free_strings (r);\n"
9828        | RStruct (_, typ) ->
9829            pr "  py_r = put_%s (r);\n" typ;
9830            pr "  guestfs_free_%s (r);\n" typ
9831        | RStructList (_, typ) ->
9832            pr "  py_r = put_%s_list (r);\n" typ;
9833            pr "  guestfs_free_%s_list (r);\n" typ
9834        | RHashtable n ->
9835            pr "  py_r = put_table (r);\n";
9836            pr "  free_strings (r);\n"
9837        | RBufferOut _ ->
9838            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
9839            pr "  free (r);\n"
9840       );
9841
9842       pr "  return py_r;\n";
9843       pr "}\n";
9844       pr "\n"
9845   ) all_functions;
9846
9847   (* Table of functions. *)
9848   pr "static PyMethodDef methods[] = {\n";
9849   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
9850   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
9851   List.iter (
9852     fun (name, _, _, _, _, _, _) ->
9853       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
9854         name name
9855   ) all_functions;
9856   pr "  { NULL, NULL, 0, NULL }\n";
9857   pr "};\n";
9858   pr "\n";
9859
9860   (* Init function. *)
9861   pr "\
9862 void
9863 initlibguestfsmod (void)
9864 {
9865   static int initialized = 0;
9866
9867   if (initialized) return;
9868   Py_InitModule ((char *) \"libguestfsmod\", methods);
9869   initialized = 1;
9870 }
9871 "
9872
9873 (* Generate Python module. *)
9874 and generate_python_py () =
9875   generate_header HashStyle LGPLv2plus;
9876
9877   pr "\
9878 u\"\"\"Python bindings for libguestfs
9879
9880 import guestfs
9881 g = guestfs.GuestFS ()
9882 g.add_drive (\"guest.img\")
9883 g.launch ()
9884 parts = g.list_partitions ()
9885
9886 The guestfs module provides a Python binding to the libguestfs API
9887 for examining and modifying virtual machine disk images.
9888
9889 Amongst the things this is good for: making batch configuration
9890 changes to guests, getting disk used/free statistics (see also:
9891 virt-df), migrating between virtualization systems (see also:
9892 virt-p2v), performing partial backups, performing partial guest
9893 clones, cloning guests and changing registry/UUID/hostname info, and
9894 much else besides.
9895
9896 Libguestfs uses Linux kernel and qemu code, and can access any type of
9897 guest filesystem that Linux and qemu can, including but not limited
9898 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
9899 schemes, qcow, qcow2, vmdk.
9900
9901 Libguestfs provides ways to enumerate guest storage (eg. partitions,
9902 LVs, what filesystem is in each LV, etc.).  It can also run commands
9903 in the context of the guest.  Also you can access filesystems over
9904 FUSE.
9905
9906 Errors which happen while using the API are turned into Python
9907 RuntimeError exceptions.
9908
9909 To create a guestfs handle you usually have to perform the following
9910 sequence of calls:
9911
9912 # Create the handle, call add_drive at least once, and possibly
9913 # several times if the guest has multiple block devices:
9914 g = guestfs.GuestFS ()
9915 g.add_drive (\"guest.img\")
9916
9917 # Launch the qemu subprocess and wait for it to become ready:
9918 g.launch ()
9919
9920 # Now you can issue commands, for example:
9921 logvols = g.lvs ()
9922
9923 \"\"\"
9924
9925 import libguestfsmod
9926
9927 class GuestFS:
9928     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
9929
9930     def __init__ (self):
9931         \"\"\"Create a new libguestfs handle.\"\"\"
9932         self._o = libguestfsmod.create ()
9933
9934     def __del__ (self):
9935         libguestfsmod.close (self._o)
9936
9937 ";
9938
9939   List.iter (
9940     fun (name, style, _, flags, _, _, longdesc) ->
9941       pr "    def %s " name;
9942       generate_py_call_args ~handle:"self" (snd style);
9943       pr ":\n";
9944
9945       if not (List.mem NotInDocs flags) then (
9946         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9947         let doc =
9948           match fst style with
9949           | RErr | RInt _ | RInt64 _ | RBool _
9950           | RConstOptString _ | RConstString _
9951           | RString _ | RBufferOut _ -> doc
9952           | RStringList _ ->
9953               doc ^ "\n\nThis function returns a list of strings."
9954           | RStruct (_, typ) ->
9955               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
9956           | RStructList (_, typ) ->
9957               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
9958           | RHashtable _ ->
9959               doc ^ "\n\nThis function returns a dictionary." in
9960         let doc =
9961           if List.mem ProtocolLimitWarning flags then
9962             doc ^ "\n\n" ^ protocol_limit_warning
9963           else doc in
9964         let doc =
9965           if List.mem DangerWillRobinson flags then
9966             doc ^ "\n\n" ^ danger_will_robinson
9967           else doc in
9968         let doc =
9969           match deprecation_notice flags with
9970           | None -> doc
9971           | Some txt -> doc ^ "\n\n" ^ txt in
9972         let doc = pod2text ~width:60 name doc in
9973         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9974         let doc = String.concat "\n        " doc in
9975         pr "        u\"\"\"%s\"\"\"\n" doc;
9976       );
9977       pr "        return libguestfsmod.%s " name;
9978       generate_py_call_args ~handle:"self._o" (snd style);
9979       pr "\n";
9980       pr "\n";
9981   ) all_functions
9982
9983 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9984 and generate_py_call_args ~handle args =
9985   pr "(%s" handle;
9986   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9987   pr ")"
9988
9989 (* Useful if you need the longdesc POD text as plain text.  Returns a
9990  * list of lines.
9991  *
9992  * Because this is very slow (the slowest part of autogeneration),
9993  * we memoize the results.
9994  *)
9995 and pod2text ~width name longdesc =
9996   let key = width, name, longdesc in
9997   try Hashtbl.find pod2text_memo key
9998   with Not_found ->
9999     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
10000     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
10001     close_out chan;
10002     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
10003     let chan = open_process_in cmd in
10004     let lines = ref [] in
10005     let rec loop i =
10006       let line = input_line chan in
10007       if i = 1 then             (* discard the first line of output *)
10008         loop (i+1)
10009       else (
10010         let line = triml line in
10011         lines := line :: !lines;
10012         loop (i+1)
10013       ) in
10014     let lines = try loop 1 with End_of_file -> List.rev !lines in
10015     unlink filename;
10016     (match close_process_in chan with
10017      | WEXITED 0 -> ()
10018      | WEXITED i ->
10019          failwithf "pod2text: process exited with non-zero status (%d)" i
10020      | WSIGNALED i | WSTOPPED i ->
10021          failwithf "pod2text: process signalled or stopped by signal %d" i
10022     );
10023     Hashtbl.add pod2text_memo key lines;
10024     pod2text_memo_updated ();
10025     lines
10026
10027 (* Generate ruby bindings. *)
10028 and generate_ruby_c () =
10029   generate_header CStyle LGPLv2plus;
10030
10031   pr "\
10032 #include <stdio.h>
10033 #include <stdlib.h>
10034
10035 #include <ruby.h>
10036
10037 #include \"guestfs.h\"
10038
10039 #include \"extconf.h\"
10040
10041 /* For Ruby < 1.9 */
10042 #ifndef RARRAY_LEN
10043 #define RARRAY_LEN(r) (RARRAY((r))->len)
10044 #endif
10045
10046 static VALUE m_guestfs;                 /* guestfs module */
10047 static VALUE c_guestfs;                 /* guestfs_h handle */
10048 static VALUE e_Error;                   /* used for all errors */
10049
10050 static void ruby_guestfs_free (void *p)
10051 {
10052   if (!p) return;
10053   guestfs_close ((guestfs_h *) p);
10054 }
10055
10056 static VALUE ruby_guestfs_create (VALUE m)
10057 {
10058   guestfs_h *g;
10059
10060   g = guestfs_create ();
10061   if (!g)
10062     rb_raise (e_Error, \"failed to create guestfs handle\");
10063
10064   /* Don't print error messages to stderr by default. */
10065   guestfs_set_error_handler (g, NULL, NULL);
10066
10067   /* Wrap it, and make sure the close function is called when the
10068    * handle goes away.
10069    */
10070   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
10071 }
10072
10073 static VALUE ruby_guestfs_close (VALUE gv)
10074 {
10075   guestfs_h *g;
10076   Data_Get_Struct (gv, guestfs_h, g);
10077
10078   ruby_guestfs_free (g);
10079   DATA_PTR (gv) = NULL;
10080
10081   return Qnil;
10082 }
10083
10084 ";
10085
10086   List.iter (
10087     fun (name, style, _, _, _, _, _) ->
10088       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
10089       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
10090       pr ")\n";
10091       pr "{\n";
10092       pr "  guestfs_h *g;\n";
10093       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
10094       pr "  if (!g)\n";
10095       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
10096         name;
10097       pr "\n";
10098
10099       List.iter (
10100         function
10101         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
10102             pr "  Check_Type (%sv, T_STRING);\n" n;
10103             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
10104             pr "  if (!%s)\n" n;
10105             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10106             pr "              \"%s\", \"%s\");\n" n name
10107         | BufferIn n ->
10108             pr "  Check_Type (%sv, T_STRING);\n" n;
10109             pr "  const char *%s = RSTRING (%sv)->ptr;\n" n n;
10110             pr "  if (!%s)\n" n;
10111             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
10112             pr "              \"%s\", \"%s\");\n" n name;
10113             pr "  size_t %s_size = RSTRING (%sv)->len;\n" n n
10114         | OptString n ->
10115             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
10116         | StringList n | DeviceList n ->
10117             pr "  char **%s;\n" n;
10118             pr "  Check_Type (%sv, T_ARRAY);\n" n;
10119             pr "  {\n";
10120             pr "    size_t i, len;\n";
10121             pr "    len = RARRAY_LEN (%sv);\n" n;
10122             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
10123               n;
10124             pr "    for (i = 0; i < len; ++i) {\n";
10125             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
10126             pr "      %s[i] = StringValueCStr (v);\n" n;
10127             pr "    }\n";
10128             pr "    %s[len] = NULL;\n" n;
10129             pr "  }\n";
10130         | Bool n ->
10131             pr "  int %s = RTEST (%sv);\n" n n
10132         | Int n ->
10133             pr "  int %s = NUM2INT (%sv);\n" n n
10134         | Int64 n ->
10135             pr "  long long %s = NUM2LL (%sv);\n" n n
10136       ) (snd style);
10137       pr "\n";
10138
10139       let error_code =
10140         match fst style with
10141         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
10142         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
10143         | RConstString _ | RConstOptString _ ->
10144             pr "  const char *r;\n"; "NULL"
10145         | RString _ -> pr "  char *r;\n"; "NULL"
10146         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
10147         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
10148         | RStructList (_, typ) ->
10149             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
10150         | RBufferOut _ ->
10151             pr "  char *r;\n";
10152             pr "  size_t size;\n";
10153             "NULL" in
10154       pr "\n";
10155
10156       pr "  r = guestfs_%s " name;
10157       generate_c_call_args ~handle:"g" style;
10158       pr ";\n";
10159
10160       List.iter (
10161         function
10162         | Pathname _ | Device _ | Dev_or_Path _ | String _
10163         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _
10164         | BufferIn _ -> ()
10165         | StringList n | DeviceList n ->
10166             pr "  free (%s);\n" n
10167       ) (snd style);
10168
10169       pr "  if (r == %s)\n" error_code;
10170       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
10171       pr "\n";
10172
10173       (match fst style with
10174        | RErr ->
10175            pr "  return Qnil;\n"
10176        | RInt _ | RBool _ ->
10177            pr "  return INT2NUM (r);\n"
10178        | RInt64 _ ->
10179            pr "  return ULL2NUM (r);\n"
10180        | RConstString _ ->
10181            pr "  return rb_str_new2 (r);\n";
10182        | RConstOptString _ ->
10183            pr "  if (r)\n";
10184            pr "    return rb_str_new2 (r);\n";
10185            pr "  else\n";
10186            pr "    return Qnil;\n";
10187        | RString _ ->
10188            pr "  VALUE rv = rb_str_new2 (r);\n";
10189            pr "  free (r);\n";
10190            pr "  return rv;\n";
10191        | RStringList _ ->
10192            pr "  size_t i, len = 0;\n";
10193            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
10194            pr "  VALUE rv = rb_ary_new2 (len);\n";
10195            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
10196            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
10197            pr "    free (r[i]);\n";
10198            pr "  }\n";
10199            pr "  free (r);\n";
10200            pr "  return rv;\n"
10201        | RStruct (_, typ) ->
10202            let cols = cols_of_struct typ in
10203            generate_ruby_struct_code typ cols
10204        | RStructList (_, typ) ->
10205            let cols = cols_of_struct typ in
10206            generate_ruby_struct_list_code typ cols
10207        | RHashtable _ ->
10208            pr "  VALUE rv = rb_hash_new ();\n";
10209            pr "  size_t i;\n";
10210            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
10211            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
10212            pr "    free (r[i]);\n";
10213            pr "    free (r[i+1]);\n";
10214            pr "  }\n";
10215            pr "  free (r);\n";
10216            pr "  return rv;\n"
10217        | RBufferOut _ ->
10218            pr "  VALUE rv = rb_str_new (r, size);\n";
10219            pr "  free (r);\n";
10220            pr "  return rv;\n";
10221       );
10222
10223       pr "}\n";
10224       pr "\n"
10225   ) all_functions;
10226
10227   pr "\
10228 /* Initialize the module. */
10229 void Init__guestfs ()
10230 {
10231   m_guestfs = rb_define_module (\"Guestfs\");
10232   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
10233   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
10234
10235   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
10236   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
10237
10238 ";
10239   (* Define the rest of the methods. *)
10240   List.iter (
10241     fun (name, style, _, _, _, _, _) ->
10242       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
10243       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
10244   ) all_functions;
10245
10246   pr "}\n"
10247
10248 (* Ruby code to return a struct. *)
10249 and generate_ruby_struct_code typ cols =
10250   pr "  VALUE rv = rb_hash_new ();\n";
10251   List.iter (
10252     function
10253     | name, FString ->
10254         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
10255     | name, FBuffer ->
10256         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
10257     | name, FUUID ->
10258         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
10259     | name, (FBytes|FUInt64) ->
10260         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10261     | name, FInt64 ->
10262         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
10263     | name, FUInt32 ->
10264         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
10265     | name, FInt32 ->
10266         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
10267     | name, FOptPercent ->
10268         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
10269     | name, FChar -> (* XXX wrong? *)
10270         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
10271   ) cols;
10272   pr "  guestfs_free_%s (r);\n" typ;
10273   pr "  return rv;\n"
10274
10275 (* Ruby code to return a struct list. *)
10276 and generate_ruby_struct_list_code typ cols =
10277   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
10278   pr "  size_t i;\n";
10279   pr "  for (i = 0; i < r->len; ++i) {\n";
10280   pr "    VALUE hv = rb_hash_new ();\n";
10281   List.iter (
10282     function
10283     | name, FString ->
10284         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
10285     | name, FBuffer ->
10286         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
10287     | name, FUUID ->
10288         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
10289     | name, (FBytes|FUInt64) ->
10290         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10291     | name, FInt64 ->
10292         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
10293     | name, FUInt32 ->
10294         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
10295     | name, FInt32 ->
10296         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
10297     | name, FOptPercent ->
10298         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
10299     | name, FChar -> (* XXX wrong? *)
10300         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
10301   ) cols;
10302   pr "    rb_ary_push (rv, hv);\n";
10303   pr "  }\n";
10304   pr "  guestfs_free_%s_list (r);\n" typ;
10305   pr "  return rv;\n"
10306
10307 (* Generate Java bindings GuestFS.java file. *)
10308 and generate_java_java () =
10309   generate_header CStyle LGPLv2plus;
10310
10311   pr "\
10312 package com.redhat.et.libguestfs;
10313
10314 import java.util.HashMap;
10315 import com.redhat.et.libguestfs.LibGuestFSException;
10316 import com.redhat.et.libguestfs.PV;
10317 import com.redhat.et.libguestfs.VG;
10318 import com.redhat.et.libguestfs.LV;
10319 import com.redhat.et.libguestfs.Stat;
10320 import com.redhat.et.libguestfs.StatVFS;
10321 import com.redhat.et.libguestfs.IntBool;
10322 import com.redhat.et.libguestfs.Dirent;
10323
10324 /**
10325  * The GuestFS object is a libguestfs handle.
10326  *
10327  * @author rjones
10328  */
10329 public class GuestFS {
10330   // Load the native code.
10331   static {
10332     System.loadLibrary (\"guestfs_jni\");
10333   }
10334
10335   /**
10336    * The native guestfs_h pointer.
10337    */
10338   long g;
10339
10340   /**
10341    * Create a libguestfs handle.
10342    *
10343    * @throws LibGuestFSException
10344    */
10345   public GuestFS () throws LibGuestFSException
10346   {
10347     g = _create ();
10348   }
10349   private native long _create () throws LibGuestFSException;
10350
10351   /**
10352    * Close a libguestfs handle.
10353    *
10354    * You can also leave handles to be collected by the garbage
10355    * collector, but this method ensures that the resources used
10356    * by the handle are freed up immediately.  If you call any
10357    * other methods after closing the handle, you will get an
10358    * exception.
10359    *
10360    * @throws LibGuestFSException
10361    */
10362   public void close () throws LibGuestFSException
10363   {
10364     if (g != 0)
10365       _close (g);
10366     g = 0;
10367   }
10368   private native void _close (long g) throws LibGuestFSException;
10369
10370   public void finalize () throws LibGuestFSException
10371   {
10372     close ();
10373   }
10374
10375 ";
10376
10377   List.iter (
10378     fun (name, style, _, flags, _, shortdesc, longdesc) ->
10379       if not (List.mem NotInDocs flags); then (
10380         let doc = replace_str longdesc "C<guestfs_" "C<g." in
10381         let doc =
10382           if List.mem ProtocolLimitWarning flags then
10383             doc ^ "\n\n" ^ protocol_limit_warning
10384           else doc in
10385         let doc =
10386           if List.mem DangerWillRobinson flags then
10387             doc ^ "\n\n" ^ danger_will_robinson
10388           else doc in
10389         let doc =
10390           match deprecation_notice flags with
10391           | None -> doc
10392           | Some txt -> doc ^ "\n\n" ^ txt in
10393         let doc = pod2text ~width:60 name doc in
10394         let doc = List.map (            (* RHBZ#501883 *)
10395           function
10396           | "" -> "<p>"
10397           | nonempty -> nonempty
10398         ) doc in
10399         let doc = String.concat "\n   * " doc in
10400
10401         pr "  /**\n";
10402         pr "   * %s\n" shortdesc;
10403         pr "   * <p>\n";
10404         pr "   * %s\n" doc;
10405         pr "   * @throws LibGuestFSException\n";
10406         pr "   */\n";
10407         pr "  ";
10408       );
10409       generate_java_prototype ~public:true ~semicolon:false name style;
10410       pr "\n";
10411       pr "  {\n";
10412       pr "    if (g == 0)\n";
10413       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
10414         name;
10415       pr "    ";
10416       if fst style <> RErr then pr "return ";
10417       pr "_%s " name;
10418       generate_java_call_args ~handle:"g" (snd style);
10419       pr ";\n";
10420       pr "  }\n";
10421       pr "  ";
10422       generate_java_prototype ~privat:true ~native:true name style;
10423       pr "\n";
10424       pr "\n";
10425   ) all_functions;
10426
10427   pr "}\n"
10428
10429 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
10430 and generate_java_call_args ~handle args =
10431   pr "(%s" handle;
10432   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
10433   pr ")"
10434
10435 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
10436     ?(semicolon=true) name style =
10437   if privat then pr "private ";
10438   if public then pr "public ";
10439   if native then pr "native ";
10440
10441   (* return type *)
10442   (match fst style with
10443    | RErr -> pr "void ";
10444    | RInt _ -> pr "int ";
10445    | RInt64 _ -> pr "long ";
10446    | RBool _ -> pr "boolean ";
10447    | RConstString _ | RConstOptString _ | RString _
10448    | RBufferOut _ -> pr "String ";
10449    | RStringList _ -> pr "String[] ";
10450    | RStruct (_, typ) ->
10451        let name = java_name_of_struct typ in
10452        pr "%s " name;
10453    | RStructList (_, typ) ->
10454        let name = java_name_of_struct typ in
10455        pr "%s[] " name;
10456    | RHashtable _ -> pr "HashMap<String,String> ";
10457   );
10458
10459   if native then pr "_%s " name else pr "%s " name;
10460   pr "(";
10461   let needs_comma = ref false in
10462   if native then (
10463     pr "long g";
10464     needs_comma := true
10465   );
10466
10467   (* args *)
10468   List.iter (
10469     fun arg ->
10470       if !needs_comma then pr ", ";
10471       needs_comma := true;
10472
10473       match arg with
10474       | Pathname n
10475       | Device n | Dev_or_Path n
10476       | String n
10477       | OptString n
10478       | FileIn n
10479       | FileOut n ->
10480           pr "String %s" n
10481       | BufferIn n ->
10482           pr "byte[] %s" n
10483       | StringList n | DeviceList n ->
10484           pr "String[] %s" n
10485       | Bool n ->
10486           pr "boolean %s" n
10487       | Int n ->
10488           pr "int %s" n
10489       | Int64 n ->
10490           pr "long %s" n
10491   ) (snd style);
10492
10493   pr ")\n";
10494   pr "    throws LibGuestFSException";
10495   if semicolon then pr ";"
10496
10497 and generate_java_struct jtyp cols () =
10498   generate_header CStyle LGPLv2plus;
10499
10500   pr "\
10501 package com.redhat.et.libguestfs;
10502
10503 /**
10504  * Libguestfs %s structure.
10505  *
10506  * @author rjones
10507  * @see GuestFS
10508  */
10509 public class %s {
10510 " jtyp jtyp;
10511
10512   List.iter (
10513     function
10514     | name, FString
10515     | name, FUUID
10516     | name, FBuffer -> pr "  public String %s;\n" name
10517     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
10518     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
10519     | name, FChar -> pr "  public char %s;\n" name
10520     | name, FOptPercent ->
10521         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
10522         pr "  public float %s;\n" name
10523   ) cols;
10524
10525   pr "}\n"
10526
10527 and generate_java_c () =
10528   generate_header CStyle LGPLv2plus;
10529
10530   pr "\
10531 #include <stdio.h>
10532 #include <stdlib.h>
10533 #include <string.h>
10534
10535 #include \"com_redhat_et_libguestfs_GuestFS.h\"
10536 #include \"guestfs.h\"
10537
10538 /* Note that this function returns.  The exception is not thrown
10539  * until after the wrapper function returns.
10540  */
10541 static void
10542 throw_exception (JNIEnv *env, const char *msg)
10543 {
10544   jclass cl;
10545   cl = (*env)->FindClass (env,
10546                           \"com/redhat/et/libguestfs/LibGuestFSException\");
10547   (*env)->ThrowNew (env, cl, msg);
10548 }
10549
10550 JNIEXPORT jlong JNICALL
10551 Java_com_redhat_et_libguestfs_GuestFS__1create
10552   (JNIEnv *env, jobject obj)
10553 {
10554   guestfs_h *g;
10555
10556   g = guestfs_create ();
10557   if (g == NULL) {
10558     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
10559     return 0;
10560   }
10561   guestfs_set_error_handler (g, NULL, NULL);
10562   return (jlong) (long) g;
10563 }
10564
10565 JNIEXPORT void JNICALL
10566 Java_com_redhat_et_libguestfs_GuestFS__1close
10567   (JNIEnv *env, jobject obj, jlong jg)
10568 {
10569   guestfs_h *g = (guestfs_h *) (long) jg;
10570   guestfs_close (g);
10571 }
10572
10573 ";
10574
10575   List.iter (
10576     fun (name, style, _, _, _, _, _) ->
10577       pr "JNIEXPORT ";
10578       (match fst style with
10579        | RErr -> pr "void ";
10580        | RInt _ -> pr "jint ";
10581        | RInt64 _ -> pr "jlong ";
10582        | RBool _ -> pr "jboolean ";
10583        | RConstString _ | RConstOptString _ | RString _
10584        | RBufferOut _ -> pr "jstring ";
10585        | RStruct _ | RHashtable _ ->
10586            pr "jobject ";
10587        | RStringList _ | RStructList _ ->
10588            pr "jobjectArray ";
10589       );
10590       pr "JNICALL\n";
10591       pr "Java_com_redhat_et_libguestfs_GuestFS_";
10592       pr "%s" (replace_str ("_" ^ name) "_" "_1");
10593       pr "\n";
10594       pr "  (JNIEnv *env, jobject obj, jlong jg";
10595       List.iter (
10596         function
10597         | Pathname n
10598         | Device n | Dev_or_Path n
10599         | String n
10600         | OptString n
10601         | FileIn n
10602         | FileOut n ->
10603             pr ", jstring j%s" n
10604         | BufferIn n ->
10605             pr ", jbyteArray j%s" n
10606         | StringList n | DeviceList n ->
10607             pr ", jobjectArray j%s" n
10608         | Bool n ->
10609             pr ", jboolean j%s" n
10610         | Int n ->
10611             pr ", jint j%s" n
10612         | Int64 n ->
10613             pr ", jlong j%s" n
10614       ) (snd style);
10615       pr ")\n";
10616       pr "{\n";
10617       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
10618       let error_code, no_ret =
10619         match fst style with
10620         | RErr -> pr "  int r;\n"; "-1", ""
10621         | RBool _
10622         | RInt _ -> pr "  int r;\n"; "-1", "0"
10623         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
10624         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10625         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
10626         | RString _ ->
10627             pr "  jstring jr;\n";
10628             pr "  char *r;\n"; "NULL", "NULL"
10629         | RStringList _ ->
10630             pr "  jobjectArray jr;\n";
10631             pr "  int r_len;\n";
10632             pr "  jclass cl;\n";
10633             pr "  jstring jstr;\n";
10634             pr "  char **r;\n"; "NULL", "NULL"
10635         | RStruct (_, typ) ->
10636             pr "  jobject jr;\n";
10637             pr "  jclass cl;\n";
10638             pr "  jfieldID fl;\n";
10639             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
10640         | RStructList (_, typ) ->
10641             pr "  jobjectArray jr;\n";
10642             pr "  jclass cl;\n";
10643             pr "  jfieldID fl;\n";
10644             pr "  jobject jfl;\n";
10645             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
10646         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
10647         | RBufferOut _ ->
10648             pr "  jstring jr;\n";
10649             pr "  char *r;\n";
10650             pr "  size_t size;\n";
10651             "NULL", "NULL" in
10652       List.iter (
10653         function
10654         | Pathname n
10655         | Device n | Dev_or_Path n
10656         | String n
10657         | OptString n
10658         | FileIn n
10659         | FileOut n ->
10660             pr "  const char *%s;\n" n
10661         | BufferIn n ->
10662             pr "  jbyte *%s;\n" n;
10663             pr "  size_t %s_size;\n" n
10664         | StringList n | DeviceList n ->
10665             pr "  int %s_len;\n" n;
10666             pr "  const char **%s;\n" n
10667         | Bool n
10668         | Int n ->
10669             pr "  int %s;\n" n
10670         | Int64 n ->
10671             pr "  int64_t %s;\n" n
10672       ) (snd style);
10673
10674       let needs_i =
10675         (match fst style with
10676          | RStringList _ | RStructList _ -> true
10677          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
10678          | RConstOptString _
10679          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
10680           List.exists (function
10681                        | StringList _ -> true
10682                        | DeviceList _ -> true
10683                        | _ -> false) (snd style) in
10684       if needs_i then
10685         pr "  size_t i;\n";
10686
10687       pr "\n";
10688
10689       (* Get the parameters. *)
10690       List.iter (
10691         function
10692         | Pathname n
10693         | Device n | Dev_or_Path n
10694         | String n
10695         | FileIn n
10696         | FileOut n ->
10697             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
10698         | OptString n ->
10699             (* This is completely undocumented, but Java null becomes
10700              * a NULL parameter.
10701              *)
10702             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
10703         | BufferIn n ->
10704             pr "  %s = (*env)->GetByteArrayElements (env, j%s, NULL);\n" n n;
10705             pr "  %s_size = (*env)->GetArrayLength (env, j%s);\n" n n
10706         | StringList n | DeviceList n ->
10707             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
10708             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
10709             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10710             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10711               n;
10712             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
10713             pr "  }\n";
10714             pr "  %s[%s_len] = NULL;\n" n n;
10715         | Bool n
10716         | Int n
10717         | Int64 n ->
10718             pr "  %s = j%s;\n" n n
10719       ) (snd style);
10720
10721       (* Make the call. *)
10722       pr "  r = guestfs_%s " name;
10723       generate_c_call_args ~handle:"g" style;
10724       pr ";\n";
10725
10726       (* Release the parameters. *)
10727       List.iter (
10728         function
10729         | Pathname n
10730         | Device n | Dev_or_Path n
10731         | String n
10732         | FileIn n
10733         | FileOut n ->
10734             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10735         | OptString n ->
10736             pr "  if (j%s)\n" n;
10737             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
10738         | BufferIn n ->
10739             pr "  (*env)->ReleaseByteArrayElements (env, j%s, %s, 0);\n" n n
10740         | StringList n | DeviceList n ->
10741             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
10742             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
10743               n;
10744             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
10745             pr "  }\n";
10746             pr "  free (%s);\n" n
10747         | Bool n
10748         | Int n
10749         | Int64 n -> ()
10750       ) (snd style);
10751
10752       (* Check for errors. *)
10753       pr "  if (r == %s) {\n" error_code;
10754       pr "    throw_exception (env, guestfs_last_error (g));\n";
10755       pr "    return %s;\n" no_ret;
10756       pr "  }\n";
10757
10758       (* Return value. *)
10759       (match fst style with
10760        | RErr -> ()
10761        | RInt _ -> pr "  return (jint) r;\n"
10762        | RBool _ -> pr "  return (jboolean) r;\n"
10763        | RInt64 _ -> pr "  return (jlong) r;\n"
10764        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
10765        | RConstOptString _ ->
10766            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
10767        | RString _ ->
10768            pr "  jr = (*env)->NewStringUTF (env, r);\n";
10769            pr "  free (r);\n";
10770            pr "  return jr;\n"
10771        | RStringList _ ->
10772            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
10773            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
10774            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
10775            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
10776            pr "  for (i = 0; i < r_len; ++i) {\n";
10777            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
10778            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
10779            pr "    free (r[i]);\n";
10780            pr "  }\n";
10781            pr "  free (r);\n";
10782            pr "  return jr;\n"
10783        | RStruct (_, typ) ->
10784            let jtyp = java_name_of_struct typ in
10785            let cols = cols_of_struct typ in
10786            generate_java_struct_return typ jtyp cols
10787        | RStructList (_, typ) ->
10788            let jtyp = java_name_of_struct typ in
10789            let cols = cols_of_struct typ in
10790            generate_java_struct_list_return typ jtyp cols
10791        | RHashtable _ ->
10792            (* XXX *)
10793            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
10794            pr "  return NULL;\n"
10795        | RBufferOut _ ->
10796            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
10797            pr "  free (r);\n";
10798            pr "  return jr;\n"
10799       );
10800
10801       pr "}\n";
10802       pr "\n"
10803   ) all_functions
10804
10805 and generate_java_struct_return typ jtyp cols =
10806   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10807   pr "  jr = (*env)->AllocObject (env, cl);\n";
10808   List.iter (
10809     function
10810     | name, FString ->
10811         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10812         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
10813     | name, FUUID ->
10814         pr "  {\n";
10815         pr "    char s[33];\n";
10816         pr "    memcpy (s, r->%s, 32);\n" name;
10817         pr "    s[32] = 0;\n";
10818         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10819         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10820         pr "  }\n";
10821     | name, FBuffer ->
10822         pr "  {\n";
10823         pr "    int len = r->%s_len;\n" name;
10824         pr "    char s[len+1];\n";
10825         pr "    memcpy (s, r->%s, len);\n" name;
10826         pr "    s[len] = 0;\n";
10827         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10828         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
10829         pr "  }\n";
10830     | name, (FBytes|FUInt64|FInt64) ->
10831         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10832         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10833     | name, (FUInt32|FInt32) ->
10834         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10835         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10836     | name, FOptPercent ->
10837         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10838         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
10839     | name, FChar ->
10840         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10841         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
10842   ) cols;
10843   pr "  free (r);\n";
10844   pr "  return jr;\n"
10845
10846 and generate_java_struct_list_return typ jtyp cols =
10847   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
10848   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
10849   pr "  for (i = 0; i < r->len; ++i) {\n";
10850   pr "    jfl = (*env)->AllocObject (env, cl);\n";
10851   List.iter (
10852     function
10853     | name, FString ->
10854         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10855         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
10856     | name, FUUID ->
10857         pr "    {\n";
10858         pr "      char s[33];\n";
10859         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
10860         pr "      s[32] = 0;\n";
10861         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10862         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10863         pr "    }\n";
10864     | name, FBuffer ->
10865         pr "    {\n";
10866         pr "      int len = r->val[i].%s_len;\n" name;
10867         pr "      char s[len+1];\n";
10868         pr "      memcpy (s, r->val[i].%s, len);\n" name;
10869         pr "      s[len] = 0;\n";
10870         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
10871         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
10872         pr "    }\n";
10873     | name, (FBytes|FUInt64|FInt64) ->
10874         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
10875         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10876     | name, (FUInt32|FInt32) ->
10877         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
10878         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10879     | name, FOptPercent ->
10880         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
10881         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
10882     | name, FChar ->
10883         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
10884         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
10885   ) cols;
10886   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
10887   pr "  }\n";
10888   pr "  guestfs_free_%s_list (r);\n" typ;
10889   pr "  return jr;\n"
10890
10891 and generate_java_makefile_inc () =
10892   generate_header HashStyle GPLv2plus;
10893
10894   pr "java_built_sources = \\\n";
10895   List.iter (
10896     fun (typ, jtyp) ->
10897         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
10898   ) java_structs;
10899   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
10900
10901 and generate_haskell_hs () =
10902   generate_header HaskellStyle LGPLv2plus;
10903
10904   (* XXX We only know how to generate partial FFI for Haskell
10905    * at the moment.  Please help out!
10906    *)
10907   let can_generate style =
10908     match style with
10909     | RErr, _
10910     | RInt _, _
10911     | RInt64 _, _ -> true
10912     | RBool _, _
10913     | RConstString _, _
10914     | RConstOptString _, _
10915     | RString _, _
10916     | RStringList _, _
10917     | RStruct _, _
10918     | RStructList _, _
10919     | RHashtable _, _
10920     | RBufferOut _, _ -> false in
10921
10922   pr "\
10923 {-# INCLUDE <guestfs.h> #-}
10924 {-# LANGUAGE ForeignFunctionInterface #-}
10925
10926 module Guestfs (
10927   create";
10928
10929   (* List out the names of the actions we want to export. *)
10930   List.iter (
10931     fun (name, style, _, _, _, _, _) ->
10932       if can_generate style then pr ",\n  %s" name
10933   ) all_functions;
10934
10935   pr "
10936   ) where
10937
10938 -- Unfortunately some symbols duplicate ones already present
10939 -- in Prelude.  We don't know which, so we hard-code a list
10940 -- here.
10941 import Prelude hiding (truncate)
10942
10943 import Foreign
10944 import Foreign.C
10945 import Foreign.C.Types
10946 import IO
10947 import Control.Exception
10948 import Data.Typeable
10949
10950 data GuestfsS = GuestfsS            -- represents the opaque C struct
10951 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
10952 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
10953
10954 -- XXX define properly later XXX
10955 data PV = PV
10956 data VG = VG
10957 data LV = LV
10958 data IntBool = IntBool
10959 data Stat = Stat
10960 data StatVFS = StatVFS
10961 data Hashtable = Hashtable
10962
10963 foreign import ccall unsafe \"guestfs_create\" c_create
10964   :: IO GuestfsP
10965 foreign import ccall unsafe \"&guestfs_close\" c_close
10966   :: FunPtr (GuestfsP -> IO ())
10967 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
10968   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
10969
10970 create :: IO GuestfsH
10971 create = do
10972   p <- c_create
10973   c_set_error_handler p nullPtr nullPtr
10974   h <- newForeignPtr c_close p
10975   return h
10976
10977 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
10978   :: GuestfsP -> IO CString
10979
10980 -- last_error :: GuestfsH -> IO (Maybe String)
10981 -- last_error h = do
10982 --   str <- withForeignPtr h (\\p -> c_last_error p)
10983 --   maybePeek peekCString str
10984
10985 last_error :: GuestfsH -> IO (String)
10986 last_error h = do
10987   str <- withForeignPtr h (\\p -> c_last_error p)
10988   if (str == nullPtr)
10989     then return \"no error\"
10990     else peekCString str
10991
10992 ";
10993
10994   (* Generate wrappers for each foreign function. *)
10995   List.iter (
10996     fun (name, style, _, _, _, _, _) ->
10997       if can_generate style then (
10998         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10999         pr "  :: ";
11000         generate_haskell_prototype ~handle:"GuestfsP" style;
11001         pr "\n";
11002         pr "\n";
11003         pr "%s :: " name;
11004         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
11005         pr "\n";
11006         pr "%s %s = do\n" name
11007           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
11008         pr "  r <- ";
11009         (* Convert pointer arguments using with* functions. *)
11010         List.iter (
11011           function
11012           | FileIn n
11013           | FileOut n
11014           | Pathname n | Device n | Dev_or_Path n | String n ->
11015               pr "withCString %s $ \\%s -> " n n
11016           | BufferIn n ->
11017               pr "withCStringLen %s $ \\(%s, %s_size) -> " n n n
11018           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
11019           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
11020           | Bool _ | Int _ | Int64 _ -> ()
11021         ) (snd style);
11022         (* Convert integer arguments. *)
11023         let args =
11024           List.map (
11025             function
11026             | Bool n -> sprintf "(fromBool %s)" n
11027             | Int n -> sprintf "(fromIntegral %s)" n
11028             | Int64 n -> sprintf "(fromIntegral %s)" n
11029             | FileIn n | FileOut n
11030             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
11031             | BufferIn n -> sprintf "%s (fromIntegral %s_size)" n n
11032           ) (snd style) in
11033         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
11034           (String.concat " " ("p" :: args));
11035         (match fst style with
11036          | RErr | RInt _ | RInt64 _ | RBool _ ->
11037              pr "  if (r == -1)\n";
11038              pr "    then do\n";
11039              pr "      err <- last_error h\n";
11040              pr "      fail err\n";
11041          | RConstString _ | RConstOptString _ | RString _
11042          | RStringList _ | RStruct _
11043          | RStructList _ | RHashtable _ | RBufferOut _ ->
11044              pr "  if (r == nullPtr)\n";
11045              pr "    then do\n";
11046              pr "      err <- last_error h\n";
11047              pr "      fail err\n";
11048         );
11049         (match fst style with
11050          | RErr ->
11051              pr "    else return ()\n"
11052          | RInt _ ->
11053              pr "    else return (fromIntegral r)\n"
11054          | RInt64 _ ->
11055              pr "    else return (fromIntegral r)\n"
11056          | RBool _ ->
11057              pr "    else return (toBool r)\n"
11058          | RConstString _
11059          | RConstOptString _
11060          | RString _
11061          | RStringList _
11062          | RStruct _
11063          | RStructList _
11064          | RHashtable _
11065          | RBufferOut _ ->
11066              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
11067         );
11068         pr "\n";
11069       )
11070   ) all_functions
11071
11072 and generate_haskell_prototype ~handle ?(hs = false) style =
11073   pr "%s -> " handle;
11074   let string = if hs then "String" else "CString" in
11075   let int = if hs then "Int" else "CInt" in
11076   let bool = if hs then "Bool" else "CInt" in
11077   let int64 = if hs then "Integer" else "Int64" in
11078   List.iter (
11079     fun arg ->
11080       (match arg with
11081        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
11082        | BufferIn _ ->
11083            if hs then pr "String"
11084            else pr "CString -> CInt"
11085        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
11086        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
11087        | Bool _ -> pr "%s" bool
11088        | Int _ -> pr "%s" int
11089        | Int64 _ -> pr "%s" int
11090        | FileIn _ -> pr "%s" string
11091        | FileOut _ -> pr "%s" string
11092       );
11093       pr " -> ";
11094   ) (snd style);
11095   pr "IO (";
11096   (match fst style with
11097    | RErr -> if not hs then pr "CInt"
11098    | RInt _ -> pr "%s" int
11099    | RInt64 _ -> pr "%s" int64
11100    | RBool _ -> pr "%s" bool
11101    | RConstString _ -> pr "%s" string
11102    | RConstOptString _ -> pr "Maybe %s" string
11103    | RString _ -> pr "%s" string
11104    | RStringList _ -> pr "[%s]" string
11105    | RStruct (_, typ) ->
11106        let name = java_name_of_struct typ in
11107        pr "%s" name
11108    | RStructList (_, typ) ->
11109        let name = java_name_of_struct typ in
11110        pr "[%s]" name
11111    | RHashtable _ -> pr "Hashtable"
11112    | RBufferOut _ -> pr "%s" string
11113   );
11114   pr ")"
11115
11116 and generate_csharp () =
11117   generate_header CPlusPlusStyle LGPLv2plus;
11118
11119   (* XXX Make this configurable by the C# assembly users. *)
11120   let library = "libguestfs.so.0" in
11121
11122   pr "\
11123 // These C# bindings are highly experimental at present.
11124 //
11125 // Firstly they only work on Linux (ie. Mono).  In order to get them
11126 // to work on Windows (ie. .Net) you would need to port the library
11127 // itself to Windows first.
11128 //
11129 // The second issue is that some calls are known to be incorrect and
11130 // can cause Mono to segfault.  Particularly: calls which pass or
11131 // return string[], or return any structure value.  This is because
11132 // we haven't worked out the correct way to do this from C#.
11133 //
11134 // The third issue is that when compiling you get a lot of warnings.
11135 // We are not sure whether the warnings are important or not.
11136 //
11137 // Fourthly we do not routinely build or test these bindings as part
11138 // of the make && make check cycle, which means that regressions might
11139 // go unnoticed.
11140 //
11141 // Suggestions and patches are welcome.
11142
11143 // To compile:
11144 //
11145 // gmcs Libguestfs.cs
11146 // mono Libguestfs.exe
11147 //
11148 // (You'll probably want to add a Test class / static main function
11149 // otherwise this won't do anything useful).
11150
11151 using System;
11152 using System.IO;
11153 using System.Runtime.InteropServices;
11154 using System.Runtime.Serialization;
11155 using System.Collections;
11156
11157 namespace Guestfs
11158 {
11159   class Error : System.ApplicationException
11160   {
11161     public Error (string message) : base (message) {}
11162     protected Error (SerializationInfo info, StreamingContext context) {}
11163   }
11164
11165   class Guestfs
11166   {
11167     IntPtr _handle;
11168
11169     [DllImport (\"%s\")]
11170     static extern IntPtr guestfs_create ();
11171
11172     public Guestfs ()
11173     {
11174       _handle = guestfs_create ();
11175       if (_handle == IntPtr.Zero)
11176         throw new Error (\"could not create guestfs handle\");
11177     }
11178
11179     [DllImport (\"%s\")]
11180     static extern void guestfs_close (IntPtr h);
11181
11182     ~Guestfs ()
11183     {
11184       guestfs_close (_handle);
11185     }
11186
11187     [DllImport (\"%s\")]
11188     static extern string guestfs_last_error (IntPtr h);
11189
11190 " library library library;
11191
11192   (* Generate C# structure bindings.  We prefix struct names with
11193    * underscore because C# cannot have conflicting struct names and
11194    * method names (eg. "class stat" and "stat").
11195    *)
11196   List.iter (
11197     fun (typ, cols) ->
11198       pr "    [StructLayout (LayoutKind.Sequential)]\n";
11199       pr "    public class _%s {\n" typ;
11200       List.iter (
11201         function
11202         | name, FChar -> pr "      char %s;\n" name
11203         | name, FString -> pr "      string %s;\n" name
11204         | name, FBuffer ->
11205             pr "      uint %s_len;\n" name;
11206             pr "      string %s;\n" name
11207         | name, FUUID ->
11208             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
11209             pr "      string %s;\n" name
11210         | name, FUInt32 -> pr "      uint %s;\n" name
11211         | name, FInt32 -> pr "      int %s;\n" name
11212         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
11213         | name, FInt64 -> pr "      long %s;\n" name
11214         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
11215       ) cols;
11216       pr "    }\n";
11217       pr "\n"
11218   ) structs;
11219
11220   (* Generate C# function bindings. *)
11221   List.iter (
11222     fun (name, style, _, _, _, shortdesc, _) ->
11223       let rec csharp_return_type () =
11224         match fst style with
11225         | RErr -> "void"
11226         | RBool n -> "bool"
11227         | RInt n -> "int"
11228         | RInt64 n -> "long"
11229         | RConstString n
11230         | RConstOptString n
11231         | RString n
11232         | RBufferOut n -> "string"
11233         | RStruct (_,n) -> "_" ^ n
11234         | RHashtable n -> "Hashtable"
11235         | RStringList n -> "string[]"
11236         | RStructList (_,n) -> sprintf "_%s[]" n
11237
11238       and c_return_type () =
11239         match fst style with
11240         | RErr
11241         | RBool _
11242         | RInt _ -> "int"
11243         | RInt64 _ -> "long"
11244         | RConstString _
11245         | RConstOptString _
11246         | RString _
11247         | RBufferOut _ -> "string"
11248         | RStruct (_,n) -> "_" ^ n
11249         | RHashtable _
11250         | RStringList _ -> "string[]"
11251         | RStructList (_,n) -> sprintf "_%s[]" n
11252
11253       and c_error_comparison () =
11254         match fst style with
11255         | RErr
11256         | RBool _
11257         | RInt _
11258         | RInt64 _ -> "== -1"
11259         | RConstString _
11260         | RConstOptString _
11261         | RString _
11262         | RBufferOut _
11263         | RStruct (_,_)
11264         | RHashtable _
11265         | RStringList _
11266         | RStructList (_,_) -> "== null"
11267
11268       and generate_extern_prototype () =
11269         pr "    static extern %s guestfs_%s (IntPtr h"
11270           (c_return_type ()) name;
11271         List.iter (
11272           function
11273           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11274           | FileIn n | FileOut n
11275           | BufferIn n ->
11276               pr ", [In] string %s" n
11277           | StringList n | DeviceList n ->
11278               pr ", [In] string[] %s" n
11279           | Bool n ->
11280               pr ", bool %s" n
11281           | Int n ->
11282               pr ", int %s" n
11283           | Int64 n ->
11284               pr ", long %s" n
11285         ) (snd style);
11286         pr ");\n"
11287
11288       and generate_public_prototype () =
11289         pr "    public %s %s (" (csharp_return_type ()) name;
11290         let comma = ref false in
11291         let next () =
11292           if !comma then pr ", ";
11293           comma := true
11294         in
11295         List.iter (
11296           function
11297           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
11298           | FileIn n | FileOut n
11299           | BufferIn n ->
11300               next (); pr "string %s" n
11301           | StringList n | DeviceList n ->
11302               next (); pr "string[] %s" n
11303           | Bool n ->
11304               next (); pr "bool %s" n
11305           | Int n ->
11306               next (); pr "int %s" n
11307           | Int64 n ->
11308               next (); pr "long %s" n
11309         ) (snd style);
11310         pr ")\n"
11311
11312       and generate_call () =
11313         pr "guestfs_%s (_handle" name;
11314         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
11315         pr ");\n";
11316       in
11317
11318       pr "    [DllImport (\"%s\")]\n" library;
11319       generate_extern_prototype ();
11320       pr "\n";
11321       pr "    /// <summary>\n";
11322       pr "    /// %s\n" shortdesc;
11323       pr "    /// </summary>\n";
11324       generate_public_prototype ();
11325       pr "    {\n";
11326       pr "      %s r;\n" (c_return_type ());
11327       pr "      r = ";
11328       generate_call ();
11329       pr "      if (r %s)\n" (c_error_comparison ());
11330       pr "        throw new Error (guestfs_last_error (_handle));\n";
11331       (match fst style with
11332        | RErr -> ()
11333        | RBool _ ->
11334            pr "      return r != 0 ? true : false;\n"
11335        | RHashtable _ ->
11336            pr "      Hashtable rr = new Hashtable ();\n";
11337            pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
11338            pr "        rr.Add (r[i], r[i+1]);\n";
11339            pr "      return rr;\n"
11340        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
11341        | RString _ | RBufferOut _ | RStruct _ | RStringList _
11342        | RStructList _ ->
11343            pr "      return r;\n"
11344       );
11345       pr "    }\n";
11346       pr "\n";
11347   ) all_functions_sorted;
11348
11349   pr "  }
11350 }
11351 "
11352
11353 and generate_bindtests () =
11354   generate_header CStyle LGPLv2plus;
11355
11356   pr "\
11357 #include <stdio.h>
11358 #include <stdlib.h>
11359 #include <inttypes.h>
11360 #include <string.h>
11361
11362 #include \"guestfs.h\"
11363 #include \"guestfs-internal.h\"
11364 #include \"guestfs-internal-actions.h\"
11365 #include \"guestfs_protocol.h\"
11366
11367 #define error guestfs_error
11368 #define safe_calloc guestfs_safe_calloc
11369 #define safe_malloc guestfs_safe_malloc
11370
11371 static void
11372 print_strings (char *const *argv)
11373 {
11374   size_t argc;
11375
11376   printf (\"[\");
11377   for (argc = 0; argv[argc] != NULL; ++argc) {
11378     if (argc > 0) printf (\", \");
11379     printf (\"\\\"%%s\\\"\", argv[argc]);
11380   }
11381   printf (\"]\\n\");
11382 }
11383
11384 /* The test0 function prints its parameters to stdout. */
11385 ";
11386
11387   let test0, tests =
11388     match test_functions with
11389     | [] -> assert false
11390     | test0 :: tests -> test0, tests in
11391
11392   let () =
11393     let (name, style, _, _, _, _, _) = test0 in
11394     generate_prototype ~extern:false ~semicolon:false ~newline:true
11395       ~handle:"g" ~prefix:"guestfs__" name style;
11396     pr "{\n";
11397     List.iter (
11398       function
11399       | Pathname n
11400       | Device n | Dev_or_Path n
11401       | String n
11402       | FileIn n
11403       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
11404       | BufferIn n ->
11405           pr "  {\n";
11406           pr "    size_t i;\n";
11407           pr "    for (i = 0; i < %s_size; ++i)\n" n;
11408           pr "      printf (\"<%%02x>\", %s[i]);\n" n;
11409           pr "    printf (\"\\n\");\n";
11410           pr "  }\n";
11411       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
11412       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
11413       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
11414       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
11415       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
11416     ) (snd style);
11417     pr "  /* Java changes stdout line buffering so we need this: */\n";
11418     pr "  fflush (stdout);\n";
11419     pr "  return 0;\n";
11420     pr "}\n";
11421     pr "\n" in
11422
11423   List.iter (
11424     fun (name, style, _, _, _, _, _) ->
11425       if String.sub name (String.length name - 3) 3 <> "err" then (
11426         pr "/* Test normal return. */\n";
11427         generate_prototype ~extern:false ~semicolon:false ~newline:true
11428           ~handle:"g" ~prefix:"guestfs__" name style;
11429         pr "{\n";
11430         (match fst style with
11431          | RErr ->
11432              pr "  return 0;\n"
11433          | RInt _ ->
11434              pr "  int r;\n";
11435              pr "  sscanf (val, \"%%d\", &r);\n";
11436              pr "  return r;\n"
11437          | RInt64 _ ->
11438              pr "  int64_t r;\n";
11439              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
11440              pr "  return r;\n"
11441          | RBool _ ->
11442              pr "  return STREQ (val, \"true\");\n"
11443          | RConstString _
11444          | RConstOptString _ ->
11445              (* Can't return the input string here.  Return a static
11446               * string so we ensure we get a segfault if the caller
11447               * tries to free it.
11448               *)
11449              pr "  return \"static string\";\n"
11450          | RString _ ->
11451              pr "  return strdup (val);\n"
11452          | RStringList _ ->
11453              pr "  char **strs;\n";
11454              pr "  int n, i;\n";
11455              pr "  sscanf (val, \"%%d\", &n);\n";
11456              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
11457              pr "  for (i = 0; i < n; ++i) {\n";
11458              pr "    strs[i] = safe_malloc (g, 16);\n";
11459              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
11460              pr "  }\n";
11461              pr "  strs[n] = NULL;\n";
11462              pr "  return strs;\n"
11463          | RStruct (_, typ) ->
11464              pr "  struct guestfs_%s *r;\n" typ;
11465              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11466              pr "  return r;\n"
11467          | RStructList (_, typ) ->
11468              pr "  struct guestfs_%s_list *r;\n" typ;
11469              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
11470              pr "  sscanf (val, \"%%d\", &r->len);\n";
11471              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
11472              pr "  return r;\n"
11473          | RHashtable _ ->
11474              pr "  char **strs;\n";
11475              pr "  int n, i;\n";
11476              pr "  sscanf (val, \"%%d\", &n);\n";
11477              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
11478              pr "  for (i = 0; i < n; ++i) {\n";
11479              pr "    strs[i*2] = safe_malloc (g, 16);\n";
11480              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
11481              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
11482              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
11483              pr "  }\n";
11484              pr "  strs[n*2] = NULL;\n";
11485              pr "  return strs;\n"
11486          | RBufferOut _ ->
11487              pr "  return strdup (val);\n"
11488         );
11489         pr "}\n";
11490         pr "\n"
11491       ) else (
11492         pr "/* Test error return. */\n";
11493         generate_prototype ~extern:false ~semicolon:false ~newline:true
11494           ~handle:"g" ~prefix:"guestfs__" name style;
11495         pr "{\n";
11496         pr "  error (g, \"error\");\n";
11497         (match fst style with
11498          | RErr | RInt _ | RInt64 _ | RBool _ ->
11499              pr "  return -1;\n"
11500          | RConstString _ | RConstOptString _
11501          | RString _ | RStringList _ | RStruct _
11502          | RStructList _
11503          | RHashtable _
11504          | RBufferOut _ ->
11505              pr "  return NULL;\n"
11506         );
11507         pr "}\n";
11508         pr "\n"
11509       )
11510   ) tests
11511
11512 and generate_ocaml_bindtests () =
11513   generate_header OCamlStyle GPLv2plus;
11514
11515   pr "\
11516 let () =
11517   let g = Guestfs.create () in
11518 ";
11519
11520   let mkargs args =
11521     String.concat " " (
11522       List.map (
11523         function
11524         | CallString s -> "\"" ^ s ^ "\""
11525         | CallOptString None -> "None"
11526         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
11527         | CallStringList xs ->
11528             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
11529         | CallInt i when i >= 0 -> string_of_int i
11530         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
11531         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
11532         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
11533         | CallBool b -> string_of_bool b
11534         | CallBuffer s -> sprintf "%S" s
11535       ) args
11536     )
11537   in
11538
11539   generate_lang_bindtests (
11540     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
11541   );
11542
11543   pr "print_endline \"EOF\"\n"
11544
11545 and generate_perl_bindtests () =
11546   pr "#!/usr/bin/perl -w\n";
11547   generate_header HashStyle GPLv2plus;
11548
11549   pr "\
11550 use strict;
11551
11552 use Sys::Guestfs;
11553
11554 my $g = Sys::Guestfs->new ();
11555 ";
11556
11557   let mkargs args =
11558     String.concat ", " (
11559       List.map (
11560         function
11561         | CallString s -> "\"" ^ s ^ "\""
11562         | CallOptString None -> "undef"
11563         | CallOptString (Some s) -> sprintf "\"%s\"" s
11564         | CallStringList xs ->
11565             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11566         | CallInt i -> string_of_int i
11567         | CallInt64 i -> Int64.to_string i
11568         | CallBool b -> if b then "1" else "0"
11569         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11570       ) args
11571     )
11572   in
11573
11574   generate_lang_bindtests (
11575     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
11576   );
11577
11578   pr "print \"EOF\\n\"\n"
11579
11580 and generate_python_bindtests () =
11581   generate_header HashStyle GPLv2plus;
11582
11583   pr "\
11584 import guestfs
11585
11586 g = guestfs.GuestFS ()
11587 ";
11588
11589   let mkargs args =
11590     String.concat ", " (
11591       List.map (
11592         function
11593         | CallString s -> "\"" ^ s ^ "\""
11594         | CallOptString None -> "None"
11595         | CallOptString (Some s) -> sprintf "\"%s\"" s
11596         | CallStringList xs ->
11597             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11598         | CallInt i -> string_of_int i
11599         | CallInt64 i -> Int64.to_string i
11600         | CallBool b -> if b then "1" else "0"
11601         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11602       ) args
11603     )
11604   in
11605
11606   generate_lang_bindtests (
11607     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
11608   );
11609
11610   pr "print \"EOF\"\n"
11611
11612 and generate_ruby_bindtests () =
11613   generate_header HashStyle GPLv2plus;
11614
11615   pr "\
11616 require 'guestfs'
11617
11618 g = Guestfs::create()
11619 ";
11620
11621   let mkargs args =
11622     String.concat ", " (
11623       List.map (
11624         function
11625         | CallString s -> "\"" ^ s ^ "\""
11626         | CallOptString None -> "nil"
11627         | CallOptString (Some s) -> sprintf "\"%s\"" s
11628         | CallStringList xs ->
11629             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11630         | CallInt i -> string_of_int i
11631         | CallInt64 i -> Int64.to_string i
11632         | CallBool b -> string_of_bool b
11633         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11634       ) args
11635     )
11636   in
11637
11638   generate_lang_bindtests (
11639     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
11640   );
11641
11642   pr "print \"EOF\\n\"\n"
11643
11644 and generate_java_bindtests () =
11645   generate_header CStyle GPLv2plus;
11646
11647   pr "\
11648 import com.redhat.et.libguestfs.*;
11649
11650 public class Bindtests {
11651     public static void main (String[] argv)
11652     {
11653         try {
11654             GuestFS g = new GuestFS ();
11655 ";
11656
11657   let mkargs args =
11658     String.concat ", " (
11659       List.map (
11660         function
11661         | CallString s -> "\"" ^ s ^ "\""
11662         | CallOptString None -> "null"
11663         | CallOptString (Some s) -> sprintf "\"%s\"" s
11664         | CallStringList xs ->
11665             "new String[]{" ^
11666               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
11667         | CallInt i -> string_of_int i
11668         | CallInt64 i -> Int64.to_string i
11669         | CallBool b -> string_of_bool b
11670         | CallBuffer s ->
11671             "new byte[] { " ^ String.concat "," (
11672               map_chars (fun c -> string_of_int (Char.code c)) s
11673             ) ^ " }"
11674       ) args
11675     )
11676   in
11677
11678   generate_lang_bindtests (
11679     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
11680   );
11681
11682   pr "
11683             System.out.println (\"EOF\");
11684         }
11685         catch (Exception exn) {
11686             System.err.println (exn);
11687             System.exit (1);
11688         }
11689     }
11690 }
11691 "
11692
11693 and generate_haskell_bindtests () =
11694   generate_header HaskellStyle GPLv2plus;
11695
11696   pr "\
11697 module Bindtests where
11698 import qualified Guestfs
11699
11700 main = do
11701   g <- Guestfs.create
11702 ";
11703
11704   let mkargs args =
11705     String.concat " " (
11706       List.map (
11707         function
11708         | CallString s -> "\"" ^ s ^ "\""
11709         | CallOptString None -> "Nothing"
11710         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
11711         | CallStringList xs ->
11712             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
11713         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
11714         | CallInt i -> string_of_int i
11715         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
11716         | CallInt64 i -> Int64.to_string i
11717         | CallBool true -> "True"
11718         | CallBool false -> "False"
11719         | CallBuffer s -> "\"" ^ c_quote s ^ "\""
11720       ) args
11721     )
11722   in
11723
11724   generate_lang_bindtests (
11725     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
11726   );
11727
11728   pr "  putStrLn \"EOF\"\n"
11729
11730 (* Language-independent bindings tests - we do it this way to
11731  * ensure there is parity in testing bindings across all languages.
11732  *)
11733 and generate_lang_bindtests call =
11734   call "test0" [CallString "abc"; CallOptString (Some "def");
11735                 CallStringList []; CallBool false;
11736                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11737                 CallBuffer "abc\000abc"];
11738   call "test0" [CallString "abc"; CallOptString None;
11739                 CallStringList []; CallBool false;
11740                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11741                 CallBuffer "abc\000abc"];
11742   call "test0" [CallString ""; CallOptString (Some "def");
11743                 CallStringList []; CallBool false;
11744                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11745                 CallBuffer "abc\000abc"];
11746   call "test0" [CallString ""; CallOptString (Some "");
11747                 CallStringList []; CallBool false;
11748                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11749                 CallBuffer "abc\000abc"];
11750   call "test0" [CallString "abc"; CallOptString (Some "def");
11751                 CallStringList ["1"]; CallBool false;
11752                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11753                 CallBuffer "abc\000abc"];
11754   call "test0" [CallString "abc"; CallOptString (Some "def");
11755                 CallStringList ["1"; "2"]; CallBool false;
11756                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11757                 CallBuffer "abc\000abc"];
11758   call "test0" [CallString "abc"; CallOptString (Some "def");
11759                 CallStringList ["1"]; CallBool true;
11760                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456";
11761                 CallBuffer "abc\000abc"];
11762   call "test0" [CallString "abc"; CallOptString (Some "def");
11763                 CallStringList ["1"]; CallBool false;
11764                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456";
11765                 CallBuffer "abc\000abc"];
11766   call "test0" [CallString "abc"; CallOptString (Some "def");
11767                 CallStringList ["1"]; CallBool false;
11768                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456";
11769                 CallBuffer "abc\000abc"];
11770   call "test0" [CallString "abc"; CallOptString (Some "def");
11771                 CallStringList ["1"]; CallBool false;
11772                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456";
11773                 CallBuffer "abc\000abc"];
11774   call "test0" [CallString "abc"; CallOptString (Some "def");
11775                 CallStringList ["1"]; CallBool false;
11776                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456";
11777                 CallBuffer "abc\000abc"];
11778   call "test0" [CallString "abc"; CallOptString (Some "def");
11779                 CallStringList ["1"]; CallBool false;
11780                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456";
11781                 CallBuffer "abc\000abc"];
11782   call "test0" [CallString "abc"; CallOptString (Some "def");
11783                 CallStringList ["1"]; CallBool false;
11784                 CallInt 0; CallInt64 0L; CallString ""; CallString "";
11785                 CallBuffer "abc\000abc"]
11786
11787 (* XXX Add here tests of the return and error functions. *)
11788
11789 (* Code to generator bindings for virt-inspector.  Currently only
11790  * implemented for OCaml code (for virt-p2v 2.0).
11791  *)
11792 let rng_input = "inspector/virt-inspector.rng"
11793
11794 (* Read the input file and parse it into internal structures.  This is
11795  * by no means a complete RELAX NG parser, but is just enough to be
11796  * able to parse the specific input file.
11797  *)
11798 type rng =
11799   | Element of string * rng list        (* <element name=name/> *)
11800   | Attribute of string * rng list        (* <attribute name=name/> *)
11801   | Interleave of rng list                (* <interleave/> *)
11802   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
11803   | OneOrMore of rng                        (* <oneOrMore/> *)
11804   | Optional of rng                        (* <optional/> *)
11805   | Choice of string list                (* <choice><value/>*</choice> *)
11806   | Value of string                        (* <value>str</value> *)
11807   | Text                                (* <text/> *)
11808
11809 let rec string_of_rng = function
11810   | Element (name, xs) ->
11811       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11812   | Attribute (name, xs) ->
11813       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
11814   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
11815   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
11816   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
11817   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
11818   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
11819   | Value value -> "Value \"" ^ value ^ "\""
11820   | Text -> "Text"
11821
11822 and string_of_rng_list xs =
11823   String.concat ", " (List.map string_of_rng xs)
11824
11825 let rec parse_rng ?defines context = function
11826   | [] -> []
11827   | Xml.Element ("element", ["name", name], children) :: rest ->
11828       Element (name, parse_rng ?defines context children)
11829       :: parse_rng ?defines context rest
11830   | Xml.Element ("attribute", ["name", name], children) :: rest ->
11831       Attribute (name, parse_rng ?defines context children)
11832       :: parse_rng ?defines context rest
11833   | Xml.Element ("interleave", [], children) :: rest ->
11834       Interleave (parse_rng ?defines context children)
11835       :: parse_rng ?defines context rest
11836   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
11837       let rng = parse_rng ?defines context [child] in
11838       (match rng with
11839        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
11840        | _ ->
11841            failwithf "%s: <zeroOrMore> contains more than one child element"
11842              context
11843       )
11844   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
11845       let rng = parse_rng ?defines context [child] in
11846       (match rng with
11847        | [child] -> OneOrMore child :: parse_rng ?defines context rest
11848        | _ ->
11849            failwithf "%s: <oneOrMore> contains more than one child element"
11850              context
11851       )
11852   | Xml.Element ("optional", [], [child]) :: rest ->
11853       let rng = parse_rng ?defines context [child] in
11854       (match rng with
11855        | [child] -> Optional child :: parse_rng ?defines context rest
11856        | _ ->
11857            failwithf "%s: <optional> contains more than one child element"
11858              context
11859       )
11860   | Xml.Element ("choice", [], children) :: rest ->
11861       let values = List.map (
11862         function Xml.Element ("value", [], [Xml.PCData value]) -> value
11863         | _ ->
11864             failwithf "%s: can't handle anything except <value> in <choice>"
11865               context
11866       ) children in
11867       Choice values
11868       :: parse_rng ?defines context rest
11869   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
11870       Value value :: parse_rng ?defines context rest
11871   | Xml.Element ("text", [], []) :: rest ->
11872       Text :: parse_rng ?defines context rest
11873   | Xml.Element ("ref", ["name", name], []) :: rest ->
11874       (* Look up the reference.  Because of limitations in this parser,
11875        * we can't handle arbitrarily nested <ref> yet.  You can only
11876        * use <ref> from inside <start>.
11877        *)
11878       (match defines with
11879        | None ->
11880            failwithf "%s: contains <ref>, but no refs are defined yet" context
11881        | Some map ->
11882            let rng = StringMap.find name map in
11883            rng @ parse_rng ?defines context rest
11884       )
11885   | x :: _ ->
11886       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
11887
11888 let grammar =
11889   let xml = Xml.parse_file rng_input in
11890   match xml with
11891   | Xml.Element ("grammar", _,
11892                  Xml.Element ("start", _, gram) :: defines) ->
11893       (* The <define/> elements are referenced in the <start> section,
11894        * so build a map of those first.
11895        *)
11896       let defines = List.fold_left (
11897         fun map ->
11898           function Xml.Element ("define", ["name", name], defn) ->
11899             StringMap.add name defn map
11900           | _ ->
11901               failwithf "%s: expected <define name=name/>" rng_input
11902       ) StringMap.empty defines in
11903       let defines = StringMap.mapi parse_rng defines in
11904
11905       (* Parse the <start> clause, passing the defines. *)
11906       parse_rng ~defines "<start>" gram
11907   | _ ->
11908       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
11909         rng_input
11910
11911 let name_of_field = function
11912   | Element (name, _) | Attribute (name, _)
11913   | ZeroOrMore (Element (name, _))
11914   | OneOrMore (Element (name, _))
11915   | Optional (Element (name, _)) -> name
11916   | Optional (Attribute (name, _)) -> name
11917   | Text -> (* an unnamed field in an element *)
11918       "data"
11919   | rng ->
11920       failwithf "name_of_field failed at: %s" (string_of_rng rng)
11921
11922 (* At the moment this function only generates OCaml types.  However we
11923  * should parameterize it later so it can generate types/structs in a
11924  * variety of languages.
11925  *)
11926 let generate_types xs =
11927   (* A simple type is one that can be printed out directly, eg.
11928    * "string option".  A complex type is one which has a name and has
11929    * to be defined via another toplevel definition, eg. a struct.
11930    *
11931    * generate_type generates code for either simple or complex types.
11932    * In the simple case, it returns the string ("string option").  In
11933    * the complex case, it returns the name ("mountpoint").  In the
11934    * complex case it has to print out the definition before returning,
11935    * so it should only be called when we are at the beginning of a
11936    * new line (BOL context).
11937    *)
11938   let rec generate_type = function
11939     | Text ->                                (* string *)
11940         "string", true
11941     | Choice values ->                        (* [`val1|`val2|...] *)
11942         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
11943     | ZeroOrMore rng ->                        (* <rng> list *)
11944         let t, is_simple = generate_type rng in
11945         t ^ " list (* 0 or more *)", is_simple
11946     | OneOrMore rng ->                        (* <rng> list *)
11947         let t, is_simple = generate_type rng in
11948         t ^ " list (* 1 or more *)", is_simple
11949                                         (* virt-inspector hack: bool *)
11950     | Optional (Attribute (name, [Value "1"])) ->
11951         "bool", true
11952     | Optional rng ->                        (* <rng> list *)
11953         let t, is_simple = generate_type rng in
11954         t ^ " option", is_simple
11955                                         (* type name = { fields ... } *)
11956     | Element (name, fields) when is_attrs_interleave fields ->
11957         generate_type_struct name (get_attrs_interleave fields)
11958     | Element (name, [field])                (* type name = field *)
11959     | Attribute (name, [field]) ->
11960         let t, is_simple = generate_type field in
11961         if is_simple then (t, true)
11962         else (
11963           pr "type %s = %s\n" name t;
11964           name, false
11965         )
11966     | Element (name, fields) ->              (* type name = { fields ... } *)
11967         generate_type_struct name fields
11968     | rng ->
11969         failwithf "generate_type failed at: %s" (string_of_rng rng)
11970
11971   and is_attrs_interleave = function
11972     | [Interleave _] -> true
11973     | Attribute _ :: fields -> is_attrs_interleave fields
11974     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11975     | _ -> false
11976
11977   and get_attrs_interleave = function
11978     | [Interleave fields] -> fields
11979     | ((Attribute _) as field) :: fields
11980     | ((Optional (Attribute _)) as field) :: fields ->
11981         field :: get_attrs_interleave fields
11982     | _ -> assert false
11983
11984   and generate_types xs =
11985     List.iter (fun x -> ignore (generate_type x)) xs
11986
11987   and generate_type_struct name fields =
11988     (* Calculate the types of the fields first.  We have to do this
11989      * before printing anything so we are still in BOL context.
11990      *)
11991     let types = List.map fst (List.map generate_type fields) in
11992
11993     (* Special case of a struct containing just a string and another
11994      * field.  Turn it into an assoc list.
11995      *)
11996     match types with
11997     | ["string"; other] ->
11998         let fname1, fname2 =
11999           match fields with
12000           | [f1; f2] -> name_of_field f1, name_of_field f2
12001           | _ -> assert false in
12002         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
12003         name, false
12004
12005     | types ->
12006         pr "type %s = {\n" name;
12007         List.iter (
12008           fun (field, ftype) ->
12009             let fname = name_of_field field in
12010             pr "  %s_%s : %s;\n" name fname ftype
12011         ) (List.combine fields types);
12012         pr "}\n";
12013         (* Return the name of this type, and
12014          * false because it's not a simple type.
12015          *)
12016         name, false
12017   in
12018
12019   generate_types xs
12020
12021 let generate_parsers xs =
12022   (* As for generate_type above, generate_parser makes a parser for
12023    * some type, and returns the name of the parser it has generated.
12024    * Because it (may) need to print something, it should always be
12025    * called in BOL context.
12026    *)
12027   let rec generate_parser = function
12028     | Text ->                                (* string *)
12029         "string_child_or_empty"
12030     | Choice values ->                        (* [`val1|`val2|...] *)
12031         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
12032           (String.concat "|"
12033              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
12034     | ZeroOrMore rng ->                        (* <rng> list *)
12035         let pa = generate_parser rng in
12036         sprintf "(fun x -> List.map %s (Xml.children x))" pa
12037     | OneOrMore rng ->                        (* <rng> list *)
12038         let pa = generate_parser rng in
12039         sprintf "(fun x -> List.map %s (Xml.children x))" pa
12040                                         (* virt-inspector hack: bool *)
12041     | Optional (Attribute (name, [Value "1"])) ->
12042         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
12043     | Optional rng ->                        (* <rng> list *)
12044         let pa = generate_parser rng in
12045         sprintf "(function None -> None | Some x -> Some (%s x))" pa
12046                                         (* type name = { fields ... } *)
12047     | Element (name, fields) when is_attrs_interleave fields ->
12048         generate_parser_struct name (get_attrs_interleave fields)
12049     | Element (name, [field]) ->        (* type name = field *)
12050         let pa = generate_parser field in
12051         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12052         pr "let %s =\n" parser_name;
12053         pr "  %s\n" pa;
12054         pr "let parse_%s = %s\n" name parser_name;
12055         parser_name
12056     | Attribute (name, [field]) ->
12057         let pa = generate_parser field in
12058         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
12059         pr "let %s =\n" parser_name;
12060         pr "  %s\n" pa;
12061         pr "let parse_%s = %s\n" name parser_name;
12062         parser_name
12063     | Element (name, fields) ->              (* type name = { fields ... } *)
12064         generate_parser_struct name ([], fields)
12065     | rng ->
12066         failwithf "generate_parser failed at: %s" (string_of_rng rng)
12067
12068   and is_attrs_interleave = function
12069     | [Interleave _] -> true
12070     | Attribute _ :: fields -> is_attrs_interleave fields
12071     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
12072     | _ -> false
12073
12074   and get_attrs_interleave = function
12075     | [Interleave fields] -> [], fields
12076     | ((Attribute _) as field) :: fields
12077     | ((Optional (Attribute _)) as field) :: fields ->
12078         let attrs, interleaves = get_attrs_interleave fields in
12079         (field :: attrs), interleaves
12080     | _ -> assert false
12081
12082   and generate_parsers xs =
12083     List.iter (fun x -> ignore (generate_parser x)) xs
12084
12085   and generate_parser_struct name (attrs, interleaves) =
12086     (* Generate parsers for the fields first.  We have to do this
12087      * before printing anything so we are still in BOL context.
12088      *)
12089     let fields = attrs @ interleaves in
12090     let pas = List.map generate_parser fields in
12091
12092     (* Generate an intermediate tuple from all the fields first.
12093      * If the type is just a string + another field, then we will
12094      * return this directly, otherwise it is turned into a record.
12095      *
12096      * RELAX NG note: This code treats <interleave> and plain lists of
12097      * fields the same.  In other words, it doesn't bother enforcing
12098      * any ordering of fields in the XML.
12099      *)
12100     pr "let parse_%s x =\n" name;
12101     pr "  let t = (\n    ";
12102     let comma = ref false in
12103     List.iter (
12104       fun x ->
12105         if !comma then pr ",\n    ";
12106         comma := true;
12107         match x with
12108         | Optional (Attribute (fname, [field])), pa ->
12109             pr "%s x" pa
12110         | Optional (Element (fname, [field])), pa ->
12111             pr "%s (optional_child %S x)" pa fname
12112         | Attribute (fname, [Text]), _ ->
12113             pr "attribute %S x" fname
12114         | (ZeroOrMore _ | OneOrMore _), pa ->
12115             pr "%s x" pa
12116         | Text, pa ->
12117             pr "%s x" pa
12118         | (field, pa) ->
12119             let fname = name_of_field field in
12120             pr "%s (child %S x)" pa fname
12121     ) (List.combine fields pas);
12122     pr "\n  ) in\n";
12123
12124     (match fields with
12125      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
12126          pr "  t\n"
12127
12128      | _ ->
12129          pr "  (Obj.magic t : %s)\n" name
12130 (*
12131          List.iter (
12132            function
12133            | (Optional (Attribute (fname, [field])), pa) ->
12134                pr "  %s_%s =\n" name fname;
12135                pr "    %s x;\n" pa
12136            | (Optional (Element (fname, [field])), pa) ->
12137                pr "  %s_%s =\n" name fname;
12138                pr "    (let x = optional_child %S x in\n" fname;
12139                pr "     %s x);\n" pa
12140            | (field, pa) ->
12141                let fname = name_of_field field in
12142                pr "  %s_%s =\n" name fname;
12143                pr "    (let x = child %S x in\n" fname;
12144                pr "     %s x);\n" pa
12145          ) (List.combine fields pas);
12146          pr "}\n"
12147 *)
12148     );
12149     sprintf "parse_%s" name
12150   in
12151
12152   generate_parsers xs
12153
12154 (* Generate ocaml/guestfs_inspector.mli. *)
12155 let generate_ocaml_inspector_mli () =
12156   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12157
12158   pr "\
12159 (** This is an OCaml language binding to the external [virt-inspector]
12160     program.
12161
12162     For more information, please read the man page [virt-inspector(1)].
12163 *)
12164
12165 ";
12166
12167   generate_types grammar;
12168   pr "(** The nested information returned from the {!inspect} function. *)\n";
12169   pr "\n";
12170
12171   pr "\
12172 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
12173 (** To inspect a libvirt domain called [name], pass a singleton
12174     list: [inspect [name]].  When using libvirt only, you may
12175     optionally pass a libvirt URI using [inspect ~connect:uri ...].
12176
12177     To inspect a disk image or images, pass a list of the filenames
12178     of the disk images: [inspect filenames]
12179
12180     This function inspects the given guest or disk images and
12181     returns a list of operating system(s) found and a large amount
12182     of information about them.  In the vast majority of cases,
12183     a virtual machine only contains a single operating system.
12184
12185     If the optional [~xml] parameter is given, then this function
12186     skips running the external virt-inspector program and just
12187     parses the given XML directly (which is expected to be XML
12188     produced from a previous run of virt-inspector).  The list of
12189     names and connect URI are ignored in this case.
12190
12191     This function can throw a wide variety of exceptions, for example
12192     if the external virt-inspector program cannot be found, or if
12193     it doesn't generate valid XML.
12194 *)
12195 "
12196
12197 (* Generate ocaml/guestfs_inspector.ml. *)
12198 let generate_ocaml_inspector_ml () =
12199   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
12200
12201   pr "open Unix\n";
12202   pr "\n";
12203
12204   generate_types grammar;
12205   pr "\n";
12206
12207   pr "\
12208 (* Misc functions which are used by the parser code below. *)
12209 let first_child = function
12210   | Xml.Element (_, _, c::_) -> c
12211   | Xml.Element (name, _, []) ->
12212       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
12213   | Xml.PCData str ->
12214       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12215
12216 let string_child_or_empty = function
12217   | Xml.Element (_, _, [Xml.PCData s]) -> s
12218   | Xml.Element (_, _, []) -> \"\"
12219   | Xml.Element (x, _, _) ->
12220       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
12221                 x ^ \" instead\")
12222   | Xml.PCData str ->
12223       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
12224
12225 let optional_child name xml =
12226   let children = Xml.children xml in
12227   try
12228     Some (List.find (function
12229                      | Xml.Element (n, _, _) when n = name -> true
12230                      | _ -> false) children)
12231   with
12232     Not_found -> None
12233
12234 let child name xml =
12235   match optional_child name xml with
12236   | Some c -> c
12237   | None ->
12238       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
12239
12240 let attribute name xml =
12241   try Xml.attrib xml name
12242   with Xml.No_attribute _ ->
12243     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
12244
12245 ";
12246
12247   generate_parsers grammar;
12248   pr "\n";
12249
12250   pr "\
12251 (* Run external virt-inspector, then use parser to parse the XML. *)
12252 let inspect ?connect ?xml names =
12253   let xml =
12254     match xml with
12255     | None ->
12256         if names = [] then invalid_arg \"inspect: no names given\";
12257         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
12258           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
12259           names in
12260         let cmd = List.map Filename.quote cmd in
12261         let cmd = String.concat \" \" cmd in
12262         let chan = open_process_in cmd in
12263         let xml = Xml.parse_in chan in
12264         (match close_process_in chan with
12265          | WEXITED 0 -> ()
12266          | WEXITED _ -> failwith \"external virt-inspector command failed\"
12267          | WSIGNALED i | WSTOPPED i ->
12268              failwith (\"external virt-inspector command died or stopped on sig \" ^
12269                        string_of_int i)
12270         );
12271         xml
12272     | Some doc ->
12273         Xml.parse_string doc in
12274   parse_operatingsystems xml
12275 "
12276
12277 and generate_max_proc_nr () =
12278   pr "%d\n" max_proc_nr
12279
12280 let output_to filename k =
12281   let filename_new = filename ^ ".new" in
12282   chan := open_out filename_new;
12283   k ();
12284   close_out !chan;
12285   chan := Pervasives.stdout;
12286
12287   (* Is the new file different from the current file? *)
12288   if Sys.file_exists filename && files_equal filename filename_new then
12289     unlink filename_new                 (* same, so skip it *)
12290   else (
12291     (* different, overwrite old one *)
12292     (try chmod filename 0o644 with Unix_error _ -> ());
12293     rename filename_new filename;
12294     chmod filename 0o444;
12295     printf "written %s\n%!" filename;
12296   )
12297
12298 let perror msg = function
12299   | Unix_error (err, _, _) ->
12300       eprintf "%s: %s\n" msg (error_message err)
12301   | exn ->
12302       eprintf "%s: %s\n" msg (Printexc.to_string exn)
12303
12304 (* Main program. *)
12305 let () =
12306   let lock_fd =
12307     try openfile "HACKING" [O_RDWR] 0
12308     with
12309     | Unix_error (ENOENT, _, _) ->
12310         eprintf "\
12311 You are probably running this from the wrong directory.
12312 Run it from the top source directory using the command
12313   src/generator.ml
12314 ";
12315         exit 1
12316     | exn ->
12317         perror "open: HACKING" exn;
12318         exit 1 in
12319
12320   (* Acquire a lock so parallel builds won't try to run the generator
12321    * twice at the same time.  Subsequent builds will wait for the first
12322    * one to finish.  Note the lock is released implicitly when the
12323    * program exits.
12324    *)
12325   (try lockf lock_fd F_LOCK 1
12326    with exn ->
12327      perror "lock: HACKING" exn;
12328      exit 1);
12329
12330   check_functions ();
12331
12332   output_to "src/guestfs_protocol.x" generate_xdr;
12333   output_to "src/guestfs-structs.h" generate_structs_h;
12334   output_to "src/guestfs-actions.h" generate_actions_h;
12335   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
12336   output_to "src/actions.c" generate_client_actions;
12337   output_to "src/bindtests.c" generate_bindtests;
12338   output_to "src/guestfs-structs.pod" generate_structs_pod;
12339   output_to "src/guestfs-actions.pod" generate_actions_pod;
12340   output_to "src/guestfs-availability.pod" generate_availability_pod;
12341   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
12342   output_to "src/libguestfs.syms" generate_linker_script;
12343   output_to "daemon/actions.h" generate_daemon_actions_h;
12344   output_to "daemon/stubs.c" generate_daemon_actions;
12345   output_to "daemon/names.c" generate_daemon_names;
12346   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
12347   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
12348   output_to "capitests/tests.c" generate_tests;
12349   output_to "fish/cmds.c" generate_fish_cmds;
12350   output_to "fish/completion.c" generate_fish_completion;
12351   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
12352   output_to "fish/prepopts.c" generate_fish_prep_options_c;
12353   output_to "fish/prepopts.h" generate_fish_prep_options_h;
12354   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
12355   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
12356   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
12357   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
12358   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
12359   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
12360   output_to "perl/Guestfs.xs" generate_perl_xs;
12361   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
12362   output_to "perl/bindtests.pl" generate_perl_bindtests;
12363   output_to "python/guestfs-py.c" generate_python_c;
12364   output_to "python/guestfs.py" generate_python_py;
12365   output_to "python/bindtests.py" generate_python_bindtests;
12366   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
12367   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
12368   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
12369
12370   List.iter (
12371     fun (typ, jtyp) ->
12372       let cols = cols_of_struct typ in
12373       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
12374       output_to filename (generate_java_struct jtyp cols);
12375   ) java_structs;
12376
12377   output_to "java/Makefile.inc" generate_java_makefile_inc;
12378   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
12379   output_to "java/Bindtests.java" generate_java_bindtests;
12380   output_to "haskell/Guestfs.hs" generate_haskell_hs;
12381   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
12382   output_to "csharp/Libguestfs.cs" generate_csharp;
12383
12384   (* Always generate this file last, and unconditionally.  It's used
12385    * by the Makefile to know when we must re-run the generator.
12386    *)
12387   let chan = open_out "src/stamp-generator" in
12388   fprintf chan "1\n";
12389   close_out chan;
12390
12391   printf "generated %d lines of code\n" !lines