Turn ProtocolLimitWarning into link to documentation section.
[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 #load "xml-light.cma";;
46
47 open Unix
48 open Printf
49
50 type style = ret * args
51 and ret =
52     (* "RErr" as a return value means an int used as a simple error
53      * indication, ie. 0 or -1.
54      *)
55   | RErr
56
57     (* "RInt" as a return value means an int which is -1 for error
58      * or any value >= 0 on success.  Only use this for smallish
59      * positive ints (0 <= i < 2^30).
60      *)
61   | RInt of string
62
63     (* "RInt64" is the same as RInt, but is guaranteed to be able
64      * to return a full 64 bit value, _except_ that -1 means error
65      * (so -1 cannot be a valid, non-error return value).
66      *)
67   | RInt64 of string
68
69     (* "RBool" is a bool return value which can be true/false or
70      * -1 for error.
71      *)
72   | RBool of string
73
74     (* "RConstString" is a string that refers to a constant value.
75      * The return value must NOT be NULL (since NULL indicates
76      * an error).
77      *
78      * Try to avoid using this.  In particular you cannot use this
79      * for values returned from the daemon, because there is no
80      * thread-safe way to return them in the C API.
81      *)
82   | RConstString of string
83
84     (* "RConstOptString" is an even more broken version of
85      * "RConstString".  The returned string may be NULL and there
86      * is no way to return an error indication.  Avoid using this!
87      *)
88   | RConstOptString of string
89
90     (* "RString" is a returned string.  It must NOT be NULL, since
91      * a NULL return indicates an error.  The caller frees this.
92      *)
93   | RString of string
94
95     (* "RStringList" is a list of strings.  No string in the list
96      * can be NULL.  The caller frees the strings and the array.
97      *)
98   | RStringList of string
99
100     (* "RStruct" is a function which returns a single named structure
101      * or an error indication (in C, a struct, and in other languages
102      * with varying representations, but usually very efficient).  See
103      * after the function list below for the structures.
104      *)
105   | RStruct of string * string          (* name of retval, name of struct *)
106
107     (* "RStructList" is a function which returns either a list/array
108      * of structures (could be zero-length), or an error indication.
109      *)
110   | RStructList of string * string      (* name of retval, name of struct *)
111
112     (* Key-value pairs of untyped strings.  Turns into a hashtable or
113      * dictionary in languages which support it.  DON'T use this as a
114      * general "bucket" for results.  Prefer a stronger typed return
115      * value if one is available, or write a custom struct.  Don't use
116      * this if the list could potentially be very long, since it is
117      * inefficient.  Keys should be unique.  NULLs are not permitted.
118      *)
119   | RHashtable of string
120
121     (* "RBufferOut" is handled almost exactly like RString, but
122      * it allows the string to contain arbitrary 8 bit data including
123      * ASCII NUL.  In the C API this causes an implicit extra parameter
124      * to be added of type <size_t *size_r>.  The extra parameter
125      * returns the actual size of the return buffer in bytes.
126      *
127      * Other programming languages support strings with arbitrary 8 bit
128      * data.
129      *
130      * At the RPC layer we have to use the opaque<> type instead of
131      * string<>.  Returned data is still limited to the max message
132      * size (ie. ~ 2 MB).
133      *)
134   | RBufferOut of string
135
136 and args = argt list    (* Function parameters, guestfs handle is implicit. *)
137
138     (* Note in future we should allow a "variable args" parameter as
139      * the final parameter, to allow commands like
140      *   chmod mode file [file(s)...]
141      * This is not implemented yet, but many commands (such as chmod)
142      * are currently defined with the argument order keeping this future
143      * possibility in mind.
144      *)
145 and argt =
146   | String of string    (* const char *name, cannot be NULL *)
147   | Device of string    (* /dev device name, cannot be NULL *)
148   | Pathname of string  (* file name, cannot be NULL *)
149   | Dev_or_Path of string (* /dev device name or Pathname, cannot be NULL *)
150   | OptString of string (* const char *name, may be NULL *)
151   | StringList of string(* list of strings (each string cannot be NULL) *)
152   | DeviceList of string(* list of Device names (each cannot be NULL) *)
153   | Bool of string      (* boolean *)
154   | Int of string       (* int (smallish ints, signed, <= 31 bits) *)
155   | Int64 of string     (* any 64 bit int *)
156     (* These are treated as filenames (simple string parameters) in
157      * the C API and bindings.  But in the RPC protocol, we transfer
158      * the actual file content up to or down from the daemon.
159      * FileIn: local machine -> daemon (in request)
160      * FileOut: daemon -> local machine (in reply)
161      * In guestfish (only), the special name "-" means read from
162      * stdin or write to stdout.
163      *)
164   | FileIn of string
165   | FileOut of string
166 (* Not implemented:
167     (* Opaque buffer which can contain arbitrary 8 bit data.
168      * In the C API, this is expressed as <char *, int> 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
179 type flags =
180   | ProtocolLimitWarning  (* display warning about protocol size limits *)
181   | DangerWillRobinson    (* flags particularly dangerous commands *)
182   | FishAlias of string   (* provide an alias for this cmd in guestfish *)
183   | FishAction of string  (* call this function in guestfish *)
184   | NotInFish             (* do not export via guestfish *)
185   | NotInDocs             (* do not add this function to documentation *)
186   | DeprecatedBy of string (* function is deprecated, use .. instead *)
187   | Optional of string    (* function is part of an optional group *)
188
189 (* You can supply zero or as many tests as you want per API call.
190  *
191  * Note that the test environment has 3 block devices, of size 500MB,
192  * 50MB and 10MB (respectively /dev/sda, /dev/sdb, /dev/sdc), and
193  * a fourth ISO block device with some known files on it (/dev/sdd).
194  *
195  * Note for partitioning purposes, the 500MB device has 1015 cylinders.
196  * Number of cylinders was 63 for IDE emulated disks with precisely
197  * the same size.  How exactly this is calculated is a mystery.
198  *
199  * The ISO block device (/dev/sdd) comes from images/test.iso.
200  *
201  * To be able to run the tests in a reasonable amount of time,
202  * the virtual machine and block devices are reused between tests.
203  * So don't try testing kill_subprocess :-x
204  *
205  * Between each test we blockdev-setrw, umount-all, lvm-remove-all.
206  *
207  * Don't assume anything about the previous contents of the block
208  * devices.  Use 'Init*' to create some initial scenarios.
209  *
210  * You can add a prerequisite clause to any individual test.  This
211  * is a run-time check, which, if it fails, causes the test to be
212  * skipped.  Useful if testing a command which might not work on
213  * all variations of libguestfs builds.  A test that has prerequisite
214  * of 'Always' is run unconditionally.
215  *
216  * In addition, packagers can skip individual tests by setting the
217  * environment variables:     eg:
218  *   SKIP_TEST_<CMD>_<NUM>=1  SKIP_TEST_COMMAND_3=1  (skips test #3 of command)
219  *   SKIP_TEST_<CMD>=1        SKIP_TEST_ZEROFREE=1   (skips all zerofree tests)
220  *)
221 type tests = (test_init * test_prereq * test) list
222 and test =
223     (* Run the command sequence and just expect nothing to fail. *)
224   | TestRun of seq
225
226     (* Run the command sequence and expect the output of the final
227      * command to be the string.
228      *)
229   | TestOutput of seq * string
230
231     (* Run the command sequence and expect the output of the final
232      * command to be the list of strings.
233      *)
234   | TestOutputList of seq * string list
235
236     (* Run the command sequence and expect the output of the final
237      * command to be the list of block devices (could be either
238      * "/dev/sd.." or "/dev/hd.." form - we don't check the 5th
239      * character of each string).
240      *)
241   | TestOutputListOfDevices of seq * string list
242
243     (* Run the command sequence and expect the output of the final
244      * command to be the integer.
245      *)
246   | TestOutputInt of seq * int
247
248     (* Run the command sequence and expect the output of the final
249      * command to be <op> <int>, eg. ">=", "1".
250      *)
251   | TestOutputIntOp of seq * string * int
252
253     (* Run the command sequence and expect the output of the final
254      * command to be a true value (!= 0 or != NULL).
255      *)
256   | TestOutputTrue of seq
257
258     (* Run the command sequence and expect the output of the final
259      * command to be a false value (== 0 or == NULL, but not an error).
260      *)
261   | TestOutputFalse of seq
262
263     (* Run the command sequence and expect the output of the final
264      * command to be a list of the given length (but don't care about
265      * content).
266      *)
267   | TestOutputLength of seq * int
268
269     (* Run the command sequence and expect the output of the final
270      * command to be a buffer (RBufferOut), ie. string + size.
271      *)
272   | TestOutputBuffer of seq * string
273
274     (* Run the command sequence and expect the output of the final
275      * command to be a structure.
276      *)
277   | TestOutputStruct of seq * test_field_compare list
278
279     (* Run the command sequence and expect the final command (only)
280      * to fail.
281      *)
282   | TestLastFail of seq
283
284 and test_field_compare =
285   | CompareWithInt of string * int
286   | CompareWithIntOp of string * string * int
287   | CompareWithString of string * string
288   | CompareFieldsIntEq of string * string
289   | CompareFieldsStrEq of string * string
290
291 (* Test prerequisites. *)
292 and test_prereq =
293     (* Test always runs. *)
294   | Always
295
296     (* Test is currently disabled - eg. it fails, or it tests some
297      * unimplemented feature.
298      *)
299   | Disabled
300
301     (* 'string' is some C code (a function body) that should return
302      * true or false.  The test will run if the code returns true.
303      *)
304   | If of string
305
306     (* As for 'If' but the test runs _unless_ the code returns true. *)
307   | Unless of string
308
309 (* Some initial scenarios for testing. *)
310 and test_init =
311     (* Do nothing, block devices could contain random stuff including
312      * LVM PVs, and some filesystems might be mounted.  This is usually
313      * a bad idea.
314      *)
315   | InitNone
316
317     (* Block devices are empty and no filesystems are mounted. *)
318   | InitEmpty
319
320     (* /dev/sda contains a single partition /dev/sda1, with random
321      * content.  /dev/sdb and /dev/sdc may have random content.
322      * No LVM.
323      *)
324   | InitPartition
325
326     (* /dev/sda contains a single partition /dev/sda1, which is formatted
327      * as ext2, empty [except for lost+found] and mounted on /.
328      * /dev/sdb and /dev/sdc may have random content.
329      * No LVM.
330      *)
331   | InitBasicFS
332
333     (* /dev/sda:
334      *   /dev/sda1 (is a PV):
335      *     /dev/VG/LV (size 8MB):
336      *       formatted as ext2, empty [except for lost+found], mounted on /
337      * /dev/sdb and /dev/sdc may have random content.
338      *)
339   | InitBasicFSonLVM
340
341     (* /dev/sdd (the ISO, see images/ directory in source)
342      * is mounted on /
343      *)
344   | InitISOFS
345
346 (* Sequence of commands for testing. *)
347 and seq = cmd list
348 and cmd = string list
349
350 (* Note about long descriptions: When referring to another
351  * action, use the format C<guestfs_other> (ie. the full name of
352  * the C function).  This will be replaced as appropriate in other
353  * language bindings.
354  *
355  * Apart from that, long descriptions are just perldoc paragraphs.
356  *)
357
358 (* Generate a random UUID (used in tests). *)
359 let uuidgen () =
360   let chan = open_process_in "uuidgen" in
361   let uuid = input_line chan in
362   (match close_process_in chan with
363    | WEXITED 0 -> ()
364    | WEXITED _ ->
365        failwith "uuidgen: process exited with non-zero status"
366    | WSIGNALED _ | WSTOPPED _ ->
367        failwith "uuidgen: process signalled or stopped by signal"
368   );
369   uuid
370
371 (* These test functions are used in the language binding tests. *)
372
373 let test_all_args = [
374   String "str";
375   OptString "optstr";
376   StringList "strlist";
377   Bool "b";
378   Int "integer";
379   Int64 "integer64";
380   FileIn "filein";
381   FileOut "fileout";
382 ]
383
384 let test_all_rets = [
385   (* except for RErr, which is tested thoroughly elsewhere *)
386   "test0rint",         RInt "valout";
387   "test0rint64",       RInt64 "valout";
388   "test0rbool",        RBool "valout";
389   "test0rconststring", RConstString "valout";
390   "test0rconstoptstring", RConstOptString "valout";
391   "test0rstring",      RString "valout";
392   "test0rstringlist",  RStringList "valout";
393   "test0rstruct",      RStruct ("valout", "lvm_pv");
394   "test0rstructlist",  RStructList ("valout", "lvm_pv");
395   "test0rhashtable",   RHashtable "valout";
396 ]
397
398 let test_functions = [
399   ("test0", (RErr, test_all_args), -1, [NotInFish; NotInDocs],
400    [],
401    "internal test function - do not use",
402    "\
403 This is an internal test function which is used to test whether
404 the automatically generated bindings can handle every possible
405 parameter type correctly.
406
407 It echos the contents of each parameter to stdout.
408
409 You probably don't want to call this function.");
410 ] @ List.flatten (
411   List.map (
412     fun (name, ret) ->
413       [(name, (ret, [String "val"]), -1, [NotInFish; NotInDocs],
414         [],
415         "internal test function - do not use",
416         "\
417 This is an internal test function which is used to test whether
418 the automatically generated bindings can handle every possible
419 return type correctly.
420
421 It converts string C<val> to the return type.
422
423 You probably don't want to call this function.");
424        (name ^ "err", (ret, []), -1, [NotInFish; NotInDocs],
425         [],
426         "internal test function - do not use",
427         "\
428 This is an internal test function which is used to test whether
429 the automatically generated bindings can handle every possible
430 return type correctly.
431
432 This function always returns an error.
433
434 You probably don't want to call this function.")]
435   ) test_all_rets
436 )
437
438 (* non_daemon_functions are any functions which don't get processed
439  * in the daemon, eg. functions for setting and getting local
440  * configuration values.
441  *)
442
443 let non_daemon_functions = test_functions @ [
444   ("launch", (RErr, []), -1, [FishAlias "run"; FishAction "launch"],
445    [],
446    "launch the qemu subprocess",
447    "\
448 Internally libguestfs is implemented by running a virtual machine
449 using L<qemu(1)>.
450
451 You should call this after configuring the handle
452 (eg. adding drives) but before performing any actions.");
453
454   ("wait_ready", (RErr, []), -1, [NotInFish],
455    [],
456    "wait until the qemu subprocess launches (no op)",
457    "\
458 This function is a no op.
459
460 In versions of the API E<lt> 1.0.71 you had to call this function
461 just after calling C<guestfs_launch> to wait for the launch
462 to complete.  However this is no longer necessary because
463 C<guestfs_launch> now does the waiting.
464
465 If you see any calls to this function in code then you can just
466 remove them, unless you want to retain compatibility with older
467 versions of the API.");
468
469   ("kill_subprocess", (RErr, []), -1, [],
470    [],
471    "kill the qemu subprocess",
472    "\
473 This kills the qemu subprocess.  You should never need to call this.");
474
475   ("add_drive", (RErr, [String "filename"]), -1, [FishAlias "add"],
476    [],
477    "add an image to examine or modify",
478    "\
479 This function adds a virtual machine disk image C<filename> to the
480 guest.  The first time you call this function, the disk appears as IDE
481 disk 0 (C</dev/sda>) in the guest, the second time as C</dev/sdb>, and
482 so on.
483
484 You don't necessarily need to be root when using libguestfs.  However
485 you obviously do need sufficient permissions to access the filename
486 for whatever operations you want to perform (ie. read access if you
487 just want to read the image or write access if you want to modify the
488 image).
489
490 This is equivalent to the qemu parameter
491 C<-drive file=filename,cache=off,if=...>.
492
493 C<cache=off> is omitted in cases where it is not supported by
494 the underlying filesystem.
495
496 C<if=...> is set at compile time by the configuration option
497 C<./configure --with-drive-if=...>.  In the rare case where you
498 might need to change this at run time, use C<guestfs_add_drive_with_if>
499 or C<guestfs_add_drive_ro_with_if>.
500
501 Note that this call checks for the existence of C<filename>.  This
502 stops you from specifying other types of drive which are supported
503 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
504 the general C<guestfs_config> call instead.");
505
506   ("add_cdrom", (RErr, [String "filename"]), -1, [FishAlias "cdrom"],
507    [],
508    "add a CD-ROM disk image to examine",
509    "\
510 This function adds a virtual CD-ROM disk image to the guest.
511
512 This is equivalent to the qemu parameter C<-cdrom filename>.
513
514 Notes:
515
516 =over 4
517
518 =item *
519
520 This call checks for the existence of C<filename>.  This
521 stops you from specifying other types of drive which are supported
522 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
523 the general C<guestfs_config> call instead.
524
525 =item *
526
527 If you just want to add an ISO file (often you use this as an
528 efficient way to transfer large files into the guest), then you
529 should probably use C<guestfs_add_drive_ro> instead.
530
531 =back");
532
533   ("add_drive_ro", (RErr, [String "filename"]), -1, [FishAlias "add-ro"],
534    [],
535    "add a drive in snapshot mode (read-only)",
536    "\
537 This adds a drive in snapshot mode, making it effectively
538 read-only.
539
540 Note that writes to the device are allowed, and will be seen for
541 the duration of the guestfs handle, but they are written
542 to a temporary file which is discarded as soon as the guestfs
543 handle is closed.  We don't currently have any method to enable
544 changes to be committed, although qemu can support this.
545
546 This is equivalent to the qemu parameter
547 C<-drive file=filename,snapshot=on,if=...>.
548
549 C<if=...> is set at compile time by the configuration option
550 C<./configure --with-drive-if=...>.  In the rare case where you
551 might need to change this at run time, use C<guestfs_add_drive_with_if>
552 or C<guestfs_add_drive_ro_with_if>.
553
554 Note that this call checks for the existence of C<filename>.  This
555 stops you from specifying other types of drive which are supported
556 by qemu such as C<nbd:> and C<http:> URLs.  To specify those, use
557 the general C<guestfs_config> call instead.");
558
559   ("config", (RErr, [String "qemuparam"; OptString "qemuvalue"]), -1, [],
560    [],
561    "add qemu parameters",
562    "\
563 This can be used to add arbitrary qemu command line parameters
564 of the form C<-param value>.  Actually it's not quite arbitrary - we
565 prevent you from setting some parameters which would interfere with
566 parameters that we use.
567
568 The first character of C<param> string must be a C<-> (dash).
569
570 C<value> can be NULL.");
571
572   ("set_qemu", (RErr, [String "qemu"]), -1, [FishAlias "qemu"],
573    [],
574    "set the qemu binary",
575    "\
576 Set the qemu binary that we will use.
577
578 The default is chosen when the library was compiled by the
579 configure script.
580
581 You can also override this by setting the C<LIBGUESTFS_QEMU>
582 environment variable.
583
584 Setting C<qemu> to C<NULL> restores the default qemu binary.");
585
586   ("get_qemu", (RConstString "qemu", []), -1, [],
587    [InitNone, Always, TestRun (
588       [["get_qemu"]])],
589    "get the qemu binary",
590    "\
591 Return the current qemu binary.
592
593 This is always non-NULL.  If it wasn't set already, then this will
594 return the default qemu binary name.");
595
596   ("set_path", (RErr, [String "searchpath"]), -1, [FishAlias "path"],
597    [],
598    "set the search path",
599    "\
600 Set the path that libguestfs searches for kernel and initrd.img.
601
602 The default is C<$libdir/guestfs> unless overridden by setting
603 C<LIBGUESTFS_PATH> environment variable.
604
605 Setting C<path> to C<NULL> restores the default path.");
606
607   ("get_path", (RConstString "path", []), -1, [],
608    [InitNone, Always, TestRun (
609       [["get_path"]])],
610    "get the search path",
611    "\
612 Return the current search path.
613
614 This is always non-NULL.  If it wasn't set already, then this will
615 return the default path.");
616
617   ("set_append", (RErr, [OptString "append"]), -1, [FishAlias "append"],
618    [],
619    "add options to kernel command line",
620    "\
621 This function is used to add additional options to the
622 guest kernel command line.
623
624 The default is C<NULL> unless overridden by setting
625 C<LIBGUESTFS_APPEND> environment variable.
626
627 Setting C<append> to C<NULL> means I<no> additional options
628 are passed (libguestfs always adds a few of its own).");
629
630   ("get_append", (RConstOptString "append", []), -1, [],
631    (* This cannot be tested with the current framework.  The
632     * function can return NULL in normal operations, which the
633     * test framework interprets as an error.
634     *)
635    [],
636    "get the additional kernel options",
637    "\
638 Return the additional kernel options which are added to the
639 guest kernel command line.
640
641 If C<NULL> then no options are added.");
642
643   ("set_autosync", (RErr, [Bool "autosync"]), -1, [FishAlias "autosync"],
644    [],
645    "set autosync mode",
646    "\
647 If C<autosync> is true, this enables autosync.  Libguestfs will make a
648 best effort attempt to run C<guestfs_umount_all> followed by
649 C<guestfs_sync> when the handle is closed
650 (also if the program exits without closing handles).
651
652 This is disabled by default (except in guestfish where it is
653 enabled by default).");
654
655   ("get_autosync", (RBool "autosync", []), -1, [],
656    [InitNone, Always, TestRun (
657       [["get_autosync"]])],
658    "get autosync mode",
659    "\
660 Get the autosync flag.");
661
662   ("set_verbose", (RErr, [Bool "verbose"]), -1, [FishAlias "verbose"],
663    [],
664    "set verbose mode",
665    "\
666 If C<verbose> is true, this turns on verbose messages (to C<stderr>).
667
668 Verbose messages are disabled unless the environment variable
669 C<LIBGUESTFS_DEBUG> is defined and set to C<1>.");
670
671   ("get_verbose", (RBool "verbose", []), -1, [],
672    [],
673    "get verbose mode",
674    "\
675 This returns the verbose messages flag.");
676
677   ("is_ready", (RBool "ready", []), -1, [],
678    [InitNone, Always, TestOutputTrue (
679       [["is_ready"]])],
680    "is ready to accept commands",
681    "\
682 This returns true iff this handle is ready to accept commands
683 (in the C<READY> state).
684
685 For more information on states, see L<guestfs(3)>.");
686
687   ("is_config", (RBool "config", []), -1, [],
688    [InitNone, Always, TestOutputFalse (
689       [["is_config"]])],
690    "is in configuration state",
691    "\
692 This returns true iff this handle is being configured
693 (in the C<CONFIG> state).
694
695 For more information on states, see L<guestfs(3)>.");
696
697   ("is_launching", (RBool "launching", []), -1, [],
698    [InitNone, Always, TestOutputFalse (
699       [["is_launching"]])],
700    "is launching subprocess",
701    "\
702 This returns true iff this handle is launching the subprocess
703 (in the C<LAUNCHING> state).
704
705 For more information on states, see L<guestfs(3)>.");
706
707   ("is_busy", (RBool "busy", []), -1, [],
708    [InitNone, Always, TestOutputFalse (
709       [["is_busy"]])],
710    "is busy processing a command",
711    "\
712 This returns true iff this handle is busy processing a command
713 (in the C<BUSY> state).
714
715 For more information on states, see L<guestfs(3)>.");
716
717   ("get_state", (RInt "state", []), -1, [],
718    [],
719    "get the current state",
720    "\
721 This returns the current state as an opaque integer.  This is
722 only useful for printing debug and internal error messages.
723
724 For more information on states, see L<guestfs(3)>.");
725
726   ("set_memsize", (RErr, [Int "memsize"]), -1, [FishAlias "memsize"],
727    [InitNone, Always, TestOutputInt (
728       [["set_memsize"; "500"];
729        ["get_memsize"]], 500)],
730    "set memory allocated to the qemu subprocess",
731    "\
732 This sets the memory size in megabytes allocated to the
733 qemu subprocess.  This only has any effect if called before
734 C<guestfs_launch>.
735
736 You can also change this by setting the environment
737 variable C<LIBGUESTFS_MEMSIZE> before the handle is
738 created.
739
740 For more information on the architecture of libguestfs,
741 see L<guestfs(3)>.");
742
743   ("get_memsize", (RInt "memsize", []), -1, [],
744    [InitNone, Always, TestOutputIntOp (
745       [["get_memsize"]], ">=", 256)],
746    "get memory allocated to the qemu subprocess",
747    "\
748 This gets the memory size in megabytes allocated to the
749 qemu subprocess.
750
751 If C<guestfs_set_memsize> was not called
752 on this handle, and if C<LIBGUESTFS_MEMSIZE> was not set,
753 then this returns the compiled-in default value for memsize.
754
755 For more information on the architecture of libguestfs,
756 see L<guestfs(3)>.");
757
758   ("get_pid", (RInt "pid", []), -1, [FishAlias "pid"],
759    [InitNone, Always, TestOutputIntOp (
760       [["get_pid"]], ">=", 1)],
761    "get PID of qemu subprocess",
762    "\
763 Return the process ID of the qemu subprocess.  If there is no
764 qemu subprocess, then this will return an error.
765
766 This is an internal call used for debugging and testing.");
767
768   ("version", (RStruct ("version", "version"), []), -1, [],
769    [InitNone, Always, TestOutputStruct (
770       [["version"]], [CompareWithInt ("major", 1)])],
771    "get the library version number",
772    "\
773 Return the libguestfs version number that the program is linked
774 against.
775
776 Note that because of dynamic linking this is not necessarily
777 the version of libguestfs that you compiled against.  You can
778 compile the program, and then at runtime dynamically link
779 against a completely different C<libguestfs.so> library.
780
781 This call was added in version C<1.0.58>.  In previous
782 versions of libguestfs there was no way to get the version
783 number.  From C code you can use ELF weak linking tricks to find out if
784 this symbol exists (if it doesn't, then it's an earlier version).
785
786 The call returns a structure with four elements.  The first
787 three (C<major>, C<minor> and C<release>) are numbers and
788 correspond to the usual version triplet.  The fourth element
789 (C<extra>) is a string and is normally empty, but may be
790 used for distro-specific information.
791
792 To construct the original version string:
793 C<$major.$minor.$release$extra>
794
795 I<Note:> Don't use this call to test for availability
796 of features.  Distro backports makes this unreliable.  Use
797 C<guestfs_available> instead.");
798
799   ("set_selinux", (RErr, [Bool "selinux"]), -1, [FishAlias "selinux"],
800    [InitNone, Always, TestOutputTrue (
801       [["set_selinux"; "true"];
802        ["get_selinux"]])],
803    "set SELinux enabled or disabled at appliance boot",
804    "\
805 This sets the selinux flag that is passed to the appliance
806 at boot time.  The default is C<selinux=0> (disabled).
807
808 Note that if SELinux is enabled, it is always in
809 Permissive mode (C<enforcing=0>).
810
811 For more information on the architecture of libguestfs,
812 see L<guestfs(3)>.");
813
814   ("get_selinux", (RBool "selinux", []), -1, [],
815    [],
816    "get SELinux enabled flag",
817    "\
818 This returns the current setting of the selinux flag which
819 is passed to the appliance at boot time.  See C<guestfs_set_selinux>.
820
821 For more information on the architecture of libguestfs,
822 see L<guestfs(3)>.");
823
824   ("set_trace", (RErr, [Bool "trace"]), -1, [FishAlias "trace"],
825    [InitNone, Always, TestOutputFalse (
826       [["set_trace"; "false"];
827        ["get_trace"]])],
828    "enable or disable command traces",
829    "\
830 If the command trace flag is set to 1, then commands are
831 printed on stdout before they are executed in a format
832 which is very similar to the one used by guestfish.  In
833 other words, you can run a program with this enabled, and
834 you will get out a script which you can feed to guestfish
835 to perform the same set of actions.
836
837 If you want to trace C API calls into libguestfs (and
838 other libraries) then possibly a better way is to use
839 the external ltrace(1) command.
840
841 Command traces are disabled unless the environment variable
842 C<LIBGUESTFS_TRACE> is defined and set to C<1>.");
843
844   ("get_trace", (RBool "trace", []), -1, [],
845    [],
846    "get command trace enabled flag",
847    "\
848 Return the command trace flag.");
849
850   ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"],
851    [InitNone, Always, TestOutputFalse (
852       [["set_direct"; "false"];
853        ["get_direct"]])],
854    "enable or disable direct appliance mode",
855    "\
856 If the direct appliance mode flag is enabled, then stdin and
857 stdout are passed directly through to the appliance once it
858 is launched.
859
860 One consequence of this is that log messages aren't caught
861 by the library and handled by C<guestfs_set_log_message_callback>,
862 but go straight to stdout.
863
864 You probably don't want to use this unless you know what you
865 are doing.
866
867 The default is disabled.");
868
869   ("get_direct", (RBool "direct", []), -1, [],
870    [],
871    "get direct appliance mode flag",
872    "\
873 Return the direct appliance mode flag.");
874
875   ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
876    [InitNone, Always, TestOutputTrue (
877       [["set_recovery_proc"; "true"];
878        ["get_recovery_proc"]])],
879    "enable or disable the recovery process",
880    "\
881 If this is called with the parameter C<false> then
882 C<guestfs_launch> does not create a recovery process.  The
883 purpose of the recovery process is to stop runaway qemu
884 processes in the case where the main program aborts abruptly.
885
886 This only has any effect if called before C<guestfs_launch>,
887 and the default is true.
888
889 About the only time when you would want to disable this is
890 if the main process will fork itself into the background
891 (\"daemonize\" itself).  In this case the recovery process
892 thinks that the main program has disappeared and so kills
893 qemu, which is not very helpful.");
894
895   ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
896    [],
897    "get recovery process enabled flag",
898    "\
899 Return the recovery process enabled flag.");
900
901   ("add_drive_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
902    [],
903    "add a drive specifying the QEMU block emulation to use",
904    "\
905 This is the same as C<guestfs_add_drive> but it allows you
906 to specify the QEMU interface emulation to use at run time.");
907
908   ("add_drive_ro_with_if", (RErr, [String "filename"; String "iface"]), -1, [],
909    [],
910    "add a drive read-only specifying the QEMU block emulation to use",
911    "\
912 This is the same as C<guestfs_add_drive_ro> but it allows you
913 to specify the QEMU interface emulation to use at run time.");
914
915 ]
916
917 (* daemon_functions are any functions which cause some action
918  * to take place in the daemon.
919  *)
920
921 let daemon_functions = [
922   ("mount", (RErr, [Device "device"; String "mountpoint"]), 1, [],
923    [InitEmpty, Always, TestOutput (
924       [["part_disk"; "/dev/sda"; "mbr"];
925        ["mkfs"; "ext2"; "/dev/sda1"];
926        ["mount"; "/dev/sda1"; "/"];
927        ["write_file"; "/new"; "new file contents"; "0"];
928        ["cat"; "/new"]], "new file contents")],
929    "mount a guest disk at a position in the filesystem",
930    "\
931 Mount a guest disk at a position in the filesystem.  Block devices
932 are named C</dev/sda>, C</dev/sdb> and so on, as they were added to
933 the guest.  If those block devices contain partitions, they will have
934 the usual names (eg. C</dev/sda1>).  Also LVM C</dev/VG/LV>-style
935 names can be used.
936
937 The rules are the same as for L<mount(2)>:  A filesystem must
938 first be mounted on C</> before others can be mounted.  Other
939 filesystems can only be mounted on directories which already
940 exist.
941
942 The mounted filesystem is writable, if we have sufficient permissions
943 on the underlying device.
944
945 The filesystem options C<sync> and C<noatime> are set with this
946 call, in order to improve reliability.");
947
948   ("sync", (RErr, []), 2, [],
949    [ InitEmpty, Always, TestRun [["sync"]]],
950    "sync disks, writes are flushed through to the disk image",
951    "\
952 This syncs the disk, so that any writes are flushed through to the
953 underlying disk image.
954
955 You should always call this if you have modified a disk image, before
956 closing the handle.");
957
958   ("touch", (RErr, [Pathname "path"]), 3, [],
959    [InitBasicFS, Always, TestOutputTrue (
960       [["touch"; "/new"];
961        ["exists"; "/new"]])],
962    "update file timestamps or create a new file",
963    "\
964 Touch acts like the L<touch(1)> command.  It can be used to
965 update the timestamps on a file, or, if the file does not exist,
966 to create a new zero-length file.");
967
968   ("cat", (RString "content", [Pathname "path"]), 4, [ProtocolLimitWarning],
969    [InitISOFS, Always, TestOutput (
970       [["cat"; "/known-2"]], "abcdef\n")],
971    "list the contents of a file",
972    "\
973 Return the contents of the file named C<path>.
974
975 Note that this function cannot correctly handle binary files
976 (specifically, files containing C<\\0> character which is treated
977 as end of string).  For those you need to use the C<guestfs_read_file>
978 or C<guestfs_download> functions which have a more complex interface.");
979
980   ("ll", (RString "listing", [Pathname "directory"]), 5, [],
981    [], (* XXX Tricky to test because it depends on the exact format
982         * of the 'ls -l' command, which changes between F10 and F11.
983         *)
984    "list the files in a directory (long format)",
985    "\
986 List the files in C<directory> (relative to the root directory,
987 there is no cwd) in the format of 'ls -la'.
988
989 This command is mostly useful for interactive sessions.  It
990 is I<not> intended that you try to parse the output string.");
991
992   ("ls", (RStringList "listing", [Pathname "directory"]), 6, [],
993    [InitBasicFS, Always, TestOutputList (
994       [["touch"; "/new"];
995        ["touch"; "/newer"];
996        ["touch"; "/newest"];
997        ["ls"; "/"]], ["lost+found"; "new"; "newer"; "newest"])],
998    "list the files in a directory",
999    "\
1000 List the files in C<directory> (relative to the root directory,
1001 there is no cwd).  The '.' and '..' entries are not returned, but
1002 hidden files are shown.
1003
1004 This command is mostly useful for interactive sessions.  Programs
1005 should probably use C<guestfs_readdir> instead.");
1006
1007   ("list_devices", (RStringList "devices", []), 7, [],
1008    [InitEmpty, Always, TestOutputListOfDevices (
1009       [["list_devices"]], ["/dev/sda"; "/dev/sdb"; "/dev/sdc"; "/dev/sdd"])],
1010    "list the block devices",
1011    "\
1012 List all the block devices.
1013
1014 The full block device names are returned, eg. C</dev/sda>");
1015
1016   ("list_partitions", (RStringList "partitions", []), 8, [],
1017    [InitBasicFS, Always, TestOutputListOfDevices (
1018       [["list_partitions"]], ["/dev/sda1"]);
1019     InitEmpty, Always, TestOutputListOfDevices (
1020       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1021        ["list_partitions"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1022    "list the partitions",
1023    "\
1024 List all the partitions detected on all block devices.
1025
1026 The full partition device names are returned, eg. C</dev/sda1>
1027
1028 This does not return logical volumes.  For that you will need to
1029 call C<guestfs_lvs>.");
1030
1031   ("pvs", (RStringList "physvols", []), 9, [Optional "lvm2"],
1032    [InitBasicFSonLVM, Always, TestOutputListOfDevices (
1033       [["pvs"]], ["/dev/sda1"]);
1034     InitEmpty, Always, TestOutputListOfDevices (
1035       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1036        ["pvcreate"; "/dev/sda1"];
1037        ["pvcreate"; "/dev/sda2"];
1038        ["pvcreate"; "/dev/sda3"];
1039        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1040    "list the LVM physical volumes (PVs)",
1041    "\
1042 List all the physical volumes detected.  This is the equivalent
1043 of the L<pvs(8)> command.
1044
1045 This returns a list of just the device names that contain
1046 PVs (eg. C</dev/sda2>).
1047
1048 See also C<guestfs_pvs_full>.");
1049
1050   ("vgs", (RStringList "volgroups", []), 10, [Optional "lvm2"],
1051    [InitBasicFSonLVM, Always, TestOutputList (
1052       [["vgs"]], ["VG"]);
1053     InitEmpty, Always, TestOutputList (
1054       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1055        ["pvcreate"; "/dev/sda1"];
1056        ["pvcreate"; "/dev/sda2"];
1057        ["pvcreate"; "/dev/sda3"];
1058        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1059        ["vgcreate"; "VG2"; "/dev/sda3"];
1060        ["vgs"]], ["VG1"; "VG2"])],
1061    "list the LVM volume groups (VGs)",
1062    "\
1063 List all the volumes groups detected.  This is the equivalent
1064 of the L<vgs(8)> command.
1065
1066 This returns a list of just the volume group names that were
1067 detected (eg. C<VolGroup00>).
1068
1069 See also C<guestfs_vgs_full>.");
1070
1071   ("lvs", (RStringList "logvols", []), 11, [Optional "lvm2"],
1072    [InitBasicFSonLVM, Always, TestOutputList (
1073       [["lvs"]], ["/dev/VG/LV"]);
1074     InitEmpty, Always, TestOutputList (
1075       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1076        ["pvcreate"; "/dev/sda1"];
1077        ["pvcreate"; "/dev/sda2"];
1078        ["pvcreate"; "/dev/sda3"];
1079        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1080        ["vgcreate"; "VG2"; "/dev/sda3"];
1081        ["lvcreate"; "LV1"; "VG1"; "50"];
1082        ["lvcreate"; "LV2"; "VG1"; "50"];
1083        ["lvcreate"; "LV3"; "VG2"; "50"];
1084        ["lvs"]], ["/dev/VG1/LV1"; "/dev/VG1/LV2"; "/dev/VG2/LV3"])],
1085    "list the LVM logical volumes (LVs)",
1086    "\
1087 List all the logical volumes detected.  This is the equivalent
1088 of the L<lvs(8)> command.
1089
1090 This returns a list of the logical volume device names
1091 (eg. C</dev/VolGroup00/LogVol00>).
1092
1093 See also C<guestfs_lvs_full>.");
1094
1095   ("pvs_full", (RStructList ("physvols", "lvm_pv"), []), 12, [Optional "lvm2"],
1096    [], (* XXX how to test? *)
1097    "list the LVM physical volumes (PVs)",
1098    "\
1099 List all the physical volumes detected.  This is the equivalent
1100 of the L<pvs(8)> command.  The \"full\" version includes all fields.");
1101
1102   ("vgs_full", (RStructList ("volgroups", "lvm_vg"), []), 13, [Optional "lvm2"],
1103    [], (* XXX how to test? *)
1104    "list the LVM volume groups (VGs)",
1105    "\
1106 List all the volumes groups detected.  This is the equivalent
1107 of the L<vgs(8)> command.  The \"full\" version includes all fields.");
1108
1109   ("lvs_full", (RStructList ("logvols", "lvm_lv"), []), 14, [Optional "lvm2"],
1110    [], (* XXX how to test? *)
1111    "list the LVM logical volumes (LVs)",
1112    "\
1113 List all the logical volumes detected.  This is the equivalent
1114 of the L<lvs(8)> command.  The \"full\" version includes all fields.");
1115
1116   ("read_lines", (RStringList "lines", [Pathname "path"]), 15, [],
1117    [InitISOFS, Always, TestOutputList (
1118       [["read_lines"; "/known-4"]], ["abc"; "def"; "ghi"]);
1119     InitISOFS, Always, TestOutputList (
1120       [["read_lines"; "/empty"]], [])],
1121    "read file as lines",
1122    "\
1123 Return the contents of the file named C<path>.
1124
1125 The file contents are returned as a list of lines.  Trailing
1126 C<LF> and C<CRLF> character sequences are I<not> returned.
1127
1128 Note that this function cannot correctly handle binary files
1129 (specifically, files containing C<\\0> character which is treated
1130 as end of line).  For those you need to use the C<guestfs_read_file>
1131 function which has a more complex interface.");
1132
1133   ("aug_init", (RErr, [Pathname "root"; Int "flags"]), 16, [Optional "augeas"],
1134    [], (* XXX Augeas code needs tests. *)
1135    "create a new Augeas handle",
1136    "\
1137 Create a new Augeas handle for editing configuration files.
1138 If there was any previous Augeas handle associated with this
1139 guestfs session, then it is closed.
1140
1141 You must call this before using any other C<guestfs_aug_*>
1142 commands.
1143
1144 C<root> is the filesystem root.  C<root> must not be NULL,
1145 use C</> instead.
1146
1147 The flags are the same as the flags defined in
1148 E<lt>augeas.hE<gt>, the logical I<or> of the following
1149 integers:
1150
1151 =over 4
1152
1153 =item C<AUG_SAVE_BACKUP> = 1
1154
1155 Keep the original file with a C<.augsave> extension.
1156
1157 =item C<AUG_SAVE_NEWFILE> = 2
1158
1159 Save changes into a file with extension C<.augnew>, and
1160 do not overwrite original.  Overrides C<AUG_SAVE_BACKUP>.
1161
1162 =item C<AUG_TYPE_CHECK> = 4
1163
1164 Typecheck lenses (can be expensive).
1165
1166 =item C<AUG_NO_STDINC> = 8
1167
1168 Do not use standard load path for modules.
1169
1170 =item C<AUG_SAVE_NOOP> = 16
1171
1172 Make save a no-op, just record what would have been changed.
1173
1174 =item C<AUG_NO_LOAD> = 32
1175
1176 Do not load the tree in C<guestfs_aug_init>.
1177
1178 =back
1179
1180 To close the handle, you can call C<guestfs_aug_close>.
1181
1182 To find out more about Augeas, see L<http://augeas.net/>.");
1183
1184   ("aug_close", (RErr, []), 26, [Optional "augeas"],
1185    [], (* XXX Augeas code needs tests. *)
1186    "close the current Augeas handle",
1187    "\
1188 Close the current Augeas handle and free up any resources
1189 used by it.  After calling this, you have to call
1190 C<guestfs_aug_init> again before you can use any other
1191 Augeas functions.");
1192
1193   ("aug_defvar", (RInt "nrnodes", [String "name"; OptString "expr"]), 17, [Optional "augeas"],
1194    [], (* XXX Augeas code needs tests. *)
1195    "define an Augeas variable",
1196    "\
1197 Defines an Augeas variable C<name> whose value is the result
1198 of evaluating C<expr>.  If C<expr> is NULL, then C<name> is
1199 undefined.
1200
1201 On success this returns the number of nodes in C<expr>, or
1202 C<0> if C<expr> evaluates to something which is not a nodeset.");
1203
1204   ("aug_defnode", (RStruct ("nrnodescreated", "int_bool"), [String "name"; String "expr"; String "val"]), 18, [Optional "augeas"],
1205    [], (* XXX Augeas code needs tests. *)
1206    "define an Augeas node",
1207    "\
1208 Defines a variable C<name> whose value is the result of
1209 evaluating C<expr>.
1210
1211 If C<expr> evaluates to an empty nodeset, a node is created,
1212 equivalent to calling C<guestfs_aug_set> C<expr>, C<value>.
1213 C<name> will be the nodeset containing that single node.
1214
1215 On success this returns a pair containing the
1216 number of nodes in the nodeset, and a boolean flag
1217 if a node was created.");
1218
1219   ("aug_get", (RString "val", [String "augpath"]), 19, [Optional "augeas"],
1220    [], (* XXX Augeas code needs tests. *)
1221    "look up the value of an Augeas path",
1222    "\
1223 Look up the value associated with C<path>.  If C<path>
1224 matches exactly one node, the C<value> is returned.");
1225
1226   ("aug_set", (RErr, [String "augpath"; String "val"]), 20, [Optional "augeas"],
1227    [], (* XXX Augeas code needs tests. *)
1228    "set Augeas path to value",
1229    "\
1230 Set the value associated with C<path> to C<value>.");
1231
1232   ("aug_insert", (RErr, [String "augpath"; String "label"; Bool "before"]), 21, [Optional "augeas"],
1233    [], (* XXX Augeas code needs tests. *)
1234    "insert a sibling Augeas node",
1235    "\
1236 Create a new sibling C<label> for C<path>, inserting it into
1237 the tree before or after C<path> (depending on the boolean
1238 flag C<before>).
1239
1240 C<path> must match exactly one existing node in the tree, and
1241 C<label> must be a label, ie. not contain C</>, C<*> or end
1242 with a bracketed index C<[N]>.");
1243
1244   ("aug_rm", (RInt "nrnodes", [String "augpath"]), 22, [Optional "augeas"],
1245    [], (* XXX Augeas code needs tests. *)
1246    "remove an Augeas path",
1247    "\
1248 Remove C<path> and all of its children.
1249
1250 On success this returns the number of entries which were removed.");
1251
1252   ("aug_mv", (RErr, [String "src"; String "dest"]), 23, [Optional "augeas"],
1253    [], (* XXX Augeas code needs tests. *)
1254    "move Augeas node",
1255    "\
1256 Move the node C<src> to C<dest>.  C<src> must match exactly
1257 one node.  C<dest> is overwritten if it exists.");
1258
1259   ("aug_match", (RStringList "matches", [String "augpath"]), 24, [Optional "augeas"],
1260    [], (* XXX Augeas code needs tests. *)
1261    "return Augeas nodes which match augpath",
1262    "\
1263 Returns a list of paths which match the path expression C<path>.
1264 The returned paths are sufficiently qualified so that they match
1265 exactly one node in the current tree.");
1266
1267   ("aug_save", (RErr, []), 25, [Optional "augeas"],
1268    [], (* XXX Augeas code needs tests. *)
1269    "write all pending Augeas changes to disk",
1270    "\
1271 This writes all pending changes to disk.
1272
1273 The flags which were passed to C<guestfs_aug_init> affect exactly
1274 how files are saved.");
1275
1276   ("aug_load", (RErr, []), 27, [Optional "augeas"],
1277    [], (* XXX Augeas code needs tests. *)
1278    "load files into the tree",
1279    "\
1280 Load files into the tree.
1281
1282 See C<aug_load> in the Augeas documentation for the full gory
1283 details.");
1284
1285   ("aug_ls", (RStringList "matches", [String "augpath"]), 28, [Optional "augeas"],
1286    [], (* XXX Augeas code needs tests. *)
1287    "list Augeas nodes under augpath",
1288    "\
1289 This is just a shortcut for listing C<guestfs_aug_match>
1290 C<path/*> and sorting the resulting nodes into alphabetical order.");
1291
1292   ("rm", (RErr, [Pathname "path"]), 29, [],
1293    [InitBasicFS, Always, TestRun
1294       [["touch"; "/new"];
1295        ["rm"; "/new"]];
1296     InitBasicFS, Always, TestLastFail
1297       [["rm"; "/new"]];
1298     InitBasicFS, Always, TestLastFail
1299       [["mkdir"; "/new"];
1300        ["rm"; "/new"]]],
1301    "remove a file",
1302    "\
1303 Remove the single file C<path>.");
1304
1305   ("rmdir", (RErr, [Pathname "path"]), 30, [],
1306    [InitBasicFS, Always, TestRun
1307       [["mkdir"; "/new"];
1308        ["rmdir"; "/new"]];
1309     InitBasicFS, Always, TestLastFail
1310       [["rmdir"; "/new"]];
1311     InitBasicFS, Always, TestLastFail
1312       [["touch"; "/new"];
1313        ["rmdir"; "/new"]]],
1314    "remove a directory",
1315    "\
1316 Remove the single directory C<path>.");
1317
1318   ("rm_rf", (RErr, [Pathname "path"]), 31, [],
1319    [InitBasicFS, Always, TestOutputFalse
1320       [["mkdir"; "/new"];
1321        ["mkdir"; "/new/foo"];
1322        ["touch"; "/new/foo/bar"];
1323        ["rm_rf"; "/new"];
1324        ["exists"; "/new"]]],
1325    "remove a file or directory recursively",
1326    "\
1327 Remove the file or directory C<path>, recursively removing the
1328 contents if its a directory.  This is like the C<rm -rf> shell
1329 command.");
1330
1331   ("mkdir", (RErr, [Pathname "path"]), 32, [],
1332    [InitBasicFS, Always, TestOutputTrue
1333       [["mkdir"; "/new"];
1334        ["is_dir"; "/new"]];
1335     InitBasicFS, Always, TestLastFail
1336       [["mkdir"; "/new/foo/bar"]]],
1337    "create a directory",
1338    "\
1339 Create a directory named C<path>.");
1340
1341   ("mkdir_p", (RErr, [Pathname "path"]), 33, [],
1342    [InitBasicFS, Always, TestOutputTrue
1343       [["mkdir_p"; "/new/foo/bar"];
1344        ["is_dir"; "/new/foo/bar"]];
1345     InitBasicFS, Always, TestOutputTrue
1346       [["mkdir_p"; "/new/foo/bar"];
1347        ["is_dir"; "/new/foo"]];
1348     InitBasicFS, Always, TestOutputTrue
1349       [["mkdir_p"; "/new/foo/bar"];
1350        ["is_dir"; "/new"]];
1351     (* Regression tests for RHBZ#503133: *)
1352     InitBasicFS, Always, TestRun
1353       [["mkdir"; "/new"];
1354        ["mkdir_p"; "/new"]];
1355     InitBasicFS, Always, TestLastFail
1356       [["touch"; "/new"];
1357        ["mkdir_p"; "/new"]]],
1358    "create a directory and parents",
1359    "\
1360 Create a directory named C<path>, creating any parent directories
1361 as necessary.  This is like the C<mkdir -p> shell command.");
1362
1363   ("chmod", (RErr, [Int "mode"; Pathname "path"]), 34, [],
1364    [], (* XXX Need stat command to test *)
1365    "change file mode",
1366    "\
1367 Change the mode (permissions) of C<path> to C<mode>.  Only
1368 numeric modes are supported.
1369
1370 I<Note>: When using this command from guestfish, C<mode>
1371 by default would be decimal, unless you prefix it with
1372 C<0> to get octal, ie. use C<0700> not C<700>.");
1373
1374   ("chown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 35, [],
1375    [], (* XXX Need stat command to test *)
1376    "change file owner and group",
1377    "\
1378 Change the file owner to C<owner> and group to C<group>.
1379
1380 Only numeric uid and gid are supported.  If you want to use
1381 names, you will need to locate and parse the password file
1382 yourself (Augeas support makes this relatively easy).");
1383
1384   ("exists", (RBool "existsflag", [Pathname "path"]), 36, [],
1385    [InitISOFS, Always, TestOutputTrue (
1386       [["exists"; "/empty"]]);
1387     InitISOFS, Always, TestOutputTrue (
1388       [["exists"; "/directory"]])],
1389    "test if file or directory exists",
1390    "\
1391 This returns C<true> if and only if there is a file, directory
1392 (or anything) with the given C<path> name.
1393
1394 See also C<guestfs_is_file>, C<guestfs_is_dir>, C<guestfs_stat>.");
1395
1396   ("is_file", (RBool "fileflag", [Pathname "path"]), 37, [],
1397    [InitISOFS, Always, TestOutputTrue (
1398       [["is_file"; "/known-1"]]);
1399     InitISOFS, Always, TestOutputFalse (
1400       [["is_file"; "/directory"]])],
1401    "test if file exists",
1402    "\
1403 This returns C<true> if and only if there is a file
1404 with the given C<path> name.  Note that it returns false for
1405 other objects like directories.
1406
1407 See also C<guestfs_stat>.");
1408
1409   ("is_dir", (RBool "dirflag", [Pathname "path"]), 38, [],
1410    [InitISOFS, Always, TestOutputFalse (
1411       [["is_dir"; "/known-3"]]);
1412     InitISOFS, Always, TestOutputTrue (
1413       [["is_dir"; "/directory"]])],
1414    "test if file exists",
1415    "\
1416 This returns C<true> if and only if there is a directory
1417 with the given C<path> name.  Note that it returns false for
1418 other objects like files.
1419
1420 See also C<guestfs_stat>.");
1421
1422   ("pvcreate", (RErr, [Device "device"]), 39, [Optional "lvm2"],
1423    [InitEmpty, Always, TestOutputListOfDevices (
1424       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1425        ["pvcreate"; "/dev/sda1"];
1426        ["pvcreate"; "/dev/sda2"];
1427        ["pvcreate"; "/dev/sda3"];
1428        ["pvs"]], ["/dev/sda1"; "/dev/sda2"; "/dev/sda3"])],
1429    "create an LVM physical volume",
1430    "\
1431 This creates an LVM physical volume on the named C<device>,
1432 where C<device> should usually be a partition name such
1433 as C</dev/sda1>.");
1434
1435   ("vgcreate", (RErr, [String "volgroup"; DeviceList "physvols"]), 40, [Optional "lvm2"],
1436    [InitEmpty, Always, TestOutputList (
1437       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1438        ["pvcreate"; "/dev/sda1"];
1439        ["pvcreate"; "/dev/sda2"];
1440        ["pvcreate"; "/dev/sda3"];
1441        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1442        ["vgcreate"; "VG2"; "/dev/sda3"];
1443        ["vgs"]], ["VG1"; "VG2"])],
1444    "create an LVM volume group",
1445    "\
1446 This creates an LVM volume group called C<volgroup>
1447 from the non-empty list of physical volumes C<physvols>.");
1448
1449   ("lvcreate", (RErr, [String "logvol"; String "volgroup"; Int "mbytes"]), 41, [Optional "lvm2"],
1450    [InitEmpty, Always, TestOutputList (
1451       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1452        ["pvcreate"; "/dev/sda1"];
1453        ["pvcreate"; "/dev/sda2"];
1454        ["pvcreate"; "/dev/sda3"];
1455        ["vgcreate"; "VG1"; "/dev/sda1 /dev/sda2"];
1456        ["vgcreate"; "VG2"; "/dev/sda3"];
1457        ["lvcreate"; "LV1"; "VG1"; "50"];
1458        ["lvcreate"; "LV2"; "VG1"; "50"];
1459        ["lvcreate"; "LV3"; "VG2"; "50"];
1460        ["lvcreate"; "LV4"; "VG2"; "50"];
1461        ["lvcreate"; "LV5"; "VG2"; "50"];
1462        ["lvs"]],
1463       ["/dev/VG1/LV1"; "/dev/VG1/LV2";
1464        "/dev/VG2/LV3"; "/dev/VG2/LV4"; "/dev/VG2/LV5"])],
1465    "create an LVM volume group",
1466    "\
1467 This creates an LVM volume group called C<logvol>
1468 on the volume group C<volgroup>, with C<size> megabytes.");
1469
1470   ("mkfs", (RErr, [String "fstype"; Device "device"]), 42, [],
1471    [InitEmpty, Always, TestOutput (
1472       [["part_disk"; "/dev/sda"; "mbr"];
1473        ["mkfs"; "ext2"; "/dev/sda1"];
1474        ["mount_options"; ""; "/dev/sda1"; "/"];
1475        ["write_file"; "/new"; "new file contents"; "0"];
1476        ["cat"; "/new"]], "new file contents")],
1477    "make a filesystem",
1478    "\
1479 This creates a filesystem on C<device> (usually a partition
1480 or LVM logical volume).  The filesystem type is C<fstype>, for
1481 example C<ext3>.");
1482
1483   ("sfdisk", (RErr, [Device "device";
1484                      Int "cyls"; Int "heads"; Int "sectors";
1485                      StringList "lines"]), 43, [DangerWillRobinson],
1486    [],
1487    "create partitions on a block device",
1488    "\
1489 This is a direct interface to the L<sfdisk(8)> program for creating
1490 partitions on block devices.
1491
1492 C<device> should be a block device, for example C</dev/sda>.
1493
1494 C<cyls>, C<heads> and C<sectors> are the number of cylinders, heads
1495 and sectors on the device, which are passed directly to sfdisk as
1496 the I<-C>, I<-H> and I<-S> parameters.  If you pass C<0> for any
1497 of these, then the corresponding parameter is omitted.  Usually for
1498 'large' disks, you can just pass C<0> for these, but for small
1499 (floppy-sized) disks, sfdisk (or rather, the kernel) cannot work
1500 out the right geometry and you will need to tell it.
1501
1502 C<lines> is a list of lines that we feed to C<sfdisk>.  For more
1503 information refer to the L<sfdisk(8)> manpage.
1504
1505 To create a single partition occupying the whole disk, you would
1506 pass C<lines> as a single element list, when the single element being
1507 the string C<,> (comma).
1508
1509 See also: C<guestfs_sfdisk_l>, C<guestfs_sfdisk_N>,
1510 C<guestfs_part_init>");
1511
1512   ("write_file", (RErr, [Pathname "path"; String "content"; Int "size"]), 44, [ProtocolLimitWarning],
1513    [InitBasicFS, Always, TestOutput (
1514       [["write_file"; "/new"; "new file contents"; "0"];
1515        ["cat"; "/new"]], "new file contents");
1516     InitBasicFS, Always, TestOutput (
1517       [["write_file"; "/new"; "\nnew file contents\n"; "0"];
1518        ["cat"; "/new"]], "\nnew file contents\n");
1519     InitBasicFS, Always, TestOutput (
1520       [["write_file"; "/new"; "\n\n"; "0"];
1521        ["cat"; "/new"]], "\n\n");
1522     InitBasicFS, Always, TestOutput (
1523       [["write_file"; "/new"; ""; "0"];
1524        ["cat"; "/new"]], "");
1525     InitBasicFS, Always, TestOutput (
1526       [["write_file"; "/new"; "\n\n\n"; "0"];
1527        ["cat"; "/new"]], "\n\n\n");
1528     InitBasicFS, Always, TestOutput (
1529       [["write_file"; "/new"; "\n"; "0"];
1530        ["cat"; "/new"]], "\n")],
1531    "create a file",
1532    "\
1533 This call creates a file called C<path>.  The contents of the
1534 file is the string C<content> (which can contain any 8 bit data),
1535 with length C<size>.
1536
1537 As a special case, if C<size> is C<0>
1538 then the length is calculated using C<strlen> (so in this case
1539 the content cannot contain embedded ASCII NULs).
1540
1541 I<NB.> Owing to a bug, writing content containing ASCII NUL
1542 characters does I<not> work, even if the length is specified.
1543 We hope to resolve this bug in a future version.  In the meantime
1544 use C<guestfs_upload>.");
1545
1546   ("umount", (RErr, [String "pathordevice"]), 45, [FishAlias "unmount"],
1547    [InitEmpty, Always, TestOutputListOfDevices (
1548       [["part_disk"; "/dev/sda"; "mbr"];
1549        ["mkfs"; "ext2"; "/dev/sda1"];
1550        ["mount_options"; ""; "/dev/sda1"; "/"];
1551        ["mounts"]], ["/dev/sda1"]);
1552     InitEmpty, Always, TestOutputList (
1553       [["part_disk"; "/dev/sda"; "mbr"];
1554        ["mkfs"; "ext2"; "/dev/sda1"];
1555        ["mount_options"; ""; "/dev/sda1"; "/"];
1556        ["umount"; "/"];
1557        ["mounts"]], [])],
1558    "unmount a filesystem",
1559    "\
1560 This unmounts the given filesystem.  The filesystem may be
1561 specified either by its mountpoint (path) or the device which
1562 contains the filesystem.");
1563
1564   ("mounts", (RStringList "devices", []), 46, [],
1565    [InitBasicFS, Always, TestOutputListOfDevices (
1566       [["mounts"]], ["/dev/sda1"])],
1567    "show mounted filesystems",
1568    "\
1569 This returns the list of currently mounted filesystems.  It returns
1570 the list of devices (eg. C</dev/sda1>, C</dev/VG/LV>).
1571
1572 Some internal mounts are not shown.
1573
1574 See also: C<guestfs_mountpoints>");
1575
1576   ("umount_all", (RErr, []), 47, [FishAlias "unmount-all"],
1577    [InitBasicFS, Always, TestOutputList (
1578       [["umount_all"];
1579        ["mounts"]], []);
1580     (* check that umount_all can unmount nested mounts correctly: *)
1581     InitEmpty, Always, TestOutputList (
1582       [["sfdiskM"; "/dev/sda"; ",100 ,200 ,"];
1583        ["mkfs"; "ext2"; "/dev/sda1"];
1584        ["mkfs"; "ext2"; "/dev/sda2"];
1585        ["mkfs"; "ext2"; "/dev/sda3"];
1586        ["mount_options"; ""; "/dev/sda1"; "/"];
1587        ["mkdir"; "/mp1"];
1588        ["mount_options"; ""; "/dev/sda2"; "/mp1"];
1589        ["mkdir"; "/mp1/mp2"];
1590        ["mount_options"; ""; "/dev/sda3"; "/mp1/mp2"];
1591        ["mkdir"; "/mp1/mp2/mp3"];
1592        ["umount_all"];
1593        ["mounts"]], [])],
1594    "unmount all filesystems",
1595    "\
1596 This unmounts all mounted filesystems.
1597
1598 Some internal mounts are not unmounted by this call.");
1599
1600   ("lvm_remove_all", (RErr, []), 48, [DangerWillRobinson; Optional "lvm2"],
1601    [],
1602    "remove all LVM LVs, VGs and PVs",
1603    "\
1604 This command removes all LVM logical volumes, volume groups
1605 and physical volumes.");
1606
1607   ("file", (RString "description", [Dev_or_Path "path"]), 49, [],
1608    [InitISOFS, Always, TestOutput (
1609       [["file"; "/empty"]], "empty");
1610     InitISOFS, Always, TestOutput (
1611       [["file"; "/known-1"]], "ASCII text");
1612     InitISOFS, Always, TestLastFail (
1613       [["file"; "/notexists"]])],
1614    "determine file type",
1615    "\
1616 This call uses the standard L<file(1)> command to determine
1617 the type or contents of the file.  This also works on devices,
1618 for example to find out whether a partition contains a filesystem.
1619
1620 This call will also transparently look inside various types
1621 of compressed file.
1622
1623 The exact command which runs is C<file -zbsL path>.  Note in
1624 particular that the filename is not prepended to the output
1625 (the C<-b> option).");
1626
1627   ("command", (RString "output", [StringList "arguments"]), 50, [ProtocolLimitWarning],
1628    [InitBasicFS, Always, TestOutput (
1629       [["upload"; "test-command"; "/test-command"];
1630        ["chmod"; "0o755"; "/test-command"];
1631        ["command"; "/test-command 1"]], "Result1");
1632     InitBasicFS, Always, TestOutput (
1633       [["upload"; "test-command"; "/test-command"];
1634        ["chmod"; "0o755"; "/test-command"];
1635        ["command"; "/test-command 2"]], "Result2\n");
1636     InitBasicFS, Always, TestOutput (
1637       [["upload"; "test-command"; "/test-command"];
1638        ["chmod"; "0o755"; "/test-command"];
1639        ["command"; "/test-command 3"]], "\nResult3");
1640     InitBasicFS, Always, TestOutput (
1641       [["upload"; "test-command"; "/test-command"];
1642        ["chmod"; "0o755"; "/test-command"];
1643        ["command"; "/test-command 4"]], "\nResult4\n");
1644     InitBasicFS, Always, TestOutput (
1645       [["upload"; "test-command"; "/test-command"];
1646        ["chmod"; "0o755"; "/test-command"];
1647        ["command"; "/test-command 5"]], "\nResult5\n\n");
1648     InitBasicFS, Always, TestOutput (
1649       [["upload"; "test-command"; "/test-command"];
1650        ["chmod"; "0o755"; "/test-command"];
1651        ["command"; "/test-command 6"]], "\n\nResult6\n\n");
1652     InitBasicFS, Always, TestOutput (
1653       [["upload"; "test-command"; "/test-command"];
1654        ["chmod"; "0o755"; "/test-command"];
1655        ["command"; "/test-command 7"]], "");
1656     InitBasicFS, Always, TestOutput (
1657       [["upload"; "test-command"; "/test-command"];
1658        ["chmod"; "0o755"; "/test-command"];
1659        ["command"; "/test-command 8"]], "\n");
1660     InitBasicFS, Always, TestOutput (
1661       [["upload"; "test-command"; "/test-command"];
1662        ["chmod"; "0o755"; "/test-command"];
1663        ["command"; "/test-command 9"]], "\n\n");
1664     InitBasicFS, Always, TestOutput (
1665       [["upload"; "test-command"; "/test-command"];
1666        ["chmod"; "0o755"; "/test-command"];
1667        ["command"; "/test-command 10"]], "Result10-1\nResult10-2\n");
1668     InitBasicFS, Always, TestOutput (
1669       [["upload"; "test-command"; "/test-command"];
1670        ["chmod"; "0o755"; "/test-command"];
1671        ["command"; "/test-command 11"]], "Result11-1\nResult11-2");
1672     InitBasicFS, Always, TestLastFail (
1673       [["upload"; "test-command"; "/test-command"];
1674        ["chmod"; "0o755"; "/test-command"];
1675        ["command"; "/test-command"]])],
1676    "run a command from the guest filesystem",
1677    "\
1678 This call runs a command from the guest filesystem.  The
1679 filesystem must be mounted, and must contain a compatible
1680 operating system (ie. something Linux, with the same
1681 or compatible processor architecture).
1682
1683 The single parameter is an argv-style list of arguments.
1684 The first element is the name of the program to run.
1685 Subsequent elements are parameters.  The list must be
1686 non-empty (ie. must contain a program name).  Note that
1687 the command runs directly, and is I<not> invoked via
1688 the shell (see C<guestfs_sh>).
1689
1690 The return value is anything printed to I<stdout> by
1691 the command.
1692
1693 If the command returns a non-zero exit status, then
1694 this function returns an error message.  The error message
1695 string is the content of I<stderr> from the command.
1696
1697 The C<$PATH> environment variable will contain at least
1698 C</usr/bin> and C</bin>.  If you require a program from
1699 another location, you should provide the full path in the
1700 first parameter.
1701
1702 Shared libraries and data files required by the program
1703 must be available on filesystems which are mounted in the
1704 correct places.  It is the caller's responsibility to ensure
1705 all filesystems that are needed are mounted at the right
1706 locations.");
1707
1708   ("command_lines", (RStringList "lines", [StringList "arguments"]), 51, [ProtocolLimitWarning],
1709    [InitBasicFS, Always, TestOutputList (
1710       [["upload"; "test-command"; "/test-command"];
1711        ["chmod"; "0o755"; "/test-command"];
1712        ["command_lines"; "/test-command 1"]], ["Result1"]);
1713     InitBasicFS, Always, TestOutputList (
1714       [["upload"; "test-command"; "/test-command"];
1715        ["chmod"; "0o755"; "/test-command"];
1716        ["command_lines"; "/test-command 2"]], ["Result2"]);
1717     InitBasicFS, Always, TestOutputList (
1718       [["upload"; "test-command"; "/test-command"];
1719        ["chmod"; "0o755"; "/test-command"];
1720        ["command_lines"; "/test-command 3"]], ["";"Result3"]);
1721     InitBasicFS, Always, TestOutputList (
1722       [["upload"; "test-command"; "/test-command"];
1723        ["chmod"; "0o755"; "/test-command"];
1724        ["command_lines"; "/test-command 4"]], ["";"Result4"]);
1725     InitBasicFS, Always, TestOutputList (
1726       [["upload"; "test-command"; "/test-command"];
1727        ["chmod"; "0o755"; "/test-command"];
1728        ["command_lines"; "/test-command 5"]], ["";"Result5";""]);
1729     InitBasicFS, Always, TestOutputList (
1730       [["upload"; "test-command"; "/test-command"];
1731        ["chmod"; "0o755"; "/test-command"];
1732        ["command_lines"; "/test-command 6"]], ["";"";"Result6";""]);
1733     InitBasicFS, Always, TestOutputList (
1734       [["upload"; "test-command"; "/test-command"];
1735        ["chmod"; "0o755"; "/test-command"];
1736        ["command_lines"; "/test-command 7"]], []);
1737     InitBasicFS, Always, TestOutputList (
1738       [["upload"; "test-command"; "/test-command"];
1739        ["chmod"; "0o755"; "/test-command"];
1740        ["command_lines"; "/test-command 8"]], [""]);
1741     InitBasicFS, Always, TestOutputList (
1742       [["upload"; "test-command"; "/test-command"];
1743        ["chmod"; "0o755"; "/test-command"];
1744        ["command_lines"; "/test-command 9"]], ["";""]);
1745     InitBasicFS, Always, TestOutputList (
1746       [["upload"; "test-command"; "/test-command"];
1747        ["chmod"; "0o755"; "/test-command"];
1748        ["command_lines"; "/test-command 10"]], ["Result10-1";"Result10-2"]);
1749     InitBasicFS, Always, TestOutputList (
1750       [["upload"; "test-command"; "/test-command"];
1751        ["chmod"; "0o755"; "/test-command"];
1752        ["command_lines"; "/test-command 11"]], ["Result11-1";"Result11-2"])],
1753    "run a command, returning lines",
1754    "\
1755 This is the same as C<guestfs_command>, but splits the
1756 result into a list of lines.
1757
1758 See also: C<guestfs_sh_lines>");
1759
1760   ("stat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 52, [],
1761    [InitISOFS, Always, TestOutputStruct (
1762       [["stat"; "/empty"]], [CompareWithInt ("size", 0)])],
1763    "get file information",
1764    "\
1765 Returns file information for the given C<path>.
1766
1767 This is the same as the C<stat(2)> system call.");
1768
1769   ("lstat", (RStruct ("statbuf", "stat"), [Pathname "path"]), 53, [],
1770    [InitISOFS, Always, TestOutputStruct (
1771       [["lstat"; "/empty"]], [CompareWithInt ("size", 0)])],
1772    "get file information for a symbolic link",
1773    "\
1774 Returns file information for the given C<path>.
1775
1776 This is the same as C<guestfs_stat> except that if C<path>
1777 is a symbolic link, then the link is stat-ed, not the file it
1778 refers to.
1779
1780 This is the same as the C<lstat(2)> system call.");
1781
1782   ("statvfs", (RStruct ("statbuf", "statvfs"), [Pathname "path"]), 54, [],
1783    [InitISOFS, Always, TestOutputStruct (
1784       [["statvfs"; "/"]], [CompareWithInt ("namemax", 255)])],
1785    "get file system statistics",
1786    "\
1787 Returns file system statistics for any mounted file system.
1788 C<path> should be a file or directory in the mounted file system
1789 (typically it is the mount point itself, but it doesn't need to be).
1790
1791 This is the same as the C<statvfs(2)> system call.");
1792
1793   ("tune2fs_l", (RHashtable "superblock", [Device "device"]), 55, [],
1794    [], (* XXX test *)
1795    "get ext2/ext3/ext4 superblock details",
1796    "\
1797 This returns the contents of the ext2, ext3 or ext4 filesystem
1798 superblock on C<device>.
1799
1800 It is the same as running C<tune2fs -l device>.  See L<tune2fs(8)>
1801 manpage for more details.  The list of fields returned isn't
1802 clearly defined, and depends on both the version of C<tune2fs>
1803 that libguestfs was built against, and the filesystem itself.");
1804
1805   ("blockdev_setro", (RErr, [Device "device"]), 56, [],
1806    [InitEmpty, Always, TestOutputTrue (
1807       [["blockdev_setro"; "/dev/sda"];
1808        ["blockdev_getro"; "/dev/sda"]])],
1809    "set block device to read-only",
1810    "\
1811 Sets the block device named C<device> to read-only.
1812
1813 This uses the L<blockdev(8)> command.");
1814
1815   ("blockdev_setrw", (RErr, [Device "device"]), 57, [],
1816    [InitEmpty, Always, TestOutputFalse (
1817       [["blockdev_setrw"; "/dev/sda"];
1818        ["blockdev_getro"; "/dev/sda"]])],
1819    "set block device to read-write",
1820    "\
1821 Sets the block device named C<device> to read-write.
1822
1823 This uses the L<blockdev(8)> command.");
1824
1825   ("blockdev_getro", (RBool "ro", [Device "device"]), 58, [],
1826    [InitEmpty, Always, TestOutputTrue (
1827       [["blockdev_setro"; "/dev/sda"];
1828        ["blockdev_getro"; "/dev/sda"]])],
1829    "is block device set to read-only",
1830    "\
1831 Returns a boolean indicating if the block device is read-only
1832 (true if read-only, false if not).
1833
1834 This uses the L<blockdev(8)> command.");
1835
1836   ("blockdev_getss", (RInt "sectorsize", [Device "device"]), 59, [],
1837    [InitEmpty, Always, TestOutputInt (
1838       [["blockdev_getss"; "/dev/sda"]], 512)],
1839    "get sectorsize of block device",
1840    "\
1841 This returns the size of sectors on a block device.
1842 Usually 512, but can be larger for modern devices.
1843
1844 (Note, this is not the size in sectors, use C<guestfs_blockdev_getsz>
1845 for that).
1846
1847 This uses the L<blockdev(8)> command.");
1848
1849   ("blockdev_getbsz", (RInt "blocksize", [Device "device"]), 60, [],
1850    [InitEmpty, Always, TestOutputInt (
1851       [["blockdev_getbsz"; "/dev/sda"]], 4096)],
1852    "get blocksize of block device",
1853    "\
1854 This returns the block size of a device.
1855
1856 (Note this is different from both I<size in blocks> and
1857 I<filesystem block size>).
1858
1859 This uses the L<blockdev(8)> command.");
1860
1861   ("blockdev_setbsz", (RErr, [Device "device"; Int "blocksize"]), 61, [],
1862    [], (* XXX test *)
1863    "set blocksize of block device",
1864    "\
1865 This sets the block size of a device.
1866
1867 (Note this is different from both I<size in blocks> and
1868 I<filesystem block size>).
1869
1870 This uses the L<blockdev(8)> command.");
1871
1872   ("blockdev_getsz", (RInt64 "sizeinsectors", [Device "device"]), 62, [],
1873    [InitEmpty, Always, TestOutputInt (
1874       [["blockdev_getsz"; "/dev/sda"]], 1024000)],
1875    "get total size of device in 512-byte sectors",
1876    "\
1877 This returns the size of the device in units of 512-byte sectors
1878 (even if the sectorsize isn't 512 bytes ... weird).
1879
1880 See also C<guestfs_blockdev_getss> for the real sector size of
1881 the device, and C<guestfs_blockdev_getsize64> for the more
1882 useful I<size in bytes>.
1883
1884 This uses the L<blockdev(8)> command.");
1885
1886   ("blockdev_getsize64", (RInt64 "sizeinbytes", [Device "device"]), 63, [],
1887    [InitEmpty, Always, TestOutputInt (
1888       [["blockdev_getsize64"; "/dev/sda"]], 524288000)],
1889    "get total size of device in bytes",
1890    "\
1891 This returns the size of the device in bytes.
1892
1893 See also C<guestfs_blockdev_getsz>.
1894
1895 This uses the L<blockdev(8)> command.");
1896
1897   ("blockdev_flushbufs", (RErr, [Device "device"]), 64, [],
1898    [InitEmpty, Always, TestRun
1899       [["blockdev_flushbufs"; "/dev/sda"]]],
1900    "flush device buffers",
1901    "\
1902 This tells the kernel to flush internal buffers associated
1903 with C<device>.
1904
1905 This uses the L<blockdev(8)> command.");
1906
1907   ("blockdev_rereadpt", (RErr, [Device "device"]), 65, [],
1908    [InitEmpty, Always, TestRun
1909       [["blockdev_rereadpt"; "/dev/sda"]]],
1910    "reread partition table",
1911    "\
1912 Reread the partition table on C<device>.
1913
1914 This uses the L<blockdev(8)> command.");
1915
1916   ("upload", (RErr, [FileIn "filename"; Dev_or_Path "remotefilename"]), 66, [],
1917    [InitBasicFS, Always, TestOutput (
1918       (* Pick a file from cwd which isn't likely to change. *)
1919       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1920        ["checksum"; "md5"; "/COPYING.LIB"]],
1921       Digest.to_hex (Digest.file "COPYING.LIB"))],
1922    "upload a file from the local machine",
1923    "\
1924 Upload local file C<filename> to C<remotefilename> on the
1925 filesystem.
1926
1927 C<filename> can also be a named pipe.
1928
1929 See also C<guestfs_download>.");
1930
1931   ("download", (RErr, [Dev_or_Path "remotefilename"; FileOut "filename"]), 67, [],
1932    [InitBasicFS, Always, TestOutput (
1933       (* Pick a file from cwd which isn't likely to change. *)
1934       [["upload"; "../COPYING.LIB"; "/COPYING.LIB"];
1935        ["download"; "/COPYING.LIB"; "testdownload.tmp"];
1936        ["upload"; "testdownload.tmp"; "/upload"];
1937        ["checksum"; "md5"; "/upload"]],
1938       Digest.to_hex (Digest.file "COPYING.LIB"))],
1939    "download a file to the local machine",
1940    "\
1941 Download file C<remotefilename> and save it as C<filename>
1942 on the local machine.
1943
1944 C<filename> can also be a named pipe.
1945
1946 See also C<guestfs_upload>, C<guestfs_cat>.");
1947
1948   ("checksum", (RString "checksum", [String "csumtype"; Pathname "path"]), 68, [],
1949    [InitISOFS, Always, TestOutput (
1950       [["checksum"; "crc"; "/known-3"]], "2891671662");
1951     InitISOFS, Always, TestLastFail (
1952       [["checksum"; "crc"; "/notexists"]]);
1953     InitISOFS, Always, TestOutput (
1954       [["checksum"; "md5"; "/known-3"]], "46d6ca27ee07cdc6fa99c2e138cc522c");
1955     InitISOFS, Always, TestOutput (
1956       [["checksum"; "sha1"; "/known-3"]], "b7ebccc3ee418311091c3eda0a45b83c0a770f15");
1957     InitISOFS, Always, TestOutput (
1958       [["checksum"; "sha224"; "/known-3"]], "d2cd1774b28f3659c14116be0a6dc2bb5c4b350ce9cd5defac707741");
1959     InitISOFS, Always, TestOutput (
1960       [["checksum"; "sha256"; "/known-3"]], "75bb71b90cd20cb13f86d2bea8dad63ac7194e7517c3b52b8d06ff52d3487d30");
1961     InitISOFS, Always, TestOutput (
1962       [["checksum"; "sha384"; "/known-3"]], "5fa7883430f357b5d7b7271d3a1d2872b51d73cba72731de6863d3dea55f30646af2799bef44d5ea776a5ec7941ac640");
1963     InitISOFS, Always, TestOutput (
1964       [["checksum"; "sha512"; "/known-3"]], "2794062c328c6b216dca90443b7f7134c5f40e56bd0ed7853123275a09982a6f992e6ca682f9d2fba34a4c5e870d8fe077694ff831e3032a004ee077e00603f6")],
1965    "compute MD5, SHAx or CRC checksum of file",
1966    "\
1967 This call computes the MD5, SHAx or CRC checksum of the
1968 file named C<path>.
1969
1970 The type of checksum to compute is given by the C<csumtype>
1971 parameter which must have one of the following values:
1972
1973 =over 4
1974
1975 =item C<crc>
1976
1977 Compute the cyclic redundancy check (CRC) specified by POSIX
1978 for the C<cksum> command.
1979
1980 =item C<md5>
1981
1982 Compute the MD5 hash (using the C<md5sum> program).
1983
1984 =item C<sha1>
1985
1986 Compute the SHA1 hash (using the C<sha1sum> program).
1987
1988 =item C<sha224>
1989
1990 Compute the SHA224 hash (using the C<sha224sum> program).
1991
1992 =item C<sha256>
1993
1994 Compute the SHA256 hash (using the C<sha256sum> program).
1995
1996 =item C<sha384>
1997
1998 Compute the SHA384 hash (using the C<sha384sum> program).
1999
2000 =item C<sha512>
2001
2002 Compute the SHA512 hash (using the C<sha512sum> program).
2003
2004 =back
2005
2006 The checksum is returned as a printable string.");
2007
2008   ("tar_in", (RErr, [FileIn "tarfile"; String "directory"]), 69, [],
2009    [InitBasicFS, Always, TestOutput (
2010       [["tar_in"; "../images/helloworld.tar"; "/"];
2011        ["cat"; "/hello"]], "hello\n")],
2012    "unpack tarfile to directory",
2013    "\
2014 This command uploads and unpacks local file C<tarfile> (an
2015 I<uncompressed> tar file) into C<directory>.
2016
2017 To upload a compressed tarball, use C<guestfs_tgz_in>.");
2018
2019   ("tar_out", (RErr, [String "directory"; FileOut "tarfile"]), 70, [],
2020    [],
2021    "pack directory into tarfile",
2022    "\
2023 This command packs the contents of C<directory> and downloads
2024 it to local file C<tarfile>.
2025
2026 To download a compressed tarball, use C<guestfs_tgz_out>.");
2027
2028   ("tgz_in", (RErr, [FileIn "tarball"; String "directory"]), 71, [],
2029    [InitBasicFS, Always, TestOutput (
2030       [["tgz_in"; "../images/helloworld.tar.gz"; "/"];
2031        ["cat"; "/hello"]], "hello\n")],
2032    "unpack compressed tarball to directory",
2033    "\
2034 This command uploads and unpacks local file C<tarball> (a
2035 I<gzip compressed> tar file) into C<directory>.
2036
2037 To upload an uncompressed tarball, use C<guestfs_tar_in>.");
2038
2039   ("tgz_out", (RErr, [Pathname "directory"; FileOut "tarball"]), 72, [],
2040    [],
2041    "pack directory into compressed tarball",
2042    "\
2043 This command packs the contents of C<directory> and downloads
2044 it to local file C<tarball>.
2045
2046 To download an uncompressed tarball, use C<guestfs_tar_out>.");
2047
2048   ("mount_ro", (RErr, [Device "device"; String "mountpoint"]), 73, [],
2049    [InitBasicFS, Always, TestLastFail (
2050       [["umount"; "/"];
2051        ["mount_ro"; "/dev/sda1"; "/"];
2052        ["touch"; "/new"]]);
2053     InitBasicFS, Always, TestOutput (
2054       [["write_file"; "/new"; "data"; "0"];
2055        ["umount"; "/"];
2056        ["mount_ro"; "/dev/sda1"; "/"];
2057        ["cat"; "/new"]], "data")],
2058    "mount a guest disk, read-only",
2059    "\
2060 This is the same as the C<guestfs_mount> command, but it
2061 mounts the filesystem with the read-only (I<-o ro>) flag.");
2062
2063   ("mount_options", (RErr, [String "options"; Device "device"; String "mountpoint"]), 74, [],
2064    [],
2065    "mount a guest disk with mount options",
2066    "\
2067 This is the same as the C<guestfs_mount> command, but it
2068 allows you to set the mount options as for the
2069 L<mount(8)> I<-o> flag.");
2070
2071   ("mount_vfs", (RErr, [String "options"; String "vfstype"; Device "device"; String "mountpoint"]), 75, [],
2072    [],
2073    "mount a guest disk with mount options and vfstype",
2074    "\
2075 This is the same as the C<guestfs_mount> command, but it
2076 allows you to set both the mount options and the vfstype
2077 as for the L<mount(8)> I<-o> and I<-t> flags.");
2078
2079   ("debug", (RString "result", [String "subcmd"; StringList "extraargs"]), 76, [],
2080    [],
2081    "debugging and internals",
2082    "\
2083 The C<guestfs_debug> command exposes some internals of
2084 C<guestfsd> (the guestfs daemon) that runs inside the
2085 qemu subprocess.
2086
2087 There is no comprehensive help for this command.  You have
2088 to look at the file C<daemon/debug.c> in the libguestfs source
2089 to find out what you can do.");
2090
2091   ("lvremove", (RErr, [Device "device"]), 77, [Optional "lvm2"],
2092    [InitEmpty, Always, TestOutputList (
2093       [["part_disk"; "/dev/sda"; "mbr"];
2094        ["pvcreate"; "/dev/sda1"];
2095        ["vgcreate"; "VG"; "/dev/sda1"];
2096        ["lvcreate"; "LV1"; "VG"; "50"];
2097        ["lvcreate"; "LV2"; "VG"; "50"];
2098        ["lvremove"; "/dev/VG/LV1"];
2099        ["lvs"]], ["/dev/VG/LV2"]);
2100     InitEmpty, Always, TestOutputList (
2101       [["part_disk"; "/dev/sda"; "mbr"];
2102        ["pvcreate"; "/dev/sda1"];
2103        ["vgcreate"; "VG"; "/dev/sda1"];
2104        ["lvcreate"; "LV1"; "VG"; "50"];
2105        ["lvcreate"; "LV2"; "VG"; "50"];
2106        ["lvremove"; "/dev/VG"];
2107        ["lvs"]], []);
2108     InitEmpty, Always, TestOutputList (
2109       [["part_disk"; "/dev/sda"; "mbr"];
2110        ["pvcreate"; "/dev/sda1"];
2111        ["vgcreate"; "VG"; "/dev/sda1"];
2112        ["lvcreate"; "LV1"; "VG"; "50"];
2113        ["lvcreate"; "LV2"; "VG"; "50"];
2114        ["lvremove"; "/dev/VG"];
2115        ["vgs"]], ["VG"])],
2116    "remove an LVM logical volume",
2117    "\
2118 Remove an LVM logical volume C<device>, where C<device> is
2119 the path to the LV, such as C</dev/VG/LV>.
2120
2121 You can also remove all LVs in a volume group by specifying
2122 the VG name, C</dev/VG>.");
2123
2124   ("vgremove", (RErr, [String "vgname"]), 78, [Optional "lvm2"],
2125    [InitEmpty, Always, TestOutputList (
2126       [["part_disk"; "/dev/sda"; "mbr"];
2127        ["pvcreate"; "/dev/sda1"];
2128        ["vgcreate"; "VG"; "/dev/sda1"];
2129        ["lvcreate"; "LV1"; "VG"; "50"];
2130        ["lvcreate"; "LV2"; "VG"; "50"];
2131        ["vgremove"; "VG"];
2132        ["lvs"]], []);
2133     InitEmpty, Always, TestOutputList (
2134       [["part_disk"; "/dev/sda"; "mbr"];
2135        ["pvcreate"; "/dev/sda1"];
2136        ["vgcreate"; "VG"; "/dev/sda1"];
2137        ["lvcreate"; "LV1"; "VG"; "50"];
2138        ["lvcreate"; "LV2"; "VG"; "50"];
2139        ["vgremove"; "VG"];
2140        ["vgs"]], [])],
2141    "remove an LVM volume group",
2142    "\
2143 Remove an LVM volume group C<vgname>, (for example C<VG>).
2144
2145 This also forcibly removes all logical volumes in the volume
2146 group (if any).");
2147
2148   ("pvremove", (RErr, [Device "device"]), 79, [Optional "lvm2"],
2149    [InitEmpty, Always, TestOutputListOfDevices (
2150       [["part_disk"; "/dev/sda"; "mbr"];
2151        ["pvcreate"; "/dev/sda1"];
2152        ["vgcreate"; "VG"; "/dev/sda1"];
2153        ["lvcreate"; "LV1"; "VG"; "50"];
2154        ["lvcreate"; "LV2"; "VG"; "50"];
2155        ["vgremove"; "VG"];
2156        ["pvremove"; "/dev/sda1"];
2157        ["lvs"]], []);
2158     InitEmpty, Always, TestOutputListOfDevices (
2159       [["part_disk"; "/dev/sda"; "mbr"];
2160        ["pvcreate"; "/dev/sda1"];
2161        ["vgcreate"; "VG"; "/dev/sda1"];
2162        ["lvcreate"; "LV1"; "VG"; "50"];
2163        ["lvcreate"; "LV2"; "VG"; "50"];
2164        ["vgremove"; "VG"];
2165        ["pvremove"; "/dev/sda1"];
2166        ["vgs"]], []);
2167     InitEmpty, Always, TestOutputListOfDevices (
2168       [["part_disk"; "/dev/sda"; "mbr"];
2169        ["pvcreate"; "/dev/sda1"];
2170        ["vgcreate"; "VG"; "/dev/sda1"];
2171        ["lvcreate"; "LV1"; "VG"; "50"];
2172        ["lvcreate"; "LV2"; "VG"; "50"];
2173        ["vgremove"; "VG"];
2174        ["pvremove"; "/dev/sda1"];
2175        ["pvs"]], [])],
2176    "remove an LVM physical volume",
2177    "\
2178 This wipes a physical volume C<device> so that LVM will no longer
2179 recognise it.
2180
2181 The implementation uses the C<pvremove> command which refuses to
2182 wipe physical volumes that contain any volume groups, so you have
2183 to remove those first.");
2184
2185   ("set_e2label", (RErr, [Device "device"; String "label"]), 80, [],
2186    [InitBasicFS, Always, TestOutput (
2187       [["set_e2label"; "/dev/sda1"; "testlabel"];
2188        ["get_e2label"; "/dev/sda1"]], "testlabel")],
2189    "set the ext2/3/4 filesystem label",
2190    "\
2191 This sets the ext2/3/4 filesystem label of the filesystem on
2192 C<device> to C<label>.  Filesystem labels are limited to
2193 16 characters.
2194
2195 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2label>
2196 to return the existing label on a filesystem.");
2197
2198   ("get_e2label", (RString "label", [Device "device"]), 81, [],
2199    [],
2200    "get the ext2/3/4 filesystem label",
2201    "\
2202 This returns the ext2/3/4 filesystem label of the filesystem on
2203 C<device>.");
2204
2205   ("set_e2uuid", (RErr, [Device "device"; String "uuid"]), 82, [],
2206    (let uuid = uuidgen () in
2207     [InitBasicFS, Always, TestOutput (
2208        [["set_e2uuid"; "/dev/sda1"; uuid];
2209         ["get_e2uuid"; "/dev/sda1"]], uuid);
2210      InitBasicFS, Always, TestOutput (
2211        [["set_e2uuid"; "/dev/sda1"; "clear"];
2212         ["get_e2uuid"; "/dev/sda1"]], "");
2213      (* We can't predict what UUIDs will be, so just check the commands run. *)
2214      InitBasicFS, Always, TestRun (
2215        [["set_e2uuid"; "/dev/sda1"; "random"]]);
2216      InitBasicFS, Always, TestRun (
2217        [["set_e2uuid"; "/dev/sda1"; "time"]])]),
2218    "set the ext2/3/4 filesystem UUID",
2219    "\
2220 This sets the ext2/3/4 filesystem UUID of the filesystem on
2221 C<device> to C<uuid>.  The format of the UUID and alternatives
2222 such as C<clear>, C<random> and C<time> are described in the
2223 L<tune2fs(8)> manpage.
2224
2225 You can use either C<guestfs_tune2fs_l> or C<guestfs_get_e2uuid>
2226 to return the existing UUID of a filesystem.");
2227
2228   ("get_e2uuid", (RString "uuid", [Device "device"]), 83, [],
2229    [],
2230    "get the ext2/3/4 filesystem UUID",
2231    "\
2232 This returns the ext2/3/4 filesystem UUID of the filesystem on
2233 C<device>.");
2234
2235   ("fsck", (RInt "status", [String "fstype"; Device "device"]), 84, [],
2236    [InitBasicFS, Always, TestOutputInt (
2237       [["umount"; "/dev/sda1"];
2238        ["fsck"; "ext2"; "/dev/sda1"]], 0);
2239     InitBasicFS, Always, TestOutputInt (
2240       [["umount"; "/dev/sda1"];
2241        ["zero"; "/dev/sda1"];
2242        ["fsck"; "ext2"; "/dev/sda1"]], 8)],
2243    "run the filesystem checker",
2244    "\
2245 This runs the filesystem checker (fsck) on C<device> which
2246 should have filesystem type C<fstype>.
2247
2248 The returned integer is the status.  See L<fsck(8)> for the
2249 list of status codes from C<fsck>.
2250
2251 Notes:
2252
2253 =over 4
2254
2255 =item *
2256
2257 Multiple status codes can be summed together.
2258
2259 =item *
2260
2261 A non-zero return code can mean \"success\", for example if
2262 errors have been corrected on the filesystem.
2263
2264 =item *
2265
2266 Checking or repairing NTFS volumes is not supported
2267 (by linux-ntfs).
2268
2269 =back
2270
2271 This command is entirely equivalent to running C<fsck -a -t fstype device>.");
2272
2273   ("zero", (RErr, [Device "device"]), 85, [],
2274    [InitBasicFS, Always, TestOutput (
2275       [["umount"; "/dev/sda1"];
2276        ["zero"; "/dev/sda1"];
2277        ["file"; "/dev/sda1"]], "data")],
2278    "write zeroes to the device",
2279    "\
2280 This command writes zeroes over the first few blocks of C<device>.
2281
2282 How many blocks are zeroed isn't specified (but it's I<not> enough
2283 to securely wipe the device).  It should be sufficient to remove
2284 any partition tables, filesystem superblocks and so on.
2285
2286 See also: C<guestfs_scrub_device>.");
2287
2288   ("grub_install", (RErr, [Pathname "root"; Device "device"]), 86, [],
2289    (* Test disabled because grub-install incompatible with virtio-blk driver.
2290     * See also: https://bugzilla.redhat.com/show_bug.cgi?id=479760
2291     *)
2292    [InitBasicFS, Disabled, TestOutputTrue (
2293       [["grub_install"; "/"; "/dev/sda1"];
2294        ["is_dir"; "/boot"]])],
2295    "install GRUB",
2296    "\
2297 This command installs GRUB (the Grand Unified Bootloader) on
2298 C<device>, with the root directory being C<root>.");
2299
2300   ("cp", (RErr, [Pathname "src"; Pathname "dest"]), 87, [],
2301    [InitBasicFS, Always, TestOutput (
2302       [["write_file"; "/old"; "file content"; "0"];
2303        ["cp"; "/old"; "/new"];
2304        ["cat"; "/new"]], "file content");
2305     InitBasicFS, Always, TestOutputTrue (
2306       [["write_file"; "/old"; "file content"; "0"];
2307        ["cp"; "/old"; "/new"];
2308        ["is_file"; "/old"]]);
2309     InitBasicFS, Always, TestOutput (
2310       [["write_file"; "/old"; "file content"; "0"];
2311        ["mkdir"; "/dir"];
2312        ["cp"; "/old"; "/dir/new"];
2313        ["cat"; "/dir/new"]], "file content")],
2314    "copy a file",
2315    "\
2316 This copies a file from C<src> to C<dest> where C<dest> is
2317 either a destination filename or destination directory.");
2318
2319   ("cp_a", (RErr, [Pathname "src"; Pathname "dest"]), 88, [],
2320    [InitBasicFS, Always, TestOutput (
2321       [["mkdir"; "/olddir"];
2322        ["mkdir"; "/newdir"];
2323        ["write_file"; "/olddir/file"; "file content"; "0"];
2324        ["cp_a"; "/olddir"; "/newdir"];
2325        ["cat"; "/newdir/olddir/file"]], "file content")],
2326    "copy a file or directory recursively",
2327    "\
2328 This copies a file or directory from C<src> to C<dest>
2329 recursively using the C<cp -a> command.");
2330
2331   ("mv", (RErr, [Pathname "src"; Pathname "dest"]), 89, [],
2332    [InitBasicFS, Always, TestOutput (
2333       [["write_file"; "/old"; "file content"; "0"];
2334        ["mv"; "/old"; "/new"];
2335        ["cat"; "/new"]], "file content");
2336     InitBasicFS, Always, TestOutputFalse (
2337       [["write_file"; "/old"; "file content"; "0"];
2338        ["mv"; "/old"; "/new"];
2339        ["is_file"; "/old"]])],
2340    "move a file",
2341    "\
2342 This moves a file from C<src> to C<dest> where C<dest> is
2343 either a destination filename or destination directory.");
2344
2345   ("drop_caches", (RErr, [Int "whattodrop"]), 90, [],
2346    [InitEmpty, Always, TestRun (
2347       [["drop_caches"; "3"]])],
2348    "drop kernel page cache, dentries and inodes",
2349    "\
2350 This instructs the guest kernel to drop its page cache,
2351 and/or dentries and inode caches.  The parameter C<whattodrop>
2352 tells the kernel what precisely to drop, see
2353 L<http://linux-mm.org/Drop_Caches>
2354
2355 Setting C<whattodrop> to 3 should drop everything.
2356
2357 This automatically calls L<sync(2)> before the operation,
2358 so that the maximum guest memory is freed.");
2359
2360   ("dmesg", (RString "kmsgs", []), 91, [],
2361    [InitEmpty, Always, TestRun (
2362       [["dmesg"]])],
2363    "return kernel messages",
2364    "\
2365 This returns the kernel messages (C<dmesg> output) from
2366 the guest kernel.  This is sometimes useful for extended
2367 debugging of problems.
2368
2369 Another way to get the same information is to enable
2370 verbose messages with C<guestfs_set_verbose> or by setting
2371 the environment variable C<LIBGUESTFS_DEBUG=1> before
2372 running the program.");
2373
2374   ("ping_daemon", (RErr, []), 92, [],
2375    [InitEmpty, Always, TestRun (
2376       [["ping_daemon"]])],
2377    "ping the guest daemon",
2378    "\
2379 This is a test probe into the guestfs daemon running inside
2380 the qemu subprocess.  Calling this function checks that the
2381 daemon responds to the ping message, without affecting the daemon
2382 or attached block device(s) in any other way.");
2383
2384   ("equal", (RBool "equality", [Pathname "file1"; Pathname "file2"]), 93, [],
2385    [InitBasicFS, Always, TestOutputTrue (
2386       [["write_file"; "/file1"; "contents of a file"; "0"];
2387        ["cp"; "/file1"; "/file2"];
2388        ["equal"; "/file1"; "/file2"]]);
2389     InitBasicFS, Always, TestOutputFalse (
2390       [["write_file"; "/file1"; "contents of a file"; "0"];
2391        ["write_file"; "/file2"; "contents of another file"; "0"];
2392        ["equal"; "/file1"; "/file2"]]);
2393     InitBasicFS, Always, TestLastFail (
2394       [["equal"; "/file1"; "/file2"]])],
2395    "test if two files have equal contents",
2396    "\
2397 This compares the two files C<file1> and C<file2> and returns
2398 true if their content is exactly equal, or false otherwise.
2399
2400 The external L<cmp(1)> program is used for the comparison.");
2401
2402   ("strings", (RStringList "stringsout", [Pathname "path"]), 94, [ProtocolLimitWarning],
2403    [InitISOFS, Always, TestOutputList (
2404       [["strings"; "/known-5"]], ["abcdefghi"; "jklmnopqr"]);
2405     InitISOFS, Always, TestOutputList (
2406       [["strings"; "/empty"]], [])],
2407    "print the printable strings in a file",
2408    "\
2409 This runs the L<strings(1)> command on a file and returns
2410 the list of printable strings found.");
2411
2412   ("strings_e", (RStringList "stringsout", [String "encoding"; Pathname "path"]), 95, [ProtocolLimitWarning],
2413    [InitISOFS, Always, TestOutputList (
2414       [["strings_e"; "b"; "/known-5"]], []);
2415     InitBasicFS, Disabled, TestOutputList (
2416       [["write_file"; "/new"; "\000h\000e\000l\000l\000o\000\n\000w\000o\000r\000l\000d\000\n"; "24"];
2417        ["strings_e"; "b"; "/new"]], ["hello"; "world"])],
2418    "print the printable strings in a file",
2419    "\
2420 This is like the C<guestfs_strings> command, but allows you to
2421 specify the encoding.
2422
2423 See the L<strings(1)> manpage for the full list of encodings.
2424
2425 Commonly useful encodings are C<l> (lower case L) which will
2426 show strings inside Windows/x86 files.
2427
2428 The returned strings are transcoded to UTF-8.");
2429
2430   ("hexdump", (RString "dump", [Pathname "path"]), 96, [ProtocolLimitWarning],
2431    [InitISOFS, Always, TestOutput (
2432       [["hexdump"; "/known-4"]], "00000000  61 62 63 0a 64 65 66 0a  67 68 69                 |abc.def.ghi|\n0000000b\n");
2433     (* Test for RHBZ#501888c2 regression which caused large hexdump
2434      * commands to segfault.
2435      *)
2436     InitISOFS, Always, TestRun (
2437       [["hexdump"; "/100krandom"]])],
2438    "dump a file in hexadecimal",
2439    "\
2440 This runs C<hexdump -C> on the given C<path>.  The result is
2441 the human-readable, canonical hex dump of the file.");
2442
2443   ("zerofree", (RErr, [Device "device"]), 97, [Optional "zerofree"],
2444    [InitNone, Always, TestOutput (
2445       [["part_disk"; "/dev/sda"; "mbr"];
2446        ["mkfs"; "ext3"; "/dev/sda1"];
2447        ["mount_options"; ""; "/dev/sda1"; "/"];
2448        ["write_file"; "/new"; "test file"; "0"];
2449        ["umount"; "/dev/sda1"];
2450        ["zerofree"; "/dev/sda1"];
2451        ["mount_options"; ""; "/dev/sda1"; "/"];
2452        ["cat"; "/new"]], "test file")],
2453    "zero unused inodes and disk blocks on ext2/3 filesystem",
2454    "\
2455 This runs the I<zerofree> program on C<device>.  This program
2456 claims to zero unused inodes and disk blocks on an ext2/3
2457 filesystem, thus making it possible to compress the filesystem
2458 more effectively.
2459
2460 You should B<not> run this program if the filesystem is
2461 mounted.
2462
2463 It is possible that using this program can damage the filesystem
2464 or data on the filesystem.");
2465
2466   ("pvresize", (RErr, [Device "device"]), 98, [Optional "lvm2"],
2467    [],
2468    "resize an LVM physical volume",
2469    "\
2470 This resizes (expands or shrinks) an existing LVM physical
2471 volume to match the new size of the underlying device.");
2472
2473   ("sfdisk_N", (RErr, [Device "device"; Int "partnum";
2474                        Int "cyls"; Int "heads"; Int "sectors";
2475                        String "line"]), 99, [DangerWillRobinson],
2476    [],
2477    "modify a single partition on a block device",
2478    "\
2479 This runs L<sfdisk(8)> option to modify just the single
2480 partition C<n> (note: C<n> counts from 1).
2481
2482 For other parameters, see C<guestfs_sfdisk>.  You should usually
2483 pass C<0> for the cyls/heads/sectors parameters.
2484
2485 See also: C<guestfs_part_add>");
2486
2487   ("sfdisk_l", (RString "partitions", [Device "device"]), 100, [],
2488    [],
2489    "display the partition table",
2490    "\
2491 This displays the partition table on C<device>, in the
2492 human-readable output of the L<sfdisk(8)> command.  It is
2493 not intended to be parsed.
2494
2495 See also: C<guestfs_part_list>");
2496
2497   ("sfdisk_kernel_geometry", (RString "partitions", [Device "device"]), 101, [],
2498    [],
2499    "display the kernel geometry",
2500    "\
2501 This displays the kernel's idea of the geometry of C<device>.
2502
2503 The result is in human-readable format, and not designed to
2504 be parsed.");
2505
2506   ("sfdisk_disk_geometry", (RString "partitions", [Device "device"]), 102, [],
2507    [],
2508    "display the disk geometry from the partition table",
2509    "\
2510 This displays the disk geometry of C<device> read from the
2511 partition table.  Especially in the case where the underlying
2512 block device has been resized, this can be different from the
2513 kernel's idea of the geometry (see C<guestfs_sfdisk_kernel_geometry>).
2514
2515 The result is in human-readable format, and not designed to
2516 be parsed.");
2517
2518   ("vg_activate_all", (RErr, [Bool "activate"]), 103, [Optional "lvm2"],
2519    [],
2520    "activate or deactivate all volume groups",
2521    "\
2522 This command activates or (if C<activate> is false) deactivates
2523 all logical volumes in all volume groups.
2524 If activated, then they are made known to the
2525 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2526 then those devices disappear.
2527
2528 This command is the same as running C<vgchange -a y|n>");
2529
2530   ("vg_activate", (RErr, [Bool "activate"; StringList "volgroups"]), 104, [Optional "lvm2"],
2531    [],
2532    "activate or deactivate some volume groups",
2533    "\
2534 This command activates or (if C<activate> is false) deactivates
2535 all logical volumes in the listed volume groups C<volgroups>.
2536 If activated, then they are made known to the
2537 kernel, ie. they appear as C</dev/mapper> devices.  If deactivated,
2538 then those devices disappear.
2539
2540 This command is the same as running C<vgchange -a y|n volgroups...>
2541
2542 Note that if C<volgroups> is an empty list then B<all> volume groups
2543 are activated or deactivated.");
2544
2545   ("lvresize", (RErr, [Device "device"; Int "mbytes"]), 105, [Optional "lvm2"],
2546    [InitNone, Always, TestOutput (
2547       [["part_disk"; "/dev/sda"; "mbr"];
2548        ["pvcreate"; "/dev/sda1"];
2549        ["vgcreate"; "VG"; "/dev/sda1"];
2550        ["lvcreate"; "LV"; "VG"; "10"];
2551        ["mkfs"; "ext2"; "/dev/VG/LV"];
2552        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2553        ["write_file"; "/new"; "test content"; "0"];
2554        ["umount"; "/"];
2555        ["lvresize"; "/dev/VG/LV"; "20"];
2556        ["e2fsck_f"; "/dev/VG/LV"];
2557        ["resize2fs"; "/dev/VG/LV"];
2558        ["mount_options"; ""; "/dev/VG/LV"; "/"];
2559        ["cat"; "/new"]], "test content")],
2560    "resize an LVM logical volume",
2561    "\
2562 This resizes (expands or shrinks) an existing LVM logical
2563 volume to C<mbytes>.  When reducing, data in the reduced part
2564 is lost.");
2565
2566   ("resize2fs", (RErr, [Device "device"]), 106, [],
2567    [], (* lvresize tests this *)
2568    "resize an ext2/ext3 filesystem",
2569    "\
2570 This resizes an ext2 or ext3 filesystem to match the size of
2571 the underlying device.
2572
2573 I<Note:> It is sometimes required that you run C<guestfs_e2fsck_f>
2574 on the C<device> before calling this command.  For unknown reasons
2575 C<resize2fs> sometimes gives an error about this and sometimes not.
2576 In any case, it is always safe to call C<guestfs_e2fsck_f> before
2577 calling this function.");
2578
2579   ("find", (RStringList "names", [Pathname "directory"]), 107, [ProtocolLimitWarning],
2580    [InitBasicFS, Always, TestOutputList (
2581       [["find"; "/"]], ["lost+found"]);
2582     InitBasicFS, Always, TestOutputList (
2583       [["touch"; "/a"];
2584        ["mkdir"; "/b"];
2585        ["touch"; "/b/c"];
2586        ["find"; "/"]], ["a"; "b"; "b/c"; "lost+found"]);
2587     InitBasicFS, Always, TestOutputList (
2588       [["mkdir_p"; "/a/b/c"];
2589        ["touch"; "/a/b/c/d"];
2590        ["find"; "/a/b/"]], ["c"; "c/d"])],
2591    "find all files and directories",
2592    "\
2593 This command lists out all files and directories, recursively,
2594 starting at C<directory>.  It is essentially equivalent to
2595 running the shell command C<find directory -print> but some
2596 post-processing happens on the output, described below.
2597
2598 This returns a list of strings I<without any prefix>.  Thus
2599 if the directory structure was:
2600
2601  /tmp/a
2602  /tmp/b
2603  /tmp/c/d
2604
2605 then the returned list from C<guestfs_find> C</tmp> would be
2606 4 elements:
2607
2608  a
2609  b
2610  c
2611  c/d
2612
2613 If C<directory> is not a directory, then this command returns
2614 an error.
2615
2616 The returned list is sorted.
2617
2618 See also C<guestfs_find0>.");
2619
2620   ("e2fsck_f", (RErr, [Device "device"]), 108, [],
2621    [], (* lvresize tests this *)
2622    "check an ext2/ext3 filesystem",
2623    "\
2624 This runs C<e2fsck -p -f device>, ie. runs the ext2/ext3
2625 filesystem checker on C<device>, noninteractively (C<-p>),
2626 even if the filesystem appears to be clean (C<-f>).
2627
2628 This command is only needed because of C<guestfs_resize2fs>
2629 (q.v.).  Normally you should use C<guestfs_fsck>.");
2630
2631   ("sleep", (RErr, [Int "secs"]), 109, [],
2632    [InitNone, Always, TestRun (
2633       [["sleep"; "1"]])],
2634    "sleep for some seconds",
2635    "\
2636 Sleep for C<secs> seconds.");
2637
2638   ("ntfs_3g_probe", (RInt "status", [Bool "rw"; Device "device"]), 110, [Optional "ntfs3g"],
2639    [InitNone, Always, TestOutputInt (
2640       [["part_disk"; "/dev/sda"; "mbr"];
2641        ["mkfs"; "ntfs"; "/dev/sda1"];
2642        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 0);
2643     InitNone, Always, TestOutputInt (
2644       [["part_disk"; "/dev/sda"; "mbr"];
2645        ["mkfs"; "ext2"; "/dev/sda1"];
2646        ["ntfs_3g_probe"; "true"; "/dev/sda1"]], 12)],
2647    "probe NTFS volume",
2648    "\
2649 This command runs the L<ntfs-3g.probe(8)> command which probes
2650 an NTFS C<device> for mountability.  (Not all NTFS volumes can
2651 be mounted read-write, and some cannot be mounted at all).
2652
2653 C<rw> is a boolean flag.  Set it to true if you want to test
2654 if the volume can be mounted read-write.  Set it to false if
2655 you want to test if the volume can be mounted read-only.
2656
2657 The return value is an integer which C<0> if the operation
2658 would succeed, or some non-zero value documented in the
2659 L<ntfs-3g.probe(8)> manual page.");
2660
2661   ("sh", (RString "output", [String "command"]), 111, [],
2662    [], (* XXX needs tests *)
2663    "run a command via the shell",
2664    "\
2665 This call runs a command from the guest filesystem via the
2666 guest's C</bin/sh>.
2667
2668 This is like C<guestfs_command>, but passes the command to:
2669
2670  /bin/sh -c \"command\"
2671
2672 Depending on the guest's shell, this usually results in
2673 wildcards being expanded, shell expressions being interpolated
2674 and so on.
2675
2676 All the provisos about C<guestfs_command> apply to this call.");
2677
2678   ("sh_lines", (RStringList "lines", [String "command"]), 112, [],
2679    [], (* XXX needs tests *)
2680    "run a command via the shell returning lines",
2681    "\
2682 This is the same as C<guestfs_sh>, but splits the result
2683 into a list of lines.
2684
2685 See also: C<guestfs_command_lines>");
2686
2687   ("glob_expand", (RStringList "paths", [Pathname "pattern"]), 113, [],
2688    (* Use Pathname here, and hence ABS_PATH (pattern,... in generated
2689     * code in stubs.c, since all valid glob patterns must start with "/".
2690     * There is no concept of "cwd" in libguestfs, hence no "."-relative names.
2691     *)
2692    [InitBasicFS, Always, TestOutputList (
2693       [["mkdir_p"; "/a/b/c"];
2694        ["touch"; "/a/b/c/d"];
2695        ["touch"; "/a/b/c/e"];
2696        ["glob_expand"; "/a/b/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2697     InitBasicFS, Always, TestOutputList (
2698       [["mkdir_p"; "/a/b/c"];
2699        ["touch"; "/a/b/c/d"];
2700        ["touch"; "/a/b/c/e"];
2701        ["glob_expand"; "/a/*/c/*"]], ["/a/b/c/d"; "/a/b/c/e"]);
2702     InitBasicFS, Always, TestOutputList (
2703       [["mkdir_p"; "/a/b/c"];
2704        ["touch"; "/a/b/c/d"];
2705        ["touch"; "/a/b/c/e"];
2706        ["glob_expand"; "/a/*/x/*"]], [])],
2707    "expand a wildcard path",
2708    "\
2709 This command searches for all the pathnames matching
2710 C<pattern> according to the wildcard expansion rules
2711 used by the shell.
2712
2713 If no paths match, then this returns an empty list
2714 (note: not an error).
2715
2716 It is just a wrapper around the C L<glob(3)> function
2717 with flags C<GLOB_MARK|GLOB_BRACE>.
2718 See that manual page for more details.");
2719
2720   ("scrub_device", (RErr, [Device "device"]), 114, [DangerWillRobinson; Optional "scrub"],
2721    [InitNone, Always, TestRun ( (* use /dev/sdc because it's smaller *)
2722       [["scrub_device"; "/dev/sdc"]])],
2723    "scrub (securely wipe) a device",
2724    "\
2725 This command writes patterns over C<device> to make data retrieval
2726 more difficult.
2727
2728 It is an interface to the L<scrub(1)> program.  See that
2729 manual page for more details.");
2730
2731   ("scrub_file", (RErr, [Pathname "file"]), 115, [Optional "scrub"],
2732    [InitBasicFS, Always, TestRun (
2733       [["write_file"; "/file"; "content"; "0"];
2734        ["scrub_file"; "/file"]])],
2735    "scrub (securely wipe) a file",
2736    "\
2737 This command writes patterns over a file to make data retrieval
2738 more difficult.
2739
2740 The file is I<removed> after scrubbing.
2741
2742 It is an interface to the L<scrub(1)> program.  See that
2743 manual page for more details.");
2744
2745   ("scrub_freespace", (RErr, [Pathname "dir"]), 116, [Optional "scrub"],
2746    [], (* XXX needs testing *)
2747    "scrub (securely wipe) free space",
2748    "\
2749 This command creates the directory C<dir> and then fills it
2750 with files until the filesystem is full, and scrubs the files
2751 as for C<guestfs_scrub_file>, and deletes them.
2752 The intention is to scrub any free space on the partition
2753 containing C<dir>.
2754
2755 It is an interface to the L<scrub(1)> program.  See that
2756 manual page for more details.");
2757
2758   ("mkdtemp", (RString "dir", [Pathname "template"]), 117, [],
2759    [InitBasicFS, Always, TestRun (
2760       [["mkdir"; "/tmp"];
2761        ["mkdtemp"; "/tmp/tmpXXXXXX"]])],
2762    "create a temporary directory",
2763    "\
2764 This command creates a temporary directory.  The
2765 C<template> parameter should be a full pathname for the
2766 temporary directory name with the final six characters being
2767 \"XXXXXX\".
2768
2769 For example: \"/tmp/myprogXXXXXX\" or \"/Temp/myprogXXXXXX\",
2770 the second one being suitable for Windows filesystems.
2771
2772 The name of the temporary directory that was created
2773 is returned.
2774
2775 The temporary directory is created with mode 0700
2776 and is owned by root.
2777
2778 The caller is responsible for deleting the temporary
2779 directory and its contents after use.
2780
2781 See also: L<mkdtemp(3)>");
2782
2783   ("wc_l", (RInt "lines", [Pathname "path"]), 118, [],
2784    [InitISOFS, Always, TestOutputInt (
2785       [["wc_l"; "/10klines"]], 10000)],
2786    "count lines in a file",
2787    "\
2788 This command counts the lines in a file, using the
2789 C<wc -l> external command.");
2790
2791   ("wc_w", (RInt "words", [Pathname "path"]), 119, [],
2792    [InitISOFS, Always, TestOutputInt (
2793       [["wc_w"; "/10klines"]], 10000)],
2794    "count words in a file",
2795    "\
2796 This command counts the words in a file, using the
2797 C<wc -w> external command.");
2798
2799   ("wc_c", (RInt "chars", [Pathname "path"]), 120, [],
2800    [InitISOFS, Always, TestOutputInt (
2801       [["wc_c"; "/100kallspaces"]], 102400)],
2802    "count characters in a file",
2803    "\
2804 This command counts the characters in a file, using the
2805 C<wc -c> external command.");
2806
2807   ("head", (RStringList "lines", [Pathname "path"]), 121, [ProtocolLimitWarning],
2808    [InitISOFS, Always, TestOutputList (
2809       [["head"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz";"3abcdefghijklmnopqrstuvwxyz";"4abcdefghijklmnopqrstuvwxyz";"5abcdefghijklmnopqrstuvwxyz";"6abcdefghijklmnopqrstuvwxyz";"7abcdefghijklmnopqrstuvwxyz";"8abcdefghijklmnopqrstuvwxyz";"9abcdefghijklmnopqrstuvwxyz"])],
2810    "return first 10 lines of a file",
2811    "\
2812 This command returns up to the first 10 lines of a file as
2813 a list of strings.");
2814
2815   ("head_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 122, [ProtocolLimitWarning],
2816    [InitISOFS, Always, TestOutputList (
2817       [["head_n"; "3"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2818     InitISOFS, Always, TestOutputList (
2819       [["head_n"; "-9997"; "/10klines"]], ["0abcdefghijklmnopqrstuvwxyz";"1abcdefghijklmnopqrstuvwxyz";"2abcdefghijklmnopqrstuvwxyz"]);
2820     InitISOFS, Always, TestOutputList (
2821       [["head_n"; "0"; "/10klines"]], [])],
2822    "return first N lines of a file",
2823    "\
2824 If the parameter C<nrlines> is a positive number, this returns the first
2825 C<nrlines> lines of the file C<path>.
2826
2827 If the parameter C<nrlines> is a negative number, this returns lines
2828 from the file C<path>, excluding the last C<nrlines> lines.
2829
2830 If the parameter C<nrlines> is zero, this returns an empty list.");
2831
2832   ("tail", (RStringList "lines", [Pathname "path"]), 123, [ProtocolLimitWarning],
2833    [InitISOFS, Always, TestOutputList (
2834       [["tail"; "/10klines"]], ["9990abcdefghijklmnopqrstuvwxyz";"9991abcdefghijklmnopqrstuvwxyz";"9992abcdefghijklmnopqrstuvwxyz";"9993abcdefghijklmnopqrstuvwxyz";"9994abcdefghijklmnopqrstuvwxyz";"9995abcdefghijklmnopqrstuvwxyz";"9996abcdefghijklmnopqrstuvwxyz";"9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"])],
2835    "return last 10 lines of a file",
2836    "\
2837 This command returns up to the last 10 lines of a file as
2838 a list of strings.");
2839
2840   ("tail_n", (RStringList "lines", [Int "nrlines"; Pathname "path"]), 124, [ProtocolLimitWarning],
2841    [InitISOFS, Always, TestOutputList (
2842       [["tail_n"; "3"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2843     InitISOFS, Always, TestOutputList (
2844       [["tail_n"; "-9998"; "/10klines"]], ["9997abcdefghijklmnopqrstuvwxyz";"9998abcdefghijklmnopqrstuvwxyz";"9999abcdefghijklmnopqrstuvwxyz"]);
2845     InitISOFS, Always, TestOutputList (
2846       [["tail_n"; "0"; "/10klines"]], [])],
2847    "return last N lines of a file",
2848    "\
2849 If the parameter C<nrlines> is a positive number, this returns the last
2850 C<nrlines> lines of the file C<path>.
2851
2852 If the parameter C<nrlines> is a negative number, this returns lines
2853 from the file C<path>, starting with the C<-nrlines>th line.
2854
2855 If the parameter C<nrlines> is zero, this returns an empty list.");
2856
2857   ("df", (RString "output", []), 125, [],
2858    [], (* XXX Tricky to test because it depends on the exact format
2859         * of the 'df' command and other imponderables.
2860         *)
2861    "report file system disk space usage",
2862    "\
2863 This command runs the C<df> command to report disk space used.
2864
2865 This command is mostly useful for interactive sessions.  It
2866 is I<not> intended that you try to parse the output string.
2867 Use C<statvfs> from programs.");
2868
2869   ("df_h", (RString "output", []), 126, [],
2870    [], (* XXX Tricky to test because it depends on the exact format
2871         * of the 'df' command and other imponderables.
2872         *)
2873    "report file system disk space usage (human readable)",
2874    "\
2875 This command runs the C<df -h> command to report disk space used
2876 in human-readable format.
2877
2878 This command is mostly useful for interactive sessions.  It
2879 is I<not> intended that you try to parse the output string.
2880 Use C<statvfs> from programs.");
2881
2882   ("du", (RInt64 "sizekb", [Pathname "path"]), 127, [],
2883    [InitISOFS, Always, TestOutputInt (
2884       [["du"; "/directory"]], 2 (* ISO fs blocksize is 2K *))],
2885    "estimate file space usage",
2886    "\
2887 This command runs the C<du -s> command to estimate file space
2888 usage for C<path>.
2889
2890 C<path> can be a file or a directory.  If C<path> is a directory
2891 then the estimate includes the contents of the directory and all
2892 subdirectories (recursively).
2893
2894 The result is the estimated size in I<kilobytes>
2895 (ie. units of 1024 bytes).");
2896
2897   ("initrd_list", (RStringList "filenames", [Pathname "path"]), 128, [],
2898    [InitISOFS, Always, TestOutputList (
2899       [["initrd_list"; "/initrd"]], ["empty";"known-1";"known-2";"known-3";"known-4"; "known-5"])],
2900    "list files in an initrd",
2901    "\
2902 This command lists out files contained in an initrd.
2903
2904 The files are listed without any initial C</> character.  The
2905 files are listed in the order they appear (not necessarily
2906 alphabetical).  Directory names are listed as separate items.
2907
2908 Old Linux kernels (2.4 and earlier) used a compressed ext2
2909 filesystem as initrd.  We I<only> support the newer initramfs
2910 format (compressed cpio files).");
2911
2912   ("mount_loop", (RErr, [Pathname "file"; Pathname "mountpoint"]), 129, [],
2913    [],
2914    "mount a file using the loop device",
2915    "\
2916 This command lets you mount C<file> (a filesystem image
2917 in a file) on a mount point.  It is entirely equivalent to
2918 the command C<mount -o loop file mountpoint>.");
2919
2920   ("mkswap", (RErr, [Device "device"]), 130, [],
2921    [InitEmpty, Always, TestRun (
2922       [["part_disk"; "/dev/sda"; "mbr"];
2923        ["mkswap"; "/dev/sda1"]])],
2924    "create a swap partition",
2925    "\
2926 Create a swap partition on C<device>.");
2927
2928   ("mkswap_L", (RErr, [String "label"; Device "device"]), 131, [],
2929    [InitEmpty, Always, TestRun (
2930       [["part_disk"; "/dev/sda"; "mbr"];
2931        ["mkswap_L"; "hello"; "/dev/sda1"]])],
2932    "create a swap partition with a label",
2933    "\
2934 Create a swap partition on C<device> with label C<label>.
2935
2936 Note that you cannot attach a swap label to a block device
2937 (eg. C</dev/sda>), just to a partition.  This appears to be
2938 a limitation of the kernel or swap tools.");
2939
2940   ("mkswap_U", (RErr, [String "uuid"; Device "device"]), 132, [Optional "linuxfsuuid"],
2941    (let uuid = uuidgen () in
2942     [InitEmpty, Always, TestRun (
2943        [["part_disk"; "/dev/sda"; "mbr"];
2944         ["mkswap_U"; uuid; "/dev/sda1"]])]),
2945    "create a swap partition with an explicit UUID",
2946    "\
2947 Create a swap partition on C<device> with UUID C<uuid>.");
2948
2949   ("mknod", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 133, [Optional "mknod"],
2950    [InitBasicFS, Always, TestOutputStruct (
2951       [["mknod"; "0o10777"; "0"; "0"; "/node"];
2952        (* NB: default umask 022 means 0777 -> 0755 in these tests *)
2953        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)]);
2954     InitBasicFS, Always, TestOutputStruct (
2955       [["mknod"; "0o60777"; "66"; "99"; "/node"];
2956        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2957    "make block, character or FIFO devices",
2958    "\
2959 This call creates block or character special devices, or
2960 named pipes (FIFOs).
2961
2962 The C<mode> parameter should be the mode, using the standard
2963 constants.  C<devmajor> and C<devminor> are the
2964 device major and minor numbers, only used when creating block
2965 and character special devices.");
2966
2967   ("mkfifo", (RErr, [Int "mode"; Pathname "path"]), 134, [Optional "mknod"],
2968    [InitBasicFS, Always, TestOutputStruct (
2969       [["mkfifo"; "0o777"; "/node"];
2970        ["stat"; "/node"]], [CompareWithInt ("mode", 0o10755)])],
2971    "make FIFO (named pipe)",
2972    "\
2973 This call creates a FIFO (named pipe) called C<path> with
2974 mode C<mode>.  It is just a convenient wrapper around
2975 C<guestfs_mknod>.");
2976
2977   ("mknod_b", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 135, [Optional "mknod"],
2978    [InitBasicFS, Always, TestOutputStruct (
2979       [["mknod_b"; "0o777"; "99"; "66"; "/node"];
2980        ["stat"; "/node"]], [CompareWithInt ("mode", 0o60755)])],
2981    "make block device node",
2982    "\
2983 This call creates a block device node called C<path> with
2984 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2985 It is just a convenient wrapper around C<guestfs_mknod>.");
2986
2987   ("mknod_c", (RErr, [Int "mode"; Int "devmajor"; Int "devminor"; Pathname "path"]), 136, [Optional "mknod"],
2988    [InitBasicFS, Always, TestOutputStruct (
2989       [["mknod_c"; "0o777"; "99"; "66"; "/node"];
2990        ["stat"; "/node"]], [CompareWithInt ("mode", 0o20755)])],
2991    "make char device node",
2992    "\
2993 This call creates a char device node called C<path> with
2994 mode C<mode> and device major/minor C<devmajor> and C<devminor>.
2995 It is just a convenient wrapper around C<guestfs_mknod>.");
2996
2997   ("umask", (RInt "oldmask", [Int "mask"]), 137, [],
2998    [], (* XXX umask is one of those stateful things that we should
2999         * reset between each test.
3000         *)
3001    "set file mode creation mask (umask)",
3002    "\
3003 This function sets the mask used for creating new files and
3004 device nodes to C<mask & 0777>.
3005
3006 Typical umask values would be C<022> which creates new files
3007 with permissions like \"-rw-r--r--\" or \"-rwxr-xr-x\", and
3008 C<002> which creates new files with permissions like
3009 \"-rw-rw-r--\" or \"-rwxrwxr-x\".
3010
3011 The default umask is C<022>.  This is important because it
3012 means that directories and device nodes will be created with
3013 C<0644> or C<0755> mode even if you specify C<0777>.
3014
3015 See also L<umask(2)>, C<guestfs_mknod>, C<guestfs_mkdir>.
3016
3017 This call returns the previous umask.");
3018
3019   ("readdir", (RStructList ("entries", "dirent"), [Pathname "dir"]), 138, [],
3020    [],
3021    "read directories entries",
3022    "\
3023 This returns the list of directory entries in directory C<dir>.
3024
3025 All entries in the directory are returned, including C<.> and
3026 C<..>.  The entries are I<not> sorted, but returned in the same
3027 order as the underlying filesystem.
3028
3029 Also this call returns basic file type information about each
3030 file.  The C<ftyp> field will contain one of the following characters:
3031
3032 =over 4
3033
3034 =item 'b'
3035
3036 Block special
3037
3038 =item 'c'
3039
3040 Char special
3041
3042 =item 'd'
3043
3044 Directory
3045
3046 =item 'f'
3047
3048 FIFO (named pipe)
3049
3050 =item 'l'
3051
3052 Symbolic link
3053
3054 =item 'r'
3055
3056 Regular file
3057
3058 =item 's'
3059
3060 Socket
3061
3062 =item 'u'
3063
3064 Unknown file type
3065
3066 =item '?'
3067
3068 The L<readdir(3)> returned a C<d_type> field with an
3069 unexpected value
3070
3071 =back
3072
3073 This function is primarily intended for use by programs.  To
3074 get a simple list of names, use C<guestfs_ls>.  To get a printable
3075 directory for human consumption, use C<guestfs_ll>.");
3076
3077   ("sfdiskM", (RErr, [Device "device"; StringList "lines"]), 139, [DangerWillRobinson],
3078    [],
3079    "create partitions on a block device",
3080    "\
3081 This is a simplified interface to the C<guestfs_sfdisk>
3082 command, where partition sizes are specified in megabytes
3083 only (rounded to the nearest cylinder) and you don't need
3084 to specify the cyls, heads and sectors parameters which
3085 were rarely if ever used anyway.
3086
3087 See also: C<guestfs_sfdisk>, the L<sfdisk(8)> manpage
3088 and C<guestfs_part_disk>");
3089
3090   ("zfile", (RString "description", [String "meth"; Pathname "path"]), 140, [DeprecatedBy "file"],
3091    [],
3092    "determine file type inside a compressed file",
3093    "\
3094 This command runs C<file> after first decompressing C<path>
3095 using C<method>.
3096
3097 C<method> must be one of C<gzip>, C<compress> or C<bzip2>.
3098
3099 Since 1.0.63, use C<guestfs_file> instead which can now
3100 process compressed files.");
3101
3102   ("getxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 141, [Optional "linuxxattrs"],
3103    [],
3104    "list extended attributes of a file or directory",
3105    "\
3106 This call lists the extended attributes of the file or directory
3107 C<path>.
3108
3109 At the system call level, this is a combination of the
3110 L<listxattr(2)> and L<getxattr(2)> calls.
3111
3112 See also: C<guestfs_lgetxattrs>, L<attr(5)>.");
3113
3114   ("lgetxattrs", (RStructList ("xattrs", "xattr"), [Pathname "path"]), 142, [Optional "linuxxattrs"],
3115    [],
3116    "list extended attributes of a file or directory",
3117    "\
3118 This is the same as C<guestfs_getxattrs>, but if C<path>
3119 is a symbolic link, then it returns the extended attributes
3120 of the link itself.");
3121
3122   ("setxattr", (RErr, [String "xattr";
3123                        String "val"; Int "vallen"; (* will be BufferIn *)
3124                        Pathname "path"]), 143, [Optional "linuxxattrs"],
3125    [],
3126    "set extended attribute of a file or directory",
3127    "\
3128 This call sets the extended attribute named C<xattr>
3129 of the file C<path> to the value C<val> (of length C<vallen>).
3130 The value is arbitrary 8 bit data.
3131
3132 See also: C<guestfs_lsetxattr>, L<attr(5)>.");
3133
3134   ("lsetxattr", (RErr, [String "xattr";
3135                         String "val"; Int "vallen"; (* will be BufferIn *)
3136                         Pathname "path"]), 144, [Optional "linuxxattrs"],
3137    [],
3138    "set extended attribute of a file or directory",
3139    "\
3140 This is the same as C<guestfs_setxattr>, but if C<path>
3141 is a symbolic link, then it sets an extended attribute
3142 of the link itself.");
3143
3144   ("removexattr", (RErr, [String "xattr"; Pathname "path"]), 145, [Optional "linuxxattrs"],
3145    [],
3146    "remove extended attribute of a file or directory",
3147    "\
3148 This call removes the extended attribute named C<xattr>
3149 of the file C<path>.
3150
3151 See also: C<guestfs_lremovexattr>, L<attr(5)>.");
3152
3153   ("lremovexattr", (RErr, [String "xattr"; Pathname "path"]), 146, [Optional "linuxxattrs"],
3154    [],
3155    "remove extended attribute of a file or directory",
3156    "\
3157 This is the same as C<guestfs_removexattr>, but if C<path>
3158 is a symbolic link, then it removes an extended attribute
3159 of the link itself.");
3160
3161   ("mountpoints", (RHashtable "mps", []), 147, [],
3162    [],
3163    "show mountpoints",
3164    "\
3165 This call is similar to C<guestfs_mounts>.  That call returns
3166 a list of devices.  This one returns a hash table (map) of
3167 device name to directory where the device is mounted.");
3168
3169   ("mkmountpoint", (RErr, [String "exemptpath"]), 148, [],
3170    (* This is a special case: while you would expect a parameter
3171     * of type "Pathname", that doesn't work, because it implies
3172     * NEED_ROOT in the generated calling code in stubs.c, and
3173     * this function cannot use NEED_ROOT.
3174     *)
3175    [],
3176    "create a mountpoint",
3177    "\
3178 C<guestfs_mkmountpoint> and C<guestfs_rmmountpoint> are
3179 specialized calls that can be used to create extra mountpoints
3180 before mounting the first filesystem.
3181
3182 These calls are I<only> necessary in some very limited circumstances,
3183 mainly the case where you want to mount a mix of unrelated and/or
3184 read-only filesystems together.
3185
3186 For example, live CDs often contain a \"Russian doll\" nest of
3187 filesystems, an ISO outer layer, with a squashfs image inside, with
3188 an ext2/3 image inside that.  You can unpack this as follows
3189 in guestfish:
3190
3191  add-ro Fedora-11-i686-Live.iso
3192  run
3193  mkmountpoint /cd
3194  mkmountpoint /squash
3195  mkmountpoint /ext3
3196  mount /dev/sda /cd
3197  mount-loop /cd/LiveOS/squashfs.img /squash
3198  mount-loop /squash/LiveOS/ext3fs.img /ext3
3199
3200 The inner filesystem is now unpacked under the /ext3 mountpoint.");
3201
3202   ("rmmountpoint", (RErr, [String "exemptpath"]), 149, [],
3203    [],
3204    "remove a mountpoint",
3205    "\
3206 This calls removes a mountpoint that was previously created
3207 with C<guestfs_mkmountpoint>.  See C<guestfs_mkmountpoint>
3208 for full details.");
3209
3210   ("read_file", (RBufferOut "content", [Pathname "path"]), 150, [ProtocolLimitWarning],
3211    [InitISOFS, Always, TestOutputBuffer (
3212       [["read_file"; "/known-4"]], "abc\ndef\nghi")],
3213    "read a file",
3214    "\
3215 This calls returns the contents of the file C<path> as a
3216 buffer.
3217
3218 Unlike C<guestfs_cat>, this function can correctly
3219 handle files that contain embedded ASCII NUL characters.
3220 However unlike C<guestfs_download>, this function is limited
3221 in the total size of file that can be handled.");
3222
3223   ("grep", (RStringList "lines", [String "regex"; Pathname "path"]), 151, [ProtocolLimitWarning],
3224    [InitISOFS, Always, TestOutputList (
3225       [["grep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"]);
3226     InitISOFS, Always, TestOutputList (
3227       [["grep"; "nomatch"; "/test-grep.txt"]], [])],
3228    "return lines matching a pattern",
3229    "\
3230 This calls the external C<grep> program and returns the
3231 matching lines.");
3232
3233   ("egrep", (RStringList "lines", [String "regex"; Pathname "path"]), 152, [ProtocolLimitWarning],
3234    [InitISOFS, Always, TestOutputList (
3235       [["egrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3236    "return lines matching a pattern",
3237    "\
3238 This calls the external C<egrep> program and returns the
3239 matching lines.");
3240
3241   ("fgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 153, [ProtocolLimitWarning],
3242    [InitISOFS, Always, TestOutputList (
3243       [["fgrep"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"])],
3244    "return lines matching a pattern",
3245    "\
3246 This calls the external C<fgrep> program and returns the
3247 matching lines.");
3248
3249   ("grepi", (RStringList "lines", [String "regex"; Pathname "path"]), 154, [ProtocolLimitWarning],
3250    [InitISOFS, Always, TestOutputList (
3251       [["grepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3252    "return lines matching a pattern",
3253    "\
3254 This calls the external C<grep -i> program and returns the
3255 matching lines.");
3256
3257   ("egrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 155, [ProtocolLimitWarning],
3258    [InitISOFS, Always, TestOutputList (
3259       [["egrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3260    "return lines matching a pattern",
3261    "\
3262 This calls the external C<egrep -i> program and returns the
3263 matching lines.");
3264
3265   ("fgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 156, [ProtocolLimitWarning],
3266    [InitISOFS, Always, TestOutputList (
3267       [["fgrepi"; "abc"; "/test-grep.txt"]], ["abc"; "abc123"; "ABC"])],
3268    "return lines matching a pattern",
3269    "\
3270 This calls the external C<fgrep -i> program and returns the
3271 matching lines.");
3272
3273   ("zgrep", (RStringList "lines", [String "regex"; Pathname "path"]), 157, [ProtocolLimitWarning],
3274    [InitISOFS, Always, TestOutputList (
3275       [["zgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3276    "return lines matching a pattern",
3277    "\
3278 This calls the external C<zgrep> program and returns the
3279 matching lines.");
3280
3281   ("zegrep", (RStringList "lines", [String "regex"; Pathname "path"]), 158, [ProtocolLimitWarning],
3282    [InitISOFS, Always, TestOutputList (
3283       [["zegrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3284    "return lines matching a pattern",
3285    "\
3286 This calls the external C<zegrep> program and returns the
3287 matching lines.");
3288
3289   ("zfgrep", (RStringList "lines", [String "pattern"; Pathname "path"]), 159, [ProtocolLimitWarning],
3290    [InitISOFS, Always, TestOutputList (
3291       [["zfgrep"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"])],
3292    "return lines matching a pattern",
3293    "\
3294 This calls the external C<zfgrep> program and returns the
3295 matching lines.");
3296
3297   ("zgrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 160, [ProtocolLimitWarning],
3298    [InitISOFS, Always, TestOutputList (
3299       [["zgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3300    "return lines matching a pattern",
3301    "\
3302 This calls the external C<zgrep -i> program and returns the
3303 matching lines.");
3304
3305   ("zegrepi", (RStringList "lines", [String "regex"; Pathname "path"]), 161, [ProtocolLimitWarning],
3306    [InitISOFS, Always, TestOutputList (
3307       [["zegrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3308    "return lines matching a pattern",
3309    "\
3310 This calls the external C<zegrep -i> program and returns the
3311 matching lines.");
3312
3313   ("zfgrepi", (RStringList "lines", [String "pattern"; Pathname "path"]), 162, [ProtocolLimitWarning],
3314    [InitISOFS, Always, TestOutputList (
3315       [["zfgrepi"; "abc"; "/test-grep.txt.gz"]], ["abc"; "abc123"; "ABC"])],
3316    "return lines matching a pattern",
3317    "\
3318 This calls the external C<zfgrep -i> program and returns the
3319 matching lines.");
3320
3321   ("realpath", (RString "rpath", [Pathname "path"]), 163, [Optional "realpath"],
3322    [InitISOFS, Always, TestOutput (
3323       [["realpath"; "/../directory"]], "/directory")],
3324    "canonicalized absolute pathname",
3325    "\
3326 Return the canonicalized absolute pathname of C<path>.  The
3327 returned path has no C<.>, C<..> or symbolic link path elements.");
3328
3329   ("ln", (RErr, [String "target"; Pathname "linkname"]), 164, [],
3330    [InitBasicFS, Always, TestOutputStruct (
3331       [["touch"; "/a"];
3332        ["ln"; "/a"; "/b"];
3333        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3334    "create a hard link",
3335    "\
3336 This command creates a hard link using the C<ln> command.");
3337
3338   ("ln_f", (RErr, [String "target"; Pathname "linkname"]), 165, [],
3339    [InitBasicFS, Always, TestOutputStruct (
3340       [["touch"; "/a"];
3341        ["touch"; "/b"];
3342        ["ln_f"; "/a"; "/b"];
3343        ["stat"; "/b"]], [CompareWithInt ("nlink", 2)])],
3344    "create a hard link",
3345    "\
3346 This command creates a hard link using the C<ln -f> command.
3347 The C<-f> option removes the link (C<linkname>) if it exists already.");
3348
3349   ("ln_s", (RErr, [String "target"; Pathname "linkname"]), 166, [],
3350    [InitBasicFS, Always, TestOutputStruct (
3351       [["touch"; "/a"];
3352        ["ln_s"; "a"; "/b"];
3353        ["lstat"; "/b"]], [CompareWithInt ("mode", 0o120777)])],
3354    "create a symbolic link",
3355    "\
3356 This command creates a symbolic link using the C<ln -s> command.");
3357
3358   ("ln_sf", (RErr, [String "target"; Pathname "linkname"]), 167, [],
3359    [InitBasicFS, Always, TestOutput (
3360       [["mkdir_p"; "/a/b"];
3361        ["touch"; "/a/b/c"];
3362        ["ln_sf"; "../d"; "/a/b/c"];
3363        ["readlink"; "/a/b/c"]], "../d")],
3364    "create a symbolic link",
3365    "\
3366 This command creates a symbolic link using the C<ln -sf> command,
3367 The C<-f> option removes the link (C<linkname>) if it exists already.");
3368
3369   ("readlink", (RString "link", [Pathname "path"]), 168, [],
3370    [] (* XXX tested above *),
3371    "read the target of a symbolic link",
3372    "\
3373 This command reads the target of a symbolic link.");
3374
3375   ("fallocate", (RErr, [Pathname "path"; Int "len"]), 169, [],
3376    [InitBasicFS, Always, TestOutputStruct (
3377       [["fallocate"; "/a"; "1000000"];
3378        ["stat"; "/a"]], [CompareWithInt ("size", 1_000_000)])],
3379    "preallocate a file in the guest filesystem",
3380    "\
3381 This command preallocates a file (containing zero bytes) named
3382 C<path> of size C<len> bytes.  If the file exists already, it
3383 is overwritten.
3384
3385 Do not confuse this with the guestfish-specific
3386 C<alloc> command which allocates a file in the host and
3387 attaches it as a device.");
3388
3389   ("swapon_device", (RErr, [Device "device"]), 170, [],
3390    [InitPartition, Always, TestRun (
3391       [["mkswap"; "/dev/sda1"];
3392        ["swapon_device"; "/dev/sda1"];
3393        ["swapoff_device"; "/dev/sda1"]])],
3394    "enable swap on device",
3395    "\
3396 This command enables the libguestfs appliance to use the
3397 swap device or partition named C<device>.  The increased
3398 memory is made available for all commands, for example
3399 those run using C<guestfs_command> or C<guestfs_sh>.
3400
3401 Note that you should not swap to existing guest swap
3402 partitions unless you know what you are doing.  They may
3403 contain hibernation information, or other information that
3404 the guest doesn't want you to trash.  You also risk leaking
3405 information about the host to the guest this way.  Instead,
3406 attach a new host device to the guest and swap on that.");
3407
3408   ("swapoff_device", (RErr, [Device "device"]), 171, [],
3409    [], (* XXX tested by swapon_device *)
3410    "disable swap on device",
3411    "\
3412 This command disables the libguestfs appliance swap
3413 device or partition named C<device>.
3414 See C<guestfs_swapon_device>.");
3415
3416   ("swapon_file", (RErr, [Pathname "file"]), 172, [],
3417    [InitBasicFS, Always, TestRun (
3418       [["fallocate"; "/swap"; "8388608"];
3419        ["mkswap_file"; "/swap"];
3420        ["swapon_file"; "/swap"];
3421        ["swapoff_file"; "/swap"]])],
3422    "enable swap on file",
3423    "\
3424 This command enables swap to a file.
3425 See C<guestfs_swapon_device> for other notes.");
3426
3427   ("swapoff_file", (RErr, [Pathname "file"]), 173, [],
3428    [], (* XXX tested by swapon_file *)
3429    "disable swap on file",
3430    "\
3431 This command disables the libguestfs appliance swap on file.");
3432
3433   ("swapon_label", (RErr, [String "label"]), 174, [],
3434    [InitEmpty, Always, TestRun (
3435       [["part_disk"; "/dev/sdb"; "mbr"];
3436        ["mkswap_L"; "swapit"; "/dev/sdb1"];
3437        ["swapon_label"; "swapit"];
3438        ["swapoff_label"; "swapit"];
3439        ["zero"; "/dev/sdb"];
3440        ["blockdev_rereadpt"; "/dev/sdb"]])],
3441    "enable swap on labeled swap partition",
3442    "\
3443 This command enables swap to a labeled swap partition.
3444 See C<guestfs_swapon_device> for other notes.");
3445
3446   ("swapoff_label", (RErr, [String "label"]), 175, [],
3447    [], (* XXX tested by swapon_label *)
3448    "disable swap on labeled swap partition",
3449    "\
3450 This command disables the libguestfs appliance swap on
3451 labeled swap partition.");
3452
3453   ("swapon_uuid", (RErr, [String "uuid"]), 176, [Optional "linuxfsuuid"],
3454    (let uuid = uuidgen () in
3455     [InitEmpty, Always, TestRun (
3456        [["mkswap_U"; uuid; "/dev/sdb"];
3457         ["swapon_uuid"; uuid];
3458         ["swapoff_uuid"; uuid]])]),
3459    "enable swap on swap partition by UUID",
3460    "\
3461 This command enables swap to a swap partition with the given UUID.
3462 See C<guestfs_swapon_device> for other notes.");
3463
3464   ("swapoff_uuid", (RErr, [String "uuid"]), 177, [Optional "linuxfsuuid"],
3465    [], (* XXX tested by swapon_uuid *)
3466    "disable swap on swap partition by UUID",
3467    "\
3468 This command disables the libguestfs appliance swap partition
3469 with the given UUID.");
3470
3471   ("mkswap_file", (RErr, [Pathname "path"]), 178, [],
3472    [InitBasicFS, Always, TestRun (
3473       [["fallocate"; "/swap"; "8388608"];
3474        ["mkswap_file"; "/swap"]])],
3475    "create a swap file",
3476    "\
3477 Create a swap file.
3478
3479 This command just writes a swap file signature to an existing
3480 file.  To create the file itself, use something like C<guestfs_fallocate>.");
3481
3482   ("inotify_init", (RErr, [Int "maxevents"]), 179, [Optional "inotify"],
3483    [InitISOFS, Always, TestRun (
3484       [["inotify_init"; "0"]])],
3485    "create an inotify handle",
3486    "\
3487 This command creates a new inotify handle.
3488 The inotify subsystem can be used to notify events which happen to
3489 objects in the guest filesystem.
3490
3491 C<maxevents> is the maximum number of events which will be
3492 queued up between calls to C<guestfs_inotify_read> or
3493 C<guestfs_inotify_files>.
3494 If this is passed as C<0>, then the kernel (or previously set)
3495 default is used.  For Linux 2.6.29 the default was 16384 events.
3496 Beyond this limit, the kernel throws away events, but records
3497 the fact that it threw them away by setting a flag
3498 C<IN_Q_OVERFLOW> in the returned structure list (see
3499 C<guestfs_inotify_read>).
3500
3501 Before any events are generated, you have to add some
3502 watches to the internal watch list.  See:
3503 C<guestfs_inotify_add_watch>,
3504 C<guestfs_inotify_rm_watch> and
3505 C<guestfs_inotify_watch_all>.
3506
3507 Queued up events should be read periodically by calling
3508 C<guestfs_inotify_read>
3509 (or C<guestfs_inotify_files> which is just a helpful
3510 wrapper around C<guestfs_inotify_read>).  If you don't
3511 read the events out often enough then you risk the internal
3512 queue overflowing.
3513
3514 The handle should be closed after use by calling
3515 C<guestfs_inotify_close>.  This also removes any
3516 watches automatically.
3517
3518 See also L<inotify(7)> for an overview of the inotify interface
3519 as exposed by the Linux kernel, which is roughly what we expose
3520 via libguestfs.  Note that there is one global inotify handle
3521 per libguestfs instance.");
3522
3523   ("inotify_add_watch", (RInt64 "wd", [Pathname "path"; Int "mask"]), 180, [Optional "inotify"],
3524    [InitBasicFS, Always, TestOutputList (
3525       [["inotify_init"; "0"];
3526        ["inotify_add_watch"; "/"; "1073741823"];
3527        ["touch"; "/a"];
3528        ["touch"; "/b"];
3529        ["inotify_files"]], ["a"; "b"])],
3530    "add an inotify watch",
3531    "\
3532 Watch C<path> for the events listed in C<mask>.
3533
3534 Note that if C<path> is a directory then events within that
3535 directory are watched, but this does I<not> happen recursively
3536 (in subdirectories).
3537
3538 Note for non-C or non-Linux callers: the inotify events are
3539 defined by the Linux kernel ABI and are listed in
3540 C</usr/include/sys/inotify.h>.");
3541
3542   ("inotify_rm_watch", (RErr, [Int(*XXX64*) "wd"]), 181, [Optional "inotify"],
3543    [],
3544    "remove an inotify watch",
3545    "\
3546 Remove a previously defined inotify watch.
3547 See C<guestfs_inotify_add_watch>.");
3548
3549   ("inotify_read", (RStructList ("events", "inotify_event"), []), 182, [Optional "inotify"],
3550    [],
3551    "return list of inotify events",
3552    "\
3553 Return the complete queue of events that have happened
3554 since the previous read call.
3555
3556 If no events have happened, this returns an empty list.
3557
3558 I<Note>: In order to make sure that all events have been
3559 read, you must call this function repeatedly until it
3560 returns an empty list.  The reason is that the call will
3561 read events up to the maximum appliance-to-host message
3562 size and leave remaining events in the queue.");
3563
3564   ("inotify_files", (RStringList "paths", []), 183, [Optional "inotify"],
3565    [],
3566    "return list of watched files that had events",
3567    "\
3568 This function is a helpful wrapper around C<guestfs_inotify_read>
3569 which just returns a list of pathnames of objects that were
3570 touched.  The returned pathnames are sorted and deduplicated.");
3571
3572   ("inotify_close", (RErr, []), 184, [Optional "inotify"],
3573    [],
3574    "close the inotify handle",
3575    "\
3576 This closes the inotify handle which was previously
3577 opened by inotify_init.  It removes all watches, throws
3578 away any pending events, and deallocates all resources.");
3579
3580   ("setcon", (RErr, [String "context"]), 185, [Optional "selinux"],
3581    [],
3582    "set SELinux security context",
3583    "\
3584 This sets the SELinux security context of the daemon
3585 to the string C<context>.
3586
3587 See the documentation about SELINUX in L<guestfs(3)>.");
3588
3589   ("getcon", (RString "context", []), 186, [Optional "selinux"],
3590    [],
3591    "get SELinux security context",
3592    "\
3593 This gets the SELinux security context of the daemon.
3594
3595 See the documentation about SELINUX in L<guestfs(3)>,
3596 and C<guestfs_setcon>");
3597
3598   ("mkfs_b", (RErr, [String "fstype"; Int "blocksize"; Device "device"]), 187, [],
3599    [InitEmpty, Always, TestOutput (
3600       [["part_disk"; "/dev/sda"; "mbr"];
3601        ["mkfs_b"; "ext2"; "4096"; "/dev/sda1"];
3602        ["mount_options"; ""; "/dev/sda1"; "/"];
3603        ["write_file"; "/new"; "new file contents"; "0"];
3604        ["cat"; "/new"]], "new file contents")],
3605    "make a filesystem with block size",
3606    "\
3607 This call is similar to C<guestfs_mkfs>, but it allows you to
3608 control the block size of the resulting filesystem.  Supported
3609 block sizes depend on the filesystem type, but typically they
3610 are C<1024>, C<2048> or C<4096> only.");
3611
3612   ("mke2journal", (RErr, [Int "blocksize"; Device "device"]), 188, [],
3613    [InitEmpty, Always, TestOutput (
3614       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3615        ["mke2journal"; "4096"; "/dev/sda1"];
3616        ["mke2fs_J"; "ext2"; "4096"; "/dev/sda2"; "/dev/sda1"];
3617        ["mount_options"; ""; "/dev/sda2"; "/"];
3618        ["write_file"; "/new"; "new file contents"; "0"];
3619        ["cat"; "/new"]], "new file contents")],
3620    "make ext2/3/4 external journal",
3621    "\
3622 This creates an ext2 external journal on C<device>.  It is equivalent
3623 to the command:
3624
3625  mke2fs -O journal_dev -b blocksize device");
3626
3627   ("mke2journal_L", (RErr, [Int "blocksize"; String "label"; Device "device"]), 189, [],
3628    [InitEmpty, Always, TestOutput (
3629       [["sfdiskM"; "/dev/sda"; ",100 ,"];
3630        ["mke2journal_L"; "4096"; "JOURNAL"; "/dev/sda1"];
3631        ["mke2fs_JL"; "ext2"; "4096"; "/dev/sda2"; "JOURNAL"];
3632        ["mount_options"; ""; "/dev/sda2"; "/"];
3633        ["write_file"; "/new"; "new file contents"; "0"];
3634        ["cat"; "/new"]], "new file contents")],
3635    "make ext2/3/4 external journal with label",
3636    "\
3637 This creates an ext2 external journal on C<device> with label C<label>.");
3638
3639   ("mke2journal_U", (RErr, [Int "blocksize"; String "uuid"; Device "device"]), 190, [Optional "linuxfsuuid"],
3640    (let uuid = uuidgen () in
3641     [InitEmpty, Always, TestOutput (
3642        [["sfdiskM"; "/dev/sda"; ",100 ,"];
3643         ["mke2journal_U"; "4096"; uuid; "/dev/sda1"];
3644         ["mke2fs_JU"; "ext2"; "4096"; "/dev/sda2"; uuid];
3645         ["mount_options"; ""; "/dev/sda2"; "/"];
3646         ["write_file"; "/new"; "new file contents"; "0"];
3647         ["cat"; "/new"]], "new file contents")]),
3648    "make ext2/3/4 external journal with UUID",
3649    "\
3650 This creates an ext2 external journal on C<device> with UUID C<uuid>.");
3651
3652   ("mke2fs_J", (RErr, [String "fstype"; Int "blocksize"; Device "device"; Device "journal"]), 191, [],
3653    [],
3654    "make ext2/3/4 filesystem with external journal",
3655    "\
3656 This creates an ext2/3/4 filesystem on C<device> with
3657 an external journal on C<journal>.  It is equivalent
3658 to the command:
3659
3660  mke2fs -t fstype -b blocksize -J device=<journal> <device>
3661
3662 See also C<guestfs_mke2journal>.");
3663
3664   ("mke2fs_JL", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "label"]), 192, [],
3665    [],
3666    "make ext2/3/4 filesystem with external journal",
3667    "\
3668 This creates an ext2/3/4 filesystem on C<device> with
3669 an external journal on the journal labeled C<label>.
3670
3671 See also C<guestfs_mke2journal_L>.");
3672
3673   ("mke2fs_JU", (RErr, [String "fstype"; Int "blocksize"; Device "device"; String "uuid"]), 193, [Optional "linuxfsuuid"],
3674    [],
3675    "make ext2/3/4 filesystem with external journal",
3676    "\
3677 This creates an ext2/3/4 filesystem on C<device> with
3678 an external journal on the journal with UUID C<uuid>.
3679
3680 See also C<guestfs_mke2journal_U>.");
3681
3682   ("modprobe", (RErr, [String "modulename"]), 194, [Optional "linuxmodules"],
3683    [InitNone, Always, TestRun [["modprobe"; "fat"]]],
3684    "load a kernel module",
3685    "\
3686 This loads a kernel module in the appliance.
3687
3688 The kernel module must have been whitelisted when libguestfs
3689 was built (see C<appliance/kmod.whitelist.in> in the source).");
3690
3691   ("echo_daemon", (RString "output", [StringList "words"]), 195, [],
3692    [InitNone, Always, TestOutput (
3693       [["echo_daemon"; "This is a test"]], "This is a test"
3694     )],
3695    "echo arguments back to the client",
3696    "\
3697 This command concatenate the list of C<words> passed with single spaces between
3698 them and returns the resulting string.
3699
3700 You can use this command to test the connection through to the daemon.
3701
3702 See also C<guestfs_ping_daemon>.");
3703
3704   ("find0", (RErr, [Pathname "directory"; FileOut "files"]), 196, [],
3705    [], (* There is a regression test for this. *)
3706    "find all files and directories, returning NUL-separated list",
3707    "\
3708 This command lists out all files and directories, recursively,
3709 starting at C<directory>, placing the resulting list in the
3710 external file called C<files>.
3711
3712 This command works the same way as C<guestfs_find> with the
3713 following exceptions:
3714
3715 =over 4
3716
3717 =item *
3718
3719 The resulting list is written to an external file.
3720
3721 =item *
3722
3723 Items (filenames) in the result are separated
3724 by C<\\0> characters.  See L<find(1)> option I<-print0>.
3725
3726 =item *
3727
3728 This command is not limited in the number of names that it
3729 can return.
3730
3731 =item *
3732
3733 The result list is not sorted.
3734
3735 =back");
3736
3737   ("case_sensitive_path", (RString "rpath", [Pathname "path"]), 197, [],
3738    [InitISOFS, Always, TestOutput (
3739       [["case_sensitive_path"; "/DIRECTORY"]], "/directory");
3740     InitISOFS, Always, TestOutput (
3741       [["case_sensitive_path"; "/DIRECTORY/"]], "/directory");
3742     InitISOFS, Always, TestOutput (
3743       [["case_sensitive_path"; "/Known-1"]], "/known-1");
3744     InitISOFS, Always, TestLastFail (
3745       [["case_sensitive_path"; "/Known-1/"]]);
3746     InitBasicFS, Always, TestOutput (
3747       [["mkdir"; "/a"];
3748        ["mkdir"; "/a/bbb"];
3749        ["touch"; "/a/bbb/c"];
3750        ["case_sensitive_path"; "/A/bbB/C"]], "/a/bbb/c");
3751     InitBasicFS, Always, TestOutput (
3752       [["mkdir"; "/a"];
3753        ["mkdir"; "/a/bbb"];
3754        ["touch"; "/a/bbb/c"];
3755        ["case_sensitive_path"; "/A////bbB/C"]], "/a/bbb/c");
3756     InitBasicFS, Always, TestLastFail (
3757       [["mkdir"; "/a"];
3758        ["mkdir"; "/a/bbb"];
3759        ["touch"; "/a/bbb/c"];
3760        ["case_sensitive_path"; "/A/bbb/../bbb/C"]])],
3761    "return true path on case-insensitive filesystem",
3762    "\
3763 This can be used to resolve case insensitive paths on
3764 a filesystem which is case sensitive.  The use case is
3765 to resolve paths which you have read from Windows configuration
3766 files or the Windows Registry, to the true path.
3767
3768 The command handles a peculiarity of the Linux ntfs-3g
3769 filesystem driver (and probably others), which is that although
3770 the underlying filesystem is case-insensitive, the driver
3771 exports the filesystem to Linux as case-sensitive.
3772
3773 One consequence of this is that special directories such
3774 as C<c:\\windows> may appear as C</WINDOWS> or C</windows>
3775 (or other things) depending on the precise details of how
3776 they were created.  In Windows itself this would not be
3777 a problem.
3778
3779 Bug or feature?  You decide:
3780 L<http://www.tuxera.com/community/ntfs-3g-faq/#posixfilenames1>
3781
3782 This function resolves the true case of each element in the
3783 path and returns the case-sensitive path.
3784
3785 Thus C<guestfs_case_sensitive_path> (\"/Windows/System32\")
3786 might return C<\"/WINDOWS/system32\"> (the exact return value
3787 would depend on details of how the directories were originally
3788 created under Windows).
3789
3790 I<Note>:
3791 This function does not handle drive names, backslashes etc.
3792
3793 See also C<guestfs_realpath>.");
3794
3795   ("vfs_type", (RString "fstype", [Device "device"]), 198, [],
3796    [InitBasicFS, Always, TestOutput (
3797       [["vfs_type"; "/dev/sda1"]], "ext2")],
3798    "get the Linux VFS type corresponding to a mounted device",
3799    "\
3800 This command gets the block device type corresponding to
3801 a mounted device called C<device>.
3802
3803 Usually the result is the name of the Linux VFS module that
3804 is used to mount this device (probably determined automatically
3805 if you used the C<guestfs_mount> call).");
3806
3807   ("truncate", (RErr, [Pathname "path"]), 199, [],
3808    [InitBasicFS, Always, TestOutputStruct (
3809       [["write_file"; "/test"; "some stuff so size is not zero"; "0"];
3810        ["truncate"; "/test"];
3811        ["stat"; "/test"]], [CompareWithInt ("size", 0)])],
3812    "truncate a file to zero size",
3813    "\
3814 This command truncates C<path> to a zero-length file.  The
3815 file must exist already.");
3816
3817   ("truncate_size", (RErr, [Pathname "path"; Int64 "size"]), 200, [],
3818    [InitBasicFS, Always, TestOutputStruct (
3819       [["touch"; "/test"];
3820        ["truncate_size"; "/test"; "1000"];
3821        ["stat"; "/test"]], [CompareWithInt ("size", 1000)])],
3822    "truncate a file to a particular size",
3823    "\
3824 This command truncates C<path> to size C<size> bytes.  The file
3825 must exist already.  If the file is smaller than C<size> then
3826 the file is extended to the required size with null bytes.");
3827
3828   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"]), 201, [],
3829    [InitBasicFS, Always, TestOutputStruct (
3830       [["touch"; "/test"];
3831        ["utimens"; "/test"; "12345"; "67890"; "9876"; "5432"];
3832        ["stat"; "/test"]], [CompareWithInt ("mtime", 9876)])],
3833    "set timestamp of a file with nanosecond precision",
3834    "\
3835 This command sets the timestamps of a file with nanosecond
3836 precision.
3837
3838 C<atsecs, atnsecs> are the last access time (atime) in secs and
3839 nanoseconds from the epoch.
3840
3841 C<mtsecs, mtnsecs> are the last modification time (mtime) in
3842 secs and nanoseconds from the epoch.
3843
3844 If the C<*nsecs> field contains the special value C<-1> then
3845 the corresponding timestamp is set to the current time.  (The
3846 C<*secs> field is ignored in this case).
3847
3848 If the C<*nsecs> field contains the special value C<-2> then
3849 the corresponding timestamp is left unchanged.  (The
3850 C<*secs> field is ignored in this case).");
3851
3852   ("mkdir_mode", (RErr, [Pathname "path"; Int "mode"]), 202, [],
3853    [InitBasicFS, Always, TestOutputStruct (
3854       [["mkdir_mode"; "/test"; "0o111"];
3855        ["stat"; "/test"]], [CompareWithInt ("mode", 0o40111)])],
3856    "create a directory with a particular mode",
3857    "\
3858 This command creates a directory, setting the initial permissions
3859 of the directory to C<mode>.  See also C<guestfs_mkdir>.");
3860
3861   ("lchown", (RErr, [Int "owner"; Int "group"; Pathname "path"]), 203, [],
3862    [], (* XXX *)
3863    "change file owner and group",
3864    "\
3865 Change the file owner to C<owner> and group to C<group>.
3866 This is like C<guestfs_chown> but if C<path> is a symlink then
3867 the link itself is changed, not the target.
3868
3869 Only numeric uid and gid are supported.  If you want to use
3870 names, you will need to locate and parse the password file
3871 yourself (Augeas support makes this relatively easy).");
3872
3873   ("lstatlist", (RStructList ("statbufs", "stat"), [Pathname "path"; StringList "names"]), 204, [],
3874    [], (* XXX *)
3875    "lstat on multiple files",
3876    "\
3877 This call allows you to perform the C<guestfs_lstat> operation
3878 on multiple files, where all files are in the directory C<path>.
3879 C<names> is the list of files from this directory.
3880
3881 On return you get a list of stat structs, with a one-to-one
3882 correspondence to the C<names> list.  If any name did not exist
3883 or could not be lstat'd, then the C<ino> field of that structure
3884 is set to C<-1>.
3885
3886 This call is intended for programs that want to efficiently
3887 list a directory contents without making many round-trips.
3888 See also C<guestfs_lxattrlist> for a similarly efficient call
3889 for getting extended attributes.  Very long directory listings
3890 might cause the protocol message size to be exceeded, causing
3891 this call to fail.  The caller must split up such requests
3892 into smaller groups of names.");
3893
3894   ("lxattrlist", (RStructList ("xattrs", "xattr"), [Pathname "path"; StringList "names"]), 205, [Optional "linuxxattrs"],
3895    [], (* XXX *)
3896    "lgetxattr on multiple files",
3897    "\
3898 This call allows you to get the extended attributes
3899 of multiple files, where all files are in the directory C<path>.
3900 C<names> is the list of files from this directory.
3901
3902 On return you get a flat list of xattr structs which must be
3903 interpreted sequentially.  The first xattr struct always has a zero-length
3904 C<attrname>.  C<attrval> in this struct is zero-length
3905 to indicate there was an error doing C<lgetxattr> for this
3906 file, I<or> is a C string which is a decimal number
3907 (the number of following attributes for this file, which could
3908 be C<\"0\">).  Then after the first xattr struct are the
3909 zero or more attributes for the first named file.
3910 This repeats for the second and subsequent files.
3911
3912 This call is intended for programs that want to efficiently
3913 list a directory contents without making many round-trips.
3914 See also C<guestfs_lstatlist> for a similarly efficient call
3915 for getting standard stats.  Very long directory listings
3916 might cause the protocol message size to be exceeded, causing
3917 this call to fail.  The caller must split up such requests
3918 into smaller groups of names.");
3919
3920   ("readlinklist", (RStringList "links", [Pathname "path"; StringList "names"]), 206, [],
3921    [], (* XXX *)
3922    "readlink on multiple files",
3923    "\
3924 This call allows you to do a C<readlink> operation
3925 on multiple files, where all files are in the directory C<path>.
3926 C<names> is the list of files from this directory.
3927
3928 On return you get a list of strings, with a one-to-one
3929 correspondence to the C<names> list.  Each string is the
3930 value of the symbol link.
3931
3932 If the C<readlink(2)> operation fails on any name, then
3933 the corresponding result string is the empty string C<\"\">.
3934 However the whole operation is completed even if there
3935 were C<readlink(2)> errors, and so you can call this
3936 function with names where you don't know if they are
3937 symbolic links already (albeit slightly less efficient).
3938
3939 This call is intended for programs that want to efficiently
3940 list a directory contents without making many round-trips.
3941 Very long directory listings might cause the protocol
3942 message size to be exceeded, causing
3943 this call to fail.  The caller must split up such requests
3944 into smaller groups of names.");
3945
3946   ("pread", (RBufferOut "content", [Pathname "path"; Int "count"; Int64 "offset"]), 207, [ProtocolLimitWarning],
3947    [InitISOFS, Always, TestOutputBuffer (
3948       [["pread"; "/known-4"; "1"; "3"]], "\n");
3949     InitISOFS, Always, TestOutputBuffer (
3950       [["pread"; "/empty"; "0"; "100"]], "")],
3951    "read part of a file",
3952    "\
3953 This command lets you read part of a file.  It reads C<count>
3954 bytes of the file, starting at C<offset>, from file C<path>.
3955
3956 This may read fewer bytes than requested.  For further details
3957 see the L<pread(2)> system call.");
3958
3959   ("part_init", (RErr, [Device "device"; String "parttype"]), 208, [],
3960    [InitEmpty, Always, TestRun (
3961       [["part_init"; "/dev/sda"; "gpt"]])],
3962    "create an empty partition table",
3963    "\
3964 This creates an empty partition table on C<device> of one of the
3965 partition types listed below.  Usually C<parttype> should be
3966 either C<msdos> or C<gpt> (for large disks).
3967
3968 Initially there are no partitions.  Following this, you should
3969 call C<guestfs_part_add> for each partition required.
3970
3971 Possible values for C<parttype> are:
3972
3973 =over 4
3974
3975 =item B<efi> | B<gpt>
3976
3977 Intel EFI / GPT partition table.
3978
3979 This is recommended for >= 2 TB partitions that will be accessed
3980 from Linux and Intel-based Mac OS X.  It also has limited backwards
3981 compatibility with the C<mbr> format.
3982
3983 =item B<mbr> | B<msdos>
3984
3985 The standard PC \"Master Boot Record\" (MBR) format used
3986 by MS-DOS and Windows.  This partition type will B<only> work
3987 for device sizes up to 2 TB.  For large disks we recommend
3988 using C<gpt>.
3989
3990 =back
3991
3992 Other partition table types that may work but are not
3993 supported include:
3994
3995 =over 4
3996
3997 =item B<aix>
3998
3999 AIX disk labels.
4000
4001 =item B<amiga> | B<rdb>
4002
4003 Amiga \"Rigid Disk Block\" format.
4004
4005 =item B<bsd>
4006
4007 BSD disk labels.
4008
4009 =item B<dasd>
4010
4011 DASD, used on IBM mainframes.
4012
4013 =item B<dvh>
4014
4015 MIPS/SGI volumes.
4016
4017 =item B<mac>
4018
4019 Old Mac partition format.  Modern Macs use C<gpt>.
4020
4021 =item B<pc98>
4022
4023 NEC PC-98 format, common in Japan apparently.
4024
4025 =item B<sun>
4026
4027 Sun disk labels.
4028
4029 =back");
4030
4031   ("part_add", (RErr, [Device "device"; String "prlogex"; Int64 "startsect"; Int64 "endsect"]), 209, [],
4032    [InitEmpty, Always, TestRun (
4033       [["part_init"; "/dev/sda"; "mbr"];
4034        ["part_add"; "/dev/sda"; "primary"; "1"; "-1"]]);
4035     InitEmpty, Always, TestRun (
4036       [["part_init"; "/dev/sda"; "gpt"];
4037        ["part_add"; "/dev/sda"; "primary"; "34"; "127"];
4038        ["part_add"; "/dev/sda"; "primary"; "128"; "-34"]]);
4039     InitEmpty, Always, TestRun (
4040       [["part_init"; "/dev/sda"; "mbr"];
4041        ["part_add"; "/dev/sda"; "primary"; "32"; "127"];
4042        ["part_add"; "/dev/sda"; "primary"; "128"; "255"];
4043        ["part_add"; "/dev/sda"; "primary"; "256"; "511"];
4044        ["part_add"; "/dev/sda"; "primary"; "512"; "-1"]])],
4045    "add a partition to the device",
4046    "\
4047 This command adds a partition to C<device>.  If there is no partition
4048 table on the device, call C<guestfs_part_init> first.
4049
4050 The C<prlogex> parameter is the type of partition.  Normally you
4051 should pass C<p> or C<primary> here, but MBR partition tables also
4052 support C<l> (or C<logical>) and C<e> (or C<extended>) partition
4053 types.
4054
4055 C<startsect> and C<endsect> are the start and end of the partition
4056 in I<sectors>.  C<endsect> may be negative, which means it counts
4057 backwards from the end of the disk (C<-1> is the last sector).
4058
4059 Creating a partition which covers the whole disk is not so easy.
4060 Use C<guestfs_part_disk> to do that.");
4061
4062   ("part_disk", (RErr, [Device "device"; String "parttype"]), 210, [DangerWillRobinson],
4063    [InitEmpty, Always, TestRun (
4064       [["part_disk"; "/dev/sda"; "mbr"]]);
4065     InitEmpty, Always, TestRun (
4066       [["part_disk"; "/dev/sda"; "gpt"]])],
4067    "partition whole disk with a single primary partition",
4068    "\
4069 This command is simply a combination of C<guestfs_part_init>
4070 followed by C<guestfs_part_add> to create a single primary partition
4071 covering the whole disk.
4072
4073 C<parttype> is the partition table type, usually C<mbr> or C<gpt>,
4074 but other possible values are described in C<guestfs_part_init>.");
4075
4076   ("part_set_bootable", (RErr, [Device "device"; Int "partnum"; Bool "bootable"]), 211, [],
4077    [InitEmpty, Always, TestRun (
4078       [["part_disk"; "/dev/sda"; "mbr"];
4079        ["part_set_bootable"; "/dev/sda"; "1"; "true"]])],
4080    "make a partition bootable",
4081    "\
4082 This sets the bootable flag on partition numbered C<partnum> on
4083 device C<device>.  Note that partitions are numbered from 1.
4084
4085 The bootable flag is used by some PC BIOSes to determine which
4086 partition to boot from.  It is by no means universally recognized,
4087 and in any case if your operating system installed a boot
4088 sector on the device itself, then that takes precedence.");
4089
4090   ("part_set_name", (RErr, [Device "device"; Int "partnum"; String "name"]), 212, [],
4091    [InitEmpty, Always, TestRun (
4092       [["part_disk"; "/dev/sda"; "gpt"];
4093        ["part_set_name"; "/dev/sda"; "1"; "thepartname"]])],
4094    "set partition name",
4095    "\
4096 This sets the partition name on partition numbered C<partnum> on
4097 device C<device>.  Note that partitions are numbered from 1.
4098
4099 The partition name can only be set on certain types of partition
4100 table.  This works on C<gpt> but not on C<mbr> partitions.");
4101
4102   ("part_list", (RStructList ("partitions", "partition"), [Device "device"]), 213, [],
4103    [], (* XXX Add a regression test for this. *)
4104    "list partitions on a device",
4105    "\
4106 This command parses the partition table on C<device> and
4107 returns the list of partitions found.
4108
4109 The fields in the returned structure are:
4110
4111 =over 4
4112
4113 =item B<part_num>
4114
4115 Partition number, counting from 1.
4116
4117 =item B<part_start>
4118
4119 Start of the partition I<in bytes>.  To get sectors you have to
4120 divide by the device's sector size, see C<guestfs_blockdev_getss>.
4121
4122 =item B<part_end>
4123
4124 End of the partition in bytes.
4125
4126 =item B<part_size>
4127
4128 Size of the partition in bytes.
4129
4130 =back");
4131
4132   ("part_get_parttype", (RString "parttype", [Device "device"]), 214, [],
4133    [InitEmpty, Always, TestOutput (
4134       [["part_disk"; "/dev/sda"; "gpt"];
4135        ["part_get_parttype"; "/dev/sda"]], "gpt")],
4136    "get the partition table type",
4137    "\
4138 This command examines the partition table on C<device> and
4139 returns the partition table type (format) being used.
4140
4141 Common return values include: C<msdos> (a DOS/Windows style MBR
4142 partition table), C<gpt> (a GPT/EFI-style partition table).  Other
4143 values are possible, although unusual.  See C<guestfs_part_init>
4144 for a full list.");
4145
4146   ("fill", (RErr, [Int "c"; Int "len"; Pathname "path"]), 215, [],
4147    [InitBasicFS, Always, TestOutputBuffer (
4148       [["fill"; "0x63"; "10"; "/test"];
4149        ["read_file"; "/test"]], "cccccccccc")],
4150    "fill a file with octets",
4151    "\
4152 This command creates a new file called C<path>.  The initial
4153 content of the file is C<len> octets of C<c>, where C<c>
4154 must be a number in the range C<[0..255]>.
4155
4156 To fill a file with zero bytes (sparsely), it is
4157 much more efficient to use C<guestfs_truncate_size>.");
4158
4159   ("available", (RErr, [StringList "groups"]), 216, [],
4160    [InitNone, Always, TestRun [["available"; ""]]],
4161    "test availability of some parts of the API",
4162    "\
4163 This command is used to check the availability of some
4164 groups of functionality in the appliance, which not all builds of
4165 the libguestfs appliance will be able to provide.
4166
4167 The libguestfs groups, and the functions that those
4168 groups correspond to, are listed in L<guestfs(3)/AVAILABILITY>.
4169
4170 The argument C<groups> is a list of group names, eg:
4171 C<[\"inotify\", \"augeas\"]> would check for the availability of
4172 the Linux inotify functions and Augeas (configuration file
4173 editing) functions.
4174
4175 The command returns no error if I<all> requested groups are available.
4176
4177 It fails with an error if one or more of the requested
4178 groups is unavailable in the appliance.
4179
4180 If an unknown group name is included in the
4181 list of groups then an error is always returned.
4182
4183 I<Notes:>
4184
4185 =over 4
4186
4187 =item *
4188
4189 You must call C<guestfs_launch> before calling this function.
4190
4191 The reason is because we don't know what groups are
4192 supported by the appliance/daemon until it is running and can
4193 be queried.
4194
4195 =item *
4196
4197 If a group of functions is available, this does not necessarily
4198 mean that they will work.  You still have to check for errors
4199 when calling individual API functions even if they are
4200 available.
4201
4202 =item *
4203
4204 It is usually the job of distro packagers to build
4205 complete functionality into the libguestfs appliance.
4206 Upstream libguestfs, if built from source with all
4207 requirements satisfied, will support everything.
4208
4209 =item *
4210
4211 This call was added in version C<1.0.80>.  In previous
4212 versions of libguestfs all you could do would be to speculatively
4213 execute a command to find out if the daemon implemented it.
4214 See also C<guestfs_version>.
4215
4216 =back");
4217
4218   ("dd", (RErr, [Dev_or_Path "src"; Dev_or_Path "dest"]), 217, [],
4219    [InitBasicFS, Always, TestOutputBuffer (
4220       [["write_file"; "/src"; "hello, world"; "0"];
4221        ["dd"; "/src"; "/dest"];
4222        ["read_file"; "/dest"]], "hello, world")],
4223    "copy from source to destination using dd",
4224    "\
4225 This command copies from one source device or file C<src>
4226 to another destination device or file C<dest>.  Normally you
4227 would use this to copy to or from a device or partition, for
4228 example to duplicate a filesystem.
4229
4230 If the destination is a device, it must be as large or larger
4231 than the source file or device, otherwise the copy will fail.
4232 This command cannot do partial copies.");
4233
4234   ("filesize", (RInt64 "size", [Pathname "file"]), 218, [],
4235    [InitBasicFS, Always, TestOutputInt (
4236       [["write_file"; "/file"; "hello, world"; "0"];
4237        ["filesize"; "/file"]], 12)],
4238    "return the size of the file in bytes",
4239    "\
4240 This command returns the size of C<file> in bytes.
4241
4242 To get other stats about a file, use C<guestfs_stat>, C<guestfs_lstat>,
4243 C<guestfs_is_dir>, C<guestfs_is_file> etc.
4244 To get the size of block devices, use C<guestfs_blockdev_getsize64>.");
4245
4246   ("lvrename", (RErr, [String "logvol"; String "newlogvol"]), 219, [],
4247    [InitBasicFSonLVM, Always, TestOutputList (
4248       [["lvrename"; "/dev/VG/LV"; "/dev/VG/LV2"];
4249        ["lvs"]], ["/dev/VG/LV2"])],
4250    "rename an LVM logical volume",
4251    "\
4252 Rename a logical volume C<logvol> with the new name C<newlogvol>.");
4253
4254   ("vgrename", (RErr, [String "volgroup"; String "newvolgroup"]), 220, [],
4255    [InitBasicFSonLVM, Always, TestOutputList (
4256       [["umount"; "/"];
4257        ["vg_activate"; "false"; "VG"];
4258        ["vgrename"; "VG"; "VG2"];
4259        ["vg_activate"; "true"; "VG2"];
4260        ["mount_options"; ""; "/dev/VG2/LV"; "/"];
4261        ["vgs"]], ["VG2"])],
4262    "rename an LVM volume group",
4263    "\
4264 Rename a volume group C<volgroup> with the new name C<newvolgroup>.");
4265
4266   ("initrd_cat", (RBufferOut "content", [Pathname "initrdpath"; String "filename"]), 221, [ProtocolLimitWarning],
4267    [InitISOFS, Always, TestOutputBuffer (
4268       [["initrd_cat"; "/initrd"; "known-4"]], "abc\ndef\nghi")],
4269    "list the contents of a single file in an initrd",
4270    "\
4271 This command unpacks the file C<filename> from the initrd file
4272 called C<initrdpath>.  The filename must be given I<without> the
4273 initial C</> character.
4274
4275 For example, in guestfish you could use the following command
4276 to examine the boot script (usually called C</init>)
4277 contained in a Linux initrd or initramfs image:
4278
4279  initrd-cat /boot/initrd-<version>.img init
4280
4281 See also C<guestfs_initrd_list>.");
4282
4283 ]
4284
4285 let all_functions = non_daemon_functions @ daemon_functions
4286
4287 (* In some places we want the functions to be displayed sorted
4288  * alphabetically, so this is useful:
4289  *)
4290 let all_functions_sorted =
4291   List.sort (fun (n1,_,_,_,_,_,_) (n2,_,_,_,_,_,_) ->
4292                compare n1 n2) all_functions
4293
4294 (* Field types for structures. *)
4295 type field =
4296   | FChar                       (* C 'char' (really, a 7 bit byte). *)
4297   | FString                     (* nul-terminated ASCII string, NOT NULL. *)
4298   | FBuffer                     (* opaque buffer of bytes, (char *, int) pair *)
4299   | FUInt32
4300   | FInt32
4301   | FUInt64
4302   | FInt64
4303   | FBytes                      (* Any int measure that counts bytes. *)
4304   | FUUID                       (* 32 bytes long, NOT nul-terminated. *)
4305   | FOptPercent                 (* [0..100], or -1 meaning "not present". *)
4306
4307 (* Because we generate extra parsing code for LVM command line tools,
4308  * we have to pull out the LVM columns separately here.
4309  *)
4310 let lvm_pv_cols = [
4311   "pv_name", FString;
4312   "pv_uuid", FUUID;
4313   "pv_fmt", FString;
4314   "pv_size", FBytes;
4315   "dev_size", FBytes;
4316   "pv_free", FBytes;
4317   "pv_used", FBytes;
4318   "pv_attr", FString (* XXX *);
4319   "pv_pe_count", FInt64;
4320   "pv_pe_alloc_count", FInt64;
4321   "pv_tags", FString;
4322   "pe_start", FBytes;
4323   "pv_mda_count", FInt64;
4324   "pv_mda_free", FBytes;
4325   (* Not in Fedora 10:
4326      "pv_mda_size", FBytes;
4327   *)
4328 ]
4329 let lvm_vg_cols = [
4330   "vg_name", FString;
4331   "vg_uuid", FUUID;
4332   "vg_fmt", FString;
4333   "vg_attr", FString (* XXX *);
4334   "vg_size", FBytes;
4335   "vg_free", FBytes;
4336   "vg_sysid", FString;
4337   "vg_extent_size", FBytes;
4338   "vg_extent_count", FInt64;
4339   "vg_free_count", FInt64;
4340   "max_lv", FInt64;
4341   "max_pv", FInt64;
4342   "pv_count", FInt64;
4343   "lv_count", FInt64;
4344   "snap_count", FInt64;
4345   "vg_seqno", FInt64;
4346   "vg_tags", FString;
4347   "vg_mda_count", FInt64;
4348   "vg_mda_free", FBytes;
4349   (* Not in Fedora 10:
4350      "vg_mda_size", FBytes;
4351   *)
4352 ]
4353 let lvm_lv_cols = [
4354   "lv_name", FString;
4355   "lv_uuid", FUUID;
4356   "lv_attr", FString (* XXX *);
4357   "lv_major", FInt64;
4358   "lv_minor", FInt64;
4359   "lv_kernel_major", FInt64;
4360   "lv_kernel_minor", FInt64;
4361   "lv_size", FBytes;
4362   "seg_count", FInt64;
4363   "origin", FString;
4364   "snap_percent", FOptPercent;
4365   "copy_percent", FOptPercent;
4366   "move_pv", FString;
4367   "lv_tags", FString;
4368   "mirror_log", FString;
4369   "modules", FString;
4370 ]
4371
4372 (* Names and fields in all structures (in RStruct and RStructList)
4373  * that we support.
4374  *)
4375 let structs = [
4376   (* The old RIntBool return type, only ever used for aug_defnode.  Do
4377    * not use this struct in any new code.
4378    *)
4379   "int_bool", [
4380     "i", FInt32;                (* for historical compatibility *)
4381     "b", FInt32;                (* for historical compatibility *)
4382   ];
4383
4384   (* LVM PVs, VGs, LVs. *)
4385   "lvm_pv", lvm_pv_cols;
4386   "lvm_vg", lvm_vg_cols;
4387   "lvm_lv", lvm_lv_cols;
4388
4389   (* Column names and types from stat structures.
4390    * NB. Can't use things like 'st_atime' because glibc header files
4391    * define some of these as macros.  Ugh.
4392    *)
4393   "stat", [
4394     "dev", FInt64;
4395     "ino", FInt64;
4396     "mode", FInt64;
4397     "nlink", FInt64;
4398     "uid", FInt64;
4399     "gid", FInt64;
4400     "rdev", FInt64;
4401     "size", FInt64;
4402     "blksize", FInt64;
4403     "blocks", FInt64;
4404     "atime", FInt64;
4405     "mtime", FInt64;
4406     "ctime", FInt64;
4407   ];
4408   "statvfs", [
4409     "bsize", FInt64;
4410     "frsize", FInt64;
4411     "blocks", FInt64;
4412     "bfree", FInt64;
4413     "bavail", FInt64;
4414     "files", FInt64;
4415     "ffree", FInt64;
4416     "favail", FInt64;
4417     "fsid", FInt64;
4418     "flag", FInt64;
4419     "namemax", FInt64;
4420   ];
4421
4422   (* Column names in dirent structure. *)
4423   "dirent", [
4424     "ino", FInt64;
4425     (* 'b' 'c' 'd' 'f' (FIFO) 'l' 'r' (regular file) 's' 'u' '?' *)
4426     "ftyp", FChar;
4427     "name", FString;
4428   ];
4429
4430   (* Version numbers. *)
4431   "version", [
4432     "major", FInt64;
4433     "minor", FInt64;
4434     "release", FInt64;
4435     "extra", FString;
4436   ];
4437
4438   (* Extended attribute. *)
4439   "xattr", [
4440     "attrname", FString;
4441     "attrval", FBuffer;
4442   ];
4443
4444   (* Inotify events. *)
4445   "inotify_event", [
4446     "in_wd", FInt64;
4447     "in_mask", FUInt32;
4448     "in_cookie", FUInt32;
4449     "in_name", FString;
4450   ];
4451
4452   (* Partition table entry. *)
4453   "partition", [
4454     "part_num", FInt32;
4455     "part_start", FBytes;
4456     "part_end", FBytes;
4457     "part_size", FBytes;
4458   ];
4459 ] (* end of structs *)
4460
4461 (* Ugh, Java has to be different ..
4462  * These names are also used by the Haskell bindings.
4463  *)
4464 let java_structs = [
4465   "int_bool", "IntBool";
4466   "lvm_pv", "PV";
4467   "lvm_vg", "VG";
4468   "lvm_lv", "LV";
4469   "stat", "Stat";
4470   "statvfs", "StatVFS";
4471   "dirent", "Dirent";
4472   "version", "Version";
4473   "xattr", "XAttr";
4474   "inotify_event", "INotifyEvent";
4475   "partition", "Partition";
4476 ]
4477
4478 (* What structs are actually returned. *)
4479 type rstructs_used_t = RStructOnly | RStructListOnly | RStructAndList
4480
4481 (* Returns a list of RStruct/RStructList structs that are returned
4482  * by any function.  Each element of returned list is a pair:
4483  *
4484  * (structname, RStructOnly)
4485  *    == there exists function which returns RStruct (_, structname)
4486  * (structname, RStructListOnly)
4487  *    == there exists function which returns RStructList (_, structname)
4488  * (structname, RStructAndList)
4489  *    == there are functions returning both RStruct (_, structname)
4490  *                                      and RStructList (_, structname)
4491  *)
4492 let rstructs_used_by functions =
4493   (* ||| is a "logical OR" for rstructs_used_t *)
4494   let (|||) a b =
4495     match a, b with
4496     | RStructAndList, _
4497     | _, RStructAndList -> RStructAndList
4498     | RStructOnly, RStructListOnly
4499     | RStructListOnly, RStructOnly -> RStructAndList
4500     | RStructOnly, RStructOnly -> RStructOnly
4501     | RStructListOnly, RStructListOnly -> RStructListOnly
4502   in
4503
4504   let h = Hashtbl.create 13 in
4505
4506   (* if elem->oldv exists, update entry using ||| operator,
4507    * else just add elem->newv to the hash
4508    *)
4509   let update elem newv =
4510     try  let oldv = Hashtbl.find h elem in
4511          Hashtbl.replace h elem (newv ||| oldv)
4512     with Not_found -> Hashtbl.add h elem newv
4513   in
4514
4515   List.iter (
4516     fun (_, style, _, _, _, _, _) ->
4517       match fst style with
4518       | RStruct (_, structname) -> update structname RStructOnly
4519       | RStructList (_, structname) -> update structname RStructListOnly
4520       | _ -> ()
4521   ) functions;
4522
4523   (* return key->values as a list of (key,value) *)
4524   Hashtbl.fold (fun key value xs -> (key, value) :: xs) h []
4525
4526 (* Used for testing language bindings. *)
4527 type callt =
4528   | CallString of string
4529   | CallOptString of string option
4530   | CallStringList of string list
4531   | CallInt of int
4532   | CallInt64 of int64
4533   | CallBool of bool
4534
4535 (* Used to memoize the result of pod2text. *)
4536 let pod2text_memo_filename = "src/.pod2text.data"
4537 let pod2text_memo : ((int * string * string), string list) Hashtbl.t =
4538   try
4539     let chan = open_in pod2text_memo_filename in
4540     let v = input_value chan in
4541     close_in chan;
4542     v
4543   with
4544     _ -> Hashtbl.create 13
4545 let pod2text_memo_updated () =
4546   let chan = open_out pod2text_memo_filename in
4547   output_value chan pod2text_memo;
4548   close_out chan
4549
4550 (* Useful functions.
4551  * Note we don't want to use any external OCaml libraries which
4552  * makes this a bit harder than it should be.
4553  *)
4554 module StringMap = Map.Make (String)
4555
4556 let failwithf fs = ksprintf failwith fs
4557
4558 let unique = let i = ref 0 in fun () -> incr i; !i
4559
4560 let replace_char s c1 c2 =
4561   let s2 = String.copy s in
4562   let r = ref false in
4563   for i = 0 to String.length s2 - 1 do
4564     if String.unsafe_get s2 i = c1 then (
4565       String.unsafe_set s2 i c2;
4566       r := true
4567     )
4568   done;
4569   if not !r then s else s2
4570
4571 let isspace c =
4572   c = ' '
4573   (* || c = '\f' *) || c = '\n' || c = '\r' || c = '\t' (* || c = '\v' *)
4574
4575 let triml ?(test = isspace) str =
4576   let i = ref 0 in
4577   let n = ref (String.length str) in
4578   while !n > 0 && test str.[!i]; do
4579     decr n;
4580     incr i
4581   done;
4582   if !i = 0 then str
4583   else String.sub str !i !n
4584
4585 let trimr ?(test = isspace) str =
4586   let n = ref (String.length str) in
4587   while !n > 0 && test str.[!n-1]; do
4588     decr n
4589   done;
4590   if !n = String.length str then str
4591   else String.sub str 0 !n
4592
4593 let trim ?(test = isspace) str =
4594   trimr ~test (triml ~test str)
4595
4596 let rec find s sub =
4597   let len = String.length s in
4598   let sublen = String.length sub in
4599   let rec loop i =
4600     if i <= len-sublen then (
4601       let rec loop2 j =
4602         if j < sublen then (
4603           if s.[i+j] = sub.[j] then loop2 (j+1)
4604           else -1
4605         ) else
4606           i (* found *)
4607       in
4608       let r = loop2 0 in
4609       if r = -1 then loop (i+1) else r
4610     ) else
4611       -1 (* not found *)
4612   in
4613   loop 0
4614
4615 let rec replace_str s s1 s2 =
4616   let len = String.length s in
4617   let sublen = String.length s1 in
4618   let i = find s s1 in
4619   if i = -1 then s
4620   else (
4621     let s' = String.sub s 0 i in
4622     let s'' = String.sub s (i+sublen) (len-i-sublen) in
4623     s' ^ s2 ^ replace_str s'' s1 s2
4624   )
4625
4626 let rec string_split sep str =
4627   let len = String.length str in
4628   let seplen = String.length sep in
4629   let i = find str sep in
4630   if i = -1 then [str]
4631   else (
4632     let s' = String.sub str 0 i in
4633     let s'' = String.sub str (i+seplen) (len-i-seplen) in
4634     s' :: string_split sep s''
4635   )
4636
4637 let files_equal n1 n2 =
4638   let cmd = sprintf "cmp -s %s %s" (Filename.quote n1) (Filename.quote n2) in
4639   match Sys.command cmd with
4640   | 0 -> true
4641   | 1 -> false
4642   | i -> failwithf "%s: failed with error code %d" cmd i
4643
4644 let rec filter_map f = function
4645   | [] -> []
4646   | x :: xs ->
4647       match f x with
4648       | Some y -> y :: filter_map f xs
4649       | None -> filter_map f xs
4650
4651 let rec find_map f = function
4652   | [] -> raise Not_found
4653   | x :: xs ->
4654       match f x with
4655       | Some y -> y
4656       | None -> find_map f xs
4657
4658 let iteri f xs =
4659   let rec loop i = function
4660     | [] -> ()
4661     | x :: xs -> f i x; loop (i+1) xs
4662   in
4663   loop 0 xs
4664
4665 let mapi f xs =
4666   let rec loop i = function
4667     | [] -> []
4668     | x :: xs -> let r = f i x in r :: loop (i+1) xs
4669   in
4670   loop 0 xs
4671
4672 let count_chars c str =
4673   let count = ref 0 in
4674   for i = 0 to String.length str - 1 do
4675     if c = String.unsafe_get str i then incr count
4676   done;
4677   !count
4678
4679 let name_of_argt = function
4680   | Pathname n | Device n | Dev_or_Path n | String n | OptString n
4681   | StringList n | DeviceList n | Bool n | Int n | Int64 n
4682   | FileIn n | FileOut n -> n
4683
4684 let java_name_of_struct typ =
4685   try List.assoc typ java_structs
4686   with Not_found ->
4687     failwithf
4688       "java_name_of_struct: no java_structs entry corresponding to %s" typ
4689
4690 let cols_of_struct typ =
4691   try List.assoc typ structs
4692   with Not_found ->
4693     failwithf "cols_of_struct: unknown struct %s" typ
4694
4695 let seq_of_test = function
4696   | TestRun s | TestOutput (s, _) | TestOutputList (s, _)
4697   | TestOutputListOfDevices (s, _)
4698   | TestOutputInt (s, _) | TestOutputIntOp (s, _, _)
4699   | TestOutputTrue s | TestOutputFalse s
4700   | TestOutputLength (s, _) | TestOutputBuffer (s, _)
4701   | TestOutputStruct (s, _)
4702   | TestLastFail s -> s
4703
4704 (* Handling for function flags. *)
4705 let protocol_limit_warning =
4706   "Because of the message protocol, there is a transfer limit
4707 of somewhere between 2MB and 4MB.  See L<guestfs(3)/PROTOCOL LIMITS>."
4708
4709 let danger_will_robinson =
4710   "B<This command is dangerous.  Without careful use you
4711 can easily destroy all your data>."
4712
4713 let deprecation_notice flags =
4714   try
4715     let alt =
4716       find_map (function DeprecatedBy str -> Some str | _ -> None) flags in
4717     let txt =
4718       sprintf "This function is deprecated.
4719 In new code, use the C<%s> call instead.
4720
4721 Deprecated functions will not be removed from the API, but the
4722 fact that they are deprecated indicates that there are problems
4723 with correct use of these functions." alt in
4724     Some txt
4725   with
4726     Not_found -> None
4727
4728 (* Create list of optional groups. *)
4729 let optgroups =
4730   let h = Hashtbl.create 13 in
4731   List.iter (
4732     fun (name, _, _, flags, _, _, _) ->
4733       List.iter (
4734         function
4735         | Optional group ->
4736             let names = try Hashtbl.find h group with Not_found -> [] in
4737             Hashtbl.replace h group (name :: names)
4738         | _ -> ()
4739       ) flags
4740   ) daemon_functions;
4741   let groups = Hashtbl.fold (fun k _ ks -> k :: ks) h [] in
4742   let groups =
4743     List.map (
4744       fun group -> group, List.sort compare (Hashtbl.find h group)
4745     ) groups in
4746   List.sort (fun x y -> compare (fst x) (fst y)) groups
4747
4748 (* Check function names etc. for consistency. *)
4749 let check_functions () =
4750   let contains_uppercase str =
4751     let len = String.length str in
4752     let rec loop i =
4753       if i >= len then false
4754       else (
4755         let c = str.[i] in
4756         if c >= 'A' && c <= 'Z' then true
4757         else loop (i+1)
4758       )
4759     in
4760     loop 0
4761   in
4762
4763   (* Check function names. *)
4764   List.iter (
4765     fun (name, _, _, _, _, _, _) ->
4766       if String.length name >= 7 && String.sub name 0 7 = "guestfs" then
4767         failwithf "function name %s does not need 'guestfs' prefix" name;
4768       if name = "" then
4769         failwithf "function name is empty";
4770       if name.[0] < 'a' || name.[0] > 'z' then
4771         failwithf "function name %s must start with lowercase a-z" name;
4772       if String.contains name '-' then
4773         failwithf "function name %s should not contain '-', use '_' instead."
4774           name
4775   ) all_functions;
4776
4777   (* Check function parameter/return names. *)
4778   List.iter (
4779     fun (name, style, _, _, _, _, _) ->
4780       let check_arg_ret_name n =
4781         if contains_uppercase n then
4782           failwithf "%s param/ret %s should not contain uppercase chars"
4783             name n;
4784         if String.contains n '-' || String.contains n '_' then
4785           failwithf "%s param/ret %s should not contain '-' or '_'"
4786             name n;
4787         if n = "value" then
4788           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;
4789         if n = "int" || n = "char" || n = "short" || n = "long" then
4790           failwithf "%s has a param/ret which conflicts with a C type (eg. 'int', 'char' etc.)" name;
4791         if n = "i" || n = "n" then
4792           failwithf "%s has a param/ret called 'i' or 'n', which will cause some conflicts in the generated code" name;
4793         if n = "argv" || n = "args" then
4794           failwithf "%s has a param/ret called 'argv' or 'args', which will cause some conflicts in the generated code" name;
4795
4796         (* List Haskell, OCaml and C keywords here.
4797          * http://www.haskell.org/haskellwiki/Keywords
4798          * http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#operator-char
4799          * http://en.wikipedia.org/wiki/C_syntax#Reserved_keywords
4800          * Formatted via: cat c haskell ocaml|sort -u|grep -vE '_|^val$' \
4801          *   |perl -pe 's/(.+)/"$1";/'|fmt -70
4802          * Omitting _-containing words, since they're handled above.
4803          * Omitting the OCaml reserved word, "val", is ok,
4804          * and saves us from renaming several parameters.
4805          *)
4806         let reserved = [
4807           "and"; "as"; "asr"; "assert"; "auto"; "begin"; "break"; "case";
4808           "char"; "class"; "const"; "constraint"; "continue"; "data";
4809           "default"; "deriving"; "do"; "done"; "double"; "downto"; "else";
4810           "end"; "enum"; "exception"; "extern"; "external"; "false"; "float";
4811           "for"; "forall"; "foreign"; "fun"; "function"; "functor"; "goto";
4812           "hiding"; "if"; "import"; "in"; "include"; "infix"; "infixl";
4813           "infixr"; "inherit"; "initializer"; "inline"; "instance"; "int";
4814           "interface";
4815           "land"; "lazy"; "let"; "long"; "lor"; "lsl"; "lsr"; "lxor";
4816           "match"; "mdo"; "method"; "mod"; "module"; "mutable"; "new";
4817           "newtype"; "object"; "of"; "open"; "or"; "private"; "qualified";
4818           "rec"; "register"; "restrict"; "return"; "short"; "sig"; "signed";
4819           "sizeof"; "static"; "struct"; "switch"; "then"; "to"; "true"; "try";
4820           "type"; "typedef"; "union"; "unsigned"; "virtual"; "void";
4821           "volatile"; "when"; "where"; "while";
4822           ] in
4823         if List.mem n reserved then
4824           failwithf "%s has param/ret using reserved word %s" name n;
4825       in
4826
4827       (match fst style with
4828        | RErr -> ()
4829        | RInt n | RInt64 n | RBool n
4830        | RConstString n | RConstOptString n | RString n
4831        | RStringList n | RStruct (n, _) | RStructList (n, _)
4832        | RHashtable n | RBufferOut n ->
4833            check_arg_ret_name n
4834       );
4835       List.iter (fun arg -> check_arg_ret_name (name_of_argt arg)) (snd style)
4836   ) all_functions;
4837
4838   (* Check short descriptions. *)
4839   List.iter (
4840     fun (name, _, _, _, _, shortdesc, _) ->
4841       if shortdesc.[0] <> Char.lowercase shortdesc.[0] then
4842         failwithf "short description of %s should begin with lowercase." name;
4843       let c = shortdesc.[String.length shortdesc-1] in
4844       if c = '\n' || c = '.' then
4845         failwithf "short description of %s should not end with . or \\n." name
4846   ) all_functions;
4847
4848   (* Check long dscriptions. *)
4849   List.iter (
4850     fun (name, _, _, _, _, _, longdesc) ->
4851       if longdesc.[String.length longdesc-1] = '\n' then
4852         failwithf "long description of %s should not end with \\n." name
4853   ) all_functions;
4854
4855   (* Check proc_nrs. *)
4856   List.iter (
4857     fun (name, _, proc_nr, _, _, _, _) ->
4858       if proc_nr <= 0 then
4859         failwithf "daemon function %s should have proc_nr > 0" name
4860   ) daemon_functions;
4861
4862   List.iter (
4863     fun (name, _, proc_nr, _, _, _, _) ->
4864       if proc_nr <> -1 then
4865         failwithf "non-daemon function %s should have proc_nr -1" name
4866   ) non_daemon_functions;
4867
4868   let proc_nrs =
4869     List.map (fun (name, _, proc_nr, _, _, _, _) -> name, proc_nr)
4870       daemon_functions in
4871   let proc_nrs =
4872     List.sort (fun (_,nr1) (_,nr2) -> compare nr1 nr2) proc_nrs in
4873   let rec loop = function
4874     | [] -> ()
4875     | [_] -> ()
4876     | (name1,nr1) :: ((name2,nr2) :: _ as rest) when nr1 < nr2 ->
4877         loop rest
4878     | (name1,nr1) :: (name2,nr2) :: _ ->
4879         failwithf "%s and %s have conflicting procedure numbers (%d, %d)"
4880           name1 name2 nr1 nr2
4881   in
4882   loop proc_nrs;
4883
4884   (* Check tests. *)
4885   List.iter (
4886     function
4887       (* Ignore functions that have no tests.  We generate a
4888        * warning when the user does 'make check' instead.
4889        *)
4890     | name, _, _, _, [], _, _ -> ()
4891     | name, _, _, _, tests, _, _ ->
4892         let funcs =
4893           List.map (
4894             fun (_, _, test) ->
4895               match seq_of_test test with
4896               | [] ->
4897                   failwithf "%s has a test containing an empty sequence" name
4898               | cmds -> List.map List.hd cmds
4899           ) tests in
4900         let funcs = List.flatten funcs in
4901
4902         let tested = List.mem name funcs in
4903
4904         if not tested then
4905           failwithf "function %s has tests but does not test itself" name
4906   ) all_functions
4907
4908 (* 'pr' prints to the current output file. *)
4909 let chan = ref Pervasives.stdout
4910 let lines = ref 0
4911 let pr fs =
4912   ksprintf
4913     (fun str ->
4914        let i = count_chars '\n' str in
4915        lines := !lines + i;
4916        output_string !chan str
4917     ) fs
4918
4919 let copyright_years =
4920   let this_year = 1900 + (localtime (time ())).tm_year in
4921   if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
4922
4923 (* Generate a header block in a number of standard styles. *)
4924 type comment_style =
4925     CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
4926 type license = GPLv2plus | LGPLv2plus
4927
4928 let generate_header ?(extra_inputs = []) comment license =
4929   let inputs = "src/generator.ml" :: extra_inputs in
4930   let c = match comment with
4931     | CStyle ->         pr "/* "; " *"
4932     | CPlusPlusStyle -> pr "// "; "//"
4933     | HashStyle ->      pr "# ";  "#"
4934     | OCamlStyle ->     pr "(* "; " *"
4935     | HaskellStyle ->   pr "{- "; "  " in
4936   pr "libguestfs generated file\n";
4937   pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
4938   List.iter (pr "%s   %s\n" c) inputs;
4939   pr "%s ANY CHANGES YOU MAKE TO THIS FILE WILL BE LOST.\n" c;
4940   pr "%s\n" c;
4941   pr "%s Copyright (C) %s Red Hat Inc.\n" c copyright_years;
4942   pr "%s\n" c;
4943   (match license with
4944    | GPLv2plus ->
4945        pr "%s This program is free software; you can redistribute it and/or modify\n" c;
4946        pr "%s it under the terms of the GNU General Public License as published by\n" c;
4947        pr "%s the Free Software Foundation; either version 2 of the License, or\n" c;
4948        pr "%s (at your option) any later version.\n" c;
4949        pr "%s\n" c;
4950        pr "%s This program is distributed in the hope that it will be useful,\n" c;
4951        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4952        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" c;
4953        pr "%s GNU General Public License for more details.\n" c;
4954        pr "%s\n" c;
4955        pr "%s You should have received a copy of the GNU General Public License along\n" c;
4956        pr "%s with this program; if not, write to the Free Software Foundation, Inc.,\n" c;
4957        pr "%s 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n" c;
4958
4959    | LGPLv2plus ->
4960        pr "%s This library is free software; you can redistribute it and/or\n" c;
4961        pr "%s modify it under the terms of the GNU Lesser General Public\n" c;
4962        pr "%s License as published by the Free Software Foundation; either\n" c;
4963        pr "%s version 2 of the License, or (at your option) any later version.\n" c;
4964        pr "%s\n" c;
4965        pr "%s This library is distributed in the hope that it will be useful,\n" c;
4966        pr "%s but WITHOUT ANY WARRANTY; without even the implied warranty of\n" c;
4967        pr "%s MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n" c;
4968        pr "%s Lesser General Public License for more details.\n" c;
4969        pr "%s\n" c;
4970        pr "%s You should have received a copy of the GNU Lesser General Public\n" c;
4971        pr "%s License along with this library; if not, write to the Free Software\n" c;
4972        pr "%s Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n" c;
4973   );
4974   (match comment with
4975    | CStyle -> pr " */\n"
4976    | CPlusPlusStyle
4977    | HashStyle -> ()
4978    | OCamlStyle -> pr " *)\n"
4979    | HaskellStyle -> pr "-}\n"
4980   );
4981   pr "\n"
4982
4983 (* Start of main code generation functions below this line. *)
4984
4985 (* Generate the pod documentation for the C API. *)
4986 let rec generate_actions_pod () =
4987   List.iter (
4988     fun (shortname, style, _, flags, _, _, longdesc) ->
4989       if not (List.mem NotInDocs flags) then (
4990         let name = "guestfs_" ^ shortname in
4991         pr "=head2 %s\n\n" name;
4992         pr " ";
4993         generate_prototype ~extern:false ~handle:"handle" name style;
4994         pr "\n\n";
4995         pr "%s\n\n" longdesc;
4996         (match fst style with
4997          | RErr ->
4998              pr "This function returns 0 on success or -1 on error.\n\n"
4999          | RInt _ ->
5000              pr "On error this function returns -1.\n\n"
5001          | RInt64 _ ->
5002              pr "On error this function returns -1.\n\n"
5003          | RBool _ ->
5004              pr "This function returns a C truth value on success or -1 on error.\n\n"
5005          | RConstString _ ->
5006              pr "This function returns a string, or NULL on error.
5007 The string is owned by the guest handle and must I<not> be freed.\n\n"
5008          | RConstOptString _ ->
5009              pr "This function returns a string which may be NULL.
5010 There is way to return an error from this function.
5011 The string is owned by the guest handle and must I<not> be freed.\n\n"
5012          | RString _ ->
5013              pr "This function returns a string, or NULL on error.
5014 I<The caller must free the returned string after use>.\n\n"
5015          | RStringList _ ->
5016              pr "This function returns a NULL-terminated array of strings
5017 (like L<environ(3)>), or NULL if there was an error.
5018 I<The caller must free the strings and the array after use>.\n\n"
5019          | RStruct (_, typ) ->
5020              pr "This function returns a C<struct guestfs_%s *>,
5021 or NULL if there was an error.
5022 I<The caller must call C<guestfs_free_%s> after use>.\n\n" typ typ
5023          | RStructList (_, typ) ->
5024              pr "This function returns a C<struct guestfs_%s_list *>
5025 (see E<lt>guestfs-structs.hE<gt>),
5026 or NULL if there was an error.
5027 I<The caller must call C<guestfs_free_%s_list> after use>.\n\n" typ typ
5028          | RHashtable _ ->
5029              pr "This function returns a NULL-terminated array of
5030 strings, or NULL if there was an error.
5031 The array of strings will always have length C<2n+1>, where
5032 C<n> keys and values alternate, followed by the trailing NULL entry.
5033 I<The caller must free the strings and the array after use>.\n\n"
5034          | RBufferOut _ ->
5035              pr "This function returns a buffer, or NULL on error.
5036 The size of the returned buffer is written to C<*size_r>.
5037 I<The caller must free the returned buffer after use>.\n\n"
5038         );
5039         if List.mem ProtocolLimitWarning flags then
5040           pr "%s\n\n" protocol_limit_warning;
5041         if List.mem DangerWillRobinson flags then
5042           pr "%s\n\n" danger_will_robinson;
5043         match deprecation_notice flags with
5044         | None -> ()
5045         | Some txt -> pr "%s\n\n" txt
5046       )
5047   ) all_functions_sorted
5048
5049 and generate_structs_pod () =
5050   (* Structs documentation. *)
5051   List.iter (
5052     fun (typ, cols) ->
5053       pr "=head2 guestfs_%s\n" typ;
5054       pr "\n";
5055       pr " struct guestfs_%s {\n" typ;
5056       List.iter (
5057         function
5058         | name, FChar -> pr "   char %s;\n" name
5059         | name, FUInt32 -> pr "   uint32_t %s;\n" name
5060         | name, FInt32 -> pr "   int32_t %s;\n" name
5061         | name, (FUInt64|FBytes) -> pr "   uint64_t %s;\n" name
5062         | name, FInt64 -> pr "   int64_t %s;\n" name
5063         | name, FString -> pr "   char *%s;\n" name
5064         | name, FBuffer ->
5065             pr "   /* The next two fields describe a byte array. */\n";
5066             pr "   uint32_t %s_len;\n" name;
5067             pr "   char *%s;\n" name
5068         | name, FUUID ->
5069             pr "   /* The next field is NOT nul-terminated, be careful when printing it: */\n";
5070             pr "   char %s[32];\n" name
5071         | name, FOptPercent ->
5072             pr "   /* The next field is [0..100] or -1 meaning 'not present': */\n";
5073             pr "   float %s;\n" name
5074       ) cols;
5075       pr " };\n";
5076       pr " \n";
5077       pr " struct guestfs_%s_list {\n" typ;
5078       pr "   uint32_t len; /* Number of elements in list. */\n";
5079       pr "   struct guestfs_%s *val; /* Elements. */\n" typ;
5080       pr " };\n";
5081       pr " \n";
5082       pr " void guestfs_free_%s (struct guestfs_free_%s *);\n" typ typ;
5083       pr " void guestfs_free_%s_list (struct guestfs_free_%s_list *);\n"
5084         typ typ;
5085       pr "\n"
5086   ) structs
5087
5088 and generate_availability_pod () =
5089   (* Availability documentation. *)
5090   pr "=over 4\n";
5091   pr "\n";
5092   List.iter (
5093     fun (group, functions) ->
5094       pr "=item B<%s>\n" group;
5095       pr "\n";
5096       pr "The following functions:\n";
5097       List.iter (pr "L</guestfs_%s>\n") functions;
5098       pr "\n"
5099   ) optgroups;
5100   pr "=back\n";
5101   pr "\n"
5102
5103 (* Generate the protocol (XDR) file, 'guestfs_protocol.x' and
5104  * indirectly 'guestfs_protocol.h' and 'guestfs_protocol.c'.
5105  *
5106  * We have to use an underscore instead of a dash because otherwise
5107  * rpcgen generates incorrect code.
5108  *
5109  * This header is NOT exported to clients, but see also generate_structs_h.
5110  *)
5111 and generate_xdr () =
5112   generate_header CStyle LGPLv2plus;
5113
5114   (* This has to be defined to get around a limitation in Sun's rpcgen. *)
5115   pr "typedef string str<>;\n";
5116   pr "\n";
5117
5118   (* Internal structures. *)
5119   List.iter (
5120     function
5121     | typ, cols ->
5122         pr "struct guestfs_int_%s {\n" typ;
5123         List.iter (function
5124                    | name, FChar -> pr "  char %s;\n" name
5125                    | name, FString -> pr "  string %s<>;\n" name
5126                    | name, FBuffer -> pr "  opaque %s<>;\n" name
5127                    | name, FUUID -> pr "  opaque %s[32];\n" name
5128                    | name, (FInt32|FUInt32) -> pr "  int %s;\n" name
5129                    | name, (FInt64|FUInt64|FBytes) -> pr "  hyper %s;\n" name
5130                    | name, FOptPercent -> pr "  float %s;\n" name
5131                   ) cols;
5132         pr "};\n";
5133         pr "\n";
5134         pr "typedef struct guestfs_int_%s guestfs_int_%s_list<>;\n" typ typ;
5135         pr "\n";
5136   ) structs;
5137
5138   List.iter (
5139     fun (shortname, style, _, _, _, _, _) ->
5140       let name = "guestfs_" ^ shortname in
5141
5142       (match snd style with
5143        | [] -> ()
5144        | args ->
5145            pr "struct %s_args {\n" name;
5146            List.iter (
5147              function
5148              | Pathname n | Device n | Dev_or_Path n | String n ->
5149                  pr "  string %s<>;\n" n
5150              | OptString n -> pr "  str *%s;\n" n
5151              | StringList n | DeviceList n -> pr "  str %s<>;\n" n
5152              | Bool n -> pr "  bool %s;\n" n
5153              | Int n -> pr "  int %s;\n" n
5154              | Int64 n -> pr "  hyper %s;\n" n
5155              | FileIn _ | FileOut _ -> ()
5156            ) args;
5157            pr "};\n\n"
5158       );
5159       (match fst style with
5160        | RErr -> ()
5161        | RInt n ->
5162            pr "struct %s_ret {\n" name;
5163            pr "  int %s;\n" n;
5164            pr "};\n\n"
5165        | RInt64 n ->
5166            pr "struct %s_ret {\n" name;
5167            pr "  hyper %s;\n" n;
5168            pr "};\n\n"
5169        | RBool n ->
5170            pr "struct %s_ret {\n" name;
5171            pr "  bool %s;\n" n;
5172            pr "};\n\n"
5173        | RConstString _ | RConstOptString _ ->
5174            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5175        | RString n ->
5176            pr "struct %s_ret {\n" name;
5177            pr "  string %s<>;\n" n;
5178            pr "};\n\n"
5179        | RStringList n ->
5180            pr "struct %s_ret {\n" name;
5181            pr "  str %s<>;\n" n;
5182            pr "};\n\n"
5183        | RStruct (n, typ) ->
5184            pr "struct %s_ret {\n" name;
5185            pr "  guestfs_int_%s %s;\n" typ n;
5186            pr "};\n\n"
5187        | RStructList (n, typ) ->
5188            pr "struct %s_ret {\n" name;
5189            pr "  guestfs_int_%s_list %s;\n" typ n;
5190            pr "};\n\n"
5191        | RHashtable n ->
5192            pr "struct %s_ret {\n" name;
5193            pr "  str %s<>;\n" n;
5194            pr "};\n\n"
5195        | RBufferOut n ->
5196            pr "struct %s_ret {\n" name;
5197            pr "  opaque %s<>;\n" n;
5198            pr "};\n\n"
5199       );
5200   ) daemon_functions;
5201
5202   (* Table of procedure numbers. *)
5203   pr "enum guestfs_procedure {\n";
5204   List.iter (
5205     fun (shortname, _, proc_nr, _, _, _, _) ->
5206       pr "  GUESTFS_PROC_%s = %d,\n" (String.uppercase shortname) proc_nr
5207   ) daemon_functions;
5208   pr "  GUESTFS_PROC_NR_PROCS\n";
5209   pr "};\n";
5210   pr "\n";
5211
5212   (* Having to choose a maximum message size is annoying for several
5213    * reasons (it limits what we can do in the API), but it (a) makes
5214    * the protocol a lot simpler, and (b) provides a bound on the size
5215    * of the daemon which operates in limited memory space.
5216    *)
5217   pr "const GUESTFS_MESSAGE_MAX = %d;\n" (4 * 1024 * 1024);
5218   pr "\n";
5219
5220   (* Message header, etc. *)
5221   pr "\
5222 /* The communication protocol is now documented in the guestfs(3)
5223  * manpage.
5224  */
5225
5226 const GUESTFS_PROGRAM = 0x2000F5F5;
5227 const GUESTFS_PROTOCOL_VERSION = 1;
5228
5229 /* These constants must be larger than any possible message length. */
5230 const GUESTFS_LAUNCH_FLAG = 0xf5f55ff5;
5231 const GUESTFS_CANCEL_FLAG = 0xffffeeee;
5232
5233 enum guestfs_message_direction {
5234   GUESTFS_DIRECTION_CALL = 0,        /* client -> daemon */
5235   GUESTFS_DIRECTION_REPLY = 1        /* daemon -> client */
5236 };
5237
5238 enum guestfs_message_status {
5239   GUESTFS_STATUS_OK = 0,
5240   GUESTFS_STATUS_ERROR = 1
5241 };
5242
5243 const GUESTFS_ERROR_LEN = 256;
5244
5245 struct guestfs_message_error {
5246   string error_message<GUESTFS_ERROR_LEN>;
5247 };
5248
5249 struct guestfs_message_header {
5250   unsigned prog;                     /* GUESTFS_PROGRAM */
5251   unsigned vers;                     /* GUESTFS_PROTOCOL_VERSION */
5252   guestfs_procedure proc;            /* GUESTFS_PROC_x */
5253   guestfs_message_direction direction;
5254   unsigned serial;                   /* message serial number */
5255   guestfs_message_status status;
5256 };
5257
5258 const GUESTFS_MAX_CHUNK_SIZE = 8192;
5259
5260 struct guestfs_chunk {
5261   int cancel;                        /* if non-zero, transfer is cancelled */
5262   /* data size is 0 bytes if the transfer has finished successfully */
5263   opaque data<GUESTFS_MAX_CHUNK_SIZE>;
5264 };
5265 "
5266
5267 (* Generate the guestfs-structs.h file. *)
5268 and generate_structs_h () =
5269   generate_header CStyle LGPLv2plus;
5270
5271   (* This is a public exported header file containing various
5272    * structures.  The structures are carefully written to have
5273    * exactly the same in-memory format as the XDR structures that
5274    * we use on the wire to the daemon.  The reason for creating
5275    * copies of these structures here is just so we don't have to
5276    * export the whole of guestfs_protocol.h (which includes much
5277    * unrelated and XDR-dependent stuff that we don't want to be
5278    * public, or required by clients).
5279    *
5280    * To reiterate, we will pass these structures to and from the
5281    * client with a simple assignment or memcpy, so the format
5282    * must be identical to what rpcgen / the RFC defines.
5283    *)
5284
5285   (* Public structures. *)
5286   List.iter (
5287     fun (typ, cols) ->
5288       pr "struct guestfs_%s {\n" typ;
5289       List.iter (
5290         function
5291         | name, FChar -> pr "  char %s;\n" name
5292         | name, FString -> pr "  char *%s;\n" name
5293         | name, FBuffer ->
5294             pr "  uint32_t %s_len;\n" name;
5295             pr "  char *%s;\n" name
5296         | name, FUUID -> pr "  char %s[32]; /* this is NOT nul-terminated, be careful when printing */\n" name
5297         | name, FUInt32 -> pr "  uint32_t %s;\n" name
5298         | name, FInt32 -> pr "  int32_t %s;\n" name
5299         | name, (FUInt64|FBytes) -> pr "  uint64_t %s;\n" name
5300         | name, FInt64 -> pr "  int64_t %s;\n" name
5301         | name, FOptPercent -> pr "  float %s; /* [0..100] or -1 */\n" name
5302       ) cols;
5303       pr "};\n";
5304       pr "\n";
5305       pr "struct guestfs_%s_list {\n" typ;
5306       pr "  uint32_t len;\n";
5307       pr "  struct guestfs_%s *val;\n" typ;
5308       pr "};\n";
5309       pr "\n";
5310       pr "extern void guestfs_free_%s (struct guestfs_%s *);\n" typ typ;
5311       pr "extern void guestfs_free_%s_list (struct guestfs_%s_list *);\n" typ typ;
5312       pr "\n"
5313   ) structs
5314
5315 (* Generate the guestfs-actions.h file. *)
5316 and generate_actions_h () =
5317   generate_header CStyle LGPLv2plus;
5318   List.iter (
5319     fun (shortname, style, _, _, _, _, _) ->
5320       let name = "guestfs_" ^ shortname in
5321       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5322         name style
5323   ) all_functions
5324
5325 (* Generate the guestfs-internal-actions.h file. *)
5326 and generate_internal_actions_h () =
5327   generate_header CStyle LGPLv2plus;
5328   List.iter (
5329     fun (shortname, style, _, _, _, _, _) ->
5330       let name = "guestfs__" ^ shortname in
5331       generate_prototype ~single_line:true ~newline:true ~handle:"handle"
5332         name style
5333   ) non_daemon_functions
5334
5335 (* Generate the client-side dispatch stubs. *)
5336 and generate_client_actions () =
5337   generate_header CStyle LGPLv2plus;
5338
5339   pr "\
5340 #include <stdio.h>
5341 #include <stdlib.h>
5342 #include <stdint.h>
5343 #include <inttypes.h>
5344
5345 #include \"guestfs.h\"
5346 #include \"guestfs-internal.h\"
5347 #include \"guestfs-internal-actions.h\"
5348 #include \"guestfs_protocol.h\"
5349
5350 #define error guestfs_error
5351 //#define perrorf guestfs_perrorf
5352 #define safe_malloc guestfs_safe_malloc
5353 #define safe_realloc guestfs_safe_realloc
5354 //#define safe_strdup guestfs_safe_strdup
5355 #define safe_memdup guestfs_safe_memdup
5356
5357 /* Check the return message from a call for validity. */
5358 static int
5359 check_reply_header (guestfs_h *g,
5360                     const struct guestfs_message_header *hdr,
5361                     unsigned int proc_nr, unsigned int serial)
5362 {
5363   if (hdr->prog != GUESTFS_PROGRAM) {
5364     error (g, \"wrong program (%%d/%%d)\", hdr->prog, GUESTFS_PROGRAM);
5365     return -1;
5366   }
5367   if (hdr->vers != GUESTFS_PROTOCOL_VERSION) {
5368     error (g, \"wrong protocol version (%%d/%%d)\",
5369            hdr->vers, GUESTFS_PROTOCOL_VERSION);
5370     return -1;
5371   }
5372   if (hdr->direction != GUESTFS_DIRECTION_REPLY) {
5373     error (g, \"unexpected message direction (%%d/%%d)\",
5374            hdr->direction, GUESTFS_DIRECTION_REPLY);
5375     return -1;
5376   }
5377   if (hdr->proc != proc_nr) {
5378     error (g, \"unexpected procedure number (%%d/%%d)\", hdr->proc, proc_nr);
5379     return -1;
5380   }
5381   if (hdr->serial != serial) {
5382     error (g, \"unexpected serial (%%d/%%d)\", hdr->serial, serial);
5383     return -1;
5384   }
5385
5386   return 0;
5387 }
5388
5389 /* Check we are in the right state to run a high-level action. */
5390 static int
5391 check_state (guestfs_h *g, const char *caller)
5392 {
5393   if (!guestfs__is_ready (g)) {
5394     if (guestfs__is_config (g) || guestfs__is_launching (g))
5395       error (g, \"%%s: call launch before using this function\\n(in guestfish, don't forget to use the 'run' command)\",
5396         caller);
5397     else
5398       error (g, \"%%s called from the wrong state, %%d != READY\",
5399         caller, guestfs__get_state (g));
5400     return -1;
5401   }
5402   return 0;
5403 }
5404
5405 ";
5406
5407   (* Generate code to generate guestfish call traces. *)
5408   let trace_call shortname style =
5409     pr "  if (guestfs__get_trace (g)) {\n";
5410
5411     let needs_i =
5412       List.exists (function
5413                    | StringList _ | DeviceList _ -> true
5414                    | _ -> false) (snd style) in
5415     if needs_i then (
5416       pr "    int i;\n";
5417       pr "\n"
5418     );
5419
5420     pr "    printf (\"%s\");\n" shortname;
5421     List.iter (
5422       function
5423       | String n                        (* strings *)
5424       | Device n
5425       | Pathname n
5426       | Dev_or_Path n
5427       | FileIn n
5428       | FileOut n ->
5429           (* guestfish doesn't support string escaping, so neither do we *)
5430           pr "    printf (\" \\\"%%s\\\"\", %s);\n" n
5431       | OptString n ->                  (* string option *)
5432           pr "    if (%s) printf (\" \\\"%%s\\\"\", %s);\n" n n;
5433           pr "    else printf (\" null\");\n"
5434       | StringList n
5435       | DeviceList n ->                 (* string list *)
5436           pr "    putchar (' ');\n";
5437           pr "    putchar ('\"');\n";
5438           pr "    for (i = 0; %s[i]; ++i) {\n" n;
5439           pr "      if (i > 0) putchar (' ');\n";
5440           pr "      fputs (%s[i], stdout);\n" n;
5441           pr "    }\n";
5442           pr "    putchar ('\"');\n";
5443       | Bool n ->                       (* boolean *)
5444           pr "    fputs (%s ? \" true\" : \" false\", stdout);\n" n
5445       | Int n ->                        (* int *)
5446           pr "    printf (\" %%d\", %s);\n" n
5447       | Int64 n ->
5448           pr "    printf (\" %%\" PRIi64, %s);\n" n
5449     ) (snd style);
5450     pr "    putchar ('\\n');\n";
5451     pr "  }\n";
5452     pr "\n";
5453   in
5454
5455   (* For non-daemon functions, generate a wrapper around each function. *)
5456   List.iter (
5457     fun (shortname, style, _, _, _, _, _) ->
5458       let name = "guestfs_" ^ shortname in
5459
5460       generate_prototype ~extern:false ~semicolon:false ~newline:true
5461         ~handle:"g" name style;
5462       pr "{\n";
5463       trace_call shortname style;
5464       pr "  return guestfs__%s " shortname;
5465       generate_c_call_args ~handle:"g" style;
5466       pr ";\n";
5467       pr "}\n";
5468       pr "\n"
5469   ) non_daemon_functions;
5470
5471   (* Client-side stubs for each function. *)
5472   List.iter (
5473     fun (shortname, style, _, _, _, _, _) ->
5474       let name = "guestfs_" ^ shortname in
5475
5476       (* Generate the action stub. *)
5477       generate_prototype ~extern:false ~semicolon:false ~newline:true
5478         ~handle:"g" name style;
5479
5480       let error_code =
5481         match fst style with
5482         | RErr | RInt _ | RInt64 _ | RBool _ -> "-1"
5483         | RConstString _ | RConstOptString _ ->
5484             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5485         | RString _ | RStringList _
5486         | RStruct _ | RStructList _
5487         | RHashtable _ | RBufferOut _ ->
5488             "NULL" in
5489
5490       pr "{\n";
5491
5492       (match snd style with
5493        | [] -> ()
5494        | _ -> pr "  struct %s_args args;\n" name
5495       );
5496
5497       pr "  guestfs_message_header hdr;\n";
5498       pr "  guestfs_message_error err;\n";
5499       let has_ret =
5500         match fst style with
5501         | RErr -> false
5502         | RConstString _ | RConstOptString _ ->
5503             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5504         | RInt _ | RInt64 _
5505         | RBool _ | RString _ | RStringList _
5506         | RStruct _ | RStructList _
5507         | RHashtable _ | RBufferOut _ ->
5508             pr "  struct %s_ret ret;\n" name;
5509             true in
5510
5511       pr "  int serial;\n";
5512       pr "  int r;\n";
5513       pr "\n";
5514       trace_call shortname style;
5515       pr "  if (check_state (g, \"%s\") == -1) return %s;\n" name error_code;
5516       pr "  guestfs___set_busy (g);\n";
5517       pr "\n";
5518
5519       (* Send the main header and arguments. *)
5520       (match snd style with
5521        | [] ->
5522            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s, NULL, NULL);\n"
5523              (String.uppercase shortname)
5524        | args ->
5525            List.iter (
5526              function
5527              | Pathname n | Device n | Dev_or_Path n | String n ->
5528                  pr "  args.%s = (char *) %s;\n" n n
5529              | OptString n ->
5530                  pr "  args.%s = %s ? (char **) &%s : NULL;\n" n n n
5531              | StringList n | DeviceList n ->
5532                  pr "  args.%s.%s_val = (char **) %s;\n" n n n;
5533                  pr "  for (args.%s.%s_len = 0; %s[args.%s.%s_len]; args.%s.%s_len++) ;\n" n n n n n n n;
5534              | Bool n ->
5535                  pr "  args.%s = %s;\n" n n
5536              | Int n ->
5537                  pr "  args.%s = %s;\n" n n
5538              | Int64 n ->
5539                  pr "  args.%s = %s;\n" n n
5540              | FileIn _ | FileOut _ -> ()
5541            ) args;
5542            pr "  serial = guestfs___send (g, GUESTFS_PROC_%s,\n"
5543              (String.uppercase shortname);
5544            pr "        (xdrproc_t) xdr_%s_args, (char *) &args);\n"
5545              name;
5546       );
5547       pr "  if (serial == -1) {\n";
5548       pr "    guestfs___end_busy (g);\n";
5549       pr "    return %s;\n" error_code;
5550       pr "  }\n";
5551       pr "\n";
5552
5553       (* Send any additional files (FileIn) requested. *)
5554       let need_read_reply_label = ref false in
5555       List.iter (
5556         function
5557         | FileIn n ->
5558             pr "  r = guestfs___send_file (g, %s);\n" n;
5559             pr "  if (r == -1) {\n";
5560             pr "    guestfs___end_busy (g);\n";
5561             pr "    return %s;\n" error_code;
5562             pr "  }\n";
5563             pr "  if (r == -2) /* daemon cancelled */\n";
5564             pr "    goto read_reply;\n";
5565             need_read_reply_label := true;
5566             pr "\n";
5567         | _ -> ()
5568       ) (snd style);
5569
5570       (* Wait for the reply from the remote end. *)
5571       if !need_read_reply_label then pr " read_reply:\n";
5572       pr "  memset (&hdr, 0, sizeof hdr);\n";
5573       pr "  memset (&err, 0, sizeof err);\n";
5574       if has_ret then pr "  memset (&ret, 0, sizeof ret);\n";
5575       pr "\n";
5576       pr "  r = guestfs___recv (g, \"%s\", &hdr, &err,\n        " shortname;
5577       if not has_ret then
5578         pr "NULL, NULL"
5579       else
5580         pr "(xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret" shortname;
5581       pr ");\n";
5582
5583       pr "  if (r == -1) {\n";
5584       pr "    guestfs___end_busy (g);\n";
5585       pr "    return %s;\n" error_code;
5586       pr "  }\n";
5587       pr "\n";
5588
5589       pr "  if (check_reply_header (g, &hdr, GUESTFS_PROC_%s, serial) == -1) {\n"
5590         (String.uppercase shortname);
5591       pr "    guestfs___end_busy (g);\n";
5592       pr "    return %s;\n" error_code;
5593       pr "  }\n";
5594       pr "\n";
5595
5596       pr "  if (hdr.status == GUESTFS_STATUS_ERROR) {\n";
5597       pr "    error (g, \"%%s: %%s\", \"%s\", err.error_message);\n" shortname;
5598       pr "    free (err.error_message);\n";
5599       pr "    guestfs___end_busy (g);\n";
5600       pr "    return %s;\n" error_code;
5601       pr "  }\n";
5602       pr "\n";
5603
5604       (* Expecting to receive further files (FileOut)? *)
5605       List.iter (
5606         function
5607         | FileOut n ->
5608             pr "  if (guestfs___recv_file (g, %s) == -1) {\n" n;
5609             pr "    guestfs___end_busy (g);\n";
5610             pr "    return %s;\n" error_code;
5611             pr "  }\n";
5612             pr "\n";
5613         | _ -> ()
5614       ) (snd style);
5615
5616       pr "  guestfs___end_busy (g);\n";
5617
5618       (match fst style with
5619        | RErr -> pr "  return 0;\n"
5620        | RInt n | RInt64 n | RBool n ->
5621            pr "  return ret.%s;\n" n
5622        | RConstString _ | RConstOptString _ ->
5623            failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5624        | RString n ->
5625            pr "  return ret.%s; /* caller will free */\n" n
5626        | RStringList n | RHashtable n ->
5627            pr "  /* caller will free this, but we need to add a NULL entry */\n";
5628            pr "  ret.%s.%s_val =\n" n n;
5629            pr "    safe_realloc (g, ret.%s.%s_val,\n" n n;
5630            pr "                  sizeof (char *) * (ret.%s.%s_len + 1));\n"
5631              n n;
5632            pr "  ret.%s.%s_val[ret.%s.%s_len] = NULL;\n" n n n n;
5633            pr "  return ret.%s.%s_val;\n" n n
5634        | RStruct (n, _) ->
5635            pr "  /* caller will free this */\n";
5636            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5637        | RStructList (n, _) ->
5638            pr "  /* caller will free this */\n";
5639            pr "  return safe_memdup (g, &ret.%s, sizeof (ret.%s));\n" n n
5640        | RBufferOut n ->
5641            pr "  /* RBufferOut is tricky: If the buffer is zero-length, then\n";
5642            pr "   * _val might be NULL here.  To make the API saner for\n";
5643            pr "   * callers, we turn this case into a unique pointer (using\n";
5644            pr "   * malloc(1)).\n";
5645            pr "   */\n";
5646            pr "  if (ret.%s.%s_len > 0) {\n" n n;
5647            pr "    *size_r = ret.%s.%s_len;\n" n n;
5648            pr "    return ret.%s.%s_val; /* caller will free */\n" n n;
5649            pr "  } else {\n";
5650            pr "    free (ret.%s.%s_val);\n" n n;
5651            pr "    char *p = safe_malloc (g, 1);\n";
5652            pr "    *size_r = ret.%s.%s_len;\n" n n;
5653            pr "    return p;\n";
5654            pr "  }\n";
5655       );
5656
5657       pr "}\n\n"
5658   ) daemon_functions;
5659
5660   (* Functions to free structures. *)
5661   pr "/* Structure-freeing functions.  These rely on the fact that the\n";
5662   pr " * structure format is identical to the XDR format.  See note in\n";
5663   pr " * generator.ml.\n";
5664   pr " */\n";
5665   pr "\n";
5666
5667   List.iter (
5668     fun (typ, _) ->
5669       pr "void\n";
5670       pr "guestfs_free_%s (struct guestfs_%s *x)\n" typ typ;
5671       pr "{\n";
5672       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s, (char *) x);\n" typ;
5673       pr "  free (x);\n";
5674       pr "}\n";
5675       pr "\n";
5676
5677       pr "void\n";
5678       pr "guestfs_free_%s_list (struct guestfs_%s_list *x)\n" typ typ;
5679       pr "{\n";
5680       pr "  xdr_free ((xdrproc_t) xdr_guestfs_int_%s_list, (char *) x);\n" typ;
5681       pr "  free (x);\n";
5682       pr "}\n";
5683       pr "\n";
5684
5685   ) structs;
5686
5687 (* Generate daemon/actions.h. *)
5688 and generate_daemon_actions_h () =
5689   generate_header CStyle GPLv2plus;
5690
5691   pr "#include \"../src/guestfs_protocol.h\"\n";
5692   pr "\n";
5693
5694   List.iter (
5695     fun (name, style, _, _, _, _, _) ->
5696       generate_prototype
5697         ~single_line:true ~newline:true ~in_daemon:true ~prefix:"do_"
5698         name style;
5699   ) daemon_functions
5700
5701 (* Generate the linker script which controls the visibility of
5702  * symbols in the public ABI and ensures no other symbols get
5703  * exported accidentally.
5704  *)
5705 and generate_linker_script () =
5706   generate_header HashStyle GPLv2plus;
5707
5708   let globals = [
5709     "guestfs_create";
5710     "guestfs_close";
5711     "guestfs_get_error_handler";
5712     "guestfs_get_out_of_memory_handler";
5713     "guestfs_last_error";
5714     "guestfs_set_error_handler";
5715     "guestfs_set_launch_done_callback";
5716     "guestfs_set_log_message_callback";
5717     "guestfs_set_out_of_memory_handler";
5718     "guestfs_set_subprocess_quit_callback";
5719
5720     (* Unofficial parts of the API: the bindings code use these
5721      * functions, so it is useful to export them.
5722      *)
5723     "guestfs_safe_calloc";
5724     "guestfs_safe_malloc";
5725   ] in
5726   let functions =
5727     List.map (fun (name, _, _, _, _, _, _) -> "guestfs_" ^ name)
5728       all_functions in
5729   let structs =
5730     List.concat (
5731       List.map (fun (typ, _) ->
5732                   ["guestfs_free_" ^ typ; "guestfs_free_" ^ typ ^ "_list"])
5733         structs
5734     ) in
5735   let globals = List.sort compare (globals @ functions @ structs) in
5736
5737   pr "{\n";
5738   pr "    global:\n";
5739   List.iter (pr "        %s;\n") globals;
5740   pr "\n";
5741
5742   pr "    local:\n";
5743   pr "        *;\n";
5744   pr "};\n"
5745
5746 (* Generate the server-side stubs. *)
5747 and generate_daemon_actions () =
5748   generate_header CStyle GPLv2plus;
5749
5750   pr "#include <config.h>\n";
5751   pr "\n";
5752   pr "#include <stdio.h>\n";
5753   pr "#include <stdlib.h>\n";
5754   pr "#include <string.h>\n";
5755   pr "#include <inttypes.h>\n";
5756   pr "#include <rpc/types.h>\n";
5757   pr "#include <rpc/xdr.h>\n";
5758   pr "\n";
5759   pr "#include \"daemon.h\"\n";
5760   pr "#include \"c-ctype.h\"\n";
5761   pr "#include \"../src/guestfs_protocol.h\"\n";
5762   pr "#include \"actions.h\"\n";
5763   pr "\n";
5764
5765   List.iter (
5766     fun (name, style, _, _, _, _, _) ->
5767       (* Generate server-side stubs. *)
5768       pr "static void %s_stub (XDR *xdr_in)\n" name;
5769       pr "{\n";
5770       let error_code =
5771         match fst style with
5772         | RErr | RInt _ -> pr "  int r;\n"; "-1"
5773         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
5774         | RBool _ -> pr "  int r;\n"; "-1"
5775         | RConstString _ | RConstOptString _ ->
5776             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5777         | RString _ -> pr "  char *r;\n"; "NULL"
5778         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
5779         | RStruct (_, typ) -> pr "  guestfs_int_%s *r;\n" typ; "NULL"
5780         | RStructList (_, typ) -> pr "  guestfs_int_%s_list *r;\n" typ; "NULL"
5781         | RBufferOut _ ->
5782             pr "  size_t size = 1;\n";
5783             pr "  char *r;\n";
5784             "NULL" in
5785
5786       (match snd style with
5787        | [] -> ()
5788        | args ->
5789            pr "  struct guestfs_%s_args args;\n" name;
5790            List.iter (
5791              function
5792              | Device n | Dev_or_Path n
5793              | Pathname n
5794              | String n -> ()
5795              | OptString n -> pr "  char *%s;\n" n
5796              | StringList n | DeviceList n -> pr "  char **%s;\n" n
5797              | Bool n -> pr "  int %s;\n" n
5798              | Int n -> pr "  int %s;\n" n
5799              | Int64 n -> pr "  int64_t %s;\n" n
5800              | FileIn _ | FileOut _ -> ()
5801            ) args
5802       );
5803       pr "\n";
5804
5805       (match snd style with
5806        | [] -> ()
5807        | args ->
5808            pr "  memset (&args, 0, sizeof args);\n";
5809            pr "\n";
5810            pr "  if (!xdr_guestfs_%s_args (xdr_in, &args)) {\n" name;
5811            pr "    reply_with_error (\"daemon failed to decode procedure arguments\");\n";
5812            pr "    return;\n";
5813            pr "  }\n";
5814            let pr_args n =
5815              pr "  char *%s = args.%s;\n" n n
5816            in
5817            let pr_list_handling_code n =
5818              pr "  %s = realloc (args.%s.%s_val,\n" n n n;
5819              pr "                sizeof (char *) * (args.%s.%s_len+1));\n" n n;
5820              pr "  if (%s == NULL) {\n" n;
5821              pr "    reply_with_perror (\"realloc\");\n";
5822              pr "    goto done;\n";
5823              pr "  }\n";
5824              pr "  %s[args.%s.%s_len] = NULL;\n" n n n;
5825              pr "  args.%s.%s_val = %s;\n" n n n;
5826            in
5827            List.iter (
5828              function
5829              | Pathname n ->
5830                  pr_args n;
5831                  pr "  ABS_PATH (%s, goto done);\n" n;
5832              | Device n ->
5833                  pr_args n;
5834                  pr "  RESOLVE_DEVICE (%s, goto done);\n" n;
5835              | Dev_or_Path n ->
5836                  pr_args n;
5837                  pr "  REQUIRE_ROOT_OR_RESOLVE_DEVICE (%s, goto done);\n" n;
5838              | String n -> pr_args n
5839              | OptString n -> pr "  %s = args.%s ? *args.%s : NULL;\n" n n n
5840              | StringList n ->
5841                  pr_list_handling_code n;
5842              | DeviceList n ->
5843                  pr_list_handling_code n;
5844                  pr "  /* Ensure that each is a device,\n";
5845                  pr "   * and perform device name translation. */\n";
5846                  pr "  { int pvi; for (pvi = 0; physvols[pvi] != NULL; ++pvi)\n";
5847                  pr "    RESOLVE_DEVICE (physvols[pvi], goto done);\n";
5848                  pr "  }\n";
5849              | Bool n -> pr "  %s = args.%s;\n" n n
5850              | Int n -> pr "  %s = args.%s;\n" n n
5851              | Int64 n -> pr "  %s = args.%s;\n" n n
5852              | FileIn _ | FileOut _ -> ()
5853            ) args;
5854            pr "\n"
5855       );
5856
5857
5858       (* this is used at least for do_equal *)
5859       if List.exists (function Pathname _ -> true | _ -> false) (snd style) then (
5860         (* Emit NEED_ROOT just once, even when there are two or
5861            more Pathname args *)
5862         pr "  NEED_ROOT (goto done);\n";
5863       );
5864
5865       (* Don't want to call the impl with any FileIn or FileOut
5866        * parameters, since these go "outside" the RPC protocol.
5867        *)
5868       let args' =
5869         List.filter (function FileIn _ | FileOut _ -> false | _ -> true)
5870           (snd style) in
5871       pr "  r = do_%s " name;
5872       generate_c_call_args (fst style, args');
5873       pr ";\n";
5874
5875       (match fst style with
5876        | RErr | RInt _ | RInt64 _ | RBool _
5877        | RConstString _ | RConstOptString _
5878        | RString _ | RStringList _ | RHashtable _
5879        | RStruct (_, _) | RStructList (_, _) ->
5880            pr "  if (r == %s)\n" error_code;
5881            pr "    /* do_%s has already called reply_with_error */\n" name;
5882            pr "    goto done;\n";
5883            pr "\n"
5884        | RBufferOut _ ->
5885            pr "  /* size == 0 && r == NULL could be a non-error case (just\n";
5886            pr "   * an ordinary zero-length buffer), so be careful ...\n";
5887            pr "   */\n";
5888            pr "  if (size == 1 && r == %s)\n" error_code;
5889            pr "    /* do_%s has already called reply_with_error */\n" name;
5890            pr "    goto done;\n";
5891            pr "\n"
5892       );
5893
5894       (* If there are any FileOut parameters, then the impl must
5895        * send its own reply.
5896        *)
5897       let no_reply =
5898         List.exists (function FileOut _ -> true | _ -> false) (snd style) in
5899       if no_reply then
5900         pr "  /* do_%s has already sent a reply */\n" name
5901       else (
5902         match fst style with
5903         | RErr -> pr "  reply (NULL, NULL);\n"
5904         | RInt n | RInt64 n | RBool n ->
5905             pr "  struct guestfs_%s_ret ret;\n" name;
5906             pr "  ret.%s = r;\n" n;
5907             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5908               name
5909         | RConstString _ | RConstOptString _ ->
5910             failwithf "RConstString|RConstOptString cannot be used by daemon functions"
5911         | RString n ->
5912             pr "  struct guestfs_%s_ret ret;\n" name;
5913             pr "  ret.%s = r;\n" n;
5914             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5915               name;
5916             pr "  free (r);\n"
5917         | RStringList n | RHashtable n ->
5918             pr "  struct guestfs_%s_ret ret;\n" name;
5919             pr "  ret.%s.%s_len = count_strings (r);\n" n n;
5920             pr "  ret.%s.%s_val = r;\n" n n;
5921             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5922               name;
5923             pr "  free_strings (r);\n"
5924         | RStruct (n, _) ->
5925             pr "  struct guestfs_%s_ret ret;\n" name;
5926             pr "  ret.%s = *r;\n" n;
5927             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5928               name;
5929             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5930               name
5931         | RStructList (n, _) ->
5932             pr "  struct guestfs_%s_ret ret;\n" name;
5933             pr "  ret.%s = *r;\n" n;
5934             pr "  reply ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5935               name;
5936             pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_ret, (char *) &ret);\n"
5937               name
5938         | RBufferOut n ->
5939             pr "  struct guestfs_%s_ret ret;\n" name;
5940             pr "  ret.%s.%s_val = r;\n" n n;
5941             pr "  ret.%s.%s_len = size;\n" n n;
5942             pr "  reply ((xdrproc_t) &xdr_guestfs_%s_ret, (char *) &ret);\n"
5943               name;
5944             pr "  free (r);\n"
5945       );
5946
5947       (* Free the args. *)
5948       (match snd style with
5949        | [] ->
5950            pr "done: ;\n";
5951        | _ ->
5952            pr "done:\n";
5953            pr "  xdr_free ((xdrproc_t) xdr_guestfs_%s_args, (char *) &args);\n"
5954              name
5955       );
5956
5957       pr "}\n\n";
5958   ) daemon_functions;
5959
5960   (* Dispatch function. *)
5961   pr "void dispatch_incoming_message (XDR *xdr_in)\n";
5962   pr "{\n";
5963   pr "  switch (proc_nr) {\n";
5964
5965   List.iter (
5966     fun (name, style, _, _, _, _, _) ->
5967       pr "    case GUESTFS_PROC_%s:\n" (String.uppercase name);
5968       pr "      %s_stub (xdr_in);\n" name;
5969       pr "      break;\n"
5970   ) daemon_functions;
5971
5972   pr "    default:\n";
5973   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";
5974   pr "  }\n";
5975   pr "}\n";
5976   pr "\n";
5977
5978   (* LVM columns and tokenization functions. *)
5979   (* XXX This generates crap code.  We should rethink how we
5980    * do this parsing.
5981    *)
5982   List.iter (
5983     function
5984     | typ, cols ->
5985         pr "static const char *lvm_%s_cols = \"%s\";\n"
5986           typ (String.concat "," (List.map fst cols));
5987         pr "\n";
5988
5989         pr "static int lvm_tokenize_%s (char *str, guestfs_int_lvm_%s *r)\n" typ typ;
5990         pr "{\n";
5991         pr "  char *tok, *p, *next;\n";
5992         pr "  int i, j;\n";
5993         pr "\n";
5994         (*
5995           pr "  fprintf (stderr, \"%%s: <<%%s>>\\n\", __func__, str);\n";
5996           pr "\n";
5997         *)
5998         pr "  if (!str) {\n";
5999         pr "    fprintf (stderr, \"%%s: failed: passed a NULL string\\n\", __func__);\n";
6000         pr "    return -1;\n";
6001         pr "  }\n";
6002         pr "  if (!*str || c_isspace (*str)) {\n";
6003         pr "    fprintf (stderr, \"%%s: failed: passed a empty string or one beginning with whitespace\\n\", __func__);\n";
6004         pr "    return -1;\n";
6005         pr "  }\n";
6006         pr "  tok = str;\n";
6007         List.iter (
6008           fun (name, coltype) ->
6009             pr "  if (!tok) {\n";
6010             pr "    fprintf (stderr, \"%%s: failed: string finished early, around token %%s\\n\", __func__, \"%s\");\n" name;
6011             pr "    return -1;\n";
6012             pr "  }\n";
6013             pr "  p = strchrnul (tok, ',');\n";
6014             pr "  if (*p) next = p+1; else next = NULL;\n";
6015             pr "  *p = '\\0';\n";
6016             (match coltype with
6017              | FString ->
6018                  pr "  r->%s = strdup (tok);\n" name;
6019                  pr "  if (r->%s == NULL) {\n" name;
6020                  pr "    perror (\"strdup\");\n";
6021                  pr "    return -1;\n";
6022                  pr "  }\n"
6023              | FUUID ->
6024                  pr "  for (i = j = 0; i < 32; ++j) {\n";
6025                  pr "    if (tok[j] == '\\0') {\n";
6026                  pr "      fprintf (stderr, \"%%s: failed to parse UUID from '%%s'\\n\", __func__, tok);\n";
6027                  pr "      return -1;\n";
6028                  pr "    } else if (tok[j] != '-')\n";
6029                  pr "      r->%s[i++] = tok[j];\n" name;
6030                  pr "  }\n";
6031              | FBytes ->
6032                  pr "  if (sscanf (tok, \"%%\"SCNu64, &r->%s) != 1) {\n" name;
6033                  pr "    fprintf (stderr, \"%%s: failed to parse size '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6034                  pr "    return -1;\n";
6035                  pr "  }\n";
6036              | FInt64 ->
6037                  pr "  if (sscanf (tok, \"%%\"SCNi64, &r->%s) != 1) {\n" name;
6038                  pr "    fprintf (stderr, \"%%s: failed to parse int '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6039                  pr "    return -1;\n";
6040                  pr "  }\n";
6041              | FOptPercent ->
6042                  pr "  if (tok[0] == '\\0')\n";
6043                  pr "    r->%s = -1;\n" name;
6044                  pr "  else if (sscanf (tok, \"%%f\", &r->%s) != 1) {\n" name;
6045                  pr "    fprintf (stderr, \"%%s: failed to parse float '%%s' from token %%s\\n\", __func__, tok, \"%s\");\n" name;
6046                  pr "    return -1;\n";
6047                  pr "  }\n";
6048              | FBuffer | FInt32 | FUInt32 | FUInt64 | FChar ->
6049                  assert false (* can never be an LVM column *)
6050             );
6051             pr "  tok = next;\n";
6052         ) cols;
6053
6054         pr "  if (tok != NULL) {\n";
6055         pr "    fprintf (stderr, \"%%s: failed: extra tokens at end of string\\n\", __func__);\n";
6056         pr "    return -1;\n";
6057         pr "  }\n";
6058         pr "  return 0;\n";
6059         pr "}\n";
6060         pr "\n";
6061
6062         pr "guestfs_int_lvm_%s_list *\n" typ;
6063         pr "parse_command_line_%ss (void)\n" typ;
6064         pr "{\n";
6065         pr "  char *out, *err;\n";
6066         pr "  char *p, *pend;\n";
6067         pr "  int r, i;\n";
6068         pr "  guestfs_int_lvm_%s_list *ret;\n" typ;
6069         pr "  void *newp;\n";
6070         pr "\n";
6071         pr "  ret = malloc (sizeof *ret);\n";
6072         pr "  if (!ret) {\n";
6073         pr "    reply_with_perror (\"malloc\");\n";
6074         pr "    return NULL;\n";
6075         pr "  }\n";
6076         pr "\n";
6077         pr "  ret->guestfs_int_lvm_%s_list_len = 0;\n" typ;
6078         pr "  ret->guestfs_int_lvm_%s_list_val = NULL;\n" typ;
6079         pr "\n";
6080         pr "  r = command (&out, &err,\n";
6081         pr "           \"/sbin/lvm\", \"%ss\",\n" typ;
6082         pr "           \"-o\", lvm_%s_cols, \"--unbuffered\", \"--noheadings\",\n" typ;
6083         pr "           \"--nosuffix\", \"--separator\", \",\", \"--units\", \"b\", NULL);\n";
6084         pr "  if (r == -1) {\n";
6085         pr "    reply_with_error (\"%%s\", err);\n";
6086         pr "    free (out);\n";
6087         pr "    free (err);\n";
6088         pr "    free (ret);\n";
6089         pr "    return NULL;\n";
6090         pr "  }\n";
6091         pr "\n";
6092         pr "  free (err);\n";
6093         pr "\n";
6094         pr "  /* Tokenize each line of the output. */\n";
6095         pr "  p = out;\n";
6096         pr "  i = 0;\n";
6097         pr "  while (p) {\n";
6098         pr "    pend = strchr (p, '\\n');       /* Get the next line of output. */\n";
6099         pr "    if (pend) {\n";
6100         pr "      *pend = '\\0';\n";
6101         pr "      pend++;\n";
6102         pr "    }\n";
6103         pr "\n";
6104         pr "    while (*p && c_isspace (*p))    /* Skip any leading whitespace. */\n";
6105         pr "      p++;\n";
6106         pr "\n";
6107         pr "    if (!*p) {                      /* Empty line?  Skip it. */\n";
6108         pr "      p = pend;\n";
6109         pr "      continue;\n";
6110         pr "    }\n";
6111         pr "\n";
6112         pr "    /* Allocate some space to store this next entry. */\n";
6113         pr "    newp = realloc (ret->guestfs_int_lvm_%s_list_val,\n" typ;
6114         pr "                sizeof (guestfs_int_lvm_%s) * (i+1));\n" typ;
6115         pr "    if (newp == NULL) {\n";
6116         pr "      reply_with_perror (\"realloc\");\n";
6117         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6118         pr "      free (ret);\n";
6119         pr "      free (out);\n";
6120         pr "      return NULL;\n";
6121         pr "    }\n";
6122         pr "    ret->guestfs_int_lvm_%s_list_val = newp;\n" typ;
6123         pr "\n";
6124         pr "    /* Tokenize the next entry. */\n";
6125         pr "    r = lvm_tokenize_%s (p, &ret->guestfs_int_lvm_%s_list_val[i]);\n" typ typ;
6126         pr "    if (r == -1) {\n";
6127         pr "      reply_with_error (\"failed to parse output of '%ss' command\");\n" typ;
6128         pr "      free (ret->guestfs_int_lvm_%s_list_val);\n" typ;
6129         pr "      free (ret);\n";
6130         pr "      free (out);\n";
6131         pr "      return NULL;\n";
6132         pr "    }\n";
6133         pr "\n";
6134         pr "    ++i;\n";
6135         pr "    p = pend;\n";
6136         pr "  }\n";
6137         pr "\n";
6138         pr "  ret->guestfs_int_lvm_%s_list_len = i;\n" typ;
6139         pr "\n";
6140         pr "  free (out);\n";
6141         pr "  return ret;\n";
6142         pr "}\n"
6143
6144   ) ["pv", lvm_pv_cols; "vg", lvm_vg_cols; "lv", lvm_lv_cols]
6145
6146 (* Generate a list of function names, for debugging in the daemon.. *)
6147 and generate_daemon_names () =
6148   generate_header CStyle GPLv2plus;
6149
6150   pr "#include <config.h>\n";
6151   pr "\n";
6152   pr "#include \"daemon.h\"\n";
6153   pr "\n";
6154
6155   pr "/* This array is indexed by proc_nr.  See guestfs_protocol.x. */\n";
6156   pr "const char *function_names[] = {\n";
6157   List.iter (
6158     fun (name, _, proc_nr, _, _, _, _) -> pr "  [%d] = \"%s\",\n" proc_nr name
6159   ) daemon_functions;
6160   pr "};\n";
6161
6162 (* Generate the optional groups for the daemon to implement
6163  * guestfs_available.
6164  *)
6165 and generate_daemon_optgroups_c () =
6166   generate_header CStyle GPLv2plus;
6167
6168   pr "#include <config.h>\n";
6169   pr "\n";
6170   pr "#include \"daemon.h\"\n";
6171   pr "#include \"optgroups.h\"\n";
6172   pr "\n";
6173
6174   pr "struct optgroup optgroups[] = {\n";
6175   List.iter (
6176     fun (group, _) ->
6177       pr "  { \"%s\", optgroup_%s_available },\n" group group
6178   ) optgroups;
6179   pr "  { NULL, NULL }\n";
6180   pr "};\n"
6181
6182 and generate_daemon_optgroups_h () =
6183   generate_header CStyle GPLv2plus;
6184
6185   List.iter (
6186     fun (group, _) ->
6187       pr "extern int optgroup_%s_available (void);\n" group
6188   ) optgroups
6189
6190 (* Generate the tests. *)
6191 and generate_tests () =
6192   generate_header CStyle GPLv2plus;
6193
6194   pr "\
6195 #include <stdio.h>
6196 #include <stdlib.h>
6197 #include <string.h>
6198 #include <unistd.h>
6199 #include <sys/types.h>
6200 #include <fcntl.h>
6201
6202 #include \"guestfs.h\"
6203 #include \"guestfs-internal.h\"
6204
6205 static guestfs_h *g;
6206 static int suppress_error = 0;
6207
6208 static void print_error (guestfs_h *g, void *data, const char *msg)
6209 {
6210   if (!suppress_error)
6211     fprintf (stderr, \"%%s\\n\", msg);
6212 }
6213
6214 /* FIXME: nearly identical code appears in fish.c */
6215 static void print_strings (char *const *argv)
6216 {
6217   int argc;
6218
6219   for (argc = 0; argv[argc] != NULL; ++argc)
6220     printf (\"\\t%%s\\n\", argv[argc]);
6221 }
6222
6223 /*
6224 static void print_table (char const *const *argv)
6225 {
6226   int i;
6227
6228   for (i = 0; argv[i] != NULL; i += 2)
6229     printf (\"%%s: %%s\\n\", argv[i], argv[i+1]);
6230 }
6231 */
6232
6233 ";
6234
6235   (* Generate a list of commands which are not tested anywhere. *)
6236   pr "static void no_test_warnings (void)\n";
6237   pr "{\n";
6238
6239   let hash : (string, bool) Hashtbl.t = Hashtbl.create 13 in
6240   List.iter (
6241     fun (_, _, _, _, tests, _, _) ->
6242       let tests = filter_map (
6243         function
6244         | (_, (Always|If _|Unless _), test) -> Some test
6245         | (_, Disabled, _) -> None
6246       ) tests in
6247       let seq = List.concat (List.map seq_of_test tests) in
6248       let cmds_tested = List.map List.hd seq in
6249       List.iter (fun cmd -> Hashtbl.replace hash cmd true) cmds_tested
6250   ) all_functions;
6251
6252   List.iter (
6253     fun (name, _, _, _, _, _, _) ->
6254       if not (Hashtbl.mem hash name) then
6255         pr "  fprintf (stderr, \"warning: \\\"guestfs_%s\\\" has no tests\\n\");\n" name
6256   ) all_functions;
6257
6258   pr "}\n";
6259   pr "\n";
6260
6261   (* Generate the actual tests.  Note that we generate the tests
6262    * in reverse order, deliberately, so that (in general) the
6263    * newest tests run first.  This makes it quicker and easier to
6264    * debug them.
6265    *)
6266   let test_names =
6267     List.map (
6268       fun (name, _, _, flags, tests, _, _) ->
6269         mapi (generate_one_test name flags) tests
6270     ) (List.rev all_functions) in
6271   let test_names = List.concat test_names in
6272   let nr_tests = List.length test_names in
6273
6274   pr "\
6275 int main (int argc, char *argv[])
6276 {
6277   char c = 0;
6278   unsigned long int n_failed = 0;
6279   const char *filename;
6280   int fd;
6281   int nr_tests, test_num = 0;
6282
6283   setbuf (stdout, NULL);
6284
6285   no_test_warnings ();
6286
6287   g = guestfs_create ();
6288   if (g == NULL) {
6289     printf (\"guestfs_create FAILED\\n\");
6290     exit (EXIT_FAILURE);
6291   }
6292
6293   guestfs_set_error_handler (g, print_error, NULL);
6294
6295   guestfs_set_path (g, \"../appliance\");
6296
6297   filename = \"test1.img\";
6298   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6299   if (fd == -1) {
6300     perror (filename);
6301     exit (EXIT_FAILURE);
6302   }
6303   if (lseek (fd, %d, SEEK_SET) == -1) {
6304     perror (\"lseek\");
6305     close (fd);
6306     unlink (filename);
6307     exit (EXIT_FAILURE);
6308   }
6309   if (write (fd, &c, 1) == -1) {
6310     perror (\"write\");
6311     close (fd);
6312     unlink (filename);
6313     exit (EXIT_FAILURE);
6314   }
6315   if (close (fd) == -1) {
6316     perror (filename);
6317     unlink (filename);
6318     exit (EXIT_FAILURE);
6319   }
6320   if (guestfs_add_drive (g, filename) == -1) {
6321     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6322     exit (EXIT_FAILURE);
6323   }
6324
6325   filename = \"test2.img\";
6326   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6327   if (fd == -1) {
6328     perror (filename);
6329     exit (EXIT_FAILURE);
6330   }
6331   if (lseek (fd, %d, SEEK_SET) == -1) {
6332     perror (\"lseek\");
6333     close (fd);
6334     unlink (filename);
6335     exit (EXIT_FAILURE);
6336   }
6337   if (write (fd, &c, 1) == -1) {
6338     perror (\"write\");
6339     close (fd);
6340     unlink (filename);
6341     exit (EXIT_FAILURE);
6342   }
6343   if (close (fd) == -1) {
6344     perror (filename);
6345     unlink (filename);
6346     exit (EXIT_FAILURE);
6347   }
6348   if (guestfs_add_drive (g, filename) == -1) {
6349     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6350     exit (EXIT_FAILURE);
6351   }
6352
6353   filename = \"test3.img\";
6354   fd = open (filename, O_WRONLY|O_CREAT|O_NOCTTY|O_NONBLOCK|O_TRUNC, 0666);
6355   if (fd == -1) {
6356     perror (filename);
6357     exit (EXIT_FAILURE);
6358   }
6359   if (lseek (fd, %d, SEEK_SET) == -1) {
6360     perror (\"lseek\");
6361     close (fd);
6362     unlink (filename);
6363     exit (EXIT_FAILURE);
6364   }
6365   if (write (fd, &c, 1) == -1) {
6366     perror (\"write\");
6367     close (fd);
6368     unlink (filename);
6369     exit (EXIT_FAILURE);
6370   }
6371   if (close (fd) == -1) {
6372     perror (filename);
6373     unlink (filename);
6374     exit (EXIT_FAILURE);
6375   }
6376   if (guestfs_add_drive (g, filename) == -1) {
6377     printf (\"guestfs_add_drive %%s FAILED\\n\", filename);
6378     exit (EXIT_FAILURE);
6379   }
6380
6381   if (guestfs_add_drive_ro (g, \"../images/test.iso\") == -1) {
6382     printf (\"guestfs_add_drive_ro ../images/test.iso FAILED\\n\");
6383     exit (EXIT_FAILURE);
6384   }
6385
6386   if (guestfs_launch (g) == -1) {
6387     printf (\"guestfs_launch FAILED\\n\");
6388     exit (EXIT_FAILURE);
6389   }
6390
6391   /* Set a timeout in case qemu hangs during launch (RHBZ#505329). */
6392   alarm (600);
6393
6394   /* Cancel previous alarm. */
6395   alarm (0);
6396
6397   nr_tests = %d;
6398
6399 " (500 * 1024 * 1024) (50 * 1024 * 1024) (10 * 1024 * 1024) nr_tests;
6400
6401   iteri (
6402     fun i test_name ->
6403       pr "  test_num++;\n";
6404       pr "  printf (\"%%3d/%%3d %s\\n\", test_num, nr_tests);\n" test_name;
6405       pr "  if (%s () == -1) {\n" test_name;
6406       pr "    printf (\"%s FAILED\\n\");\n" test_name;
6407       pr "    n_failed++;\n";
6408       pr "  }\n";
6409   ) test_names;
6410   pr "\n";
6411
6412   pr "  guestfs_close (g);\n";
6413   pr "  unlink (\"test1.img\");\n";
6414   pr "  unlink (\"test2.img\");\n";
6415   pr "  unlink (\"test3.img\");\n";
6416   pr "\n";
6417
6418   pr "  if (n_failed > 0) {\n";
6419   pr "    printf (\"***** %%lu / %%d tests FAILED *****\\n\", n_failed, nr_tests);\n";
6420   pr "    exit (EXIT_FAILURE);\n";
6421   pr "  }\n";
6422   pr "\n";
6423
6424   pr "  exit (EXIT_SUCCESS);\n";
6425   pr "}\n"
6426
6427 and generate_one_test name flags i (init, prereq, test) =
6428   let test_name = sprintf "test_%s_%d" name i in
6429
6430   pr "\
6431 static int %s_skip (void)
6432 {
6433   const char *str;
6434
6435   str = getenv (\"TEST_ONLY\");
6436   if (str)
6437     return strstr (str, \"%s\") == NULL;
6438   str = getenv (\"SKIP_%s\");
6439   if (str && STREQ (str, \"1\")) return 1;
6440   str = getenv (\"SKIP_TEST_%s\");
6441   if (str && STREQ (str, \"1\")) return 1;
6442   return 0;
6443 }
6444
6445 " test_name name (String.uppercase test_name) (String.uppercase name);
6446
6447   (match prereq with
6448    | Disabled | Always -> ()
6449    | If code | Unless code ->
6450        pr "static int %s_prereq (void)\n" test_name;
6451        pr "{\n";
6452        pr "  %s\n" code;
6453        pr "}\n";
6454        pr "\n";
6455   );
6456
6457   pr "\
6458 static int %s (void)
6459 {
6460   if (%s_skip ()) {
6461     printf (\"        %%s skipped (reason: environment variable set)\\n\", \"%s\");
6462     return 0;
6463   }
6464
6465 " test_name test_name test_name;
6466
6467   (* Optional functions should only be tested if the relevant
6468    * support is available in the daemon.
6469    *)
6470   List.iter (
6471     function
6472     | Optional group ->
6473         pr "  {\n";
6474         pr "    const char *groups[] = { \"%s\", NULL };\n" group;
6475         pr "    int r;\n";
6476         pr "    suppress_error = 1;\n";
6477         pr "    r = guestfs_available (g, (char **) groups);\n";
6478         pr "    suppress_error = 0;\n";
6479         pr "    if (r == -1) {\n";
6480         pr "      printf (\"        %%s skipped (reason: group %%s not available in daemon)\\n\", \"%s\", groups[0]);\n" test_name;
6481         pr "      return 0;\n";
6482         pr "    }\n";
6483         pr "  }\n";
6484     | _ -> ()
6485   ) flags;
6486
6487   (match prereq with
6488    | Disabled ->
6489        pr "  printf (\"        %%s skipped (reason: test disabled in generator)\\n\", \"%s\");\n" test_name
6490    | If _ ->
6491        pr "  if (! %s_prereq ()) {\n" test_name;
6492        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6493        pr "    return 0;\n";
6494        pr "  }\n";
6495        pr "\n";
6496        generate_one_test_body name i test_name init test;
6497    | Unless _ ->
6498        pr "  if (%s_prereq ()) {\n" test_name;
6499        pr "    printf (\"        %%s skipped (reason: test prerequisite)\\n\", \"%s\");\n" test_name;
6500        pr "    return 0;\n";
6501        pr "  }\n";
6502        pr "\n";
6503        generate_one_test_body name i test_name init test;
6504    | Always ->
6505        generate_one_test_body name i test_name init test
6506   );
6507
6508   pr "  return 0;\n";
6509   pr "}\n";
6510   pr "\n";
6511   test_name
6512
6513 and generate_one_test_body name i test_name init test =
6514   (match init with
6515    | InitNone (* XXX at some point, InitNone and InitEmpty became
6516                * folded together as the same thing.  Really we should
6517                * make InitNone do nothing at all, but the tests may
6518                * need to be checked to make sure this is OK.
6519                *)
6520    | InitEmpty ->
6521        pr "  /* InitNone|InitEmpty for %s */\n" test_name;
6522        List.iter (generate_test_command_call test_name)
6523          [["blockdev_setrw"; "/dev/sda"];
6524           ["umount_all"];
6525           ["lvm_remove_all"]]
6526    | InitPartition ->
6527        pr "  /* InitPartition for %s: create /dev/sda1 */\n" test_name;
6528        List.iter (generate_test_command_call test_name)
6529          [["blockdev_setrw"; "/dev/sda"];
6530           ["umount_all"];
6531           ["lvm_remove_all"];
6532           ["part_disk"; "/dev/sda"; "mbr"]]
6533    | InitBasicFS ->
6534        pr "  /* InitBasicFS for %s: create ext2 on /dev/sda1 */\n" test_name;
6535        List.iter (generate_test_command_call test_name)
6536          [["blockdev_setrw"; "/dev/sda"];
6537           ["umount_all"];
6538           ["lvm_remove_all"];
6539           ["part_disk"; "/dev/sda"; "mbr"];
6540           ["mkfs"; "ext2"; "/dev/sda1"];
6541           ["mount_options"; ""; "/dev/sda1"; "/"]]
6542    | InitBasicFSonLVM ->
6543        pr "  /* InitBasicFSonLVM for %s: create ext2 on /dev/VG/LV */\n"
6544          test_name;
6545        List.iter (generate_test_command_call test_name)
6546          [["blockdev_setrw"; "/dev/sda"];
6547           ["umount_all"];
6548           ["lvm_remove_all"];
6549           ["part_disk"; "/dev/sda"; "mbr"];
6550           ["pvcreate"; "/dev/sda1"];
6551           ["vgcreate"; "VG"; "/dev/sda1"];
6552           ["lvcreate"; "LV"; "VG"; "8"];
6553           ["mkfs"; "ext2"; "/dev/VG/LV"];
6554           ["mount_options"; ""; "/dev/VG/LV"; "/"]]
6555    | InitISOFS ->
6556        pr "  /* InitISOFS for %s */\n" test_name;
6557        List.iter (generate_test_command_call test_name)
6558          [["blockdev_setrw"; "/dev/sda"];
6559           ["umount_all"];
6560           ["lvm_remove_all"];
6561           ["mount_ro"; "/dev/sdd"; "/"]]
6562   );
6563
6564   let get_seq_last = function
6565     | [] ->
6566         failwithf "%s: you cannot use [] (empty list) when expecting a command"
6567           test_name
6568     | seq ->
6569         let seq = List.rev seq in
6570         List.rev (List.tl seq), List.hd seq
6571   in
6572
6573   match test with
6574   | TestRun seq ->
6575       pr "  /* TestRun for %s (%d) */\n" name i;
6576       List.iter (generate_test_command_call test_name) seq
6577   | TestOutput (seq, expected) ->
6578       pr "  /* TestOutput for %s (%d) */\n" name i;
6579       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6580       let seq, last = get_seq_last seq in
6581       let test () =
6582         pr "    if (STRNEQ (r, expected)) {\n";
6583         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6584         pr "      return -1;\n";
6585         pr "    }\n"
6586       in
6587       List.iter (generate_test_command_call test_name) seq;
6588       generate_test_command_call ~test test_name last
6589   | TestOutputList (seq, expected) ->
6590       pr "  /* TestOutputList for %s (%d) */\n" name i;
6591       let seq, last = get_seq_last seq in
6592       let test () =
6593         iteri (
6594           fun i str ->
6595             pr "    if (!r[%d]) {\n" i;
6596             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6597             pr "      print_strings (r);\n";
6598             pr "      return -1;\n";
6599             pr "    }\n";
6600             pr "    {\n";
6601             pr "      const char *expected = \"%s\";\n" (c_quote str);
6602             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6603             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6604             pr "        return -1;\n";
6605             pr "      }\n";
6606             pr "    }\n"
6607         ) expected;
6608         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6609         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6610           test_name;
6611         pr "      print_strings (r);\n";
6612         pr "      return -1;\n";
6613         pr "    }\n"
6614       in
6615       List.iter (generate_test_command_call test_name) seq;
6616       generate_test_command_call ~test test_name last
6617   | TestOutputListOfDevices (seq, expected) ->
6618       pr "  /* TestOutputListOfDevices for %s (%d) */\n" name i;
6619       let seq, last = get_seq_last seq in
6620       let test () =
6621         iteri (
6622           fun i str ->
6623             pr "    if (!r[%d]) {\n" i;
6624             pr "      fprintf (stderr, \"%s: short list returned from command\\n\");\n" test_name;
6625             pr "      print_strings (r);\n";
6626             pr "      return -1;\n";
6627             pr "    }\n";
6628             pr "    {\n";
6629             pr "      const char *expected = \"%s\";\n" (c_quote str);
6630             pr "      r[%d][5] = 's';\n" i;
6631             pr "      if (STRNEQ (r[%d], expected)) {\n" i;
6632             pr "        fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r[%d]);\n" test_name i;
6633             pr "        return -1;\n";
6634             pr "      }\n";
6635             pr "    }\n"
6636         ) expected;
6637         pr "    if (r[%d] != NULL) {\n" (List.length expected);
6638         pr "      fprintf (stderr, \"%s: extra elements returned from command\\n\");\n"
6639           test_name;
6640         pr "      print_strings (r);\n";
6641         pr "      return -1;\n";
6642         pr "    }\n"
6643       in
6644       List.iter (generate_test_command_call test_name) seq;
6645       generate_test_command_call ~test test_name last
6646   | TestOutputInt (seq, expected) ->
6647       pr "  /* TestOutputInt for %s (%d) */\n" name i;
6648       let seq, last = get_seq_last seq in
6649       let test () =
6650         pr "    if (r != %d) {\n" expected;
6651         pr "      fprintf (stderr, \"%s: expected %d but got %%d\\n\","
6652           test_name expected;
6653         pr "               (int) r);\n";
6654         pr "      return -1;\n";
6655         pr "    }\n"
6656       in
6657       List.iter (generate_test_command_call test_name) seq;
6658       generate_test_command_call ~test test_name last
6659   | TestOutputIntOp (seq, op, expected) ->
6660       pr "  /* TestOutputIntOp for %s (%d) */\n" name i;
6661       let seq, last = get_seq_last seq in
6662       let test () =
6663         pr "    if (! (r %s %d)) {\n" op expected;
6664         pr "      fprintf (stderr, \"%s: expected %s %d but got %%d\\n\","
6665           test_name op expected;
6666         pr "               (int) r);\n";
6667         pr "      return -1;\n";
6668         pr "    }\n"
6669       in
6670       List.iter (generate_test_command_call test_name) seq;
6671       generate_test_command_call ~test test_name last
6672   | TestOutputTrue seq ->
6673       pr "  /* TestOutputTrue for %s (%d) */\n" name i;
6674       let seq, last = get_seq_last seq in
6675       let test () =
6676         pr "    if (!r) {\n";
6677         pr "      fprintf (stderr, \"%s: expected true, got false\\n\");\n"
6678           test_name;
6679         pr "      return -1;\n";
6680         pr "    }\n"
6681       in
6682       List.iter (generate_test_command_call test_name) seq;
6683       generate_test_command_call ~test test_name last
6684   | TestOutputFalse seq ->
6685       pr "  /* TestOutputFalse for %s (%d) */\n" name i;
6686       let seq, last = get_seq_last seq in
6687       let test () =
6688         pr "    if (r) {\n";
6689         pr "      fprintf (stderr, \"%s: expected false, got true\\n\");\n"
6690           test_name;
6691         pr "      return -1;\n";
6692         pr "    }\n"
6693       in
6694       List.iter (generate_test_command_call test_name) seq;
6695       generate_test_command_call ~test test_name last
6696   | TestOutputLength (seq, expected) ->
6697       pr "  /* TestOutputLength for %s (%d) */\n" name i;
6698       let seq, last = get_seq_last seq in
6699       let test () =
6700         pr "    int j;\n";
6701         pr "    for (j = 0; j < %d; ++j)\n" expected;
6702         pr "      if (r[j] == NULL) {\n";
6703         pr "        fprintf (stderr, \"%s: short list returned\\n\");\n"
6704           test_name;
6705         pr "        print_strings (r);\n";
6706         pr "        return -1;\n";
6707         pr "      }\n";
6708         pr "    if (r[j] != NULL) {\n";
6709         pr "      fprintf (stderr, \"%s: long list returned\\n\");\n"
6710           test_name;
6711         pr "      print_strings (r);\n";
6712         pr "      return -1;\n";
6713         pr "    }\n"
6714       in
6715       List.iter (generate_test_command_call test_name) seq;
6716       generate_test_command_call ~test test_name last
6717   | TestOutputBuffer (seq, expected) ->
6718       pr "  /* TestOutputBuffer for %s (%d) */\n" name i;
6719       pr "  const char *expected = \"%s\";\n" (c_quote expected);
6720       let seq, last = get_seq_last seq in
6721       let len = String.length expected in
6722       let test () =
6723         pr "    if (size != %d) {\n" len;
6724         pr "      fprintf (stderr, \"%s: returned size of buffer wrong, expected %d but got %%zu\\n\", size);\n" test_name len;
6725         pr "      return -1;\n";
6726         pr "    }\n";
6727         pr "    if (STRNEQLEN (r, expected, size)) {\n";
6728         pr "      fprintf (stderr, \"%s: expected \\\"%%s\\\" but got \\\"%%s\\\"\\n\", expected, r);\n" test_name;
6729         pr "      return -1;\n";
6730         pr "    }\n"
6731       in
6732       List.iter (generate_test_command_call test_name) seq;
6733       generate_test_command_call ~test test_name last
6734   | TestOutputStruct (seq, checks) ->
6735       pr "  /* TestOutputStruct for %s (%d) */\n" name i;
6736       let seq, last = get_seq_last seq in
6737       let test () =
6738         List.iter (
6739           function
6740           | CompareWithInt (field, expected) ->
6741               pr "    if (r->%s != %d) {\n" field expected;
6742               pr "      fprintf (stderr, \"%s: %s was %%d, expected %d\\n\",\n"
6743                 test_name field expected;
6744               pr "               (int) r->%s);\n" field;
6745               pr "      return -1;\n";
6746               pr "    }\n"
6747           | CompareWithIntOp (field, op, expected) ->
6748               pr "    if (!(r->%s %s %d)) {\n" field op expected;
6749               pr "      fprintf (stderr, \"%s: %s was %%d, expected %s %d\\n\",\n"
6750                 test_name field op expected;
6751               pr "               (int) r->%s);\n" field;
6752               pr "      return -1;\n";
6753               pr "    }\n"
6754           | CompareWithString (field, expected) ->
6755               pr "    if (STRNEQ (r->%s, \"%s\")) {\n" field expected;
6756               pr "      fprintf (stderr, \"%s: %s was \"%%s\", expected \"%s\"\\n\",\n"
6757                 test_name field expected;
6758               pr "               r->%s);\n" field;
6759               pr "      return -1;\n";
6760               pr "    }\n"
6761           | CompareFieldsIntEq (field1, field2) ->
6762               pr "    if (r->%s != r->%s) {\n" field1 field2;
6763               pr "      fprintf (stderr, \"%s: %s (%%d) <> %s (%%d)\\n\",\n"
6764                 test_name field1 field2;
6765               pr "               (int) r->%s, (int) r->%s);\n" field1 field2;
6766               pr "      return -1;\n";
6767               pr "    }\n"
6768           | CompareFieldsStrEq (field1, field2) ->
6769               pr "    if (STRNEQ (r->%s, r->%s)) {\n" field1 field2;
6770               pr "      fprintf (stderr, \"%s: %s (\"%%s\") <> %s (\"%%s\")\\n\",\n"
6771                 test_name field1 field2;
6772               pr "               r->%s, r->%s);\n" field1 field2;
6773               pr "      return -1;\n";
6774               pr "    }\n"
6775         ) checks
6776       in
6777       List.iter (generate_test_command_call test_name) seq;
6778       generate_test_command_call ~test test_name last
6779   | TestLastFail seq ->
6780       pr "  /* TestLastFail for %s (%d) */\n" name i;
6781       let seq, last = get_seq_last seq in
6782       List.iter (generate_test_command_call test_name) seq;
6783       generate_test_command_call test_name ~expect_error:true last
6784
6785 (* Generate the code to run a command, leaving the result in 'r'.
6786  * If you expect to get an error then you should set expect_error:true.
6787  *)
6788 and generate_test_command_call ?(expect_error = false) ?test test_name cmd =
6789   match cmd with
6790   | [] -> assert false
6791   | name :: args ->
6792       (* Look up the command to find out what args/ret it has. *)
6793       let style =
6794         try
6795           let _, style, _, _, _, _, _ =
6796             List.find (fun (n, _, _, _, _, _, _) -> n = name) all_functions in
6797           style
6798         with Not_found ->
6799           failwithf "%s: in test, command %s was not found" test_name name in
6800
6801       if List.length (snd style) <> List.length args then
6802         failwithf "%s: in test, wrong number of args given to %s"
6803           test_name name;
6804
6805       pr "  {\n";
6806
6807       List.iter (
6808         function
6809         | OptString n, "NULL" -> ()
6810         | Pathname n, arg
6811         | Device n, arg
6812         | Dev_or_Path n, arg
6813         | String n, arg
6814         | OptString n, arg ->
6815             pr "    const char *%s = \"%s\";\n" n (c_quote arg);
6816         | Int _, _
6817         | Int64 _, _
6818         | Bool _, _
6819         | FileIn _, _ | FileOut _, _ -> ()
6820         | StringList n, "" | DeviceList n, "" ->
6821             pr "    const char *const %s[1] = { NULL };\n" n
6822         | StringList n, arg | DeviceList n, arg ->
6823             let strs = string_split " " arg in
6824             iteri (
6825               fun i str ->
6826                 pr "    const char *%s_%d = \"%s\";\n" n i (c_quote str);
6827             ) strs;
6828             pr "    const char *const %s[] = {\n" n;
6829             iteri (
6830               fun i _ -> pr "      %s_%d,\n" n i
6831             ) strs;
6832             pr "      NULL\n";
6833             pr "    };\n";
6834       ) (List.combine (snd style) args);
6835
6836       let error_code =
6837         match fst style with
6838         | RErr | RInt _ | RBool _ -> pr "    int r;\n"; "-1"
6839         | RInt64 _ -> pr "    int64_t r;\n"; "-1"
6840         | RConstString _ | RConstOptString _ ->
6841             pr "    const char *r;\n"; "NULL"
6842         | RString _ -> pr "    char *r;\n"; "NULL"
6843         | RStringList _ | RHashtable _ ->
6844             pr "    char **r;\n";
6845             pr "    int i;\n";
6846             "NULL"
6847         | RStruct (_, typ) ->
6848             pr "    struct guestfs_%s *r;\n" typ; "NULL"
6849         | RStructList (_, typ) ->
6850             pr "    struct guestfs_%s_list *r;\n" typ; "NULL"
6851         | RBufferOut _ ->
6852             pr "    char *r;\n";
6853             pr "    size_t size;\n";
6854             "NULL" in
6855
6856       pr "    suppress_error = %d;\n" (if expect_error then 1 else 0);
6857       pr "    r = guestfs_%s (g" name;
6858
6859       (* Generate the parameters. *)
6860       List.iter (
6861         function
6862         | OptString _, "NULL" -> pr ", NULL"
6863         | Pathname n, _
6864         | Device n, _ | Dev_or_Path n, _
6865         | String n, _
6866         | OptString n, _ ->
6867             pr ", %s" n
6868         | FileIn _, arg | FileOut _, arg ->
6869             pr ", \"%s\"" (c_quote arg)
6870         | StringList n, _ | DeviceList n, _ ->
6871             pr ", (char **) %s" n
6872         | Int _, arg ->
6873             let i =
6874               try int_of_string arg
6875               with Failure "int_of_string" ->
6876                 failwithf "%s: expecting an int, but got '%s'" test_name arg in
6877             pr ", %d" i
6878         | Int64 _, arg ->
6879             let i =
6880               try Int64.of_string arg
6881               with Failure "int_of_string" ->
6882                 failwithf "%s: expecting an int64, but got '%s'" test_name arg in
6883             pr ", %Ld" i
6884         | Bool _, arg ->
6885             let b = bool_of_string arg in pr ", %d" (if b then 1 else 0)
6886       ) (List.combine (snd style) args);
6887
6888       (match fst style with
6889        | RBufferOut _ -> pr ", &size"
6890        | _ -> ()
6891       );
6892
6893       pr ");\n";
6894
6895       if not expect_error then
6896         pr "    if (r == %s)\n" error_code
6897       else
6898         pr "    if (r != %s)\n" error_code;
6899       pr "      return -1;\n";
6900
6901       (* Insert the test code. *)
6902       (match test with
6903        | None -> ()
6904        | Some f -> f ()
6905       );
6906
6907       (match fst style with
6908        | RErr | RInt _ | RInt64 _ | RBool _
6909        | RConstString _ | RConstOptString _ -> ()
6910        | RString _ | RBufferOut _ -> pr "    free (r);\n"
6911        | RStringList _ | RHashtable _ ->
6912            pr "    for (i = 0; r[i] != NULL; ++i)\n";
6913            pr "      free (r[i]);\n";
6914            pr "    free (r);\n"
6915        | RStruct (_, typ) ->
6916            pr "    guestfs_free_%s (r);\n" typ
6917        | RStructList (_, typ) ->
6918            pr "    guestfs_free_%s_list (r);\n" typ
6919       );
6920
6921       pr "  }\n"
6922
6923 and c_quote str =
6924   let str = replace_str str "\r" "\\r" in
6925   let str = replace_str str "\n" "\\n" in
6926   let str = replace_str str "\t" "\\t" in
6927   let str = replace_str str "\000" "\\0" in
6928   str
6929
6930 (* Generate a lot of different functions for guestfish. *)
6931 and generate_fish_cmds () =
6932   generate_header CStyle GPLv2plus;
6933
6934   let all_functions =
6935     List.filter (
6936       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6937     ) all_functions in
6938   let all_functions_sorted =
6939     List.filter (
6940       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
6941     ) all_functions_sorted in
6942
6943   pr "#include <config.h>\n";
6944   pr "\n";
6945   pr "#include <stdio.h>\n";
6946   pr "#include <stdlib.h>\n";
6947   pr "#include <string.h>\n";
6948   pr "#include <inttypes.h>\n";
6949   pr "\n";
6950   pr "#include <guestfs.h>\n";
6951   pr "#include \"c-ctype.h\"\n";
6952   pr "#include \"full-write.h\"\n";
6953   pr "#include \"xstrtol.h\"\n";
6954   pr "#include \"fish.h\"\n";
6955   pr "\n";
6956
6957   (* list_commands function, which implements guestfish -h *)
6958   pr "void list_commands (void)\n";
6959   pr "{\n";
6960   pr "  printf (\"    %%-16s     %%s\\n\", _(\"Command\"), _(\"Description\"));\n";
6961   pr "  list_builtin_commands ();\n";
6962   List.iter (
6963     fun (name, _, _, flags, _, shortdesc, _) ->
6964       let name = replace_char name '_' '-' in
6965       pr "  printf (\"%%-20s %%s\\n\", \"%s\", _(\"%s\"));\n"
6966         name shortdesc
6967   ) all_functions_sorted;
6968   pr "  printf (\"    %%s\\n\",";
6969   pr "          _(\"Use -h <cmd> / help <cmd> to show detailed help for a command.\"));\n";
6970   pr "}\n";
6971   pr "\n";
6972
6973   (* display_command function, which implements guestfish -h cmd *)
6974   pr "void display_command (const char *cmd)\n";
6975   pr "{\n";
6976   List.iter (
6977     fun (name, style, _, flags, _, shortdesc, longdesc) ->
6978       let name2 = replace_char name '_' '-' in
6979       let alias =
6980         try find_map (function FishAlias n -> Some n | _ -> None) flags
6981         with Not_found -> name in
6982       let longdesc = replace_str longdesc "C<guestfs_" "C<" in
6983       let synopsis =
6984         match snd style with
6985         | [] -> name2
6986         | args ->
6987             sprintf "%s %s"
6988               name2 (String.concat " " (List.map name_of_argt args)) in
6989
6990       let warnings =
6991         if List.mem ProtocolLimitWarning flags then
6992           ("\n\n" ^ protocol_limit_warning)
6993         else "" in
6994
6995       (* For DangerWillRobinson commands, we should probably have
6996        * guestfish prompt before allowing you to use them (especially
6997        * in interactive mode). XXX
6998        *)
6999       let warnings =
7000         warnings ^
7001           if List.mem DangerWillRobinson flags then
7002             ("\n\n" ^ danger_will_robinson)
7003           else "" in
7004
7005       let warnings =
7006         warnings ^
7007           match deprecation_notice flags with
7008           | None -> ""
7009           | Some txt -> "\n\n" ^ txt in
7010
7011       let describe_alias =
7012         if name <> alias then
7013           sprintf "\n\nYou can use '%s' as an alias for this command." alias
7014         else "" in
7015
7016       pr "  if (";
7017       pr "STRCASEEQ (cmd, \"%s\")" name;
7018       if name <> name2 then
7019         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7020       if name <> alias then
7021         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7022       pr ")\n";
7023       pr "    pod2text (\"%s\", _(\"%s\"), %S);\n"
7024         name2 shortdesc
7025         ("=head1 SYNOPSIS\n\n " ^ synopsis ^ "\n\n" ^
7026          "=head1 DESCRIPTION\n\n" ^
7027          longdesc ^ warnings ^ describe_alias);
7028       pr "  else\n"
7029   ) all_functions;
7030   pr "    display_builtin_command (cmd);\n";
7031   pr "}\n";
7032   pr "\n";
7033
7034   let emit_print_list_function typ =
7035     pr "static void print_%s_list (struct guestfs_%s_list *%ss)\n"
7036       typ typ typ;
7037     pr "{\n";
7038     pr "  unsigned int i;\n";
7039     pr "\n";
7040     pr "  for (i = 0; i < %ss->len; ++i) {\n" typ;
7041     pr "    printf (\"[%%d] = {\\n\", i);\n";
7042     pr "    print_%s_indent (&%ss->val[i], \"  \");\n" typ typ;
7043     pr "    printf (\"}\\n\");\n";
7044     pr "  }\n";
7045     pr "}\n";
7046     pr "\n";
7047   in
7048
7049   (* print_* functions *)
7050   List.iter (
7051     fun (typ, cols) ->
7052       let needs_i =
7053         List.exists (function (_, (FUUID|FBuffer)) -> true | _ -> false) cols in
7054
7055       pr "static void print_%s_indent (struct guestfs_%s *%s, const char *indent)\n" typ typ typ;
7056       pr "{\n";
7057       if needs_i then (
7058         pr "  unsigned int i;\n";
7059         pr "\n"
7060       );
7061       List.iter (
7062         function
7063         | name, FString ->
7064             pr "  printf (\"%%s%s: %%s\\n\", indent, %s->%s);\n" name typ name
7065         | name, FUUID ->
7066             pr "  printf (\"%%s%s: \", indent);\n" name;
7067             pr "  for (i = 0; i < 32; ++i)\n";
7068             pr "    printf (\"%%c\", %s->%s[i]);\n" typ name;
7069             pr "  printf (\"\\n\");\n"
7070         | name, FBuffer ->
7071             pr "  printf (\"%%s%s: \", indent);\n" name;
7072             pr "  for (i = 0; i < %s->%s_len; ++i)\n" typ name;
7073             pr "    if (c_isprint (%s->%s[i]))\n" typ name;
7074             pr "      printf (\"%%c\", %s->%s[i]);\n" typ name;
7075             pr "    else\n";
7076             pr "      printf (\"\\\\x%%02x\", %s->%s[i]);\n" typ name;
7077             pr "  printf (\"\\n\");\n"
7078         | name, (FUInt64|FBytes) ->
7079             pr "  printf (\"%%s%s: %%\" PRIu64 \"\\n\", indent, %s->%s);\n"
7080               name typ name
7081         | name, FInt64 ->
7082             pr "  printf (\"%%s%s: %%\" PRIi64 \"\\n\", indent, %s->%s);\n"
7083               name typ name
7084         | name, FUInt32 ->
7085             pr "  printf (\"%%s%s: %%\" PRIu32 \"\\n\", indent, %s->%s);\n"
7086               name typ name
7087         | name, FInt32 ->
7088             pr "  printf (\"%%s%s: %%\" PRIi32 \"\\n\", indent, %s->%s);\n"
7089               name typ name
7090         | name, FChar ->
7091             pr "  printf (\"%%s%s: %%c\\n\", indent, %s->%s);\n"
7092               name typ name
7093         | name, FOptPercent ->
7094             pr "  if (%s->%s >= 0) printf (\"%%s%s: %%g %%%%\\n\", indent, %s->%s);\n"
7095               typ name name typ name;
7096             pr "  else printf (\"%%s%s: \\n\", indent);\n" name
7097       ) cols;
7098       pr "}\n";
7099       pr "\n";
7100   ) structs;
7101
7102   (* Emit a print_TYPE_list function definition only if that function is used. *)
7103   List.iter (
7104     function
7105     | typ, (RStructListOnly | RStructAndList) ->
7106         (* generate the function for typ *)
7107         emit_print_list_function typ
7108     | typ, _ -> () (* empty *)
7109   ) (rstructs_used_by all_functions);
7110
7111   (* Emit a print_TYPE function definition only if that function is used. *)
7112   List.iter (
7113     function
7114     | typ, (RStructOnly | RStructAndList) ->
7115         pr "static void print_%s (struct guestfs_%s *%s)\n" typ typ typ;
7116         pr "{\n";
7117         pr "  print_%s_indent (%s, \"\");\n" typ typ;
7118         pr "}\n";
7119         pr "\n";
7120     | typ, _ -> () (* empty *)
7121   ) (rstructs_used_by all_functions);
7122
7123   (* run_<action> actions *)
7124   List.iter (
7125     fun (name, style, _, flags, _, _, _) ->
7126       pr "static int run_%s (const char *cmd, int argc, char *argv[])\n" name;
7127       pr "{\n";
7128       (match fst style with
7129        | RErr
7130        | RInt _
7131        | RBool _ -> pr "  int r;\n"
7132        | RInt64 _ -> pr "  int64_t r;\n"
7133        | RConstString _ | RConstOptString _ -> pr "  const char *r;\n"
7134        | RString _ -> pr "  char *r;\n"
7135        | RStringList _ | RHashtable _ -> pr "  char **r;\n"
7136        | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ
7137        | RStructList (_, typ) -> pr "  struct guestfs_%s_list *r;\n" typ
7138        | RBufferOut _ ->
7139            pr "  char *r;\n";
7140            pr "  size_t size;\n";
7141       );
7142       List.iter (
7143         function
7144         | Device n
7145         | String n
7146         | OptString n
7147         | FileIn n
7148         | FileOut n -> pr "  const char *%s;\n" n
7149         | Pathname n
7150         | Dev_or_Path n -> pr "  char *%s;\n" n
7151         | StringList n | DeviceList n -> pr "  char **%s;\n" n
7152         | Bool n -> pr "  int %s;\n" n
7153         | Int n -> pr "  int %s;\n" n
7154         | Int64 n -> pr "  int64_t %s;\n" n
7155       ) (snd style);
7156
7157       (* Check and convert parameters. *)
7158       let argc_expected = List.length (snd style) in
7159       pr "  if (argc != %d) {\n" argc_expected;
7160       pr "    fprintf (stderr, _(\"%%s should have %%d parameter(s)\\n\"), cmd, %d);\n"
7161         argc_expected;
7162       pr "    fprintf (stderr, _(\"type 'help %%s' for help on %%s\\n\"), cmd, cmd);\n";
7163       pr "    return -1;\n";
7164       pr "  }\n";
7165
7166       let parse_integer fn fntyp rtyp range name i =
7167         pr "  {\n";
7168         pr "    strtol_error xerr;\n";
7169         pr "    %s r;\n" fntyp;
7170         pr "\n";
7171         pr "    xerr = %s (argv[%d], NULL, 0, &r, \"\");\n" fn i;
7172         pr "    if (xerr != LONGINT_OK) {\n";
7173         pr "      fprintf (stderr,\n";
7174         pr "               _(\"%%s: %%s: invalid integer parameter (%%s returned %%d)\\n\"),\n";
7175         pr "               cmd, \"%s\", \"%s\", xerr);\n" name fn;
7176         pr "      return -1;\n";
7177         pr "    }\n";
7178         (match range with
7179          | None -> ()
7180          | Some (min, max, comment) ->
7181              pr "    /* %s */\n" comment;
7182              pr "    if (r < %s || r > %s) {\n" min max;
7183              pr "      fprintf (stderr, _(\"%%s: %%s: integer out of range\\n\"), cmd, \"%s\");\n"
7184                name;
7185              pr "      return -1;\n";
7186              pr "    }\n";
7187              pr "    /* The check above should ensure this assignment does not overflow. */\n";
7188         );
7189         pr "    %s = r;\n" name;
7190         pr "  }\n";
7191       in
7192
7193       iteri (
7194         fun i ->
7195           function
7196           | Device name
7197           | String name ->
7198               pr "  %s = argv[%d];\n" name i
7199           | Pathname name
7200           | Dev_or_Path name ->
7201               pr "  %s = resolve_win_path (argv[%d]);\n" name i;
7202               pr "  if (%s == NULL) return -1;\n" name
7203           | OptString name ->
7204               pr "  %s = STRNEQ (argv[%d], \"\") ? argv[%d] : NULL;\n"
7205                 name i i
7206           | FileIn name ->
7207               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdin\";\n"
7208                 name i i
7209           | FileOut name ->
7210               pr "  %s = STRNEQ (argv[%d], \"-\") ? argv[%d] : \"/dev/stdout\";\n"
7211                 name i i
7212           | StringList name | DeviceList name ->
7213               pr "  %s = parse_string_list (argv[%d]);\n" name i;
7214               pr "  if (%s == NULL) return -1;\n" name;
7215           | Bool name ->
7216               pr "  %s = is_true (argv[%d]) ? 1 : 0;\n" name i
7217           | Int name ->
7218               let range =
7219                 let min = "(-(2LL<<30))"
7220                 and max = "((2LL<<30)-1)"
7221                 and comment =
7222                   "The Int type in the generator is a signed 31 bit int." in
7223                 Some (min, max, comment) in
7224               parse_integer "xstrtol" "long" "int" range name i
7225           | Int64 name ->
7226               parse_integer "xstrtoll" "long long" "int64_t" None name i
7227       ) (snd style);
7228
7229       (* Call C API function. *)
7230       let fn =
7231         try find_map (function FishAction n -> Some n | _ -> None) flags
7232         with Not_found -> sprintf "guestfs_%s" name in
7233       pr "  r = %s " fn;
7234       generate_c_call_args ~handle:"g" style;
7235       pr ";\n";
7236
7237       List.iter (
7238         function
7239         | Device name | String name
7240         | OptString name | FileIn name | FileOut name | Bool name
7241         | Int name | Int64 name -> ()
7242         | Pathname name | Dev_or_Path name ->
7243             pr "  free (%s);\n" name
7244         | StringList name | DeviceList name ->
7245             pr "  free_strings (%s);\n" name
7246       ) (snd style);
7247
7248       (* Check return value for errors and display command results. *)
7249       (match fst style with
7250        | RErr -> pr "  return r;\n"
7251        | RInt _ ->
7252            pr "  if (r == -1) return -1;\n";
7253            pr "  printf (\"%%d\\n\", r);\n";
7254            pr "  return 0;\n"
7255        | RInt64 _ ->
7256            pr "  if (r == -1) return -1;\n";
7257            pr "  printf (\"%%\" PRIi64 \"\\n\", r);\n";
7258            pr "  return 0;\n"
7259        | RBool _ ->
7260            pr "  if (r == -1) return -1;\n";
7261            pr "  if (r) printf (\"true\\n\"); else printf (\"false\\n\");\n";
7262            pr "  return 0;\n"
7263        | RConstString _ ->
7264            pr "  if (r == NULL) return -1;\n";
7265            pr "  printf (\"%%s\\n\", r);\n";
7266            pr "  return 0;\n"
7267        | RConstOptString _ ->
7268            pr "  printf (\"%%s\\n\", r ? : \"(null)\");\n";
7269            pr "  return 0;\n"
7270        | RString _ ->
7271            pr "  if (r == NULL) return -1;\n";
7272            pr "  printf (\"%%s\\n\", r);\n";
7273            pr "  free (r);\n";
7274            pr "  return 0;\n"
7275        | RStringList _ ->
7276            pr "  if (r == NULL) return -1;\n";
7277            pr "  print_strings (r);\n";
7278            pr "  free_strings (r);\n";
7279            pr "  return 0;\n"
7280        | RStruct (_, typ) ->
7281            pr "  if (r == NULL) return -1;\n";
7282            pr "  print_%s (r);\n" typ;
7283            pr "  guestfs_free_%s (r);\n" typ;
7284            pr "  return 0;\n"
7285        | RStructList (_, typ) ->
7286            pr "  if (r == NULL) return -1;\n";
7287            pr "  print_%s_list (r);\n" typ;
7288            pr "  guestfs_free_%s_list (r);\n" typ;
7289            pr "  return 0;\n"
7290        | RHashtable _ ->
7291            pr "  if (r == NULL) return -1;\n";
7292            pr "  print_table (r);\n";
7293            pr "  free_strings (r);\n";
7294            pr "  return 0;\n"
7295        | RBufferOut _ ->
7296            pr "  if (r == NULL) return -1;\n";
7297            pr "  if (full_write (1, r, size) != size) {\n";
7298            pr "    perror (\"write\");\n";
7299            pr "    free (r);\n";
7300            pr "    return -1;\n";
7301            pr "  }\n";
7302            pr "  free (r);\n";
7303            pr "  return 0;\n"
7304       );
7305       pr "}\n";
7306       pr "\n"
7307   ) all_functions;
7308
7309   (* run_action function *)
7310   pr "int run_action (const char *cmd, int argc, char *argv[])\n";
7311   pr "{\n";
7312   List.iter (
7313     fun (name, _, _, flags, _, _, _) ->
7314       let name2 = replace_char name '_' '-' in
7315       let alias =
7316         try find_map (function FishAlias n -> Some n | _ -> None) flags
7317         with Not_found -> name in
7318       pr "  if (";
7319       pr "STRCASEEQ (cmd, \"%s\")" name;
7320       if name <> name2 then
7321         pr " || STRCASEEQ (cmd, \"%s\")" name2;
7322       if name <> alias then
7323         pr " || STRCASEEQ (cmd, \"%s\")" alias;
7324       pr ")\n";
7325       pr "    return run_%s (cmd, argc, argv);\n" name;
7326       pr "  else\n";
7327   ) all_functions;
7328   pr "    {\n";
7329   pr "      fprintf (stderr, _(\"%%s: unknown command\\n\"), cmd);\n";
7330   pr "      return -1;\n";
7331   pr "    }\n";
7332   pr "  return 0;\n";
7333   pr "}\n";
7334   pr "\n"
7335
7336 (* Readline completion for guestfish. *)
7337 and generate_fish_completion () =
7338   generate_header CStyle GPLv2plus;
7339
7340   let all_functions =
7341     List.filter (
7342       fun (_, _, _, flags, _, _, _) -> not (List.mem NotInFish flags)
7343     ) all_functions in
7344
7345   pr "\
7346 #include <config.h>
7347
7348 #include <stdio.h>
7349 #include <stdlib.h>
7350 #include <string.h>
7351
7352 #ifdef HAVE_LIBREADLINE
7353 #include <readline/readline.h>
7354 #endif
7355
7356 #include \"fish.h\"
7357
7358 #ifdef HAVE_LIBREADLINE
7359
7360 static const char *const commands[] = {
7361   BUILTIN_COMMANDS_FOR_COMPLETION,
7362 ";
7363
7364   (* Get the commands, including the aliases.  They don't need to be
7365    * sorted - the generator() function just does a dumb linear search.
7366    *)
7367   let commands =
7368     List.map (
7369       fun (name, _, _, flags, _, _, _) ->
7370         let name2 = replace_char name '_' '-' in
7371         let alias =
7372           try find_map (function FishAlias n -> Some n | _ -> None) flags
7373           with Not_found -> name in
7374
7375         if name <> alias then [name2; alias] else [name2]
7376     ) all_functions in
7377   let commands = List.flatten commands in
7378
7379   List.iter (pr "  \"%s\",\n") commands;
7380
7381   pr "  NULL
7382 };
7383
7384 static char *
7385 generator (const char *text, int state)
7386 {
7387   static int index, len;
7388   const char *name;
7389
7390   if (!state) {
7391     index = 0;
7392     len = strlen (text);
7393   }
7394
7395   rl_attempted_completion_over = 1;
7396
7397   while ((name = commands[index]) != NULL) {
7398     index++;
7399     if (STRCASEEQLEN (name, text, len))
7400       return strdup (name);
7401   }
7402
7403   return NULL;
7404 }
7405
7406 #endif /* HAVE_LIBREADLINE */
7407
7408 char **do_completion (const char *text, int start, int end)
7409 {
7410   char **matches = NULL;
7411
7412 #ifdef HAVE_LIBREADLINE
7413   rl_completion_append_character = ' ';
7414
7415   if (start == 0)
7416     matches = rl_completion_matches (text, generator);
7417   else if (complete_dest_paths)
7418     matches = rl_completion_matches (text, complete_dest_paths_generator);
7419 #endif
7420
7421   return matches;
7422 }
7423 ";
7424
7425 (* Generate the POD documentation for guestfish. *)
7426 and generate_fish_actions_pod () =
7427   let all_functions_sorted =
7428     List.filter (
7429       fun (_, _, _, flags, _, _, _) ->
7430         not (List.mem NotInFish flags || List.mem NotInDocs flags)
7431     ) all_functions_sorted in
7432
7433   let rex = Str.regexp "C<guestfs_\\([^>]+\\)>" in
7434
7435   List.iter (
7436     fun (name, style, _, flags, _, _, longdesc) ->
7437       let longdesc =
7438         Str.global_substitute rex (
7439           fun s ->
7440             let sub =
7441               try Str.matched_group 1 s
7442               with Not_found ->
7443                 failwithf "error substituting C<guestfs_...> in longdesc of function %s" name in
7444             "C<" ^ replace_char sub '_' '-' ^ ">"
7445         ) longdesc in
7446       let name = replace_char name '_' '-' in
7447       let alias =
7448         try find_map (function FishAlias n -> Some n | _ -> None) flags
7449         with Not_found -> name in
7450
7451       pr "=head2 %s" name;
7452       if name <> alias then
7453         pr " | %s" alias;
7454       pr "\n";
7455       pr "\n";
7456       pr " %s" name;
7457       List.iter (
7458         function
7459         | Pathname n | Device n | Dev_or_Path n | String n -> pr " %s" n
7460         | OptString n -> pr " %s" n
7461         | StringList n | DeviceList n -> pr " '%s ...'" n
7462         | Bool _ -> pr " true|false"
7463         | Int n -> pr " %s" n
7464         | Int64 n -> pr " %s" n
7465         | FileIn n | FileOut n -> pr " (%s|-)" n
7466       ) (snd style);
7467       pr "\n";
7468       pr "\n";
7469       pr "%s\n\n" longdesc;
7470
7471       if List.exists (function FileIn _ | FileOut _ -> true
7472                       | _ -> false) (snd style) then
7473         pr "Use C<-> instead of a filename to read/write from stdin/stdout.\n\n";
7474
7475       if List.mem ProtocolLimitWarning flags then
7476         pr "%s\n\n" protocol_limit_warning;
7477
7478       if List.mem DangerWillRobinson flags then
7479         pr "%s\n\n" danger_will_robinson;
7480
7481       match deprecation_notice flags with
7482       | None -> ()
7483       | Some txt -> pr "%s\n\n" txt
7484   ) all_functions_sorted
7485
7486 (* Generate a C function prototype. *)
7487 and generate_prototype ?(extern = true) ?(static = false) ?(semicolon = true)
7488     ?(single_line = false) ?(newline = false) ?(in_daemon = false)
7489     ?(prefix = "")
7490     ?handle name style =
7491   if extern then pr "extern ";
7492   if static then pr "static ";
7493   (match fst style with
7494    | RErr -> pr "int "
7495    | RInt _ -> pr "int "
7496    | RInt64 _ -> pr "int64_t "
7497    | RBool _ -> pr "int "
7498    | RConstString _ | RConstOptString _ -> pr "const char *"
7499    | RString _ | RBufferOut _ -> pr "char *"
7500    | RStringList _ | RHashtable _ -> pr "char **"
7501    | RStruct (_, typ) ->
7502        if not in_daemon then pr "struct guestfs_%s *" typ
7503        else pr "guestfs_int_%s *" typ
7504    | RStructList (_, typ) ->
7505        if not in_daemon then pr "struct guestfs_%s_list *" typ
7506        else pr "guestfs_int_%s_list *" typ
7507   );
7508   let is_RBufferOut = match fst style with RBufferOut _ -> true | _ -> false in
7509   pr "%s%s (" prefix name;
7510   if handle = None && List.length (snd style) = 0 && not is_RBufferOut then
7511     pr "void"
7512   else (
7513     let comma = ref false in
7514     (match handle with
7515      | None -> ()
7516      | Some handle -> pr "guestfs_h *%s" handle; comma := true
7517     );
7518     let next () =
7519       if !comma then (
7520         if single_line then pr ", " else pr ",\n\t\t"
7521       );
7522       comma := true
7523     in
7524     List.iter (
7525       function
7526       | Pathname n
7527       | Device n | Dev_or_Path n
7528       | String n
7529       | OptString n ->
7530           next ();
7531           pr "const char *%s" n
7532       | StringList n | DeviceList n ->
7533           next ();
7534           pr "char *const *%s" n
7535       | Bool n -> next (); pr "int %s" n
7536       | Int n -> next (); pr "int %s" n
7537       | Int64 n -> next (); pr "int64_t %s" n
7538       | FileIn n
7539       | FileOut n ->
7540           if not in_daemon then (next (); pr "const char *%s" n)
7541     ) (snd style);
7542     if is_RBufferOut then (next (); pr "size_t *size_r");
7543   );
7544   pr ")";
7545   if semicolon then pr ";";
7546   if newline then pr "\n"
7547
7548 (* Generate C call arguments, eg "(handle, foo, bar)" *)
7549 and generate_c_call_args ?handle ?(decl = false) style =
7550   pr "(";
7551   let comma = ref false in
7552   let next () =
7553     if !comma then pr ", ";
7554     comma := true
7555   in
7556   (match handle with
7557    | None -> ()
7558    | Some handle -> pr "%s" handle; comma := true
7559   );
7560   List.iter (
7561     fun arg ->
7562       next ();
7563       pr "%s" (name_of_argt arg)
7564   ) (snd style);
7565   (* For RBufferOut calls, add implicit &size parameter. *)
7566   if not decl then (
7567     match fst style with
7568     | RBufferOut _ ->
7569         next ();
7570         pr "&size"
7571     | _ -> ()
7572   );
7573   pr ")"
7574
7575 (* Generate the OCaml bindings interface. *)
7576 and generate_ocaml_mli () =
7577   generate_header OCamlStyle LGPLv2plus;
7578
7579   pr "\
7580 (** For API documentation you should refer to the C API
7581     in the guestfs(3) manual page.  The OCaml API uses almost
7582     exactly the same calls. *)
7583
7584 type t
7585 (** A [guestfs_h] handle. *)
7586
7587 exception Error of string
7588 (** This exception is raised when there is an error. *)
7589
7590 exception Handle_closed of string
7591 (** This exception is raised if you use a {!Guestfs.t} handle
7592     after calling {!close} on it.  The string is the name of
7593     the function. *)
7594
7595 val create : unit -> t
7596 (** Create a {!Guestfs.t} handle. *)
7597
7598 val close : t -> unit
7599 (** Close the {!Guestfs.t} handle and free up all resources used
7600     by it immediately.
7601
7602     Handles are closed by the garbage collector when they become
7603     unreferenced, but callers can call this in order to provide
7604     predictable cleanup. *)
7605
7606 ";
7607   generate_ocaml_structure_decls ();
7608
7609   (* The actions. *)
7610   List.iter (
7611     fun (name, style, _, _, _, shortdesc, _) ->
7612       generate_ocaml_prototype name style;
7613       pr "(** %s *)\n" shortdesc;
7614       pr "\n"
7615   ) all_functions_sorted
7616
7617 (* Generate the OCaml bindings implementation. *)
7618 and generate_ocaml_ml () =
7619   generate_header OCamlStyle LGPLv2plus;
7620
7621   pr "\
7622 type t
7623
7624 exception Error of string
7625 exception Handle_closed of string
7626
7627 external create : unit -> t = \"ocaml_guestfs_create\"
7628 external close : t -> unit = \"ocaml_guestfs_close\"
7629
7630 (* Give the exceptions names, so they can be raised from the C code. *)
7631 let () =
7632   Callback.register_exception \"ocaml_guestfs_error\" (Error \"\");
7633   Callback.register_exception \"ocaml_guestfs_closed\" (Handle_closed \"\")
7634
7635 ";
7636
7637   generate_ocaml_structure_decls ();
7638
7639   (* The actions. *)
7640   List.iter (
7641     fun (name, style, _, _, _, shortdesc, _) ->
7642       generate_ocaml_prototype ~is_external:true name style;
7643   ) all_functions_sorted
7644
7645 (* Generate the OCaml bindings C implementation. *)
7646 and generate_ocaml_c () =
7647   generate_header CStyle LGPLv2plus;
7648
7649   pr "\
7650 #include <stdio.h>
7651 #include <stdlib.h>
7652 #include <string.h>
7653
7654 #include <caml/config.h>
7655 #include <caml/alloc.h>
7656 #include <caml/callback.h>
7657 #include <caml/fail.h>
7658 #include <caml/memory.h>
7659 #include <caml/mlvalues.h>
7660 #include <caml/signals.h>
7661
7662 #include <guestfs.h>
7663
7664 #include \"guestfs_c.h\"
7665
7666 /* Copy a hashtable of string pairs into an assoc-list.  We return
7667  * the list in reverse order, but hashtables aren't supposed to be
7668  * ordered anyway.
7669  */
7670 static CAMLprim value
7671 copy_table (char * const * argv)
7672 {
7673   CAMLparam0 ();
7674   CAMLlocal5 (rv, pairv, kv, vv, cons);
7675   int i;
7676
7677   rv = Val_int (0);
7678   for (i = 0; argv[i] != NULL; i += 2) {
7679     kv = caml_copy_string (argv[i]);
7680     vv = caml_copy_string (argv[i+1]);
7681     pairv = caml_alloc (2, 0);
7682     Store_field (pairv, 0, kv);
7683     Store_field (pairv, 1, vv);
7684     cons = caml_alloc (2, 0);
7685     Store_field (cons, 1, rv);
7686     rv = cons;
7687     Store_field (cons, 0, pairv);
7688   }
7689
7690   CAMLreturn (rv);
7691 }
7692
7693 ";
7694
7695   (* Struct copy functions. *)
7696
7697   let emit_ocaml_copy_list_function typ =
7698     pr "static CAMLprim value\n";
7699     pr "copy_%s_list (const struct guestfs_%s_list *%ss)\n" typ typ typ;
7700     pr "{\n";
7701     pr "  CAMLparam0 ();\n";
7702     pr "  CAMLlocal2 (rv, v);\n";
7703     pr "  unsigned int i;\n";
7704     pr "\n";
7705     pr "  if (%ss->len == 0)\n" typ;
7706     pr "    CAMLreturn (Atom (0));\n";
7707     pr "  else {\n";
7708     pr "    rv = caml_alloc (%ss->len, 0);\n" typ;
7709     pr "    for (i = 0; i < %ss->len; ++i) {\n" typ;
7710     pr "      v = copy_%s (&%ss->val[i]);\n" typ typ;
7711     pr "      caml_modify (&Field (rv, i), v);\n";
7712     pr "    }\n";
7713     pr "    CAMLreturn (rv);\n";
7714     pr "  }\n";
7715     pr "}\n";
7716     pr "\n";
7717   in
7718
7719   List.iter (
7720     fun (typ, cols) ->
7721       let has_optpercent_col =
7722         List.exists (function (_, FOptPercent) -> true | _ -> false) cols in
7723
7724       pr "static CAMLprim value\n";
7725       pr "copy_%s (const struct guestfs_%s *%s)\n" typ typ typ;
7726       pr "{\n";
7727       pr "  CAMLparam0 ();\n";
7728       if has_optpercent_col then
7729         pr "  CAMLlocal3 (rv, v, v2);\n"
7730       else
7731         pr "  CAMLlocal2 (rv, v);\n";
7732       pr "\n";
7733       pr "  rv = caml_alloc (%d, 0);\n" (List.length cols);
7734       iteri (
7735         fun i col ->
7736           (match col with
7737            | name, FString ->
7738                pr "  v = caml_copy_string (%s->%s);\n" typ name
7739            | name, FBuffer ->
7740                pr "  v = caml_alloc_string (%s->%s_len);\n" typ name;
7741                pr "  memcpy (String_val (v), %s->%s, %s->%s_len);\n"
7742                  typ name typ name
7743            | name, FUUID ->
7744                pr "  v = caml_alloc_string (32);\n";
7745                pr "  memcpy (String_val (v), %s->%s, 32);\n" typ name
7746            | name, (FBytes|FInt64|FUInt64) ->
7747                pr "  v = caml_copy_int64 (%s->%s);\n" typ name
7748            | name, (FInt32|FUInt32) ->
7749                pr "  v = caml_copy_int32 (%s->%s);\n" typ name
7750            | name, FOptPercent ->
7751                pr "  if (%s->%s >= 0) { /* Some %s */\n" typ name name;
7752                pr "    v2 = caml_copy_double (%s->%s);\n" typ name;
7753                pr "    v = caml_alloc (1, 0);\n";
7754                pr "    Store_field (v, 0, v2);\n";
7755                pr "  } else /* None */\n";
7756                pr "    v = Val_int (0);\n";
7757            | name, FChar ->
7758                pr "  v = Val_int (%s->%s);\n" typ name
7759           );
7760           pr "  Store_field (rv, %d, v);\n" i
7761       ) cols;
7762       pr "  CAMLreturn (rv);\n";
7763       pr "}\n";
7764       pr "\n";
7765   ) structs;
7766
7767   (* Emit a copy_TYPE_list function definition only if that function is used. *)
7768   List.iter (
7769     function
7770     | typ, (RStructListOnly | RStructAndList) ->
7771         (* generate the function for typ *)
7772         emit_ocaml_copy_list_function typ
7773     | typ, _ -> () (* empty *)
7774   ) (rstructs_used_by all_functions);
7775
7776   (* The wrappers. *)
7777   List.iter (
7778     fun (name, style, _, _, _, _, _) ->
7779       pr "/* Automatically generated wrapper for function\n";
7780       pr " * ";
7781       generate_ocaml_prototype name style;
7782       pr " */\n";
7783       pr "\n";
7784
7785       let params =
7786         "gv" :: List.map (fun arg -> name_of_argt arg ^ "v") (snd style) in
7787
7788       let needs_extra_vs =
7789         match fst style with RConstOptString _ -> true | _ -> false in
7790
7791       pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7792       pr "CAMLprim value ocaml_guestfs_%s (value %s" name (List.hd params);
7793       List.iter (pr ", value %s") (List.tl params); pr ");\n";
7794       pr "\n";
7795
7796       pr "CAMLprim value\n";
7797       pr "ocaml_guestfs_%s (value %s" name (List.hd params);
7798       List.iter (pr ", value %s") (List.tl params);
7799       pr ")\n";
7800       pr "{\n";
7801
7802       (match params with
7803        | [p1; p2; p3; p4; p5] ->
7804            pr "  CAMLparam5 (%s);\n" (String.concat ", " params)
7805        | p1 :: p2 :: p3 :: p4 :: p5 :: rest ->
7806            pr "  CAMLparam5 (%s);\n" (String.concat ", " [p1; p2; p3; p4; p5]);
7807            pr "  CAMLxparam%d (%s);\n"
7808              (List.length rest) (String.concat ", " rest)
7809        | ps ->
7810            pr "  CAMLparam%d (%s);\n" (List.length ps) (String.concat ", " ps)
7811       );
7812       if not needs_extra_vs then
7813         pr "  CAMLlocal1 (rv);\n"
7814       else
7815         pr "  CAMLlocal3 (rv, v, v2);\n";
7816       pr "\n";
7817
7818       pr "  guestfs_h *g = Guestfs_val (gv);\n";
7819       pr "  if (g == NULL)\n";
7820       pr "    ocaml_guestfs_raise_closed (\"%s\");\n" name;
7821       pr "\n";
7822
7823       List.iter (
7824         function
7825         | Pathname n
7826         | Device n | Dev_or_Path n
7827         | String n
7828         | FileIn n
7829         | FileOut n ->
7830             pr "  const char *%s = String_val (%sv);\n" n n
7831         | OptString n ->
7832             pr "  const char *%s =\n" n;
7833             pr "    %sv != Val_int (0) ? String_val (Field (%sv, 0)) : NULL;\n"
7834               n n
7835         | StringList n | DeviceList n ->
7836             pr "  char **%s = ocaml_guestfs_strings_val (g, %sv);\n" n n
7837         | Bool n ->
7838             pr "  int %s = Bool_val (%sv);\n" n n
7839         | Int n ->
7840             pr "  int %s = Int_val (%sv);\n" n n
7841         | Int64 n ->
7842             pr "  int64_t %s = Int64_val (%sv);\n" n n
7843       ) (snd style);
7844       let error_code =
7845         match fst style with
7846         | RErr -> pr "  int r;\n"; "-1"
7847         | RInt _ -> pr "  int r;\n"; "-1"
7848         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
7849         | RBool _ -> pr "  int r;\n"; "-1"
7850         | RConstString _ | RConstOptString _ ->
7851             pr "  const char *r;\n"; "NULL"
7852         | RString _ -> pr "  char *r;\n"; "NULL"
7853         | RStringList _ ->
7854             pr "  int i;\n";
7855             pr "  char **r;\n";
7856             "NULL"
7857         | RStruct (_, typ) ->
7858             pr "  struct guestfs_%s *r;\n" typ; "NULL"
7859         | RStructList (_, typ) ->
7860             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
7861         | RHashtable _ ->
7862             pr "  int i;\n";
7863             pr "  char **r;\n";
7864             "NULL"
7865         | RBufferOut _ ->
7866             pr "  char *r;\n";
7867             pr "  size_t size;\n";
7868             "NULL" in
7869       pr "\n";
7870
7871       pr "  caml_enter_blocking_section ();\n";
7872       pr "  r = guestfs_%s " name;
7873       generate_c_call_args ~handle:"g" style;
7874       pr ";\n";
7875       pr "  caml_leave_blocking_section ();\n";
7876
7877       List.iter (
7878         function
7879         | StringList n | DeviceList n ->
7880             pr "  ocaml_guestfs_free_strings (%s);\n" n;
7881         | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
7882         | Bool _ | Int _ | Int64 _
7883         | FileIn _ | FileOut _ -> ()
7884       ) (snd style);
7885
7886       pr "  if (r == %s)\n" error_code;
7887       pr "    ocaml_guestfs_raise_error (g, \"%s\");\n" name;
7888       pr "\n";
7889
7890       (match fst style with
7891        | RErr -> pr "  rv = Val_unit;\n"
7892        | RInt _ -> pr "  rv = Val_int (r);\n"
7893        | RInt64 _ ->
7894            pr "  rv = caml_copy_int64 (r);\n"
7895        | RBool _ -> pr "  rv = Val_bool (r);\n"
7896        | RConstString _ ->
7897            pr "  rv = caml_copy_string (r);\n"
7898        | RConstOptString _ ->
7899            pr "  if (r) { /* Some string */\n";
7900            pr "    v = caml_alloc (1, 0);\n";
7901            pr "    v2 = caml_copy_string (r);\n";
7902            pr "    Store_field (v, 0, v2);\n";
7903            pr "  } else /* None */\n";
7904            pr "    v = Val_int (0);\n";
7905        | RString _ ->
7906            pr "  rv = caml_copy_string (r);\n";
7907            pr "  free (r);\n"
7908        | RStringList _ ->
7909            pr "  rv = caml_copy_string_array ((const char **) r);\n";
7910            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7911            pr "  free (r);\n"
7912        | RStruct (_, typ) ->
7913            pr "  rv = copy_%s (r);\n" typ;
7914            pr "  guestfs_free_%s (r);\n" typ;
7915        | RStructList (_, typ) ->
7916            pr "  rv = copy_%s_list (r);\n" typ;
7917            pr "  guestfs_free_%s_list (r);\n" typ;
7918        | RHashtable _ ->
7919            pr "  rv = copy_table (r);\n";
7920            pr "  for (i = 0; r[i] != NULL; ++i) free (r[i]);\n";
7921            pr "  free (r);\n";
7922        | RBufferOut _ ->
7923            pr "  rv = caml_alloc_string (size);\n";
7924            pr "  memcpy (String_val (rv), r, size);\n";
7925       );
7926
7927       pr "  CAMLreturn (rv);\n";
7928       pr "}\n";
7929       pr "\n";
7930
7931       if List.length params > 5 then (
7932         pr "/* Emit prototype to appease gcc's -Wmissing-prototypes. */\n";
7933         pr "CAMLprim value ";
7934         pr "ocaml_guestfs_%s_byte (value *argv, int argn);\n" name;
7935         pr "CAMLprim value\n";
7936         pr "ocaml_guestfs_%s_byte (value *argv, int argn)\n" name;
7937         pr "{\n";
7938         pr "  return ocaml_guestfs_%s (argv[0]" name;
7939         iteri (fun i _ -> pr ", argv[%d]" i) (List.tl params);
7940         pr ");\n";
7941         pr "}\n";
7942         pr "\n"
7943       )
7944   ) all_functions_sorted
7945
7946 and generate_ocaml_structure_decls () =
7947   List.iter (
7948     fun (typ, cols) ->
7949       pr "type %s = {\n" typ;
7950       List.iter (
7951         function
7952         | name, FString -> pr "  %s : string;\n" name
7953         | name, FBuffer -> pr "  %s : string;\n" name
7954         | name, FUUID -> pr "  %s : string;\n" name
7955         | name, (FBytes|FInt64|FUInt64) -> pr "  %s : int64;\n" name
7956         | name, (FInt32|FUInt32) -> pr "  %s : int32;\n" name
7957         | name, FChar -> pr "  %s : char;\n" name
7958         | name, FOptPercent -> pr "  %s : float option;\n" name
7959       ) cols;
7960       pr "}\n";
7961       pr "\n"
7962   ) structs
7963
7964 and generate_ocaml_prototype ?(is_external = false) name style =
7965   if is_external then pr "external " else pr "val ";
7966   pr "%s : t -> " name;
7967   List.iter (
7968     function
7969     | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "string -> "
7970     | OptString _ -> pr "string option -> "
7971     | StringList _ | DeviceList _ -> pr "string array -> "
7972     | Bool _ -> pr "bool -> "
7973     | Int _ -> pr "int -> "
7974     | Int64 _ -> pr "int64 -> "
7975   ) (snd style);
7976   (match fst style with
7977    | RErr -> pr "unit" (* all errors are turned into exceptions *)
7978    | RInt _ -> pr "int"
7979    | RInt64 _ -> pr "int64"
7980    | RBool _ -> pr "bool"
7981    | RConstString _ -> pr "string"
7982    | RConstOptString _ -> pr "string option"
7983    | RString _ | RBufferOut _ -> pr "string"
7984    | RStringList _ -> pr "string array"
7985    | RStruct (_, typ) -> pr "%s" typ
7986    | RStructList (_, typ) -> pr "%s array" typ
7987    | RHashtable _ -> pr "(string * string) list"
7988   );
7989   if is_external then (
7990     pr " = ";
7991     if List.length (snd style) + 1 > 5 then
7992       pr "\"ocaml_guestfs_%s_byte\" " name;
7993     pr "\"ocaml_guestfs_%s\"" name
7994   );
7995   pr "\n"
7996
7997 (* Generate Perl xs code, a sort of crazy variation of C with macros. *)
7998 and generate_perl_xs () =
7999   generate_header CStyle LGPLv2plus;
8000
8001   pr "\
8002 #include \"EXTERN.h\"
8003 #include \"perl.h\"
8004 #include \"XSUB.h\"
8005
8006 #include <guestfs.h>
8007
8008 #ifndef PRId64
8009 #define PRId64 \"lld\"
8010 #endif
8011
8012 static SV *
8013 my_newSVll(long long val) {
8014 #ifdef USE_64_BIT_ALL
8015   return newSViv(val);
8016 #else
8017   char buf[100];
8018   int len;
8019   len = snprintf(buf, 100, \"%%\" PRId64, val);
8020   return newSVpv(buf, len);
8021 #endif
8022 }
8023
8024 #ifndef PRIu64
8025 #define PRIu64 \"llu\"
8026 #endif
8027
8028 static SV *
8029 my_newSVull(unsigned long long val) {
8030 #ifdef USE_64_BIT_ALL
8031   return newSVuv(val);
8032 #else
8033   char buf[100];
8034   int len;
8035   len = snprintf(buf, 100, \"%%\" PRIu64, val);
8036   return newSVpv(buf, len);
8037 #endif
8038 }
8039
8040 /* http://www.perlmonks.org/?node_id=680842 */
8041 static char **
8042 XS_unpack_charPtrPtr (SV *arg) {
8043   char **ret;
8044   AV *av;
8045   I32 i;
8046
8047   if (!arg || !SvOK (arg) || !SvROK (arg) || SvTYPE (SvRV (arg)) != SVt_PVAV)
8048     croak (\"array reference expected\");
8049
8050   av = (AV *)SvRV (arg);
8051   ret = malloc ((av_len (av) + 1 + 1) * sizeof (char *));
8052   if (!ret)
8053     croak (\"malloc failed\");
8054
8055   for (i = 0; i <= av_len (av); i++) {
8056     SV **elem = av_fetch (av, i, 0);
8057
8058     if (!elem || !*elem)
8059       croak (\"missing element in list\");
8060
8061     ret[i] = SvPV_nolen (*elem);
8062   }
8063
8064   ret[i] = NULL;
8065
8066   return ret;
8067 }
8068
8069 MODULE = Sys::Guestfs  PACKAGE = Sys::Guestfs
8070
8071 PROTOTYPES: ENABLE
8072
8073 guestfs_h *
8074 _create ()
8075    CODE:
8076       RETVAL = guestfs_create ();
8077       if (!RETVAL)
8078         croak (\"could not create guestfs handle\");
8079       guestfs_set_error_handler (RETVAL, NULL, NULL);
8080  OUTPUT:
8081       RETVAL
8082
8083 void
8084 DESTROY (g)
8085       guestfs_h *g;
8086  PPCODE:
8087       guestfs_close (g);
8088
8089 ";
8090
8091   List.iter (
8092     fun (name, style, _, _, _, _, _) ->
8093       (match fst style with
8094        | RErr -> pr "void\n"
8095        | RInt _ -> pr "SV *\n"
8096        | RInt64 _ -> pr "SV *\n"
8097        | RBool _ -> pr "SV *\n"
8098        | RConstString _ -> pr "SV *\n"
8099        | RConstOptString _ -> pr "SV *\n"
8100        | RString _ -> pr "SV *\n"
8101        | RBufferOut _ -> pr "SV *\n"
8102        | RStringList _
8103        | RStruct _ | RStructList _
8104        | RHashtable _ ->
8105            pr "void\n" (* all lists returned implictly on the stack *)
8106       );
8107       (* Call and arguments. *)
8108       pr "%s " name;
8109       generate_c_call_args ~handle:"g" ~decl:true style;
8110       pr "\n";
8111       pr "      guestfs_h *g;\n";
8112       iteri (
8113         fun i ->
8114           function
8115           | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8116               pr "      char *%s;\n" n
8117           | OptString n ->
8118               (* http://www.perlmonks.org/?node_id=554277
8119                * Note that the implicit handle argument means we have
8120                * to add 1 to the ST(x) operator.
8121                *)
8122               pr "      char *%s = SvOK(ST(%d)) ? SvPV_nolen(ST(%d)) : NULL;\n" n (i+1) (i+1)
8123           | StringList n | DeviceList n -> pr "      char **%s;\n" n
8124           | Bool n -> pr "      int %s;\n" n
8125           | Int n -> pr "      int %s;\n" n
8126           | Int64 n -> pr "      int64_t %s;\n" n
8127       ) (snd style);
8128
8129       let do_cleanups () =
8130         List.iter (
8131           function
8132           | Pathname _ | Device _ | Dev_or_Path _ | String _ | OptString _
8133           | Bool _ | Int _ | Int64 _
8134           | FileIn _ | FileOut _ -> ()
8135           | StringList n | DeviceList n -> pr "      free (%s);\n" n
8136         ) (snd style)
8137       in
8138
8139       (* Code. *)
8140       (match fst style with
8141        | RErr ->
8142            pr "PREINIT:\n";
8143            pr "      int r;\n";
8144            pr " PPCODE:\n";
8145            pr "      r = guestfs_%s " name;
8146            generate_c_call_args ~handle:"g" style;
8147            pr ";\n";
8148            do_cleanups ();
8149            pr "      if (r == -1)\n";
8150            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8151        | RInt n
8152        | RBool n ->
8153            pr "PREINIT:\n";
8154            pr "      int %s;\n" n;
8155            pr "   CODE:\n";
8156            pr "      %s = guestfs_%s " n name;
8157            generate_c_call_args ~handle:"g" style;
8158            pr ";\n";
8159            do_cleanups ();
8160            pr "      if (%s == -1)\n" n;
8161            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8162            pr "      RETVAL = newSViv (%s);\n" n;
8163            pr " OUTPUT:\n";
8164            pr "      RETVAL\n"
8165        | RInt64 n ->
8166            pr "PREINIT:\n";
8167            pr "      int64_t %s;\n" n;
8168            pr "   CODE:\n";
8169            pr "      %s = guestfs_%s " n name;
8170            generate_c_call_args ~handle:"g" style;
8171            pr ";\n";
8172            do_cleanups ();
8173            pr "      if (%s == -1)\n" n;
8174            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8175            pr "      RETVAL = my_newSVll (%s);\n" n;
8176            pr " OUTPUT:\n";
8177            pr "      RETVAL\n"
8178        | RConstString n ->
8179            pr "PREINIT:\n";
8180            pr "      const char *%s;\n" n;
8181            pr "   CODE:\n";
8182            pr "      %s = guestfs_%s " n name;
8183            generate_c_call_args ~handle:"g" style;
8184            pr ";\n";
8185            do_cleanups ();
8186            pr "      if (%s == NULL)\n" n;
8187            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8188            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8189            pr " OUTPUT:\n";
8190            pr "      RETVAL\n"
8191        | RConstOptString n ->
8192            pr "PREINIT:\n";
8193            pr "      const char *%s;\n" n;
8194            pr "   CODE:\n";
8195            pr "      %s = guestfs_%s " n name;
8196            generate_c_call_args ~handle:"g" style;
8197            pr ";\n";
8198            do_cleanups ();
8199            pr "      if (%s == NULL)\n" n;
8200            pr "        RETVAL = &PL_sv_undef;\n";
8201            pr "      else\n";
8202            pr "        RETVAL = newSVpv (%s, 0);\n" n;
8203            pr " OUTPUT:\n";
8204            pr "      RETVAL\n"
8205        | RString n ->
8206            pr "PREINIT:\n";
8207            pr "      char *%s;\n" n;
8208            pr "   CODE:\n";
8209            pr "      %s = guestfs_%s " n name;
8210            generate_c_call_args ~handle:"g" style;
8211            pr ";\n";
8212            do_cleanups ();
8213            pr "      if (%s == NULL)\n" n;
8214            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8215            pr "      RETVAL = newSVpv (%s, 0);\n" n;
8216            pr "      free (%s);\n" n;
8217            pr " OUTPUT:\n";
8218            pr "      RETVAL\n"
8219        | RStringList n | RHashtable n ->
8220            pr "PREINIT:\n";
8221            pr "      char **%s;\n" n;
8222            pr "      int i, n;\n";
8223            pr " PPCODE:\n";
8224            pr "      %s = guestfs_%s " n name;
8225            generate_c_call_args ~handle:"g" style;
8226            pr ";\n";
8227            do_cleanups ();
8228            pr "      if (%s == NULL)\n" n;
8229            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8230            pr "      for (n = 0; %s[n] != NULL; ++n) /**/;\n" n;
8231            pr "      EXTEND (SP, n);\n";
8232            pr "      for (i = 0; i < n; ++i) {\n";
8233            pr "        PUSHs (sv_2mortal (newSVpv (%s[i], 0)));\n" n;
8234            pr "        free (%s[i]);\n" n;
8235            pr "      }\n";
8236            pr "      free (%s);\n" n;
8237        | RStruct (n, typ) ->
8238            let cols = cols_of_struct typ in
8239            generate_perl_struct_code typ cols name style n do_cleanups
8240        | RStructList (n, typ) ->
8241            let cols = cols_of_struct typ in
8242            generate_perl_struct_list_code typ cols name style n do_cleanups
8243        | RBufferOut n ->
8244            pr "PREINIT:\n";
8245            pr "      char *%s;\n" n;
8246            pr "      size_t size;\n";
8247            pr "   CODE:\n";
8248            pr "      %s = guestfs_%s " n name;
8249            generate_c_call_args ~handle:"g" style;
8250            pr ";\n";
8251            do_cleanups ();
8252            pr "      if (%s == NULL)\n" n;
8253            pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8254            pr "      RETVAL = newSVpv (%s, size);\n" n;
8255            pr "      free (%s);\n" n;
8256            pr " OUTPUT:\n";
8257            pr "      RETVAL\n"
8258       );
8259
8260       pr "\n"
8261   ) all_functions
8262
8263 and generate_perl_struct_list_code typ cols name style n do_cleanups =
8264   pr "PREINIT:\n";
8265   pr "      struct guestfs_%s_list *%s;\n" typ n;
8266   pr "      int i;\n";
8267   pr "      HV *hv;\n";
8268   pr " PPCODE:\n";
8269   pr "      %s = guestfs_%s " n name;
8270   generate_c_call_args ~handle:"g" style;
8271   pr ";\n";
8272   do_cleanups ();
8273   pr "      if (%s == NULL)\n" n;
8274   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8275   pr "      EXTEND (SP, %s->len);\n" n;
8276   pr "      for (i = 0; i < %s->len; ++i) {\n" n;
8277   pr "        hv = newHV ();\n";
8278   List.iter (
8279     function
8280     | name, FString ->
8281         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 0), 0);\n"
8282           name (String.length name) n name
8283     | name, FUUID ->
8284         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, 32), 0);\n"
8285           name (String.length name) n name
8286     | name, FBuffer ->
8287         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (%s->val[i].%s, %s->val[i].%s_len), 0);\n"
8288           name (String.length name) n name n name
8289     | name, (FBytes|FUInt64) ->
8290         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVull (%s->val[i].%s), 0);\n"
8291           name (String.length name) n name
8292     | name, FInt64 ->
8293         pr "        (void) hv_store (hv, \"%s\", %d, my_newSVll (%s->val[i].%s), 0);\n"
8294           name (String.length name) n name
8295     | name, (FInt32|FUInt32) ->
8296         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8297           name (String.length name) n name
8298     | name, FChar ->
8299         pr "        (void) hv_store (hv, \"%s\", %d, newSVpv (&%s->val[i].%s, 1), 0);\n"
8300           name (String.length name) n name
8301     | name, FOptPercent ->
8302         pr "        (void) hv_store (hv, \"%s\", %d, newSVnv (%s->val[i].%s), 0);\n"
8303           name (String.length name) n name
8304   ) cols;
8305   pr "        PUSHs (sv_2mortal (newRV ((SV *) hv)));\n";
8306   pr "      }\n";
8307   pr "      guestfs_free_%s_list (%s);\n" typ n
8308
8309 and generate_perl_struct_code typ cols name style n do_cleanups =
8310   pr "PREINIT:\n";
8311   pr "      struct guestfs_%s *%s;\n" typ n;
8312   pr " PPCODE:\n";
8313   pr "      %s = guestfs_%s " n name;
8314   generate_c_call_args ~handle:"g" style;
8315   pr ";\n";
8316   do_cleanups ();
8317   pr "      if (%s == NULL)\n" n;
8318   pr "        croak (\"%%s\", guestfs_last_error (g));\n";
8319   pr "      EXTEND (SP, 2 * %d);\n" (List.length cols);
8320   List.iter (
8321     fun ((name, _) as col) ->
8322       pr "      PUSHs (sv_2mortal (newSVpv (\"%s\", 0)));\n" name;
8323
8324       match col with
8325       | name, FString ->
8326           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 0)));\n"
8327             n name
8328       | name, FBuffer ->
8329           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, %s->%s_len)));\n"
8330             n name n name
8331       | name, FUUID ->
8332           pr "      PUSHs (sv_2mortal (newSVpv (%s->%s, 32)));\n"
8333             n name
8334       | name, (FBytes|FUInt64) ->
8335           pr "      PUSHs (sv_2mortal (my_newSVull (%s->%s)));\n"
8336             n name
8337       | name, FInt64 ->
8338           pr "      PUSHs (sv_2mortal (my_newSVll (%s->%s)));\n"
8339             n name
8340       | name, (FInt32|FUInt32) ->
8341           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8342             n name
8343       | name, FChar ->
8344           pr "      PUSHs (sv_2mortal (newSVpv (&%s->%s, 1)));\n"
8345             n name
8346       | name, FOptPercent ->
8347           pr "      PUSHs (sv_2mortal (newSVnv (%s->%s)));\n"
8348             n name
8349   ) cols;
8350   pr "      free (%s);\n" n
8351
8352 (* Generate Sys/Guestfs.pm. *)
8353 and generate_perl_pm () =
8354   generate_header HashStyle LGPLv2plus;
8355
8356   pr "\
8357 =pod
8358
8359 =head1 NAME
8360
8361 Sys::Guestfs - Perl bindings for libguestfs
8362
8363 =head1 SYNOPSIS
8364
8365  use Sys::Guestfs;
8366
8367  my $h = Sys::Guestfs->new ();
8368  $h->add_drive ('guest.img');
8369  $h->launch ();
8370  $h->mount ('/dev/sda1', '/');
8371  $h->touch ('/hello');
8372  $h->sync ();
8373
8374 =head1 DESCRIPTION
8375
8376 The C<Sys::Guestfs> module provides a Perl XS binding to the
8377 libguestfs API for examining and modifying virtual machine
8378 disk images.
8379
8380 Amongst the things this is good for: making batch configuration
8381 changes to guests, getting disk used/free statistics (see also:
8382 virt-df), migrating between virtualization systems (see also:
8383 virt-p2v), performing partial backups, performing partial guest
8384 clones, cloning guests and changing registry/UUID/hostname info, and
8385 much else besides.
8386
8387 Libguestfs uses Linux kernel and qemu code, and can access any type of
8388 guest filesystem that Linux and qemu can, including but not limited
8389 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8390 schemes, qcow, qcow2, vmdk.
8391
8392 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8393 LVs, what filesystem is in each LV, etc.).  It can also run commands
8394 in the context of the guest.  Also you can access filesystems over
8395 FUSE.
8396
8397 See also L<Sys::Guestfs::Lib(3)> for a set of useful library
8398 functions for using libguestfs from Perl, including integration
8399 with libvirt.
8400
8401 =head1 ERRORS
8402
8403 All errors turn into calls to C<croak> (see L<Carp(3)>).
8404
8405 =head1 METHODS
8406
8407 =over 4
8408
8409 =cut
8410
8411 package Sys::Guestfs;
8412
8413 use strict;
8414 use warnings;
8415
8416 require XSLoader;
8417 XSLoader::load ('Sys::Guestfs');
8418
8419 =item $h = Sys::Guestfs->new ();
8420
8421 Create a new guestfs handle.
8422
8423 =cut
8424
8425 sub new {
8426   my $proto = shift;
8427   my $class = ref ($proto) || $proto;
8428
8429   my $self = Sys::Guestfs::_create ();
8430   bless $self, $class;
8431   return $self;
8432 }
8433
8434 ";
8435
8436   (* Actions.  We only need to print documentation for these as
8437    * they are pulled in from the XS code automatically.
8438    *)
8439   List.iter (
8440     fun (name, style, _, flags, _, _, longdesc) ->
8441       if not (List.mem NotInDocs flags) then (
8442         let longdesc = replace_str longdesc "C<guestfs_" "C<$h-E<gt>" in
8443         pr "=item ";
8444         generate_perl_prototype name style;
8445         pr "\n\n";
8446         pr "%s\n\n" longdesc;
8447         if List.mem ProtocolLimitWarning flags then
8448           pr "%s\n\n" protocol_limit_warning;
8449         if List.mem DangerWillRobinson flags then
8450           pr "%s\n\n" danger_will_robinson;
8451         match deprecation_notice flags with
8452         | None -> ()
8453         | Some txt -> pr "%s\n\n" txt
8454       )
8455   ) all_functions_sorted;
8456
8457   (* End of file. *)
8458   pr "\
8459 =cut
8460
8461 1;
8462
8463 =back
8464
8465 =head1 COPYRIGHT
8466
8467 Copyright (C) %s Red Hat Inc.
8468
8469 =head1 LICENSE
8470
8471 Please see the file COPYING.LIB for the full license.
8472
8473 =head1 SEE ALSO
8474
8475 L<guestfs(3)>,
8476 L<guestfish(1)>,
8477 L<http://libguestfs.org>,
8478 L<Sys::Guestfs::Lib(3)>.
8479
8480 =cut
8481 " copyright_years
8482
8483 and generate_perl_prototype name style =
8484   (match fst style with
8485    | RErr -> ()
8486    | RBool n
8487    | RInt n
8488    | RInt64 n
8489    | RConstString n
8490    | RConstOptString n
8491    | RString n
8492    | RBufferOut n -> pr "$%s = " n
8493    | RStruct (n,_)
8494    | RHashtable n -> pr "%%%s = " n
8495    | RStringList n
8496    | RStructList (n,_) -> pr "@%s = " n
8497   );
8498   pr "$h->%s (" name;
8499   let comma = ref false in
8500   List.iter (
8501     fun arg ->
8502       if !comma then pr ", ";
8503       comma := true;
8504       match arg with
8505       | Pathname n | Device n | Dev_or_Path n | String n
8506       | OptString n | Bool n | Int n | Int64 n | FileIn n | FileOut n ->
8507           pr "$%s" n
8508       | StringList n | DeviceList n ->
8509           pr "\\@%s" n
8510   ) (snd style);
8511   pr ");"
8512
8513 (* Generate Python C module. *)
8514 and generate_python_c () =
8515   generate_header CStyle LGPLv2plus;
8516
8517   pr "\
8518 #include <Python.h>
8519
8520 #include <stdio.h>
8521 #include <stdlib.h>
8522 #include <assert.h>
8523
8524 #include \"guestfs.h\"
8525
8526 typedef struct {
8527   PyObject_HEAD
8528   guestfs_h *g;
8529 } Pyguestfs_Object;
8530
8531 static guestfs_h *
8532 get_handle (PyObject *obj)
8533 {
8534   assert (obj);
8535   assert (obj != Py_None);
8536   return ((Pyguestfs_Object *) obj)->g;
8537 }
8538
8539 static PyObject *
8540 put_handle (guestfs_h *g)
8541 {
8542   assert (g);
8543   return
8544     PyCObject_FromVoidPtrAndDesc ((void *) g, (char *) \"guestfs_h\", NULL);
8545 }
8546
8547 /* This list should be freed (but not the strings) after use. */
8548 static char **
8549 get_string_list (PyObject *obj)
8550 {
8551   int i, len;
8552   char **r;
8553
8554   assert (obj);
8555
8556   if (!PyList_Check (obj)) {
8557     PyErr_SetString (PyExc_RuntimeError, \"expecting a list parameter\");
8558     return NULL;
8559   }
8560
8561   len = PyList_Size (obj);
8562   r = malloc (sizeof (char *) * (len+1));
8563   if (r == NULL) {
8564     PyErr_SetString (PyExc_RuntimeError, \"get_string_list: out of memory\");
8565     return NULL;
8566   }
8567
8568   for (i = 0; i < len; ++i)
8569     r[i] = PyString_AsString (PyList_GetItem (obj, i));
8570   r[len] = NULL;
8571
8572   return r;
8573 }
8574
8575 static PyObject *
8576 put_string_list (char * const * const argv)
8577 {
8578   PyObject *list;
8579   int argc, i;
8580
8581   for (argc = 0; argv[argc] != NULL; ++argc)
8582     ;
8583
8584   list = PyList_New (argc);
8585   for (i = 0; i < argc; ++i)
8586     PyList_SetItem (list, i, PyString_FromString (argv[i]));
8587
8588   return list;
8589 }
8590
8591 static PyObject *
8592 put_table (char * const * const argv)
8593 {
8594   PyObject *list, *item;
8595   int argc, i;
8596
8597   for (argc = 0; argv[argc] != NULL; ++argc)
8598     ;
8599
8600   list = PyList_New (argc >> 1);
8601   for (i = 0; i < argc; i += 2) {
8602     item = PyTuple_New (2);
8603     PyTuple_SetItem (item, 0, PyString_FromString (argv[i]));
8604     PyTuple_SetItem (item, 1, PyString_FromString (argv[i+1]));
8605     PyList_SetItem (list, i >> 1, item);
8606   }
8607
8608   return list;
8609 }
8610
8611 static void
8612 free_strings (char **argv)
8613 {
8614   int argc;
8615
8616   for (argc = 0; argv[argc] != NULL; ++argc)
8617     free (argv[argc]);
8618   free (argv);
8619 }
8620
8621 static PyObject *
8622 py_guestfs_create (PyObject *self, PyObject *args)
8623 {
8624   guestfs_h *g;
8625
8626   g = guestfs_create ();
8627   if (g == NULL) {
8628     PyErr_SetString (PyExc_RuntimeError,
8629                      \"guestfs.create: failed to allocate handle\");
8630     return NULL;
8631   }
8632   guestfs_set_error_handler (g, NULL, NULL);
8633   return put_handle (g);
8634 }
8635
8636 static PyObject *
8637 py_guestfs_close (PyObject *self, PyObject *args)
8638 {
8639   PyObject *py_g;
8640   guestfs_h *g;
8641
8642   if (!PyArg_ParseTuple (args, (char *) \"O:guestfs_close\", &py_g))
8643     return NULL;
8644   g = get_handle (py_g);
8645
8646   guestfs_close (g);
8647
8648   Py_INCREF (Py_None);
8649   return Py_None;
8650 }
8651
8652 ";
8653
8654   let emit_put_list_function typ =
8655     pr "static PyObject *\n";
8656     pr "put_%s_list (struct guestfs_%s_list *%ss)\n" typ typ typ;
8657     pr "{\n";
8658     pr "  PyObject *list;\n";
8659     pr "  int i;\n";
8660     pr "\n";
8661     pr "  list = PyList_New (%ss->len);\n" typ;
8662     pr "  for (i = 0; i < %ss->len; ++i)\n" typ;
8663     pr "    PyList_SetItem (list, i, put_%s (&%ss->val[i]));\n" typ typ;
8664     pr "  return list;\n";
8665     pr "};\n";
8666     pr "\n"
8667   in
8668
8669   (* Structures, turned into Python dictionaries. *)
8670   List.iter (
8671     fun (typ, cols) ->
8672       pr "static PyObject *\n";
8673       pr "put_%s (struct guestfs_%s *%s)\n" typ typ typ;
8674       pr "{\n";
8675       pr "  PyObject *dict;\n";
8676       pr "\n";
8677       pr "  dict = PyDict_New ();\n";
8678       List.iter (
8679         function
8680         | name, FString ->
8681             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8682             pr "                        PyString_FromString (%s->%s));\n"
8683               typ name
8684         | name, FBuffer ->
8685             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8686             pr "                        PyString_FromStringAndSize (%s->%s, %s->%s_len));\n"
8687               typ name typ name
8688         | name, FUUID ->
8689             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8690             pr "                        PyString_FromStringAndSize (%s->%s, 32));\n"
8691               typ name
8692         | name, (FBytes|FUInt64) ->
8693             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8694             pr "                        PyLong_FromUnsignedLongLong (%s->%s));\n"
8695               typ name
8696         | name, FInt64 ->
8697             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8698             pr "                        PyLong_FromLongLong (%s->%s));\n"
8699               typ name
8700         | name, FUInt32 ->
8701             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8702             pr "                        PyLong_FromUnsignedLong (%s->%s));\n"
8703               typ name
8704         | name, FInt32 ->
8705             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8706             pr "                        PyLong_FromLong (%s->%s));\n"
8707               typ name
8708         | name, FOptPercent ->
8709             pr "  if (%s->%s >= 0)\n" typ name;
8710             pr "    PyDict_SetItemString (dict, \"%s\",\n" name;
8711             pr "                          PyFloat_FromDouble ((double) %s->%s));\n"
8712               typ name;
8713             pr "  else {\n";
8714             pr "    Py_INCREF (Py_None);\n";
8715             pr "    PyDict_SetItemString (dict, \"%s\", Py_None);\n" name;
8716             pr "  }\n"
8717         | name, FChar ->
8718             pr "  PyDict_SetItemString (dict, \"%s\",\n" name;
8719             pr "                        PyString_FromStringAndSize (&dirent->%s, 1));\n" name
8720       ) cols;
8721       pr "  return dict;\n";
8722       pr "};\n";
8723       pr "\n";
8724
8725   ) structs;
8726
8727   (* Emit a put_TYPE_list function definition only if that function is used. *)
8728   List.iter (
8729     function
8730     | typ, (RStructListOnly | RStructAndList) ->
8731         (* generate the function for typ *)
8732         emit_put_list_function typ
8733     | typ, _ -> () (* empty *)
8734   ) (rstructs_used_by all_functions);
8735
8736   (* Python wrapper functions. *)
8737   List.iter (
8738     fun (name, style, _, _, _, _, _) ->
8739       pr "static PyObject *\n";
8740       pr "py_guestfs_%s (PyObject *self, PyObject *args)\n" name;
8741       pr "{\n";
8742
8743       pr "  PyObject *py_g;\n";
8744       pr "  guestfs_h *g;\n";
8745       pr "  PyObject *py_r;\n";
8746
8747       let error_code =
8748         match fst style with
8749         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
8750         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
8751         | RConstString _ | RConstOptString _ ->
8752             pr "  const char *r;\n"; "NULL"
8753         | RString _ -> pr "  char *r;\n"; "NULL"
8754         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
8755         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
8756         | RStructList (_, typ) ->
8757             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
8758         | RBufferOut _ ->
8759             pr "  char *r;\n";
8760             pr "  size_t size;\n";
8761             "NULL" in
8762
8763       List.iter (
8764         function
8765         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
8766             pr "  const char *%s;\n" n
8767         | OptString n -> pr "  const char *%s;\n" n
8768         | StringList n | DeviceList n ->
8769             pr "  PyObject *py_%s;\n" n;
8770             pr "  char **%s;\n" n
8771         | Bool n -> pr "  int %s;\n" n
8772         | Int n -> pr "  int %s;\n" n
8773         | Int64 n -> pr "  long long %s;\n" n
8774       ) (snd style);
8775
8776       pr "\n";
8777
8778       (* Convert the parameters. *)
8779       pr "  if (!PyArg_ParseTuple (args, (char *) \"O";
8780       List.iter (
8781         function
8782         | Pathname _ | Device _ | Dev_or_Path _ | String _ | FileIn _ | FileOut _ -> pr "s"
8783         | OptString _ -> pr "z"
8784         | StringList _ | DeviceList _ -> pr "O"
8785         | Bool _ -> pr "i" (* XXX Python has booleans? *)
8786         | Int _ -> pr "i"
8787         | Int64 _ -> pr "L" (* XXX Whoever thought it was a good idea to
8788                              * emulate C's int/long/long long in Python?
8789                              *)
8790       ) (snd style);
8791       pr ":guestfs_%s\",\n" name;
8792       pr "                         &py_g";
8793       List.iter (
8794         function
8795         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n -> pr ", &%s" n
8796         | OptString n -> pr ", &%s" n
8797         | StringList n | DeviceList n -> pr ", &py_%s" n
8798         | Bool n -> pr ", &%s" n
8799         | Int n -> pr ", &%s" n
8800         | Int64 n -> pr ", &%s" n
8801       ) (snd style);
8802
8803       pr "))\n";
8804       pr "    return NULL;\n";
8805
8806       pr "  g = get_handle (py_g);\n";
8807       List.iter (
8808         function
8809         | Pathname _ | Device _ | Dev_or_Path _ | String _
8810         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8811         | StringList n | DeviceList n ->
8812             pr "  %s = get_string_list (py_%s);\n" n n;
8813             pr "  if (!%s) return NULL;\n" n
8814       ) (snd style);
8815
8816       pr "\n";
8817
8818       pr "  r = guestfs_%s " name;
8819       generate_c_call_args ~handle:"g" style;
8820       pr ";\n";
8821
8822       List.iter (
8823         function
8824         | Pathname _ | Device _ | Dev_or_Path _ | String _
8825         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
8826         | StringList n | DeviceList n ->
8827             pr "  free (%s);\n" n
8828       ) (snd style);
8829
8830       pr "  if (r == %s) {\n" error_code;
8831       pr "    PyErr_SetString (PyExc_RuntimeError, guestfs_last_error (g));\n";
8832       pr "    return NULL;\n";
8833       pr "  }\n";
8834       pr "\n";
8835
8836       (match fst style with
8837        | RErr ->
8838            pr "  Py_INCREF (Py_None);\n";
8839            pr "  py_r = Py_None;\n"
8840        | RInt _
8841        | RBool _ -> pr "  py_r = PyInt_FromLong ((long) r);\n"
8842        | RInt64 _ -> pr "  py_r = PyLong_FromLongLong (r);\n"
8843        | RConstString _ -> pr "  py_r = PyString_FromString (r);\n"
8844        | RConstOptString _ ->
8845            pr "  if (r)\n";
8846            pr "    py_r = PyString_FromString (r);\n";
8847            pr "  else {\n";
8848            pr "    Py_INCREF (Py_None);\n";
8849            pr "    py_r = Py_None;\n";
8850            pr "  }\n"
8851        | RString _ ->
8852            pr "  py_r = PyString_FromString (r);\n";
8853            pr "  free (r);\n"
8854        | RStringList _ ->
8855            pr "  py_r = put_string_list (r);\n";
8856            pr "  free_strings (r);\n"
8857        | RStruct (_, typ) ->
8858            pr "  py_r = put_%s (r);\n" typ;
8859            pr "  guestfs_free_%s (r);\n" typ
8860        | RStructList (_, typ) ->
8861            pr "  py_r = put_%s_list (r);\n" typ;
8862            pr "  guestfs_free_%s_list (r);\n" typ
8863        | RHashtable n ->
8864            pr "  py_r = put_table (r);\n";
8865            pr "  free_strings (r);\n"
8866        | RBufferOut _ ->
8867            pr "  py_r = PyString_FromStringAndSize (r, size);\n";
8868            pr "  free (r);\n"
8869       );
8870
8871       pr "  return py_r;\n";
8872       pr "}\n";
8873       pr "\n"
8874   ) all_functions;
8875
8876   (* Table of functions. *)
8877   pr "static PyMethodDef methods[] = {\n";
8878   pr "  { (char *) \"create\", py_guestfs_create, METH_VARARGS, NULL },\n";
8879   pr "  { (char *) \"close\", py_guestfs_close, METH_VARARGS, NULL },\n";
8880   List.iter (
8881     fun (name, _, _, _, _, _, _) ->
8882       pr "  { (char *) \"%s\", py_guestfs_%s, METH_VARARGS, NULL },\n"
8883         name name
8884   ) all_functions;
8885   pr "  { NULL, NULL, 0, NULL }\n";
8886   pr "};\n";
8887   pr "\n";
8888
8889   (* Init function. *)
8890   pr "\
8891 void
8892 initlibguestfsmod (void)
8893 {
8894   static int initialized = 0;
8895
8896   if (initialized) return;
8897   Py_InitModule ((char *) \"libguestfsmod\", methods);
8898   initialized = 1;
8899 }
8900 "
8901
8902 (* Generate Python module. *)
8903 and generate_python_py () =
8904   generate_header HashStyle LGPLv2plus;
8905
8906   pr "\
8907 u\"\"\"Python bindings for libguestfs
8908
8909 import guestfs
8910 g = guestfs.GuestFS ()
8911 g.add_drive (\"guest.img\")
8912 g.launch ()
8913 parts = g.list_partitions ()
8914
8915 The guestfs module provides a Python binding to the libguestfs API
8916 for examining and modifying virtual machine disk images.
8917
8918 Amongst the things this is good for: making batch configuration
8919 changes to guests, getting disk used/free statistics (see also:
8920 virt-df), migrating between virtualization systems (see also:
8921 virt-p2v), performing partial backups, performing partial guest
8922 clones, cloning guests and changing registry/UUID/hostname info, and
8923 much else besides.
8924
8925 Libguestfs uses Linux kernel and qemu code, and can access any type of
8926 guest filesystem that Linux and qemu can, including but not limited
8927 to: ext2/3/4, btrfs, FAT and NTFS, LVM, many different disk partition
8928 schemes, qcow, qcow2, vmdk.
8929
8930 Libguestfs provides ways to enumerate guest storage (eg. partitions,
8931 LVs, what filesystem is in each LV, etc.).  It can also run commands
8932 in the context of the guest.  Also you can access filesystems over
8933 FUSE.
8934
8935 Errors which happen while using the API are turned into Python
8936 RuntimeError exceptions.
8937
8938 To create a guestfs handle you usually have to perform the following
8939 sequence of calls:
8940
8941 # Create the handle, call add_drive at least once, and possibly
8942 # several times if the guest has multiple block devices:
8943 g = guestfs.GuestFS ()
8944 g.add_drive (\"guest.img\")
8945
8946 # Launch the qemu subprocess and wait for it to become ready:
8947 g.launch ()
8948
8949 # Now you can issue commands, for example:
8950 logvols = g.lvs ()
8951
8952 \"\"\"
8953
8954 import libguestfsmod
8955
8956 class GuestFS:
8957     \"\"\"Instances of this class are libguestfs API handles.\"\"\"
8958
8959     def __init__ (self):
8960         \"\"\"Create a new libguestfs handle.\"\"\"
8961         self._o = libguestfsmod.create ()
8962
8963     def __del__ (self):
8964         libguestfsmod.close (self._o)
8965
8966 ";
8967
8968   List.iter (
8969     fun (name, style, _, flags, _, _, longdesc) ->
8970       pr "    def %s " name;
8971       generate_py_call_args ~handle:"self" (snd style);
8972       pr ":\n";
8973
8974       if not (List.mem NotInDocs flags) then (
8975         let doc = replace_str longdesc "C<guestfs_" "C<g." in
8976         let doc =
8977           match fst style with
8978           | RErr | RInt _ | RInt64 _ | RBool _
8979           | RConstOptString _ | RConstString _
8980           | RString _ | RBufferOut _ -> doc
8981           | RStringList _ ->
8982               doc ^ "\n\nThis function returns a list of strings."
8983           | RStruct (_, typ) ->
8984               doc ^ sprintf "\n\nThis function returns a dictionary, with keys matching the various fields in the guestfs_%s structure." typ
8985           | RStructList (_, typ) ->
8986               doc ^ sprintf "\n\nThis function returns a list of %ss.  Each %s is represented as a dictionary." typ typ
8987           | RHashtable _ ->
8988               doc ^ "\n\nThis function returns a dictionary." in
8989         let doc =
8990           if List.mem ProtocolLimitWarning flags then
8991             doc ^ "\n\n" ^ protocol_limit_warning
8992           else doc in
8993         let doc =
8994           if List.mem DangerWillRobinson flags then
8995             doc ^ "\n\n" ^ danger_will_robinson
8996           else doc in
8997         let doc =
8998           match deprecation_notice flags with
8999           | None -> doc
9000           | Some txt -> doc ^ "\n\n" ^ txt in
9001         let doc = pod2text ~width:60 name doc in
9002         let doc = List.map (fun line -> replace_str line "\\" "\\\\") doc in
9003         let doc = String.concat "\n        " doc in
9004         pr "        u\"\"\"%s\"\"\"\n" doc;
9005       );
9006       pr "        return libguestfsmod.%s " name;
9007       generate_py_call_args ~handle:"self._o" (snd style);
9008       pr "\n";
9009       pr "\n";
9010   ) all_functions
9011
9012 (* Generate Python call arguments, eg "(handle, foo, bar)" *)
9013 and generate_py_call_args ~handle args =
9014   pr "(%s" handle;
9015   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9016   pr ")"
9017
9018 (* Useful if you need the longdesc POD text as plain text.  Returns a
9019  * list of lines.
9020  *
9021  * Because this is very slow (the slowest part of autogeneration),
9022  * we memoize the results.
9023  *)
9024 and pod2text ~width name longdesc =
9025   let key = width, name, longdesc in
9026   try Hashtbl.find pod2text_memo key
9027   with Not_found ->
9028     let filename, chan = Filename.open_temp_file "gen" ".tmp" in
9029     fprintf chan "=head1 %s\n\n%s\n" name longdesc;
9030     close_out chan;
9031     let cmd = sprintf "pod2text -w %d %s" width (Filename.quote filename) in
9032     let chan = open_process_in cmd in
9033     let lines = ref [] in
9034     let rec loop i =
9035       let line = input_line chan in
9036       if i = 1 then             (* discard the first line of output *)
9037         loop (i+1)
9038       else (
9039         let line = triml line in
9040         lines := line :: !lines;
9041         loop (i+1)
9042       ) in
9043     let lines = try loop 1 with End_of_file -> List.rev !lines in
9044     unlink filename;
9045     (match close_process_in chan with
9046      | WEXITED 0 -> ()
9047      | WEXITED i ->
9048          failwithf "pod2text: process exited with non-zero status (%d)" i
9049      | WSIGNALED i | WSTOPPED i ->
9050          failwithf "pod2text: process signalled or stopped by signal %d" i
9051     );
9052     Hashtbl.add pod2text_memo key lines;
9053     pod2text_memo_updated ();
9054     lines
9055
9056 (* Generate ruby bindings. *)
9057 and generate_ruby_c () =
9058   generate_header CStyle LGPLv2plus;
9059
9060   pr "\
9061 #include <stdio.h>
9062 #include <stdlib.h>
9063
9064 #include <ruby.h>
9065
9066 #include \"guestfs.h\"
9067
9068 #include \"extconf.h\"
9069
9070 /* For Ruby < 1.9 */
9071 #ifndef RARRAY_LEN
9072 #define RARRAY_LEN(r) (RARRAY((r))->len)
9073 #endif
9074
9075 static VALUE m_guestfs;                 /* guestfs module */
9076 static VALUE c_guestfs;                 /* guestfs_h handle */
9077 static VALUE e_Error;                   /* used for all errors */
9078
9079 static void ruby_guestfs_free (void *p)
9080 {
9081   if (!p) return;
9082   guestfs_close ((guestfs_h *) p);
9083 }
9084
9085 static VALUE ruby_guestfs_create (VALUE m)
9086 {
9087   guestfs_h *g;
9088
9089   g = guestfs_create ();
9090   if (!g)
9091     rb_raise (e_Error, \"failed to create guestfs handle\");
9092
9093   /* Don't print error messages to stderr by default. */
9094   guestfs_set_error_handler (g, NULL, NULL);
9095
9096   /* Wrap it, and make sure the close function is called when the
9097    * handle goes away.
9098    */
9099   return Data_Wrap_Struct (c_guestfs, NULL, ruby_guestfs_free, g);
9100 }
9101
9102 static VALUE ruby_guestfs_close (VALUE gv)
9103 {
9104   guestfs_h *g;
9105   Data_Get_Struct (gv, guestfs_h, g);
9106
9107   ruby_guestfs_free (g);
9108   DATA_PTR (gv) = NULL;
9109
9110   return Qnil;
9111 }
9112
9113 ";
9114
9115   List.iter (
9116     fun (name, style, _, _, _, _, _) ->
9117       pr "static VALUE ruby_guestfs_%s (VALUE gv" name;
9118       List.iter (fun arg -> pr ", VALUE %sv" (name_of_argt arg)) (snd style);
9119       pr ")\n";
9120       pr "{\n";
9121       pr "  guestfs_h *g;\n";
9122       pr "  Data_Get_Struct (gv, guestfs_h, g);\n";
9123       pr "  if (!g)\n";
9124       pr "    rb_raise (rb_eArgError, \"%%s: used handle after closing it\", \"%s\");\n"
9125         name;
9126       pr "\n";
9127
9128       List.iter (
9129         function
9130         | Pathname n | Device n | Dev_or_Path n | String n | FileIn n | FileOut n ->
9131             pr "  Check_Type (%sv, T_STRING);\n" n;
9132             pr "  const char *%s = StringValueCStr (%sv);\n" n n;
9133             pr "  if (!%s)\n" n;
9134             pr "    rb_raise (rb_eTypeError, \"expected string for parameter %%s of %%s\",\n";
9135             pr "              \"%s\", \"%s\");\n" n name
9136         | OptString n ->
9137             pr "  const char *%s = !NIL_P (%sv) ? StringValueCStr (%sv) : NULL;\n" n n n
9138         | StringList n | DeviceList n ->
9139             pr "  char **%s;\n" n;
9140             pr "  Check_Type (%sv, T_ARRAY);\n" n;
9141             pr "  {\n";
9142             pr "    int i, len;\n";
9143             pr "    len = RARRAY_LEN (%sv);\n" n;
9144             pr "    %s = guestfs_safe_malloc (g, sizeof (char *) * (len+1));\n"
9145               n;
9146             pr "    for (i = 0; i < len; ++i) {\n";
9147             pr "      VALUE v = rb_ary_entry (%sv, i);\n" n;
9148             pr "      %s[i] = StringValueCStr (v);\n" n;
9149             pr "    }\n";
9150             pr "    %s[len] = NULL;\n" n;
9151             pr "  }\n";
9152         | Bool n ->
9153             pr "  int %s = RTEST (%sv);\n" n n
9154         | Int n ->
9155             pr "  int %s = NUM2INT (%sv);\n" n n
9156         | Int64 n ->
9157             pr "  long long %s = NUM2LL (%sv);\n" n n
9158       ) (snd style);
9159       pr "\n";
9160
9161       let error_code =
9162         match fst style with
9163         | RErr | RInt _ | RBool _ -> pr "  int r;\n"; "-1"
9164         | RInt64 _ -> pr "  int64_t r;\n"; "-1"
9165         | RConstString _ | RConstOptString _ ->
9166             pr "  const char *r;\n"; "NULL"
9167         | RString _ -> pr "  char *r;\n"; "NULL"
9168         | RStringList _ | RHashtable _ -> pr "  char **r;\n"; "NULL"
9169         | RStruct (_, typ) -> pr "  struct guestfs_%s *r;\n" typ; "NULL"
9170         | RStructList (_, typ) ->
9171             pr "  struct guestfs_%s_list *r;\n" typ; "NULL"
9172         | RBufferOut _ ->
9173             pr "  char *r;\n";
9174             pr "  size_t size;\n";
9175             "NULL" in
9176       pr "\n";
9177
9178       pr "  r = guestfs_%s " name;
9179       generate_c_call_args ~handle:"g" style;
9180       pr ";\n";
9181
9182       List.iter (
9183         function
9184         | Pathname _ | Device _ | Dev_or_Path _ | String _
9185         | FileIn _ | FileOut _ | OptString _ | Bool _ | Int _ | Int64 _ -> ()
9186         | StringList n | DeviceList n ->
9187             pr "  free (%s);\n" n
9188       ) (snd style);
9189
9190       pr "  if (r == %s)\n" error_code;
9191       pr "    rb_raise (e_Error, \"%%s\", guestfs_last_error (g));\n";
9192       pr "\n";
9193
9194       (match fst style with
9195        | RErr ->
9196            pr "  return Qnil;\n"
9197        | RInt _ | RBool _ ->
9198            pr "  return INT2NUM (r);\n"
9199        | RInt64 _ ->
9200            pr "  return ULL2NUM (r);\n"
9201        | RConstString _ ->
9202            pr "  return rb_str_new2 (r);\n";
9203        | RConstOptString _ ->
9204            pr "  if (r)\n";
9205            pr "    return rb_str_new2 (r);\n";
9206            pr "  else\n";
9207            pr "    return Qnil;\n";
9208        | RString _ ->
9209            pr "  VALUE rv = rb_str_new2 (r);\n";
9210            pr "  free (r);\n";
9211            pr "  return rv;\n";
9212        | RStringList _ ->
9213            pr "  int i, len = 0;\n";
9214            pr "  for (i = 0; r[i] != NULL; ++i) len++;\n";
9215            pr "  VALUE rv = rb_ary_new2 (len);\n";
9216            pr "  for (i = 0; r[i] != NULL; ++i) {\n";
9217            pr "    rb_ary_push (rv, rb_str_new2 (r[i]));\n";
9218            pr "    free (r[i]);\n";
9219            pr "  }\n";
9220            pr "  free (r);\n";
9221            pr "  return rv;\n"
9222        | RStruct (_, typ) ->
9223            let cols = cols_of_struct typ in
9224            generate_ruby_struct_code typ cols
9225        | RStructList (_, typ) ->
9226            let cols = cols_of_struct typ in
9227            generate_ruby_struct_list_code typ cols
9228        | RHashtable _ ->
9229            pr "  VALUE rv = rb_hash_new ();\n";
9230            pr "  int i;\n";
9231            pr "  for (i = 0; r[i] != NULL; i+=2) {\n";
9232            pr "    rb_hash_aset (rv, rb_str_new2 (r[i]), rb_str_new2 (r[i+1]));\n";
9233            pr "    free (r[i]);\n";
9234            pr "    free (r[i+1]);\n";
9235            pr "  }\n";
9236            pr "  free (r);\n";
9237            pr "  return rv;\n"
9238        | RBufferOut _ ->
9239            pr "  VALUE rv = rb_str_new (r, size);\n";
9240            pr "  free (r);\n";
9241            pr "  return rv;\n";
9242       );
9243
9244       pr "}\n";
9245       pr "\n"
9246   ) all_functions;
9247
9248   pr "\
9249 /* Initialize the module. */
9250 void Init__guestfs ()
9251 {
9252   m_guestfs = rb_define_module (\"Guestfs\");
9253   c_guestfs = rb_define_class_under (m_guestfs, \"Guestfs\", rb_cObject);
9254   e_Error = rb_define_class_under (m_guestfs, \"Error\", rb_eStandardError);
9255
9256   rb_define_module_function (m_guestfs, \"create\", ruby_guestfs_create, 0);
9257   rb_define_method (c_guestfs, \"close\", ruby_guestfs_close, 0);
9258
9259 ";
9260   (* Define the rest of the methods. *)
9261   List.iter (
9262     fun (name, style, _, _, _, _, _) ->
9263       pr "  rb_define_method (c_guestfs, \"%s\",\n" name;
9264       pr "        ruby_guestfs_%s, %d);\n" name (List.length (snd style))
9265   ) all_functions;
9266
9267   pr "}\n"
9268
9269 (* Ruby code to return a struct. *)
9270 and generate_ruby_struct_code typ cols =
9271   pr "  VALUE rv = rb_hash_new ();\n";
9272   List.iter (
9273     function
9274     | name, FString ->
9275         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new2 (r->%s));\n" name name
9276     | name, FBuffer ->
9277         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, r->%s_len));\n" name name name
9278     | name, FUUID ->
9279         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_str_new (r->%s, 32));\n" name name
9280     | name, (FBytes|FUInt64) ->
9281         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9282     | name, FInt64 ->
9283         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), LL2NUM (r->%s));\n" name name
9284     | name, FUInt32 ->
9285         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), UINT2NUM (r->%s));\n" name name
9286     | name, FInt32 ->
9287         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), INT2NUM (r->%s));\n" name name
9288     | name, FOptPercent ->
9289         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), rb_dbl2big (r->%s));\n" name name
9290     | name, FChar -> (* XXX wrong? *)
9291         pr "  rb_hash_aset (rv, rb_str_new2 (\"%s\"), ULL2NUM (r->%s));\n" name name
9292   ) cols;
9293   pr "  guestfs_free_%s (r);\n" typ;
9294   pr "  return rv;\n"
9295
9296 (* Ruby code to return a struct list. *)
9297 and generate_ruby_struct_list_code typ cols =
9298   pr "  VALUE rv = rb_ary_new2 (r->len);\n";
9299   pr "  int i;\n";
9300   pr "  for (i = 0; i < r->len; ++i) {\n";
9301   pr "    VALUE hv = rb_hash_new ();\n";
9302   List.iter (
9303     function
9304     | name, FString ->
9305         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new2 (r->val[i].%s));\n" name name
9306     | name, FBuffer ->
9307         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
9308     | name, FUUID ->
9309         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_str_new (r->val[i].%s, 32));\n" name name
9310     | name, (FBytes|FUInt64) ->
9311         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9312     | name, FInt64 ->
9313         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), LL2NUM (r->val[i].%s));\n" name name
9314     | name, FUInt32 ->
9315         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), UINT2NUM (r->val[i].%s));\n" name name
9316     | name, FInt32 ->
9317         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), INT2NUM (r->val[i].%s));\n" name name
9318     | name, FOptPercent ->
9319         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), rb_dbl2big (r->val[i].%s));\n" name name
9320     | name, FChar -> (* XXX wrong? *)
9321         pr "    rb_hash_aset (hv, rb_str_new2 (\"%s\"), ULL2NUM (r->val[i].%s));\n" name name
9322   ) cols;
9323   pr "    rb_ary_push (rv, hv);\n";
9324   pr "  }\n";
9325   pr "  guestfs_free_%s_list (r);\n" typ;
9326   pr "  return rv;\n"
9327
9328 (* Generate Java bindings GuestFS.java file. *)
9329 and generate_java_java () =
9330   generate_header CStyle LGPLv2plus;
9331
9332   pr "\
9333 package com.redhat.et.libguestfs;
9334
9335 import java.util.HashMap;
9336 import com.redhat.et.libguestfs.LibGuestFSException;
9337 import com.redhat.et.libguestfs.PV;
9338 import com.redhat.et.libguestfs.VG;
9339 import com.redhat.et.libguestfs.LV;
9340 import com.redhat.et.libguestfs.Stat;
9341 import com.redhat.et.libguestfs.StatVFS;
9342 import com.redhat.et.libguestfs.IntBool;
9343 import com.redhat.et.libguestfs.Dirent;
9344
9345 /**
9346  * The GuestFS object is a libguestfs handle.
9347  *
9348  * @author rjones
9349  */
9350 public class GuestFS {
9351   // Load the native code.
9352   static {
9353     System.loadLibrary (\"guestfs_jni\");
9354   }
9355
9356   /**
9357    * The native guestfs_h pointer.
9358    */
9359   long g;
9360
9361   /**
9362    * Create a libguestfs handle.
9363    *
9364    * @throws LibGuestFSException
9365    */
9366   public GuestFS () throws LibGuestFSException
9367   {
9368     g = _create ();
9369   }
9370   private native long _create () throws LibGuestFSException;
9371
9372   /**
9373    * Close a libguestfs handle.
9374    *
9375    * You can also leave handles to be collected by the garbage
9376    * collector, but this method ensures that the resources used
9377    * by the handle are freed up immediately.  If you call any
9378    * other methods after closing the handle, you will get an
9379    * exception.
9380    *
9381    * @throws LibGuestFSException
9382    */
9383   public void close () throws LibGuestFSException
9384   {
9385     if (g != 0)
9386       _close (g);
9387     g = 0;
9388   }
9389   private native void _close (long g) throws LibGuestFSException;
9390
9391   public void finalize () throws LibGuestFSException
9392   {
9393     close ();
9394   }
9395
9396 ";
9397
9398   List.iter (
9399     fun (name, style, _, flags, _, shortdesc, longdesc) ->
9400       if not (List.mem NotInDocs flags); then (
9401         let doc = replace_str longdesc "C<guestfs_" "C<g." in
9402         let doc =
9403           if List.mem ProtocolLimitWarning flags then
9404             doc ^ "\n\n" ^ protocol_limit_warning
9405           else doc in
9406         let doc =
9407           if List.mem DangerWillRobinson flags then
9408             doc ^ "\n\n" ^ danger_will_robinson
9409           else doc in
9410         let doc =
9411           match deprecation_notice flags with
9412           | None -> doc
9413           | Some txt -> doc ^ "\n\n" ^ txt in
9414         let doc = pod2text ~width:60 name doc in
9415         let doc = List.map (            (* RHBZ#501883 *)
9416           function
9417           | "" -> "<p>"
9418           | nonempty -> nonempty
9419         ) doc in
9420         let doc = String.concat "\n   * " doc in
9421
9422         pr "  /**\n";
9423         pr "   * %s\n" shortdesc;
9424         pr "   * <p>\n";
9425         pr "   * %s\n" doc;
9426         pr "   * @throws LibGuestFSException\n";
9427         pr "   */\n";
9428         pr "  ";
9429       );
9430       generate_java_prototype ~public:true ~semicolon:false name style;
9431       pr "\n";
9432       pr "  {\n";
9433       pr "    if (g == 0)\n";
9434       pr "      throw new LibGuestFSException (\"%s: handle is closed\");\n"
9435         name;
9436       pr "    ";
9437       if fst style <> RErr then pr "return ";
9438       pr "_%s " name;
9439       generate_java_call_args ~handle:"g" (snd style);
9440       pr ";\n";
9441       pr "  }\n";
9442       pr "  ";
9443       generate_java_prototype ~privat:true ~native:true name style;
9444       pr "\n";
9445       pr "\n";
9446   ) all_functions;
9447
9448   pr "}\n"
9449
9450 (* Generate Java call arguments, eg "(handle, foo, bar)" *)
9451 and generate_java_call_args ~handle args =
9452   pr "(%s" handle;
9453   List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
9454   pr ")"
9455
9456 and generate_java_prototype ?(public=false) ?(privat=false) ?(native=false)
9457     ?(semicolon=true) name style =
9458   if privat then pr "private ";
9459   if public then pr "public ";
9460   if native then pr "native ";
9461
9462   (* return type *)
9463   (match fst style with
9464    | RErr -> pr "void ";
9465    | RInt _ -> pr "int ";
9466    | RInt64 _ -> pr "long ";
9467    | RBool _ -> pr "boolean ";
9468    | RConstString _ | RConstOptString _ | RString _
9469    | RBufferOut _ -> pr "String ";
9470    | RStringList _ -> pr "String[] ";
9471    | RStruct (_, typ) ->
9472        let name = java_name_of_struct typ in
9473        pr "%s " name;
9474    | RStructList (_, typ) ->
9475        let name = java_name_of_struct typ in
9476        pr "%s[] " name;
9477    | RHashtable _ -> pr "HashMap<String,String> ";
9478   );
9479
9480   if native then pr "_%s " name else pr "%s " name;
9481   pr "(";
9482   let needs_comma = ref false in
9483   if native then (
9484     pr "long g";
9485     needs_comma := true
9486   );
9487
9488   (* args *)
9489   List.iter (
9490     fun arg ->
9491       if !needs_comma then pr ", ";
9492       needs_comma := true;
9493
9494       match arg with
9495       | Pathname n
9496       | Device n | Dev_or_Path n
9497       | String n
9498       | OptString n
9499       | FileIn n
9500       | FileOut n ->
9501           pr "String %s" n
9502       | StringList n | DeviceList n ->
9503           pr "String[] %s" n
9504       | Bool n ->
9505           pr "boolean %s" n
9506       | Int n ->
9507           pr "int %s" n
9508       | Int64 n ->
9509           pr "long %s" n
9510   ) (snd style);
9511
9512   pr ")\n";
9513   pr "    throws LibGuestFSException";
9514   if semicolon then pr ";"
9515
9516 and generate_java_struct jtyp cols () =
9517   generate_header CStyle LGPLv2plus;
9518
9519   pr "\
9520 package com.redhat.et.libguestfs;
9521
9522 /**
9523  * Libguestfs %s structure.
9524  *
9525  * @author rjones
9526  * @see GuestFS
9527  */
9528 public class %s {
9529 " jtyp jtyp;
9530
9531   List.iter (
9532     function
9533     | name, FString
9534     | name, FUUID
9535     | name, FBuffer -> pr "  public String %s;\n" name
9536     | name, (FBytes|FUInt64|FInt64) -> pr "  public long %s;\n" name
9537     | name, (FUInt32|FInt32) -> pr "  public int %s;\n" name
9538     | name, FChar -> pr "  public char %s;\n" name
9539     | name, FOptPercent ->
9540         pr "  /* The next field is [0..100] or -1 meaning 'not present': */\n";
9541         pr "  public float %s;\n" name
9542   ) cols;
9543
9544   pr "}\n"
9545
9546 and generate_java_c () =
9547   generate_header CStyle LGPLv2plus;
9548
9549   pr "\
9550 #include <stdio.h>
9551 #include <stdlib.h>
9552 #include <string.h>
9553
9554 #include \"com_redhat_et_libguestfs_GuestFS.h\"
9555 #include \"guestfs.h\"
9556
9557 /* Note that this function returns.  The exception is not thrown
9558  * until after the wrapper function returns.
9559  */
9560 static void
9561 throw_exception (JNIEnv *env, const char *msg)
9562 {
9563   jclass cl;
9564   cl = (*env)->FindClass (env,
9565                           \"com/redhat/et/libguestfs/LibGuestFSException\");
9566   (*env)->ThrowNew (env, cl, msg);
9567 }
9568
9569 JNIEXPORT jlong JNICALL
9570 Java_com_redhat_et_libguestfs_GuestFS__1create
9571   (JNIEnv *env, jobject obj)
9572 {
9573   guestfs_h *g;
9574
9575   g = guestfs_create ();
9576   if (g == NULL) {
9577     throw_exception (env, \"GuestFS.create: failed to allocate handle\");
9578     return 0;
9579   }
9580   guestfs_set_error_handler (g, NULL, NULL);
9581   return (jlong) (long) g;
9582 }
9583
9584 JNIEXPORT void JNICALL
9585 Java_com_redhat_et_libguestfs_GuestFS__1close
9586   (JNIEnv *env, jobject obj, jlong jg)
9587 {
9588   guestfs_h *g = (guestfs_h *) (long) jg;
9589   guestfs_close (g);
9590 }
9591
9592 ";
9593
9594   List.iter (
9595     fun (name, style, _, _, _, _, _) ->
9596       pr "JNIEXPORT ";
9597       (match fst style with
9598        | RErr -> pr "void ";
9599        | RInt _ -> pr "jint ";
9600        | RInt64 _ -> pr "jlong ";
9601        | RBool _ -> pr "jboolean ";
9602        | RConstString _ | RConstOptString _ | RString _
9603        | RBufferOut _ -> pr "jstring ";
9604        | RStruct _ | RHashtable _ ->
9605            pr "jobject ";
9606        | RStringList _ | RStructList _ ->
9607            pr "jobjectArray ";
9608       );
9609       pr "JNICALL\n";
9610       pr "Java_com_redhat_et_libguestfs_GuestFS_";
9611       pr "%s" (replace_str ("_" ^ name) "_" "_1");
9612       pr "\n";
9613       pr "  (JNIEnv *env, jobject obj, jlong jg";
9614       List.iter (
9615         function
9616         | Pathname n
9617         | Device n | Dev_or_Path n
9618         | String n
9619         | OptString n
9620         | FileIn n
9621         | FileOut n ->
9622             pr ", jstring j%s" n
9623         | StringList n | DeviceList n ->
9624             pr ", jobjectArray j%s" n
9625         | Bool n ->
9626             pr ", jboolean j%s" n
9627         | Int n ->
9628             pr ", jint j%s" n
9629         | Int64 n ->
9630             pr ", jlong j%s" n
9631       ) (snd style);
9632       pr ")\n";
9633       pr "{\n";
9634       pr "  guestfs_h *g = (guestfs_h *) (long) jg;\n";
9635       let error_code, no_ret =
9636         match fst style with
9637         | RErr -> pr "  int r;\n"; "-1", ""
9638         | RBool _
9639         | RInt _ -> pr "  int r;\n"; "-1", "0"
9640         | RInt64 _ -> pr "  int64_t r;\n"; "-1", "0"
9641         | RConstString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9642         | RConstOptString _ -> pr "  const char *r;\n"; "NULL", "NULL"
9643         | RString _ ->
9644             pr "  jstring jr;\n";
9645             pr "  char *r;\n"; "NULL", "NULL"
9646         | RStringList _ ->
9647             pr "  jobjectArray jr;\n";
9648             pr "  int r_len;\n";
9649             pr "  jclass cl;\n";
9650             pr "  jstring jstr;\n";
9651             pr "  char **r;\n"; "NULL", "NULL"
9652         | RStruct (_, typ) ->
9653             pr "  jobject jr;\n";
9654             pr "  jclass cl;\n";
9655             pr "  jfieldID fl;\n";
9656             pr "  struct guestfs_%s *r;\n" typ; "NULL", "NULL"
9657         | RStructList (_, typ) ->
9658             pr "  jobjectArray jr;\n";
9659             pr "  jclass cl;\n";
9660             pr "  jfieldID fl;\n";
9661             pr "  jobject jfl;\n";
9662             pr "  struct guestfs_%s_list *r;\n" typ; "NULL", "NULL"
9663         | RHashtable _ -> pr "  char **r;\n"; "NULL", "NULL"
9664         | RBufferOut _ ->
9665             pr "  jstring jr;\n";
9666             pr "  char *r;\n";
9667             pr "  size_t size;\n";
9668             "NULL", "NULL" in
9669       List.iter (
9670         function
9671         | Pathname n
9672         | Device n | Dev_or_Path n
9673         | String n
9674         | OptString n
9675         | FileIn n
9676         | FileOut n ->
9677             pr "  const char *%s;\n" n
9678         | StringList n | DeviceList n ->
9679             pr "  int %s_len;\n" n;
9680             pr "  const char **%s;\n" n
9681         | Bool n
9682         | Int n ->
9683             pr "  int %s;\n" n
9684         | Int64 n ->
9685             pr "  int64_t %s;\n" n
9686       ) (snd style);
9687
9688       let needs_i =
9689         (match fst style with
9690          | RStringList _ | RStructList _ -> true
9691          | RErr | RBool _ | RInt _ | RInt64 _ | RConstString _
9692          | RConstOptString _
9693          | RString _ | RBufferOut _ | RStruct _ | RHashtable _ -> false) ||
9694           List.exists (function
9695                        | StringList _ -> true
9696                        | DeviceList _ -> true
9697                        | _ -> false) (snd style) in
9698       if needs_i then
9699         pr "  int i;\n";
9700
9701       pr "\n";
9702
9703       (* Get the parameters. *)
9704       List.iter (
9705         function
9706         | Pathname n
9707         | Device n | Dev_or_Path n
9708         | String n
9709         | FileIn n
9710         | FileOut n ->
9711             pr "  %s = (*env)->GetStringUTFChars (env, j%s, NULL);\n" n n
9712         | OptString n ->
9713             (* This is completely undocumented, but Java null becomes
9714              * a NULL parameter.
9715              *)
9716             pr "  %s = j%s ? (*env)->GetStringUTFChars (env, j%s, NULL) : NULL;\n" n n n
9717         | StringList n | DeviceList n ->
9718             pr "  %s_len = (*env)->GetArrayLength (env, j%s);\n" n n;
9719             pr "  %s = guestfs_safe_malloc (g, sizeof (char *) * (%s_len+1));\n" n n;
9720             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9721             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9722               n;
9723             pr "    %s[i] = (*env)->GetStringUTFChars (env, o, NULL);\n" n;
9724             pr "  }\n";
9725             pr "  %s[%s_len] = NULL;\n" n n;
9726         | Bool n
9727         | Int n
9728         | Int64 n ->
9729             pr "  %s = j%s;\n" n n
9730       ) (snd style);
9731
9732       (* Make the call. *)
9733       pr "  r = guestfs_%s " name;
9734       generate_c_call_args ~handle:"g" style;
9735       pr ";\n";
9736
9737       (* Release the parameters. *)
9738       List.iter (
9739         function
9740         | Pathname n
9741         | Device n | Dev_or_Path n
9742         | String n
9743         | FileIn n
9744         | FileOut n ->
9745             pr "  (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9746         | OptString n ->
9747             pr "  if (j%s)\n" n;
9748             pr "    (*env)->ReleaseStringUTFChars (env, j%s, %s);\n" n n
9749         | StringList n | DeviceList n ->
9750             pr "  for (i = 0; i < %s_len; ++i) {\n" n;
9751             pr "    jobject o = (*env)->GetObjectArrayElement (env, j%s, i);\n"
9752               n;
9753             pr "    (*env)->ReleaseStringUTFChars (env, o, %s[i]);\n" n;
9754             pr "  }\n";
9755             pr "  free (%s);\n" n
9756         | Bool n
9757         | Int n
9758         | Int64 n -> ()
9759       ) (snd style);
9760
9761       (* Check for errors. *)
9762       pr "  if (r == %s) {\n" error_code;
9763       pr "    throw_exception (env, guestfs_last_error (g));\n";
9764       pr "    return %s;\n" no_ret;
9765       pr "  }\n";
9766
9767       (* Return value. *)
9768       (match fst style with
9769        | RErr -> ()
9770        | RInt _ -> pr "  return (jint) r;\n"
9771        | RBool _ -> pr "  return (jboolean) r;\n"
9772        | RInt64 _ -> pr "  return (jlong) r;\n"
9773        | RConstString _ -> pr "  return (*env)->NewStringUTF (env, r);\n"
9774        | RConstOptString _ ->
9775            pr "  return (*env)->NewStringUTF (env, r); /* XXX r NULL? */\n"
9776        | RString _ ->
9777            pr "  jr = (*env)->NewStringUTF (env, r);\n";
9778            pr "  free (r);\n";
9779            pr "  return jr;\n"
9780        | RStringList _ ->
9781            pr "  for (r_len = 0; r[r_len] != NULL; ++r_len) ;\n";
9782            pr "  cl = (*env)->FindClass (env, \"java/lang/String\");\n";
9783            pr "  jstr = (*env)->NewStringUTF (env, \"\");\n";
9784            pr "  jr = (*env)->NewObjectArray (env, r_len, cl, jstr);\n";
9785            pr "  for (i = 0; i < r_len; ++i) {\n";
9786            pr "    jstr = (*env)->NewStringUTF (env, r[i]);\n";
9787            pr "    (*env)->SetObjectArrayElement (env, jr, i, jstr);\n";
9788            pr "    free (r[i]);\n";
9789            pr "  }\n";
9790            pr "  free (r);\n";
9791            pr "  return jr;\n"
9792        | RStruct (_, typ) ->
9793            let jtyp = java_name_of_struct typ in
9794            let cols = cols_of_struct typ in
9795            generate_java_struct_return typ jtyp cols
9796        | RStructList (_, typ) ->
9797            let jtyp = java_name_of_struct typ in
9798            let cols = cols_of_struct typ in
9799            generate_java_struct_list_return typ jtyp cols
9800        | RHashtable _ ->
9801            (* XXX *)
9802            pr "  throw_exception (env, \"%s: internal error: please let us know how to make a Java HashMap from JNI bindings!\");\n" name;
9803            pr "  return NULL;\n"
9804        | RBufferOut _ ->
9805            pr "  jr = (*env)->NewStringUTF (env, r); /* XXX size */\n";
9806            pr "  free (r);\n";
9807            pr "  return jr;\n"
9808       );
9809
9810       pr "}\n";
9811       pr "\n"
9812   ) all_functions
9813
9814 and generate_java_struct_return typ jtyp cols =
9815   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9816   pr "  jr = (*env)->AllocObject (env, cl);\n";
9817   List.iter (
9818     function
9819     | name, FString ->
9820         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9821         pr "  (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, r->%s));\n" name;
9822     | name, FUUID ->
9823         pr "  {\n";
9824         pr "    char s[33];\n";
9825         pr "    memcpy (s, r->%s, 32);\n" name;
9826         pr "    s[32] = 0;\n";
9827         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9828         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9829         pr "  }\n";
9830     | name, FBuffer ->
9831         pr "  {\n";
9832         pr "    int len = r->%s_len;\n" name;
9833         pr "    char s[len+1];\n";
9834         pr "    memcpy (s, r->%s, len);\n" name;
9835         pr "    s[len] = 0;\n";
9836         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9837         pr "    (*env)->SetObjectField (env, jr, fl, (*env)->NewStringUTF (env, s));\n";
9838         pr "  }\n";
9839     | name, (FBytes|FUInt64|FInt64) ->
9840         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9841         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9842     | name, (FUInt32|FInt32) ->
9843         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9844         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9845     | name, FOptPercent ->
9846         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9847         pr "  (*env)->SetFloatField (env, jr, fl, r->%s);\n" name;
9848     | name, FChar ->
9849         pr "  fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9850         pr "  (*env)->SetLongField (env, jr, fl, r->%s);\n" name;
9851   ) cols;
9852   pr "  free (r);\n";
9853   pr "  return jr;\n"
9854
9855 and generate_java_struct_list_return typ jtyp cols =
9856   pr "  cl = (*env)->FindClass (env, \"com/redhat/et/libguestfs/%s\");\n" jtyp;
9857   pr "  jr = (*env)->NewObjectArray (env, r->len, cl, NULL);\n";
9858   pr "  for (i = 0; i < r->len; ++i) {\n";
9859   pr "    jfl = (*env)->AllocObject (env, cl);\n";
9860   List.iter (
9861     function
9862     | name, FString ->
9863         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9864         pr "    (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, r->val[i].%s));\n" name;
9865     | name, FUUID ->
9866         pr "    {\n";
9867         pr "      char s[33];\n";
9868         pr "      memcpy (s, r->val[i].%s, 32);\n" name;
9869         pr "      s[32] = 0;\n";
9870         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9871         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9872         pr "    }\n";
9873     | name, FBuffer ->
9874         pr "    {\n";
9875         pr "      int len = r->val[i].%s_len;\n" name;
9876         pr "      char s[len+1];\n";
9877         pr "      memcpy (s, r->val[i].%s, len);\n" name;
9878         pr "      s[len] = 0;\n";
9879         pr "      fl = (*env)->GetFieldID (env, cl, \"%s\", \"Ljava/lang/String;\");\n" name;
9880         pr "      (*env)->SetObjectField (env, jfl, fl, (*env)->NewStringUTF (env, s));\n";
9881         pr "    }\n";
9882     | name, (FBytes|FUInt64|FInt64) ->
9883         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"J\");\n" name;
9884         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9885     | name, (FUInt32|FInt32) ->
9886         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"I\");\n" name;
9887         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9888     | name, FOptPercent ->
9889         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"F\");\n" name;
9890         pr "    (*env)->SetFloatField (env, jfl, fl, r->val[i].%s);\n" name;
9891     | name, FChar ->
9892         pr "    fl = (*env)->GetFieldID (env, cl, \"%s\", \"C\");\n" name;
9893         pr "    (*env)->SetLongField (env, jfl, fl, r->val[i].%s);\n" name;
9894   ) cols;
9895   pr "    (*env)->SetObjectArrayElement (env, jfl, i, jfl);\n";
9896   pr "  }\n";
9897   pr "  guestfs_free_%s_list (r);\n" typ;
9898   pr "  return jr;\n"
9899
9900 and generate_java_makefile_inc () =
9901   generate_header HashStyle GPLv2plus;
9902
9903   pr "java_built_sources = \\\n";
9904   List.iter (
9905     fun (typ, jtyp) ->
9906         pr "\tcom/redhat/et/libguestfs/%s.java \\\n" jtyp;
9907   ) java_structs;
9908   pr "\tcom/redhat/et/libguestfs/GuestFS.java\n"
9909
9910 and generate_haskell_hs () =
9911   generate_header HaskellStyle LGPLv2plus;
9912
9913   (* XXX We only know how to generate partial FFI for Haskell
9914    * at the moment.  Please help out!
9915    *)
9916   let can_generate style =
9917     match style with
9918     | RErr, _
9919     | RInt _, _
9920     | RInt64 _, _ -> true
9921     | RBool _, _
9922     | RConstString _, _
9923     | RConstOptString _, _
9924     | RString _, _
9925     | RStringList _, _
9926     | RStruct _, _
9927     | RStructList _, _
9928     | RHashtable _, _
9929     | RBufferOut _, _ -> false in
9930
9931   pr "\
9932 {-# INCLUDE <guestfs.h> #-}
9933 {-# LANGUAGE ForeignFunctionInterface #-}
9934
9935 module Guestfs (
9936   create";
9937
9938   (* List out the names of the actions we want to export. *)
9939   List.iter (
9940     fun (name, style, _, _, _, _, _) ->
9941       if can_generate style then pr ",\n  %s" name
9942   ) all_functions;
9943
9944   pr "
9945   ) where
9946
9947 -- Unfortunately some symbols duplicate ones already present
9948 -- in Prelude.  We don't know which, so we hard-code a list
9949 -- here.
9950 import Prelude hiding (truncate)
9951
9952 import Foreign
9953 import Foreign.C
9954 import Foreign.C.Types
9955 import IO
9956 import Control.Exception
9957 import Data.Typeable
9958
9959 data GuestfsS = GuestfsS            -- represents the opaque C struct
9960 type GuestfsP = Ptr GuestfsS        -- guestfs_h *
9961 type GuestfsH = ForeignPtr GuestfsS -- guestfs_h * with attached finalizer
9962
9963 -- XXX define properly later XXX
9964 data PV = PV
9965 data VG = VG
9966 data LV = LV
9967 data IntBool = IntBool
9968 data Stat = Stat
9969 data StatVFS = StatVFS
9970 data Hashtable = Hashtable
9971
9972 foreign import ccall unsafe \"guestfs_create\" c_create
9973   :: IO GuestfsP
9974 foreign import ccall unsafe \"&guestfs_close\" c_close
9975   :: FunPtr (GuestfsP -> IO ())
9976 foreign import ccall unsafe \"guestfs_set_error_handler\" c_set_error_handler
9977   :: GuestfsP -> Ptr CInt -> Ptr CInt -> IO ()
9978
9979 create :: IO GuestfsH
9980 create = do
9981   p <- c_create
9982   c_set_error_handler p nullPtr nullPtr
9983   h <- newForeignPtr c_close p
9984   return h
9985
9986 foreign import ccall unsafe \"guestfs_last_error\" c_last_error
9987   :: GuestfsP -> IO CString
9988
9989 -- last_error :: GuestfsH -> IO (Maybe String)
9990 -- last_error h = do
9991 --   str <- withForeignPtr h (\\p -> c_last_error p)
9992 --   maybePeek peekCString str
9993
9994 last_error :: GuestfsH -> IO (String)
9995 last_error h = do
9996   str <- withForeignPtr h (\\p -> c_last_error p)
9997   if (str == nullPtr)
9998     then return \"no error\"
9999     else peekCString str
10000
10001 ";
10002
10003   (* Generate wrappers for each foreign function. *)
10004   List.iter (
10005     fun (name, style, _, _, _, _, _) ->
10006       if can_generate style then (
10007         pr "foreign import ccall unsafe \"guestfs_%s\" c_%s\n" name name;
10008         pr "  :: ";
10009         generate_haskell_prototype ~handle:"GuestfsP" style;
10010         pr "\n";
10011         pr "\n";
10012         pr "%s :: " name;
10013         generate_haskell_prototype ~handle:"GuestfsH" ~hs:true style;
10014         pr "\n";
10015         pr "%s %s = do\n" name
10016           (String.concat " " ("h" :: List.map name_of_argt (snd style)));
10017         pr "  r <- ";
10018         (* Convert pointer arguments using with* functions. *)
10019         List.iter (
10020           function
10021           | FileIn n
10022           | FileOut n
10023           | Pathname n | Device n | Dev_or_Path n | String n -> pr "withCString %s $ \\%s -> " n n
10024           | OptString n -> pr "maybeWith withCString %s $ \\%s -> " n n
10025           | StringList n | DeviceList n -> pr "withMany withCString %s $ \\%s -> withArray0 nullPtr %s $ \\%s -> " n n n n
10026           | Bool _ | Int _ | Int64 _ -> ()
10027         ) (snd style);
10028         (* Convert integer arguments. *)
10029         let args =
10030           List.map (
10031             function
10032             | Bool n -> sprintf "(fromBool %s)" n
10033             | Int n -> sprintf "(fromIntegral %s)" n
10034             | Int64 n -> sprintf "(fromIntegral %s)" n
10035             | FileIn n | FileOut n
10036             | Pathname n | Device n | Dev_or_Path n | String n | OptString n | StringList n | DeviceList n -> n
10037           ) (snd style) in
10038         pr "withForeignPtr h (\\p -> c_%s %s)\n" name
10039           (String.concat " " ("p" :: args));
10040         (match fst style with
10041          | RErr | RInt _ | RInt64 _ | RBool _ ->
10042              pr "  if (r == -1)\n";
10043              pr "    then do\n";
10044              pr "      err <- last_error h\n";
10045              pr "      fail err\n";
10046          | RConstString _ | RConstOptString _ | RString _
10047          | RStringList _ | RStruct _
10048          | RStructList _ | RHashtable _ | RBufferOut _ ->
10049              pr "  if (r == nullPtr)\n";
10050              pr "    then do\n";
10051              pr "      err <- last_error h\n";
10052              pr "      fail err\n";
10053         );
10054         (match fst style with
10055          | RErr ->
10056              pr "    else return ()\n"
10057          | RInt _ ->
10058              pr "    else return (fromIntegral r)\n"
10059          | RInt64 _ ->
10060              pr "    else return (fromIntegral r)\n"
10061          | RBool _ ->
10062              pr "    else return (toBool r)\n"
10063          | RConstString _
10064          | RConstOptString _
10065          | RString _
10066          | RStringList _
10067          | RStruct _
10068          | RStructList _
10069          | RHashtable _
10070          | RBufferOut _ ->
10071              pr "    else return ()\n" (* XXXXXXXXXXXXXXXXXXXX *)
10072         );
10073         pr "\n";
10074       )
10075   ) all_functions
10076
10077 and generate_haskell_prototype ~handle ?(hs = false) style =
10078   pr "%s -> " handle;
10079   let string = if hs then "String" else "CString" in
10080   let int = if hs then "Int" else "CInt" in
10081   let bool = if hs then "Bool" else "CInt" in
10082   let int64 = if hs then "Integer" else "Int64" in
10083   List.iter (
10084     fun arg ->
10085       (match arg with
10086        | Pathname _ | Device _ | Dev_or_Path _ | String _ -> pr "%s" string
10087        | OptString _ -> if hs then pr "Maybe String" else pr "CString"
10088        | StringList _ | DeviceList _ -> if hs then pr "[String]" else pr "Ptr CString"
10089        | Bool _ -> pr "%s" bool
10090        | Int _ -> pr "%s" int
10091        | Int64 _ -> pr "%s" int
10092        | FileIn _ -> pr "%s" string
10093        | FileOut _ -> pr "%s" string
10094       );
10095       pr " -> ";
10096   ) (snd style);
10097   pr "IO (";
10098   (match fst style with
10099    | RErr -> if not hs then pr "CInt"
10100    | RInt _ -> pr "%s" int
10101    | RInt64 _ -> pr "%s" int64
10102    | RBool _ -> pr "%s" bool
10103    | RConstString _ -> pr "%s" string
10104    | RConstOptString _ -> pr "Maybe %s" string
10105    | RString _ -> pr "%s" string
10106    | RStringList _ -> pr "[%s]" string
10107    | RStruct (_, typ) ->
10108        let name = java_name_of_struct typ in
10109        pr "%s" name
10110    | RStructList (_, typ) ->
10111        let name = java_name_of_struct typ in
10112        pr "[%s]" name
10113    | RHashtable _ -> pr "Hashtable"
10114    | RBufferOut _ -> pr "%s" string
10115   );
10116   pr ")"
10117
10118 and generate_csharp () =
10119   generate_header CPlusPlusStyle LGPLv2plus;
10120
10121   (* XXX Make this configurable by the C# assembly users. *)
10122   let library = "libguestfs.so.0" in
10123
10124   pr "\
10125 // These C# bindings are highly experimental at present.
10126 //
10127 // Firstly they only work on Linux (ie. Mono).  In order to get them
10128 // to work on Windows (ie. .Net) you would need to port the library
10129 // itself to Windows first.
10130 //
10131 // The second issue is that some calls are known to be incorrect and
10132 // can cause Mono to segfault.  Particularly: calls which pass or
10133 // return string[], or return any structure value.  This is because
10134 // we haven't worked out the correct way to do this from C#.
10135 //
10136 // The third issue is that when compiling you get a lot of warnings.
10137 // We are not sure whether the warnings are important or not.
10138 //
10139 // Fourthly we do not routinely build or test these bindings as part
10140 // of the make && make check cycle, which means that regressions might
10141 // go unnoticed.
10142 //
10143 // Suggestions and patches are welcome.
10144
10145 // To compile:
10146 //
10147 // gmcs Libguestfs.cs
10148 // mono Libguestfs.exe
10149 //
10150 // (You'll probably want to add a Test class / static main function
10151 // otherwise this won't do anything useful).
10152
10153 using System;
10154 using System.IO;
10155 using System.Runtime.InteropServices;
10156 using System.Runtime.Serialization;
10157 using System.Collections;
10158
10159 namespace Guestfs
10160 {
10161   class Error : System.ApplicationException
10162   {
10163     public Error (string message) : base (message) {}
10164     protected Error (SerializationInfo info, StreamingContext context) {}
10165   }
10166
10167   class Guestfs
10168   {
10169     IntPtr _handle;
10170
10171     [DllImport (\"%s\")]
10172     static extern IntPtr guestfs_create ();
10173
10174     public Guestfs ()
10175     {
10176       _handle = guestfs_create ();
10177       if (_handle == IntPtr.Zero)
10178         throw new Error (\"could not create guestfs handle\");
10179     }
10180
10181     [DllImport (\"%s\")]
10182     static extern void guestfs_close (IntPtr h);
10183
10184     ~Guestfs ()
10185     {
10186       guestfs_close (_handle);
10187     }
10188
10189     [DllImport (\"%s\")]
10190     static extern string guestfs_last_error (IntPtr h);
10191
10192 " library library library;
10193
10194   (* Generate C# structure bindings.  We prefix struct names with
10195    * underscore because C# cannot have conflicting struct names and
10196    * method names (eg. "class stat" and "stat").
10197    *)
10198   List.iter (
10199     fun (typ, cols) ->
10200       pr "    [StructLayout (LayoutKind.Sequential)]\n";
10201       pr "    public class _%s {\n" typ;
10202       List.iter (
10203         function
10204         | name, FChar -> pr "      char %s;\n" name
10205         | name, FString -> pr "      string %s;\n" name
10206         | name, FBuffer ->
10207             pr "      uint %s_len;\n" name;
10208             pr "      string %s;\n" name
10209         | name, FUUID ->
10210             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
10211             pr "      string %s;\n" name
10212         | name, FUInt32 -> pr "      uint %s;\n" name
10213         | name, FInt32 -> pr "      int %s;\n" name
10214         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
10215         | name, FInt64 -> pr "      long %s;\n" name
10216         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
10217       ) cols;
10218       pr "    }\n";
10219       pr "\n"
10220   ) structs;
10221
10222   (* Generate C# function bindings. *)
10223   List.iter (
10224     fun (name, style, _, _, _, shortdesc, _) ->
10225       let rec csharp_return_type () =
10226         match fst style with
10227         | RErr -> "void"
10228         | RBool n -> "bool"
10229         | RInt n -> "int"
10230         | RInt64 n -> "long"
10231         | RConstString n
10232         | RConstOptString n
10233         | RString n
10234         | RBufferOut n -> "string"
10235         | RStruct (_,n) -> "_" ^ n
10236         | RHashtable n -> "Hashtable"
10237         | RStringList n -> "string[]"
10238         | RStructList (_,n) -> sprintf "_%s[]" n
10239
10240       and c_return_type () =
10241         match fst style with
10242         | RErr
10243         | RBool _
10244         | RInt _ -> "int"
10245         | RInt64 _ -> "long"
10246         | RConstString _
10247         | RConstOptString _
10248         | RString _
10249         | RBufferOut _ -> "string"
10250         | RStruct (_,n) -> "_" ^ n
10251         | RHashtable _
10252         | RStringList _ -> "string[]"
10253         | RStructList (_,n) -> sprintf "_%s[]" n
10254     
10255       and c_error_comparison () =
10256         match fst style with
10257         | RErr
10258         | RBool _
10259         | RInt _
10260         | RInt64 _ -> "== -1"
10261         | RConstString _
10262         | RConstOptString _
10263         | RString _
10264         | RBufferOut _
10265         | RStruct (_,_)
10266         | RHashtable _
10267         | RStringList _
10268         | RStructList (_,_) -> "== null"
10269     
10270       and generate_extern_prototype () =
10271         pr "    static extern %s guestfs_%s (IntPtr h"
10272           (c_return_type ()) name;
10273         List.iter (
10274           function
10275           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10276           | FileIn n | FileOut n ->
10277               pr ", [In] string %s" n
10278           | StringList n | DeviceList n ->
10279               pr ", [In] string[] %s" n
10280           | Bool n ->
10281               pr ", bool %s" n
10282           | Int n ->
10283               pr ", int %s" n
10284           | Int64 n ->
10285               pr ", long %s" n
10286         ) (snd style);
10287         pr ");\n"
10288
10289       and generate_public_prototype () =
10290         pr "    public %s %s (" (csharp_return_type ()) name;
10291         let comma = ref false in
10292         let next () =
10293           if !comma then pr ", ";
10294           comma := true
10295         in
10296         List.iter (
10297           function
10298           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
10299           | FileIn n | FileOut n ->
10300               next (); pr "string %s" n
10301           | StringList n | DeviceList n ->
10302               next (); pr "string[] %s" n
10303           | Bool n ->
10304               next (); pr "bool %s" n
10305           | Int n ->
10306               next (); pr "int %s" n
10307           | Int64 n ->
10308               next (); pr "long %s" n
10309         ) (snd style);
10310         pr ")\n"
10311
10312       and generate_call () =
10313         pr "guestfs_%s (_handle" name;
10314         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
10315         pr ");\n";
10316       in
10317
10318       pr "    [DllImport (\"%s\")]\n" library;
10319       generate_extern_prototype ();
10320       pr "\n";
10321       pr "    /// <summary>\n";
10322       pr "    /// %s\n" shortdesc;
10323       pr "    /// </summary>\n";
10324       generate_public_prototype ();
10325       pr "    {\n";
10326       pr "      %s r;\n" (c_return_type ());
10327       pr "      r = ";
10328       generate_call ();
10329       pr "      if (r %s)\n" (c_error_comparison ());
10330       pr "        throw new Error (guestfs_last_error (_handle));\n";
10331       (match fst style with
10332        | RErr -> ()
10333        | RBool _ ->
10334            pr "      return r != 0 ? true : false;\n"
10335        | RHashtable _ ->
10336            pr "      Hashtable rr = new Hashtable ();\n";
10337            pr "      for (int i = 0; i < r.Length; i += 2)\n";
10338            pr "        rr.Add (r[i], r[i+1]);\n";
10339            pr "      return rr;\n"
10340        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
10341        | RString _ | RBufferOut _ | RStruct _ | RStringList _
10342        | RStructList _ ->
10343            pr "      return r;\n"
10344       );
10345       pr "    }\n";
10346       pr "\n";
10347   ) all_functions_sorted;
10348
10349   pr "  }
10350 }
10351 "
10352
10353 and generate_bindtests () =
10354   generate_header CStyle LGPLv2plus;
10355
10356   pr "\
10357 #include <stdio.h>
10358 #include <stdlib.h>
10359 #include <inttypes.h>
10360 #include <string.h>
10361
10362 #include \"guestfs.h\"
10363 #include \"guestfs-internal.h\"
10364 #include \"guestfs-internal-actions.h\"
10365 #include \"guestfs_protocol.h\"
10366
10367 #define error guestfs_error
10368 #define safe_calloc guestfs_safe_calloc
10369 #define safe_malloc guestfs_safe_malloc
10370
10371 static void
10372 print_strings (char *const *argv)
10373 {
10374   int argc;
10375
10376   printf (\"[\");
10377   for (argc = 0; argv[argc] != NULL; ++argc) {
10378     if (argc > 0) printf (\", \");
10379     printf (\"\\\"%%s\\\"\", argv[argc]);
10380   }
10381   printf (\"]\\n\");
10382 }
10383
10384 /* The test0 function prints its parameters to stdout. */
10385 ";
10386
10387   let test0, tests =
10388     match test_functions with
10389     | [] -> assert false
10390     | test0 :: tests -> test0, tests in
10391
10392   let () =
10393     let (name, style, _, _, _, _, _) = test0 in
10394     generate_prototype ~extern:false ~semicolon:false ~newline:true
10395       ~handle:"g" ~prefix:"guestfs__" name style;
10396     pr "{\n";
10397     List.iter (
10398       function
10399       | Pathname n
10400       | Device n | Dev_or_Path n
10401       | String n
10402       | FileIn n
10403       | FileOut n -> pr "  printf (\"%%s\\n\", %s);\n" n
10404       | OptString n -> pr "  printf (\"%%s\\n\", %s ? %s : \"null\");\n" n n
10405       | StringList n | DeviceList n -> pr "  print_strings (%s);\n" n
10406       | Bool n -> pr "  printf (\"%%s\\n\", %s ? \"true\" : \"false\");\n" n
10407       | Int n -> pr "  printf (\"%%d\\n\", %s);\n" n
10408       | Int64 n -> pr "  printf (\"%%\" PRIi64 \"\\n\", %s);\n" n
10409     ) (snd style);
10410     pr "  /* Java changes stdout line buffering so we need this: */\n";
10411     pr "  fflush (stdout);\n";
10412     pr "  return 0;\n";
10413     pr "}\n";
10414     pr "\n" in
10415
10416   List.iter (
10417     fun (name, style, _, _, _, _, _) ->
10418       if String.sub name (String.length name - 3) 3 <> "err" then (
10419         pr "/* Test normal return. */\n";
10420         generate_prototype ~extern:false ~semicolon:false ~newline:true
10421           ~handle:"g" ~prefix:"guestfs__" name style;
10422         pr "{\n";
10423         (match fst style with
10424          | RErr ->
10425              pr "  return 0;\n"
10426          | RInt _ ->
10427              pr "  int r;\n";
10428              pr "  sscanf (val, \"%%d\", &r);\n";
10429              pr "  return r;\n"
10430          | RInt64 _ ->
10431              pr "  int64_t r;\n";
10432              pr "  sscanf (val, \"%%\" SCNi64, &r);\n";
10433              pr "  return r;\n"
10434          | RBool _ ->
10435              pr "  return STREQ (val, \"true\");\n"
10436          | RConstString _
10437          | RConstOptString _ ->
10438              (* Can't return the input string here.  Return a static
10439               * string so we ensure we get a segfault if the caller
10440               * tries to free it.
10441               *)
10442              pr "  return \"static string\";\n"
10443          | RString _ ->
10444              pr "  return strdup (val);\n"
10445          | RStringList _ ->
10446              pr "  char **strs;\n";
10447              pr "  int n, i;\n";
10448              pr "  sscanf (val, \"%%d\", &n);\n";
10449              pr "  strs = safe_malloc (g, (n+1) * sizeof (char *));\n";
10450              pr "  for (i = 0; i < n; ++i) {\n";
10451              pr "    strs[i] = safe_malloc (g, 16);\n";
10452              pr "    snprintf (strs[i], 16, \"%%d\", i);\n";
10453              pr "  }\n";
10454              pr "  strs[n] = NULL;\n";
10455              pr "  return strs;\n"
10456          | RStruct (_, typ) ->
10457              pr "  struct guestfs_%s *r;\n" typ;
10458              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10459              pr "  return r;\n"
10460          | RStructList (_, typ) ->
10461              pr "  struct guestfs_%s_list *r;\n" typ;
10462              pr "  r = safe_calloc (g, sizeof *r, 1);\n";
10463              pr "  sscanf (val, \"%%d\", &r->len);\n";
10464              pr "  r->val = safe_calloc (g, r->len, sizeof *r->val);\n";
10465              pr "  return r;\n"
10466          | RHashtable _ ->
10467              pr "  char **strs;\n";
10468              pr "  int n, i;\n";
10469              pr "  sscanf (val, \"%%d\", &n);\n";
10470              pr "  strs = safe_malloc (g, (n*2+1) * sizeof (*strs));\n";
10471              pr "  for (i = 0; i < n; ++i) {\n";
10472              pr "    strs[i*2] = safe_malloc (g, 16);\n";
10473              pr "    strs[i*2+1] = safe_malloc (g, 16);\n";
10474              pr "    snprintf (strs[i*2], 16, \"%%d\", i);\n";
10475              pr "    snprintf (strs[i*2+1], 16, \"%%d\", i);\n";
10476              pr "  }\n";
10477              pr "  strs[n*2] = NULL;\n";
10478              pr "  return strs;\n"
10479          | RBufferOut _ ->
10480              pr "  return strdup (val);\n"
10481         );
10482         pr "}\n";
10483         pr "\n"
10484       ) else (
10485         pr "/* Test error return. */\n";
10486         generate_prototype ~extern:false ~semicolon:false ~newline:true
10487           ~handle:"g" ~prefix:"guestfs__" name style;
10488         pr "{\n";
10489         pr "  error (g, \"error\");\n";
10490         (match fst style with
10491          | RErr | RInt _ | RInt64 _ | RBool _ ->
10492              pr "  return -1;\n"
10493          | RConstString _ | RConstOptString _
10494          | RString _ | RStringList _ | RStruct _
10495          | RStructList _
10496          | RHashtable _
10497          | RBufferOut _ ->
10498              pr "  return NULL;\n"
10499         );
10500         pr "}\n";
10501         pr "\n"
10502       )
10503   ) tests
10504
10505 and generate_ocaml_bindtests () =
10506   generate_header OCamlStyle GPLv2plus;
10507
10508   pr "\
10509 let () =
10510   let g = Guestfs.create () in
10511 ";
10512
10513   let mkargs args =
10514     String.concat " " (
10515       List.map (
10516         function
10517         | CallString s -> "\"" ^ s ^ "\""
10518         | CallOptString None -> "None"
10519         | CallOptString (Some s) -> sprintf "(Some \"%s\")" s
10520         | CallStringList xs ->
10521             "[|" ^ String.concat ";" (List.map (sprintf "\"%s\"") xs) ^ "|]"
10522         | CallInt i when i >= 0 -> string_of_int i
10523         | CallInt i (* when i < 0 *) -> "(" ^ string_of_int i ^ ")"
10524         | CallInt64 i when i >= 0L -> Int64.to_string i ^ "L"
10525         | CallInt64 i (* when i < 0L *) -> "(" ^ Int64.to_string i ^ "L)"
10526         | CallBool b -> string_of_bool b
10527       ) args
10528     )
10529   in
10530
10531   generate_lang_bindtests (
10532     fun f args -> pr "  Guestfs.%s g %s;\n" f (mkargs args)
10533   );
10534
10535   pr "print_endline \"EOF\"\n"
10536
10537 and generate_perl_bindtests () =
10538   pr "#!/usr/bin/perl -w\n";
10539   generate_header HashStyle GPLv2plus;
10540
10541   pr "\
10542 use strict;
10543
10544 use Sys::Guestfs;
10545
10546 my $g = Sys::Guestfs->new ();
10547 ";
10548
10549   let mkargs args =
10550     String.concat ", " (
10551       List.map (
10552         function
10553         | CallString s -> "\"" ^ s ^ "\""
10554         | CallOptString None -> "undef"
10555         | CallOptString (Some s) -> sprintf "\"%s\"" s
10556         | CallStringList xs ->
10557             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10558         | CallInt i -> string_of_int i
10559         | CallInt64 i -> Int64.to_string i
10560         | CallBool b -> if b then "1" else "0"
10561       ) args
10562     )
10563   in
10564
10565   generate_lang_bindtests (
10566     fun f args -> pr "$g->%s (%s);\n" f (mkargs args)
10567   );
10568
10569   pr "print \"EOF\\n\"\n"
10570
10571 and generate_python_bindtests () =
10572   generate_header HashStyle GPLv2plus;
10573
10574   pr "\
10575 import guestfs
10576
10577 g = guestfs.GuestFS ()
10578 ";
10579
10580   let mkargs args =
10581     String.concat ", " (
10582       List.map (
10583         function
10584         | CallString s -> "\"" ^ s ^ "\""
10585         | CallOptString None -> "None"
10586         | CallOptString (Some s) -> sprintf "\"%s\"" s
10587         | CallStringList xs ->
10588             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10589         | CallInt i -> string_of_int i
10590         | CallInt64 i -> Int64.to_string i
10591         | CallBool b -> if b then "1" else "0"
10592       ) args
10593     )
10594   in
10595
10596   generate_lang_bindtests (
10597     fun f args -> pr "g.%s (%s)\n" f (mkargs args)
10598   );
10599
10600   pr "print \"EOF\"\n"
10601
10602 and generate_ruby_bindtests () =
10603   generate_header HashStyle GPLv2plus;
10604
10605   pr "\
10606 require 'guestfs'
10607
10608 g = Guestfs::create()
10609 ";
10610
10611   let mkargs args =
10612     String.concat ", " (
10613       List.map (
10614         function
10615         | CallString s -> "\"" ^ s ^ "\""
10616         | CallOptString None -> "nil"
10617         | CallOptString (Some s) -> sprintf "\"%s\"" s
10618         | CallStringList xs ->
10619             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10620         | CallInt i -> string_of_int i
10621         | CallInt64 i -> Int64.to_string i
10622         | CallBool b -> string_of_bool b
10623       ) args
10624     )
10625   in
10626
10627   generate_lang_bindtests (
10628     fun f args -> pr "g.%s(%s)\n" f (mkargs args)
10629   );
10630
10631   pr "print \"EOF\\n\"\n"
10632
10633 and generate_java_bindtests () =
10634   generate_header CStyle GPLv2plus;
10635
10636   pr "\
10637 import com.redhat.et.libguestfs.*;
10638
10639 public class Bindtests {
10640     public static void main (String[] argv)
10641     {
10642         try {
10643             GuestFS g = new GuestFS ();
10644 ";
10645
10646   let mkargs args =
10647     String.concat ", " (
10648       List.map (
10649         function
10650         | CallString s -> "\"" ^ s ^ "\""
10651         | CallOptString None -> "null"
10652         | CallOptString (Some s) -> sprintf "\"%s\"" s
10653         | CallStringList xs ->
10654             "new String[]{" ^
10655               String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "}"
10656         | CallInt i -> string_of_int i
10657         | CallInt64 i -> Int64.to_string i
10658         | CallBool b -> string_of_bool b
10659       ) args
10660     )
10661   in
10662
10663   generate_lang_bindtests (
10664     fun f args -> pr "            g.%s (%s);\n" f (mkargs args)
10665   );
10666
10667   pr "
10668             System.out.println (\"EOF\");
10669         }
10670         catch (Exception exn) {
10671             System.err.println (exn);
10672             System.exit (1);
10673         }
10674     }
10675 }
10676 "
10677
10678 and generate_haskell_bindtests () =
10679   generate_header HaskellStyle GPLv2plus;
10680
10681   pr "\
10682 module Bindtests where
10683 import qualified Guestfs
10684
10685 main = do
10686   g <- Guestfs.create
10687 ";
10688
10689   let mkargs args =
10690     String.concat " " (
10691       List.map (
10692         function
10693         | CallString s -> "\"" ^ s ^ "\""
10694         | CallOptString None -> "Nothing"
10695         | CallOptString (Some s) -> sprintf "(Just \"%s\")" s
10696         | CallStringList xs ->
10697             "[" ^ String.concat "," (List.map (sprintf "\"%s\"") xs) ^ "]"
10698         | CallInt i when i < 0 -> "(" ^ string_of_int i ^ ")"
10699         | CallInt i -> string_of_int i
10700         | CallInt64 i when i < 0L -> "(" ^ Int64.to_string i ^ ")"
10701         | CallInt64 i -> Int64.to_string i
10702         | CallBool true -> "True"
10703         | CallBool false -> "False"
10704       ) args
10705     )
10706   in
10707
10708   generate_lang_bindtests (
10709     fun f args -> pr "  Guestfs.%s g %s\n" f (mkargs args)
10710   );
10711
10712   pr "  putStrLn \"EOF\"\n"
10713
10714 (* Language-independent bindings tests - we do it this way to
10715  * ensure there is parity in testing bindings across all languages.
10716  *)
10717 and generate_lang_bindtests call =
10718   call "test0" [CallString "abc"; CallOptString (Some "def");
10719                 CallStringList []; CallBool false;
10720                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10721   call "test0" [CallString "abc"; CallOptString None;
10722                 CallStringList []; CallBool false;
10723                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10724   call "test0" [CallString ""; CallOptString (Some "def");
10725                 CallStringList []; CallBool false;
10726                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10727   call "test0" [CallString ""; CallOptString (Some "");
10728                 CallStringList []; CallBool false;
10729                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10730   call "test0" [CallString "abc"; CallOptString (Some "def");
10731                 CallStringList ["1"]; CallBool false;
10732                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10733   call "test0" [CallString "abc"; CallOptString (Some "def");
10734                 CallStringList ["1"; "2"]; CallBool false;
10735                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10736   call "test0" [CallString "abc"; CallOptString (Some "def");
10737                 CallStringList ["1"]; CallBool true;
10738                 CallInt 0; CallInt64 0L; CallString "123"; CallString "456"];
10739   call "test0" [CallString "abc"; CallOptString (Some "def");
10740                 CallStringList ["1"]; CallBool false;
10741                 CallInt (-1); CallInt64 (-1L); CallString "123"; CallString "456"];
10742   call "test0" [CallString "abc"; CallOptString (Some "def");
10743                 CallStringList ["1"]; CallBool false;
10744                 CallInt (-2); CallInt64 (-2L); CallString "123"; CallString "456"];
10745   call "test0" [CallString "abc"; CallOptString (Some "def");
10746                 CallStringList ["1"]; CallBool false;
10747                 CallInt 1; CallInt64 1L; CallString "123"; CallString "456"];
10748   call "test0" [CallString "abc"; CallOptString (Some "def");
10749                 CallStringList ["1"]; CallBool false;
10750                 CallInt 2; CallInt64 2L; CallString "123"; CallString "456"];
10751   call "test0" [CallString "abc"; CallOptString (Some "def");
10752                 CallStringList ["1"]; CallBool false;
10753                 CallInt 4095; CallInt64 4095L; CallString "123"; CallString "456"];
10754   call "test0" [CallString "abc"; CallOptString (Some "def");
10755                 CallStringList ["1"]; CallBool false;
10756                 CallInt 0; CallInt64 0L; CallString ""; CallString ""]
10757
10758 (* XXX Add here tests of the return and error functions. *)
10759
10760 (* Code to generator bindings for virt-inspector.  Currently only
10761  * implemented for OCaml code (for virt-p2v 2.0).
10762  *)
10763 let rng_input = "inspector/virt-inspector.rng"
10764
10765 (* Read the input file and parse it into internal structures.  This is
10766  * by no means a complete RELAX NG parser, but is just enough to be
10767  * able to parse the specific input file.
10768  *)
10769 type rng =
10770   | Element of string * rng list        (* <element name=name/> *)
10771   | Attribute of string * rng list        (* <attribute name=name/> *)
10772   | Interleave of rng list                (* <interleave/> *)
10773   | ZeroOrMore of rng                        (* <zeroOrMore/> *)
10774   | OneOrMore of rng                        (* <oneOrMore/> *)
10775   | Optional of rng                        (* <optional/> *)
10776   | Choice of string list                (* <choice><value/>*</choice> *)
10777   | Value of string                        (* <value>str</value> *)
10778   | Text                                (* <text/> *)
10779
10780 let rec string_of_rng = function
10781   | Element (name, xs) ->
10782       "Element (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10783   | Attribute (name, xs) ->
10784       "Attribute (\"" ^ name ^ "\", (" ^ string_of_rng_list xs ^ "))"
10785   | Interleave xs -> "Interleave (" ^ string_of_rng_list xs ^ ")"
10786   | ZeroOrMore rng -> "ZeroOrMore (" ^ string_of_rng rng ^ ")"
10787   | OneOrMore rng -> "OneOrMore (" ^ string_of_rng rng ^ ")"
10788   | Optional rng -> "Optional (" ^ string_of_rng rng ^ ")"
10789   | Choice values -> "Choice [" ^ String.concat ", " values ^ "]"
10790   | Value value -> "Value \"" ^ value ^ "\""
10791   | Text -> "Text"
10792
10793 and string_of_rng_list xs =
10794   String.concat ", " (List.map string_of_rng xs)
10795
10796 let rec parse_rng ?defines context = function
10797   | [] -> []
10798   | Xml.Element ("element", ["name", name], children) :: rest ->
10799       Element (name, parse_rng ?defines context children)
10800       :: parse_rng ?defines context rest
10801   | Xml.Element ("attribute", ["name", name], children) :: rest ->
10802       Attribute (name, parse_rng ?defines context children)
10803       :: parse_rng ?defines context rest
10804   | Xml.Element ("interleave", [], children) :: rest ->
10805       Interleave (parse_rng ?defines context children)
10806       :: parse_rng ?defines context rest
10807   | Xml.Element ("zeroOrMore", [], [child]) :: rest ->
10808       let rng = parse_rng ?defines context [child] in
10809       (match rng with
10810        | [child] -> ZeroOrMore child :: parse_rng ?defines context rest
10811        | _ ->
10812            failwithf "%s: <zeroOrMore> contains more than one child element"
10813              context
10814       )
10815   | Xml.Element ("oneOrMore", [], [child]) :: rest ->
10816       let rng = parse_rng ?defines context [child] in
10817       (match rng with
10818        | [child] -> OneOrMore child :: parse_rng ?defines context rest
10819        | _ ->
10820            failwithf "%s: <oneOrMore> contains more than one child element"
10821              context
10822       )
10823   | Xml.Element ("optional", [], [child]) :: rest ->
10824       let rng = parse_rng ?defines context [child] in
10825       (match rng with
10826        | [child] -> Optional child :: parse_rng ?defines context rest
10827        | _ ->
10828            failwithf "%s: <optional> contains more than one child element"
10829              context
10830       )
10831   | Xml.Element ("choice", [], children) :: rest ->
10832       let values = List.map (
10833         function Xml.Element ("value", [], [Xml.PCData value]) -> value
10834         | _ ->
10835             failwithf "%s: can't handle anything except <value> in <choice>"
10836               context
10837       ) children in
10838       Choice values
10839       :: parse_rng ?defines context rest
10840   | Xml.Element ("value", [], [Xml.PCData value]) :: rest ->
10841       Value value :: parse_rng ?defines context rest
10842   | Xml.Element ("text", [], []) :: rest ->
10843       Text :: parse_rng ?defines context rest
10844   | Xml.Element ("ref", ["name", name], []) :: rest ->
10845       (* Look up the reference.  Because of limitations in this parser,
10846        * we can't handle arbitrarily nested <ref> yet.  You can only
10847        * use <ref> from inside <start>.
10848        *)
10849       (match defines with
10850        | None ->
10851            failwithf "%s: contains <ref>, but no refs are defined yet" context
10852        | Some map ->
10853            let rng = StringMap.find name map in
10854            rng @ parse_rng ?defines context rest
10855       )
10856   | x :: _ ->
10857       failwithf "%s: can't handle '%s' in schema" context (Xml.to_string x)
10858
10859 let grammar =
10860   let xml = Xml.parse_file rng_input in
10861   match xml with
10862   | Xml.Element ("grammar", _,
10863                  Xml.Element ("start", _, gram) :: defines) ->
10864       (* The <define/> elements are referenced in the <start> section,
10865        * so build a map of those first.
10866        *)
10867       let defines = List.fold_left (
10868         fun map ->
10869           function Xml.Element ("define", ["name", name], defn) ->
10870             StringMap.add name defn map
10871           | _ ->
10872               failwithf "%s: expected <define name=name/>" rng_input
10873       ) StringMap.empty defines in
10874       let defines = StringMap.mapi parse_rng defines in
10875
10876       (* Parse the <start> clause, passing the defines. *)
10877       parse_rng ~defines "<start>" gram
10878   | _ ->
10879       failwithf "%s: input is not <grammar><start/><define>*</grammar>"
10880         rng_input
10881
10882 let name_of_field = function
10883   | Element (name, _) | Attribute (name, _)
10884   | ZeroOrMore (Element (name, _))
10885   | OneOrMore (Element (name, _))
10886   | Optional (Element (name, _)) -> name
10887   | Optional (Attribute (name, _)) -> name
10888   | Text -> (* an unnamed field in an element *)
10889       "data"
10890   | rng ->
10891       failwithf "name_of_field failed at: %s" (string_of_rng rng)
10892
10893 (* At the moment this function only generates OCaml types.  However we
10894  * should parameterize it later so it can generate types/structs in a
10895  * variety of languages.
10896  *)
10897 let generate_types xs =
10898   (* A simple type is one that can be printed out directly, eg.
10899    * "string option".  A complex type is one which has a name and has
10900    * to be defined via another toplevel definition, eg. a struct.
10901    *
10902    * generate_type generates code for either simple or complex types.
10903    * In the simple case, it returns the string ("string option").  In
10904    * the complex case, it returns the name ("mountpoint").  In the
10905    * complex case it has to print out the definition before returning,
10906    * so it should only be called when we are at the beginning of a
10907    * new line (BOL context).
10908    *)
10909   let rec generate_type = function
10910     | Text ->                                (* string *)
10911         "string", true
10912     | Choice values ->                        (* [`val1|`val2|...] *)
10913         "[" ^ String.concat "|" (List.map ((^)"`") values) ^ "]", true
10914     | ZeroOrMore rng ->                        (* <rng> list *)
10915         let t, is_simple = generate_type rng in
10916         t ^ " list (* 0 or more *)", is_simple
10917     | OneOrMore rng ->                        (* <rng> list *)
10918         let t, is_simple = generate_type rng in
10919         t ^ " list (* 1 or more *)", is_simple
10920                                         (* virt-inspector hack: bool *)
10921     | Optional (Attribute (name, [Value "1"])) ->
10922         "bool", true
10923     | Optional rng ->                        (* <rng> list *)
10924         let t, is_simple = generate_type rng in
10925         t ^ " option", is_simple
10926                                         (* type name = { fields ... } *)
10927     | Element (name, fields) when is_attrs_interleave fields ->
10928         generate_type_struct name (get_attrs_interleave fields)
10929     | Element (name, [field])                (* type name = field *)
10930     | Attribute (name, [field]) ->
10931         let t, is_simple = generate_type field in
10932         if is_simple then (t, true)
10933         else (
10934           pr "type %s = %s\n" name t;
10935           name, false
10936         )
10937     | Element (name, fields) ->              (* type name = { fields ... } *)
10938         generate_type_struct name fields
10939     | rng ->
10940         failwithf "generate_type failed at: %s" (string_of_rng rng)
10941
10942   and is_attrs_interleave = function
10943     | [Interleave _] -> true
10944     | Attribute _ :: fields -> is_attrs_interleave fields
10945     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
10946     | _ -> false
10947
10948   and get_attrs_interleave = function
10949     | [Interleave fields] -> fields
10950     | ((Attribute _) as field) :: fields
10951     | ((Optional (Attribute _)) as field) :: fields ->
10952         field :: get_attrs_interleave fields
10953     | _ -> assert false
10954
10955   and generate_types xs =
10956     List.iter (fun x -> ignore (generate_type x)) xs
10957
10958   and generate_type_struct name fields =
10959     (* Calculate the types of the fields first.  We have to do this
10960      * before printing anything so we are still in BOL context.
10961      *)
10962     let types = List.map fst (List.map generate_type fields) in
10963
10964     (* Special case of a struct containing just a string and another
10965      * field.  Turn it into an assoc list.
10966      *)
10967     match types with
10968     | ["string"; other] ->
10969         let fname1, fname2 =
10970           match fields with
10971           | [f1; f2] -> name_of_field f1, name_of_field f2
10972           | _ -> assert false in
10973         pr "type %s = string * %s (* %s -> %s *)\n" name other fname1 fname2;
10974         name, false
10975
10976     | types ->
10977         pr "type %s = {\n" name;
10978         List.iter (
10979           fun (field, ftype) ->
10980             let fname = name_of_field field in
10981             pr "  %s_%s : %s;\n" name fname ftype
10982         ) (List.combine fields types);
10983         pr "}\n";
10984         (* Return the name of this type, and
10985          * false because it's not a simple type.
10986          *)
10987         name, false
10988   in
10989
10990   generate_types xs
10991
10992 let generate_parsers xs =
10993   (* As for generate_type above, generate_parser makes a parser for
10994    * some type, and returns the name of the parser it has generated.
10995    * Because it (may) need to print something, it should always be
10996    * called in BOL context.
10997    *)
10998   let rec generate_parser = function
10999     | Text ->                                (* string *)
11000         "string_child_or_empty"
11001     | Choice values ->                        (* [`val1|`val2|...] *)
11002         sprintf "(fun x -> match Xml.pcdata (first_child x) with %s | str -> failwith (\"unexpected field value: \" ^ str))"
11003           (String.concat "|"
11004              (List.map (fun v -> sprintf "%S -> `%s" v v) values))
11005     | ZeroOrMore rng ->                        (* <rng> list *)
11006         let pa = generate_parser rng in
11007         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11008     | OneOrMore rng ->                        (* <rng> list *)
11009         let pa = generate_parser rng in
11010         sprintf "(fun x -> List.map %s (Xml.children x))" pa
11011                                         (* virt-inspector hack: bool *)
11012     | Optional (Attribute (name, [Value "1"])) ->
11013         sprintf "(fun x -> try ignore (Xml.attrib x %S); true with Xml.No_attribute _ -> false)" name
11014     | Optional rng ->                        (* <rng> list *)
11015         let pa = generate_parser rng in
11016         sprintf "(function None -> None | Some x -> Some (%s x))" pa
11017                                         (* type name = { fields ... } *)
11018     | Element (name, fields) when is_attrs_interleave fields ->
11019         generate_parser_struct name (get_attrs_interleave fields)
11020     | Element (name, [field]) ->        (* type name = field *)
11021         let pa = generate_parser field in
11022         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11023         pr "let %s =\n" parser_name;
11024         pr "  %s\n" pa;
11025         pr "let parse_%s = %s\n" name parser_name;
11026         parser_name
11027     | Attribute (name, [field]) ->
11028         let pa = generate_parser field in
11029         let parser_name = sprintf "parse_%s_%d" name (unique ()) in
11030         pr "let %s =\n" parser_name;
11031         pr "  %s\n" pa;
11032         pr "let parse_%s = %s\n" name parser_name;
11033         parser_name
11034     | Element (name, fields) ->              (* type name = { fields ... } *)
11035         generate_parser_struct name ([], fields)
11036     | rng ->
11037         failwithf "generate_parser failed at: %s" (string_of_rng rng)
11038
11039   and is_attrs_interleave = function
11040     | [Interleave _] -> true
11041     | Attribute _ :: fields -> is_attrs_interleave fields
11042     | Optional (Attribute _) :: fields -> is_attrs_interleave fields
11043     | _ -> false
11044
11045   and get_attrs_interleave = function
11046     | [Interleave fields] -> [], fields
11047     | ((Attribute _) as field) :: fields
11048     | ((Optional (Attribute _)) as field) :: fields ->
11049         let attrs, interleaves = get_attrs_interleave fields in
11050         (field :: attrs), interleaves
11051     | _ -> assert false
11052
11053   and generate_parsers xs =
11054     List.iter (fun x -> ignore (generate_parser x)) xs
11055
11056   and generate_parser_struct name (attrs, interleaves) =
11057     (* Generate parsers for the fields first.  We have to do this
11058      * before printing anything so we are still in BOL context.
11059      *)
11060     let fields = attrs @ interleaves in
11061     let pas = List.map generate_parser fields in
11062
11063     (* Generate an intermediate tuple from all the fields first.
11064      * If the type is just a string + another field, then we will
11065      * return this directly, otherwise it is turned into a record.
11066      *
11067      * RELAX NG note: This code treats <interleave> and plain lists of
11068      * fields the same.  In other words, it doesn't bother enforcing
11069      * any ordering of fields in the XML.
11070      *)
11071     pr "let parse_%s x =\n" name;
11072     pr "  let t = (\n    ";
11073     let comma = ref false in
11074     List.iter (
11075       fun x ->
11076         if !comma then pr ",\n    ";
11077         comma := true;
11078         match x with
11079         | Optional (Attribute (fname, [field])), pa ->
11080             pr "%s x" pa
11081         | Optional (Element (fname, [field])), pa ->
11082             pr "%s (optional_child %S x)" pa fname
11083         | Attribute (fname, [Text]), _ ->
11084             pr "attribute %S x" fname
11085         | (ZeroOrMore _ | OneOrMore _), pa ->
11086             pr "%s x" pa
11087         | Text, pa ->
11088             pr "%s x" pa
11089         | (field, pa) ->
11090             let fname = name_of_field field in
11091             pr "%s (child %S x)" pa fname
11092     ) (List.combine fields pas);
11093     pr "\n  ) in\n";
11094
11095     (match fields with
11096      | [Element (_, [Text]) | Attribute (_, [Text]); _] ->
11097          pr "  t\n"
11098
11099      | _ ->
11100          pr "  (Obj.magic t : %s)\n" name
11101 (*
11102          List.iter (
11103            function
11104            | (Optional (Attribute (fname, [field])), pa) ->
11105                pr "  %s_%s =\n" name fname;
11106                pr "    %s x;\n" pa
11107            | (Optional (Element (fname, [field])), pa) ->
11108                pr "  %s_%s =\n" name fname;
11109                pr "    (let x = optional_child %S x in\n" fname;
11110                pr "     %s x);\n" pa
11111            | (field, pa) ->
11112                let fname = name_of_field field in
11113                pr "  %s_%s =\n" name fname;
11114                pr "    (let x = child %S x in\n" fname;
11115                pr "     %s x);\n" pa
11116          ) (List.combine fields pas);
11117          pr "}\n"
11118 *)
11119     );
11120     sprintf "parse_%s" name
11121   in
11122
11123   generate_parsers xs
11124
11125 (* Generate ocaml/guestfs_inspector.mli. *)
11126 let generate_ocaml_inspector_mli () =
11127   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11128
11129   pr "\
11130 (** This is an OCaml language binding to the external [virt-inspector]
11131     program.
11132
11133     For more information, please read the man page [virt-inspector(1)].
11134 *)
11135
11136 ";
11137
11138   generate_types grammar;
11139   pr "(** The nested information returned from the {!inspect} function. *)\n";
11140   pr "\n";
11141
11142   pr "\
11143 val inspect : ?connect:string -> ?xml:string -> string list -> operatingsystems
11144 (** To inspect a libvirt domain called [name], pass a singleton
11145     list: [inspect [name]].  When using libvirt only, you may
11146     optionally pass a libvirt URI using [inspect ~connect:uri ...].
11147
11148     To inspect a disk image or images, pass a list of the filenames
11149     of the disk images: [inspect filenames]
11150
11151     This function inspects the given guest or disk images and
11152     returns a list of operating system(s) found and a large amount
11153     of information about them.  In the vast majority of cases,
11154     a virtual machine only contains a single operating system.
11155
11156     If the optional [~xml] parameter is given, then this function
11157     skips running the external virt-inspector program and just
11158     parses the given XML directly (which is expected to be XML
11159     produced from a previous run of virt-inspector).  The list of
11160     names and connect URI are ignored in this case.
11161
11162     This function can throw a wide variety of exceptions, for example
11163     if the external virt-inspector program cannot be found, or if
11164     it doesn't generate valid XML.
11165 *)
11166 "
11167
11168 (* Generate ocaml/guestfs_inspector.ml. *)
11169 let generate_ocaml_inspector_ml () =
11170   generate_header ~extra_inputs:[rng_input] OCamlStyle LGPLv2plus;
11171
11172   pr "open Unix\n";
11173   pr "\n";
11174
11175   generate_types grammar;
11176   pr "\n";
11177
11178   pr "\
11179 (* Misc functions which are used by the parser code below. *)
11180 let first_child = function
11181   | Xml.Element (_, _, c::_) -> c
11182   | Xml.Element (name, _, []) ->
11183       failwith (\"expected <\" ^ name ^ \"/> to have a child node\")
11184   | Xml.PCData str ->
11185       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11186
11187 let string_child_or_empty = function
11188   | Xml.Element (_, _, [Xml.PCData s]) -> s
11189   | Xml.Element (_, _, []) -> \"\"
11190   | Xml.Element (x, _, _) ->
11191       failwith (\"expected XML tag with a single PCDATA child, but got \" ^
11192                 x ^ \" instead\")
11193   | Xml.PCData str ->
11194       failwith (\"expected XML tag, but read PCDATA '\" ^ str ^ \"' instead\")
11195
11196 let optional_child name xml =
11197   let children = Xml.children xml in
11198   try
11199     Some (List.find (function
11200                      | Xml.Element (n, _, _) when n = name -> true
11201                      | _ -> false) children)
11202   with
11203     Not_found -> None
11204
11205 let child name xml =
11206   match optional_child name xml with
11207   | Some c -> c
11208   | None ->
11209       failwith (\"mandatory field <\" ^ name ^ \"/> missing in XML output\")
11210
11211 let attribute name xml =
11212   try Xml.attrib xml name
11213   with Xml.No_attribute _ ->
11214     failwith (\"mandatory attribute \" ^ name ^ \" missing in XML output\")
11215
11216 ";
11217
11218   generate_parsers grammar;
11219   pr "\n";
11220
11221   pr "\
11222 (* Run external virt-inspector, then use parser to parse the XML. *)
11223 let inspect ?connect ?xml names =
11224   let xml =
11225     match xml with
11226     | None ->
11227         if names = [] then invalid_arg \"inspect: no names given\";
11228         let cmd = [ \"virt-inspector\"; \"--xml\" ] @
11229           (match connect with None -> [] | Some uri -> [ \"--connect\"; uri ]) @
11230           names in
11231         let cmd = List.map Filename.quote cmd in
11232         let cmd = String.concat \" \" cmd in
11233         let chan = open_process_in cmd in
11234         let xml = Xml.parse_in chan in
11235         (match close_process_in chan with
11236          | WEXITED 0 -> ()
11237          | WEXITED _ -> failwith \"external virt-inspector command failed\"
11238          | WSIGNALED i | WSTOPPED i ->
11239              failwith (\"external virt-inspector command died or stopped on sig \" ^
11240                        string_of_int i)
11241         );
11242         xml
11243     | Some doc ->
11244         Xml.parse_string doc in
11245   parse_operatingsystems xml
11246 "
11247
11248 (* This is used to generate the src/MAX_PROC_NR file which
11249  * contains the maximum procedure number, a surrogate for the
11250  * ABI version number.  See src/Makefile.am for the details.
11251  *)
11252 and generate_max_proc_nr () =
11253   let proc_nrs = List.map (
11254     fun (_, _, proc_nr, _, _, _, _) -> proc_nr
11255   ) daemon_functions in
11256
11257   let max_proc_nr = List.fold_left max 0 proc_nrs in
11258
11259   pr "%d\n" max_proc_nr
11260
11261 let output_to filename k =
11262   let filename_new = filename ^ ".new" in
11263   chan := open_out filename_new;
11264   k ();
11265   close_out !chan;
11266   chan := Pervasives.stdout;
11267
11268   (* Is the new file different from the current file? *)
11269   if Sys.file_exists filename && files_equal filename filename_new then
11270     unlink filename_new                 (* same, so skip it *)
11271   else (
11272     (* different, overwrite old one *)
11273     (try chmod filename 0o644 with Unix_error _ -> ());
11274     rename filename_new filename;
11275     chmod filename 0o444;
11276     printf "written %s\n%!" filename;
11277   )
11278
11279 let perror msg = function
11280   | Unix_error (err, _, _) ->
11281       eprintf "%s: %s\n" msg (error_message err)
11282   | exn ->
11283       eprintf "%s: %s\n" msg (Printexc.to_string exn)
11284
11285 (* Main program. *)
11286 let () =
11287   let lock_fd =
11288     try openfile "HACKING" [O_RDWR] 0
11289     with
11290     | Unix_error (ENOENT, _, _) ->
11291         eprintf "\
11292 You are probably running this from the wrong directory.
11293 Run it from the top source directory using the command
11294   src/generator.ml
11295 ";
11296         exit 1
11297     | exn ->
11298         perror "open: HACKING" exn;
11299         exit 1 in
11300
11301   (* Acquire a lock so parallel builds won't try to run the generator
11302    * twice at the same time.  Subsequent builds will wait for the first
11303    * one to finish.  Note the lock is released implicitly when the
11304    * program exits.
11305    *)
11306   (try lockf lock_fd F_LOCK 1
11307    with exn ->
11308      perror "lock: HACKING" exn;
11309      exit 1);
11310
11311   check_functions ();
11312
11313   output_to "src/guestfs_protocol.x" generate_xdr;
11314   output_to "src/guestfs-structs.h" generate_structs_h;
11315   output_to "src/guestfs-actions.h" generate_actions_h;
11316   output_to "src/guestfs-internal-actions.h" generate_internal_actions_h;
11317   output_to "src/guestfs-actions.c" generate_client_actions;
11318   output_to "src/guestfs-bindtests.c" generate_bindtests;
11319   output_to "src/guestfs-structs.pod" generate_structs_pod;
11320   output_to "src/guestfs-actions.pod" generate_actions_pod;
11321   output_to "src/guestfs-availability.pod" generate_availability_pod;
11322   output_to "src/MAX_PROC_NR" generate_max_proc_nr;
11323   output_to "src/libguestfs.syms" generate_linker_script;
11324   output_to "daemon/actions.h" generate_daemon_actions_h;
11325   output_to "daemon/stubs.c" generate_daemon_actions;
11326   output_to "daemon/names.c" generate_daemon_names;
11327   output_to "daemon/optgroups.c" generate_daemon_optgroups_c;
11328   output_to "daemon/optgroups.h" generate_daemon_optgroups_h;
11329   output_to "capitests/tests.c" generate_tests;
11330   output_to "fish/cmds.c" generate_fish_cmds;
11331   output_to "fish/completion.c" generate_fish_completion;
11332   output_to "fish/guestfish-actions.pod" generate_fish_actions_pod;
11333   output_to "ocaml/guestfs.mli" generate_ocaml_mli;
11334   output_to "ocaml/guestfs.ml" generate_ocaml_ml;
11335   output_to "ocaml/guestfs_c_actions.c" generate_ocaml_c;
11336   output_to "ocaml/bindtests.ml" generate_ocaml_bindtests;
11337   output_to "ocaml/guestfs_inspector.mli" generate_ocaml_inspector_mli;
11338   output_to "ocaml/guestfs_inspector.ml" generate_ocaml_inspector_ml;
11339   output_to "perl/Guestfs.xs" generate_perl_xs;
11340   output_to "perl/lib/Sys/Guestfs.pm" generate_perl_pm;
11341   output_to "perl/bindtests.pl" generate_perl_bindtests;
11342   output_to "python/guestfs-py.c" generate_python_c;
11343   output_to "python/guestfs.py" generate_python_py;
11344   output_to "python/bindtests.py" generate_python_bindtests;
11345   output_to "ruby/ext/guestfs/_guestfs.c" generate_ruby_c;
11346   output_to "ruby/bindtests.rb" generate_ruby_bindtests;
11347   output_to "java/com/redhat/et/libguestfs/GuestFS.java" generate_java_java;
11348
11349   List.iter (
11350     fun (typ, jtyp) ->
11351       let cols = cols_of_struct typ in
11352       let filename = sprintf "java/com/redhat/et/libguestfs/%s.java" jtyp in
11353       output_to filename (generate_java_struct jtyp cols);
11354   ) java_structs;
11355
11356   output_to "java/Makefile.inc" generate_java_makefile_inc;
11357   output_to "java/com_redhat_et_libguestfs_GuestFS.c" generate_java_c;
11358   output_to "java/Bindtests.java" generate_java_bindtests;
11359   output_to "haskell/Guestfs.hs" generate_haskell_hs;
11360   output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
11361   output_to "csharp/Libguestfs.cs" generate_csharp;
11362
11363   (* Always generate this file last, and unconditionally.  It's used
11364    * by the Makefile to know when we must re-run the generator.
11365    *)
11366   let chan = open_out "src/stamp-generator" in
11367   fprintf chan "1\n";
11368   close_out chan;
11369
11370   printf "generated %d lines of code\n" !lines